Вопрос

Я пытаюсь перетасовать массив, но то, как я делаю, это работает, только примерно каждый пятый раз. Я бы очень признателен, если бы кто-то мог объяснить, почему он не работает должным образом и, возможно, предложит твик.

private Button[] scrambleBoard(Button[] buttons)
{
    for (int x = 100 * buttons.Count(); x > 0; x--)
    {
        Random rand = new Random();
        int first = rand.Next(buttons.Count());
        int second = rand.Next(buttons.Count());


        Button temp = buttons[first];
        buttons[first] = buttons[second];
        buttons[second] = temp;
    }

    return buttons;
}
Это было полезно?

Решение

Переместите следующую линию за пределами петли:

Random rand = new Random();

Семя по умолчанию, используемое System.Random основан на Environment.TickCount. Отказ В тесной петле клещница может не изменяться между последовательными итерациями, поэтому он может в конечном итоге использовать с тем же сеемкой снова и снова. Следовательно, цикл будет многократно поменять такой же два элемента до изменения тика-подсчета (он не может сделать это до завершения петли). Чтобы убедиться, что это проблема, вы можете попробовать добавить Thread.Sleep(100) или аналогично внутри петли; Вы должны быть в состоянии увидеть шаффл, работающую правильно (хотя и очень медленно).

Вы также должны отметить, что Техника, которую вы используете Развернуть массив пристрастный; Не каждая перестановка одинаково вероятно. Возможно, вы захотите использовать алгоритм спретра, который, как известно, является беспристрастным, таким как Fisher-Yates Shuffle.

В качестве альтернативы вы можете использовать действительно простую технику для перемещения. Это немного неэффективно, но беспристрастный:

var rand = new Random();
return buttons.OrderBy(button => rand.Next()).ToArray();

Другие советы

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

Вы можете решить проблему, объявляя случайном классе как статическое снаружи корпуса метода.

private static Random rand = new Random();

private Button[] scrambleBoard(Button[] buttons)
{
    for (int x = 100 * buttons.Count(); x > 0; x--)
    {
        int first = rand.Next(buttons.Count());
        int second = rand.Next(buttons.Count());


        Button temp = buttons[first];
        buttons[first] = buttons[second];
        buttons[second] = temp;
    }

    return buttons;
}

Ваш вопрос ответил, но я подумал, что поделюсь приятным маленьким трюком для перетаскивания коллекции, используя LINQ и GUID. Это создает случайно заказанный список с приятным распространением значений.

private Button[] scrambleBoard(Button[] buttons)
{
    return buttons.OrderBy(b => Guid.NewGuid()).ToArray();
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top