如何根据用户输入生成与范围不同的数字

时间:2018-05-25 21:35:38

标签: c# winforms random

我正在尝试根据用户输入生成具有不同范围的随机数。在我的程序中,用户将输入iLvl作为1-100之间的数字,具体取决于该数字,我将生成一个适合等级范围的数字,并将其分配给preRoll,然后在论坛上打印出来。我遇到的问题是,无论我输入哪个号码,我都会得到相同的号码(仅从5到8不等)。我不确定为什么会发生这种情况,但我认为它必须对产生数字的系统时钟做一些事情。如果问题太模糊或基本没问题,我会道歉但是我在理解随机数生成器在c#中的工作原理时遇到了一些麻烦。感谢您的所有反馈,如果有任何其他问题,请告诉我

toss_number = input("How many times do you want to toss the coin?\n")

while True:
    if toss_number.isdigit():
        break
    else:
        toss_number = input("Please input NUMBER of times you want to toss a coin.\n")

3 个答案:

答案 0 :(得分:3)

您在if语句中使用逻辑OR是错误的。

if(someNumber >= 1 || someNumber <= 4) // do things

所有数字都大于或等于1或小于或等于4,因此这个条件总是匹配的。由于您正在建立边界,因此您希望使用逻辑AND。

if(someNumber >= 1 && someNumber <= 4) // do things

这仅匹配数字1..4。 3大于或等于1且小于或等于4,因此它匹配。 5大于或等于1,但也大于4,所以它不会超过你的条件。

答案 1 :(得分:1)

系统时钟并非用于生成随机数&#34; - 它用于为随机生成算法提供一次性种子值,以使其后续的数字序列基于。当您在非常接近的时间创建多个Random实例时,使用基于时间的种子值只是一个问题,然后期望每个实例使用不同的种子。这样的事情会显示问题:

  Random rand1 = new Random();
  Random rand2 = new Random();
  Thread.Sleep(2000);
  Random rand3 = new Random();

几乎可以肯定rand1和rand2将获得与另一个相同的随机数序列,而rand3赢了。但这不是问题 - 只需创建一个随机实例,并将其用于所有随机数,而不是多个实例(如果你不能保证他们不会有相同的基于时间的种子价值)。

在代码中,您可以创建getrandom实例,并在开头创建一个用于生成范围随机数的函数:

private static readonly Random getrandom = new Random();

public static int GenRan(int min, int max)
{
    lock (getrandom) // synchronize
    {
        return getrandom.Next(min, max);
    }
}

但你永远不会使用GenRan。而是在Click事件中创建一个新的随机对象:

Random obj = new Random();

虽然这看起来像某种错误,但它不会导致您描述的问题,因为您只需使用该对象生成每个随机数。所以内部,至少,似乎这可能会奏效。

由于有问题的代码在_Click方法中,我认为它是为事件调用的。每个方法调用最多生成一个随机数,并在每次调用时创建一个新的Random实例。似乎不太可能将UI事件处理程序调用得足够紧密,背靠背,以解决此问题。此外,问题不在于您获得了随机数的相同序列(这是多个随机实例创建的时间过于接近会发生的情况),但它并没有似乎是尊重Next方法的参数,它指示随机数的范围。因此,这与基于时间的种子价值完全没有任何关系。

所以这一切都是非常错误的。相反,它是错误的,因为条件语句被错误地写了。以下是您的代码中的一些内容:

        if ( iLvl >= 1 || iLvl <= 4)       // teir 8
        {
            preRoll = obj.Next(5, 9);
        }
        else if (iLvl >= 5 || iLvl <= 10)  // teir 7
        {
            preRoll = obj.Next(10, 19);
        }
        else if (iLvl >= 11 || iLvl <= 17)  // teir 6
        {
            preRoll = obj.Next(20, 29);
        }

这是条件块开始的方式。让我们一起来看,值为3。

首先我们点击这个:

        if ( iLvl >= 1 || iLvl <= 4)       // teir 8

并且满足第一个条件 - iLvl&gt; = 1.并且其余条件是&#34;或者iLvl&lt; = 4&#34;。因此,满足任一条件将执行以下语句:

        {
            preRoll = obj.Next(5, 9);
        }

请注意,这将完全描述您获得的结果范围。

如果您还没有看到问题,那就让我们继续前进,价值为6。

        if ( iLvl >= 1 || iLvl <= 4)       // teir 8
        {
            preRoll = obj.Next(5, 9);
        }
        else if (iLvl >= 5 || iLvl <= 10)  // teir 7
        {
            preRoll = obj.Next(10, 19);
        }

如果您希望第一个块为false,而第二个块为true,则会出现错误。 大于零,任何值&lt;大于零的所有值都满足第一个块。当然,我们的新价值是&#34; 6&#34;大于零,因此需要第一个条件。实际上,所有值> 0将使用该条件,这就是您的问题。

要修复,您应该使用&#34;&amp;&amp;&#34;而不是&#34; ||&#34;,以确保满足块执行的条件。

答案 2 :(得分:0)

您正在检查AtomicInteger index = new AtomicInteger(1); Map<String, Integer> nameMap = mySet.stream() .sorted(myComparator) .collect(Collectors .toMap(MyObject::getName, value -> index.getAndIncrement(), (e1, e2) -> e1, LinkedHashMap::new)); iLvl >= 1,所以除非iLvl小于1,否则这将始终为真。使用iLvl <= 4(和)代替&&(或)以确保两个条件均为真。

或者,你可以这样简化你的陈述:

||