Algoritmo: genera posiciones aleatorias que no se repiten dentro de un rango específico

pregunta:

  En los juegos, a menudo nos encontramos con el siguiente problema: generar posiciones aleatorias que no se repiten dentro de un rango específico.

  Por ejemplo, en cierto evento de "Bendición de sacerdotes", se deben generar n cofres del tesoro únicos en la puerta de la ciudad.

  Para resolver este problema, primero podemos dividir el rango en m posiciones diferentes según el tamaño del cofre del tesoro (celda básica), y registrar sus números con una matriz int. Finalmente, el número aleatorio requerido se obtiene por eliminación aleatoria.

 

solución: 

  La abstracción es la figura anterior, es decir, en el área roja, las celdas verdes se cortan en celdas de largo x ancho y finalmente se seleccionan al azar. El código real es el siguiente:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


/// <summary>
/// 将区域切分为单元格,并在其中选取随机数组生成
/// </summary>
public class RandomCreat : MonoBehaviour
{

    public Vector3 startPos;

    public Vector3 endPos;

    public Vector3 size;

    public int num;

    // Start is called before the first frame update
    void Start()
    {
        var _list = GetRandomPosInPlane(startPos, endPos, size, num);
        foreach (var idx in _list)
        {
            var _obj = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            _obj.transform.position = idx;
        }


    }

    // Update is called once per frame
    void Update()
    {
        
    }

    
    /// <summary>
    /// 在同一平面中生成随机不重复数组
    /// </summary>
    /// <param name="_startPos">起始坐标</param>
    /// <param name="_endPos">结束坐标</param>
    /// <param name="_size">格子大小</param>
    /// <param name="_num">获得的个数</param>
    /// <returns></returns>
    public List<Vector3> GetRandomPosInPlane(Vector3 _startPos, Vector3 _endPos, Vector3 _size,int _num)
    {
        //先将位置切割为n个单元格
        var _sizePos = _endPos - _startPos;
        int _x = (int)(_sizePos.x / _size.x);
        int _z = (int)(_sizePos.z / _size.z);
        //将这些单元格按照序号编入数组
        var _allList = new List<int>();
        var _maxNum = _x * _z;
        for (var _i = 0; _i < _maxNum; _i++) _allList.Add(_i);
        //从编号数组中随机出个数
        var _getListNum = new List<int>();
        while (_getListNum.Count < _num && _allList.Count > 0)
        {
            var _r = _allList[Random.Range(0, _allList.Count)];
            _getListNum.Add(_r);
            _allList.Remove(_r);
        }
        //将编号还原为坐标
        var _getList = new List<Vector3>();
        foreach (var idx in _getListNum) 
            _getList.Add(new Vector3(_startPos.x + (0.5f + idx % _x) * _size.x, _startPos.y, _startPos.z + (0.5f + idx / _x) * _size.z));
        return _getList;
    }


}

prueba:

    Podemos colgar el script en un objeto para probar el efecto de implementación específico:

    

   Cuando se seleccionan 10, los resultados son diferentes cada vez.

Resumir:

  Con los ejemplos anteriores, podemos abstraer una solución más general. De esta forma, cuando te encuentres con otros gráficos o áreas 3D en el futuro, puedes usar esta idea para resolverlos:

1. Dividir el espacio en m*n áreas según la unidad básica;

2. Numere y escriba todas las áreas en una matriz int

3. Obtener la matriz numerada que queremos de la matriz int eliminando

4. Luego convierta la matriz numerada en nuestro valor de posición final

Supongo que te gusta

Origin blog.csdn.net/Tel17610887670/article/details/130343260
Recomendado
Clasificación