2

下面的代码相当简单——它用随机选择的像素填充设计表面——没什么特别的(暂时忽略第二种方法中的 XXXXXXX)。

private void PaintBackground()
{
    Random rnd = new Random();

    Bitmap b = new Bitmap(this.Width, this.Height);
    for (int vertical = 0; vertical < this.Height; vertical++)
    {
        for (int horizontal = 0; horizontal < this.Width; horizontal++)
        {
            Color randomColour = GetRandomColor(rnd);
            b.SetPixel(horizontal, vertical, randomColour);
        }
    }

    Graphics g = this.CreateGraphics();
    g.DrawImage(b, new Point(0, 0));
}

public Color GetRandomColor(Random rnd)
{
    XXXXXXXXXXXXXXXX

    byte r = Convert.ToByte(rnd.Next(0, 255));
    byte g = Convert.ToByte(rnd.Next(0, 255));
    byte b = Convert.ToByte(rnd.Next(0, 255));

    return Color.FromArgb(255, r, g, b);
}

我的问题是这个...

如果您将 XXXXXXXXX 替换为“随机 rnd = new Random();” 测试图案完全变成相同颜色的水平条,因此不是随机的。

来人解释一下这是为什么?

据我所知,第二次尝试的唯一区别是 GetRandomColour 方法创建并使用了 Random 类的新实例,但我看不出它是如何产生水平条的。

4

4 回答 4

7

来自MSDN

随机数生成从种子值开始。如果重复使用相同的种子,则会生成相同的数字序列。产生不同序列的一种方法是使种子值与时间相关,从而为每个新的 Random 实例产生不同的序列。默认情况下, Random 类的无参数构造函数使用系统时钟生成其种子值,而它的参数化构造函数可以根据当前时间的刻度数取一个 Int32 值。但是,由于时钟的分辨率有限,因此使用无参数构造函数以紧密连续的方式创建不同的 Random 对象会创建生成相同随机数序列的随机数生成器。以下示例说明了两个紧密连续实例化的 Random 对象生成相同的随机数序列。

因此,给定相同的种子,Random 实例将产生相同的数字序列。在您的示例中,由于系统时钟的分辨率有限,随机实例是使用与种子相同的滴答计数创建的,从而产生相同的序列。

连续调用GetRandomColor()在系统时钟的一个时间片内执行。要对此进行测试,请尝试使用Thread.Sleep(1). 您应该看到生成了不同的颜色。

于 2010-01-19T12:48:06.917 回答
3

您的应用程序运行得如此之快,以至于初始化 PRNG 的种子在整个循环中保持不变。

因此它不是真正随机的,因此称为伪随机数生成器。

于 2010-01-19T12:46:49.977 回答
1

创建时随机具有默认种子零。在该函数中重新创建它总是会给出相同的数字。在构造函数中创建它,然后重用以获得不同的随机数。

于 2010-01-19T12:48:15.277 回答
1

随机并不是真正的随机。它们是“伪随机”。你真正在做的(从机器的角度来看)是在起始点一遍又一遍地生成相同的随机数。您真正需要做的是将构造函数传递给“种子”,或者具有可以调用 Next() 方法的更高范围的随机数。

于 2010-01-19T12:48:43.543 回答