XNA随机选择纹理总是选择相同的纹理

时间:2011-10-13 06:49:13

标签: c# windows-phone-7 xna xna-4.0

我使用此代码将大约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 个答案:

答案 0 :(得分:5)

试试这个:

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
.
.
.

答案 1 :(得分:2)

来自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);          

    }

答案 2 :(得分:0)

new Random().Next(0, 4600)

表示你每次都初始化rng(可能是同一个种子?) 将新方法移到方法外部(静态成员或类似方法)。

答案 3 :(得分:0)

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);          

        }

查看Revisiting randomness了解详情。

也没有理由使用rand.Next(0, 4600)%46。您可以直接使用rand.Next(0,46)

请注意,此代码仍会返回重复的条目。如果你想完全避免使用:

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

来自Is using Random and OrderBy a good shuffle algorithm?

Shuffle