XNA Случайно выбранная текстура всегда выбирает одну и ту же текстуру - PullRequest
2 голосов
/ 13 октября 2011

Я сделал этот код для загрузки около 8 различных текстур в список объектов со свойством текстуры.

У меня есть папка с текстурами под названием «1.png, 2.png, 3.png, ......., 46.png», и я хочу, чтобы 8 различных объектов загружались со случайно выбранными текстурами.

        DockedFruitsList = new List<Fruit>(8);
        for (int i = 0; i < 8; i++)
        {
            Fruit temp = new Fruit();
            temp = new Fruit();
            temp.Position = AvailablePositions[i];
            int random=(new Random().Next(0, 4600) % 46);
            temp.Texture = Content.Load<Texture2D>(@"Fruits/" + random);
            DockedFruitsList.Add(temp);          

        }

Дело в том, что, несмотря на то, что случайное число всегда генерирует различное число, результат рисования всегда имеет одну и ту же текстуру, он меняется от цикла к другому, но он всегда одинаков для всех 8 текстур

spriteBatch.Begin();
        for (int i = 0; i < DockedFruitsList.Count; i++)
        {
            spriteBatch.Draw(DockedFruitsList[i].Texture, DockedFruitsList[i].Position, Color.White);
        }
        spriteBatch.End();

Ответы [ 4 ]

5 голосов
/ 13 октября 2011

Попробуйте это:

for (int i = 0; i < 100; i++)
    Console.WriteLine(new Random().Next(0, 10));

Скорее всего, вы получите такой результат:

5
5
5
.
.
.

Это связано с тем, что начальное число класса Random инициализируется значением, основанным на времени. Если вы инициализируете много экземпляров класса Random около одного и того же момента времени, то все они получат одинаковое начальное число, и поэтому все значения, которые они будут создавать, будут одинаковыми.

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

var r = new Random();
for (int i = 0; i < 100; i++)
    Console.WriteLine(r.Next(0, 10));

Выход:

2
8
0
.
.
.
2 голосов
/ 13 октября 2011

Из MSDN:

Генерация случайного числа начинается с начального значения.Если одно и то же начальное число используется повторно, генерируется одна и та же серия чисел.По умолчанию конструктор без параметров класса Random использует системные часы для генерации его начального значения

Системные часы, которые он использует, изменяют только свое значение каждые несколько миллисекунд, поэтому, если вы вызываете new Random() очень быстро, оноВы будете засеяны тем же номером, поэтому вызовы Next... приведут к одинаковым результатам.

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


Создайте объект Random один раз и используйте его повторно (обратите внимание, я сейчас преобразуюrandom в строку, и я тоже случайно вызвал другой метод):

    var rand = new Random();
    DockedFruitsList = new List<Fruit>(8);
    for (int i = 0; i < 8; i++)
    {
        Fruit temp = new Fruit();
        temp = new Fruit();
        temp.Position = AvailablePositions[i];
        int random=(rand.Next(46) + 1);
        temp.Texture = Content.Load<Texture2D>(@"Fruits/" + random.ToString());
        DockedFruitsList.Add(temp);          

    }
0 голосов
/ 13 октября 2011

Random засевается временем (GetTickCount()), время меняется только каждые несколько миллисекунд.Таким образом, все случайные экземпляры, созданные в этом интервале, будут возвращать одну и ту же последовательность.Правильным является только создание единственного экземпляра Random вне цикла.

        DockedFruitsList = new List<Fruit>(8);
        Random rand = new Random();
        for (int i = 0; i < 8; i++)
        {
            Fruit temp = new Fruit();
            temp = new Fruit();
            temp.Position = AvailablePositions[i];
            int random=(rand.Next(1, 46));
            temp.Texture = Content.Load<Texture2D>(@"Fruits/" + random);
            DockedFruitsList.Add(temp);          

        }

Проверка Пересмотр случайности для получения дополнительной информации.

Нет также причиниспользовать rand.Next(0, 4600)%46.Вы можете использовать rand.Next(0,46) напрямую.

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

Random rand=new Random();
foreach(int randomFruid in Range(1,46).Shuffle(rand).Take(8))
{
   ...
}

С Shuffle из Является ли использование Random и OrderBy хорошим алгоритмом перемешивания?

0 голосов
/ 13 октября 2011
new Random().Next(0, 4600)

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

...