Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 随机生成的值并不是真正随机的_C#_Random - Fatal编程技术网

C# 随机生成的值并不是真正随机的

C# 随机生成的值并不是真正随机的,c#,random,C#,Random,我正在用C#做一个简单的游戏,并使用Random类每2秒生成一个随机数,但它给出的数字我可以提前猜到,因为它每次递增一个特定的数字 private int RandomNumber; //This Timer function runs every 2 seconds private void TmrGenerateRandomNum(object sender, EventArgs e) { Random r = new Random(); RandomNumber = r.

我正在用C#做一个简单的游戏,并使用
Random
类每2秒生成一个随机数,但它给出的数字我可以提前猜到,因为它每次递增一个特定的数字

private int RandomNumber;

//This Timer function runs every 2 seconds
private void TmrGenerateRandomNum(object sender, EventArgs e)
{
    Random r = new Random();
    RandomNumber = r.Next(50, 200); //Trying to get random values between 50 and 200
    Label1.Text = RandomNumber.ToString();
}
这实际上是我仅有的代码,我每次都通过
Label1
显示该值。例如,问题是,如果我第一次得到52,下一个“随机”生成的值是71或72,下一个是91或92,下一个是111或112。正如你所看到的,它正以20ish的速度递增。然后它突然又得到了一个真正的随机值,比如说163。但接下来生成的数字是183,再次增加20。因为183+20超出了这个范围,所以它又得到了一个真正的随机值,比如说83。但下一个生成的数字是103或104,然后是123或124

这不是“随机”的,因为你可以知道下一个数字是多少。。。这让我快发疯了。
你知道它为什么会这样做吗?有解决办法吗

虽然生成真正的随机数相对比较困难,但您应该能够得到比实际更好的结果。正如评论所建议的,您现在可能遇到的问题是,您不应该每次调用函数时都“重新开始”。作为测试,您可以尝试将一些值(如
5
)作为参数传递给
Random
构造函数。然后你会发现你的结果并不是随机的。要解决这个问题,正如注释所建议的,您应该将随机对象的构造移动到全局某个位置,以便随机性可以随着时间的推移“构建”在自身上,而不是总是被重置。一旦确认可以通过重复调用获得不同的值,然后将参数删除到
Random
构造函数中,这样就不会在每次重新启动程序时获得相同的随机数序列。

更深入的解释: 基本上,在计算机中生成真正的随机值几乎是不可能的,您得到的所有随机值都是伪随机的,并且基于以下值:

  • 用户输入,如过去2分钟内按下了多少键
  • 内存使用情况,此时正在使用多少KB的内存
  • 最常见的一种方法是:使用以毫秒为单位的当前时间生成一个“种子”,用于生成一系列尽可能随机的数学数字
  • 这就是问题的根源。例如,如果您有以下代码

    Random r1 = new Random();
    Random r2 = new Random();
    
    Console.WriteLine(r1.next())
    Console.WriteLine(r2.next())
    

    奇迹般的是,尽管r1和r2是两个不同的实例,但它们总是会得到相同的数字。这是因为代码块是在随机数的时间窗口中执行的,使用seedvalue来启动序列。如果不提供任何内容,则需要使用当前datetime.now值。如果您提供相同的值(如3842),您将得到相同的随机值序列。你的系列似乎是非常密切相关的,所以你看到相同的价值观。所有这些都可以在msdn的文档中阅读,请参见实例化伪随机:

    实例化随机数生成器

    通过向随机类构造函数提供种子值(伪随机数生成算法的起始值),可以实例化随机数生成器。可以显式或隐式提供种子值:

    随机(Int32)构造函数使用您提供的显式种子值

    Random()构造函数使用系统时钟提供种子值。这是实例化随机数生成器最常用的方法

    如果同一种子用于单独的随机对象,它们将生成相同的随机数序列。这对于创建处理随机值的测试套件,或者重放从随机数中获取数据的游戏非常有用。但是,请注意,在不同版本的.NET Framework下运行的进程中的随机对象可能返回不同的随机数序列,即使它们是用相同的种子值实例化的

    资料来源:


    您可以在我引用的源代码上方找到更多信息,甚至是“更好”方法的方法。

    您最好使用CPRNG或密码Psudo随机数生成器,它不需要由用户进行种子设定,通常会随系统事件不断更新

    要生成加密安全的随机数,请使用类或从中派生类


    参见MSDN。

    Move
    Random r=new Random()在该方法之外。您需要使您的
    Random r
    静态,或者至少更全局,而不是局部,因为您每次都使用相同的种子创建它。@MikaJones
    Random
    不是随机数,而是随机数生成器。您只需要一个生成器来生成(伪)随机序列。您不需要为每个(伪)随机数使用单独的生成器。代码/注释的可能重复也是错误的<代码>r。下一步(50200)
    将生成一个介于50和199之间(含50和199)的值