Как сгенерировать неповторяющиеся случайные числа в Unity - PullRequest
0 голосов
/ 26 мая 2020

Я пытаюсь создать простую игру Bin go и хочу убедиться, что числа не повторяются на карточке bin go. У меня есть генератор случайных чисел, но по какой-то причине код, который я использую, не работает, поскольку одни и те же числа будут постоянно повторяться. Может ли кто-нибудь взглянуть на мой код ниже и сказать мне, что мне нужно исправить, или исправить код для меня?

public Grid(int width, int height, float cellSize)
{
    this.width = width;
    this.height = height;
    this.cellSize = cellSize;

    gridArray = new int[width, height];
    debugTextArray = new TextMesh[width, height];
    for (int x = 0; x < gridArray.GetLength(0); x++)
    {
        for (int y = 0; y < gridArray.GetLength(1); y++)
        {
            debugTextArray[x, y] = UtilsClass.CreateWorldText(gridArray[x, y].ToString(), null, GetWorldPosition(x, y) + new Vector3(cellSize, cellSize) * .5f, 20, Color.white, TextAnchor.MiddleCenter);
            Debug.DrawLine(GetWorldPosition(x, y), GetWorldPosition(x, y + 1), Color.white, 100f);
            Debug.DrawLine(GetWorldPosition(x, y), GetWorldPosition(x + 1, y), Color.white, 100f);
        }
    }
    Debug.DrawLine(GetWorldPosition(0, height), GetWorldPosition(width, height), Color.white, 100f);
    Debug.DrawLine(GetWorldPosition(width, 0), GetWorldPosition(width, height), Color.white, 100f);


    for (int x = 0; x <= 4; x++)
    {
        RandomValue(0, x);
        RandomValue(1, x);
        RandomValue(2, x);
        RandomValue(3, x);
        RandomValue(4, x);
    }

}

private Vector3 GetWorldPosition(int x, int y)
{
    return new Vector3(x, y) * cellSize;
}

public void RandomValue(int x, int y)
{

    if (x >= 0 && y >= 0 && x < width && y < height)
    {
        list = new List<int>(new int[Lenght]);

        for (int j = 0; j < 25; j++)
        {

            Rand = UnityEngine.Random.Range(1, 50);


            while (list.Contains(Rand))
            {
                Rand = UnityEngine.Random.Range(1, 50);

            }

            list[j] = Rand;
            gridArray[x, y] = list[j];
        }


        debugTextArray[x, y].text = gridArray[x, y].ToString();
        debugTextArray[2, 2].text = "Free";
    }
}

Ответы [ 2 ]

0 голосов
/ 26 мая 2020

В основном ваша концепция функции RandomValue () верна, но проблема в том, что она проверяется только в том же столбце, поэтому вам нужно перенести концепцию RandomValue () на уровень Grid (). Вам нужен список, содержащий все утвержденные значения, затем проверьте Contains () в Grid ().

Но на самом деле вы можете сделать это во всех go. Убедитесь, что ваша ширина * высота не больше maxValue.

Dictionary<Vector2Int, int> CreateBingoGrid(int width, int height, int maxValue)
{
    var grid = new Dictionary<Vector2Int, int>();
    for (int x = 0; x < width; x++)
    {
        for (int y = 0; y < height; y++)
        {
            var num = Random.Range(1, maxValue);
            while (grid.ContainsValue(num))
            {
                num = Random.Range(1, maxValue);
            }
            grid.Add(new Vector2Int(x, y), num);
        }
    }
    return grid;
}
0 голосов
/ 26 мая 2020

Как упоминалось в комментарии к вашему вопросу, вероятно, проще всего просто перетасовать числа в диапазоне [1,50], а затем взять первые 25 или сколько угодно.

Причина, по которой ваш код работает неправильно, и вы видите много повторов, потому что вы вызываете функцию RandomValue () несколько раз по отдельности, а переменная списка, с которой вы сравниваете, если значение уже находится на диаграмме, находится внутри этой функции. Это означает, что он будет проверять только значения, сгенерированные в этом вызове, в данном случае это означает только одну строку.

Кроме того, если вы составляете список, который, как вы знаете, всегда будет одного размера, вам следует вместо этого используйте массив. Списки предназначены для случаев, когда вы хотите, чтобы размер можно было регулировать.

Решение 1:

Очень простой способ сгенерировать массив с числами от 1 до 50:

//Initialize Array
int[] numbers = new int[50];
for (int i = 1; i <= numbers.Length; i++)
{
    numbers[i] = i;
}

//Shuffle Array
for (int i = 0; i < numbers.Length; i++ )
{
    int tmp = numbers[i];
    int r = Random.Range(i, numbers.Length);
    numbers[i] = numbers[r];
    numbers[r] = tmp;
}

//Get first 'n' numbers
int[] result = Array.Copy(numbers, 0, result, 0, n);
return result;

Я не уверен, что это наиболее эффективный способ, но он сработает.

Решение 2:

Чтобы изменить код для проверки по всему списку, я изменил бы этот раздел:

for (int x = 0; x <= 4; x++)
{
    RandomValue(0, x);
    RandomValue(1, x);
    RandomValue(2, x);
    RandomValue(3, x);
    RandomValue(4, x);
}

Примерно так:

List<int> values = new List<int>();
for (int y = 0; y < height; y++)
{
    for (int x = 0; x < width; x++)
    {
        int r = RandomValue(1, 50);
        while (values.Contains(r))
        {
            r = RandomValue(1, 50);
        }
        values[y * width + x].Add(r);
        gridArray[x, y] = r;
    }
}

int RandomValue(int min, int max) {
    return UnityEngine.Random.Range(min, max);
}

Надеюсь, это поможет!

...