只有在使用调试器逐步执行代码时,代码才能正确运行?

5
可能是重复内容:
随机数生成器仅生成一个随机数
我刚才对这段代码感到有些困惑。代码如下:
public blockType generateRandomBlock()
{
    Random random = new Random();
    int makeBlockOfType = random.Next(0, 100);

    blockType t = blockType.normal;
    if (makeBlockOfType <= 80 && makeBlockOfType >= 60)
    {
        t = blockType.blue;
    }
    else if (makeBlockOfType > 80 && makeBlockOfType <= 95)
    {
        t = blockType.orange;
    }
    else if (makeBlockOfType > 95 && makeBlockOfType <= 100)
    {
        t = blockType.green;
    }

    return t;
}

相当简单,它根据随机生成的数字(基于系统时间)返回一个枚举值。不幸的是,由于某种奇怪的原因,即使对每个被放入游戏中的块运行此代码,所有块都是相同颜色。不过,当我用调试器逐步执行并在某些运行后查看结果时,我发现基于所提供的机会,这些块现在是多颜色的。 我有点困惑为什么会这样。
对此,我正在使用MonoGame,它使用Mono编译器而不是Microsoft的编译器。这可能是问题吗?我已经尝试将此代码内联到正在调用它的构造函数中,但我得到了相同的结果(我猜编译器无论如何都会内联代码)。
我已经尝试重新启动Visual Studio,而不是让运行程序进行构建; 没有变化。
非常感谢任何建议和帮助!

1
尝试将随机创建移出该方法,这应该会有所帮助。 - Arsen Mkrtchyan
new Random() 使用时间作为种子,该种子在几毫秒内保持不变。 - CodesInChaos
它在调试中能够工作的原因是调用之间有时间,而随机数实际上获得了不同的种子。 - Archy
嗯,这很有道理。不需要解释。然而,由于对象的实例被创建并立即生成块类型,问题仍然存在。因此,将Random对象移动到全局静态类中并每次引用它是否明智? - Serguei Fedorov
3个回答

7
你应该只实例化一次Random(将其设置为私有字段并在构造函数中实例化),请参见类似问题:Random.Next返回相同的值 请查看Random文档

随机数生成从种子值开始。如果重复使用相同的种子,则生成相同的数字序列。

在你的情况下,你用相同的种子创建了一个Random实例(时间间隔太短),并且你取了第一个值,这个值对于给定的种子来说是相同的。

4
每次调用该方法时,您都在重新创建随机数生成器:
public blockType generateRandomBlock()
{
    Random random = new Random();

随机数生成器的种子是基于时间的,因此连续调用会返回相同的值。

将生成器的创建移至程序外:

Random random = new Random();
public blockType generateRandomBlock()
{

3
当您在短时间内连续创建多个Random实例时,它们很可能会以相同的时间相关种子值进行初始化。
为了解决这个问题,您应该将Random初始化为实例字段。
private readonly Random random = new Random();

public blockType generateRandomBlock()
{
    int makeBlockOfType = random.Next(0, 100);

    // ...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接