随机生成的值不是真正随机的

时间:2017-12-22 22:02:57

标签: 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.Next(50, 200); //Trying to get random values between 50 and 200
    Label1.Text = RandomNumber.ToString();
}

这实际上是我唯一的代码,我每次都通过Label1显示值。问题是,例如,如果我第一次得到52,则下一个"随机生成的值是71或72,下一个是91或92,下一个是111或112。你可以看到,它增加了20。然后它突然得到一个真正的随机值,比如说,163。然后下一个生成的数字是183,再次增加20.由于183 + 20超出范围,它再次获得一个真正的随机值,比如83.但是生成的下一个数字再次是103,或104,然后是123或124 ...

这不是"随机"因为你可以告诉下一个将会是什么数字...这让我发疯。 你知道为什么会这样做,并且有解决方法吗?

4 个答案:

答案 0 :(得分:0)

虽然真正的随机数相对难以生成,但您应该能够获得比您更好的结果。正如评论所建议的那样,您现在可能遇到的问题是,您不应该在"重新开始。每次调用函数。作为测试,您可以尝试将5之类的值作为参数传递给Random构造函数。然后你会注意到你的结果真的不是随机的。要解决这个问题,正如评论所暗示的那样,你应该将Random对象的构造移到全局某处,以便随机性可以构建"随着时间的推移而不是总是被重置。确认您可以通过重复调用获得不同的值,然后参数移除到Random构造函数,这样您每次都不会获得相同的随机数序列重新启动你的程序。

答案 1 :(得分:0)

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

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

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

    奇迹般地,你总是从r1和r2得到相同的数字,尽管它们是两个独立的实例。这是因为代码块是在< 1 ms的时间窗口中执行的,这为这两个随机数生成器提供了相同的种子,因此它们将生成相同的数字列表。

    在您的情况下,数字生成器每2秒实例化一次,因此它们会获得递增的种子。很难说这是否会导致一个递增的起始数字,但它可能是一个开始。

    所以相反,尝试初始化一个Random()并始终在其上调用.next()函数,你应该得到一个更随机的数字列表

答案 2 :(得分:0)

随机数使用种子值来启动序列。如果你什么都不给,它需要当前的datetime.now值。如果你提供相同的值(如3842),你将得到相同的随机值序列保证。你的系列似乎非常密切相关,所以你看到相同的价值观。所有这些都可以在msdn的文档中阅读,请参阅Instantiate伪随机:

  

实例化随机数生成器

     

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

     

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

     

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

     

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

来源:https://msdn.microsoft.com/en-us/library/system.random(v=vs.110).aspx#Instantiate

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

答案 3 :(得分:0)

您可以做的最好的事情是使用CPRNG或Cryptograph Psudo随机数生成器,它不需要由tyhe用户播种,并且通常会连续更新系统事件。

要生成加密安全随机数,请使用RNGCryptoServiceProvider类或从System.Security.Cryptography.RandomNumberGenerator派生一个类。

请参阅MSDN Random Class