XNA随机选择的纹理始终拾取相同的纹理

本文关键字:纹理 随机 选择 XNA | 更新日期: 2023-09-27 18:11:19

我编写这段代码是为了将大约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();

XNA随机选择的纹理始终拾取相同的纹理

试试这个:

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

来自msdn:

随机数的生成从种子值开始。如果重复使用相同的种子,则会生成相同的数字序列。默认情况下,Random类的无参数构造函数使用系统时钟生成其种子值

它使用的系统时钟只会每隔几毫秒改变一次值,所以如果你很快调用new Random(),它就会被设定为相同的数字,因此对Next...的调用会产生相同的结果。

请注意,如果您对其进行了调试,逐步执行代码会给系统时钟提前的时间,因此,除非它在没有中断/逐步执行的情况下运行循环,否则您不会得到错误


创建一次Random对象,然后重用它(注意,我现在正在将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);          
    }
new Random().Next(0, 4600)

意味着您每次都初始化rng(可能使用相同的种子?(将新成员移动到方法之外(静态成员或类似成员(。

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 random了解更多详细信息。

也没有理由使用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的Shuffle使用Random和OrderBy是一个好的shuffle算法吗?