【问题标题】:Generating random numbers without repeating.C# [duplicate]生成随机数而不重复。C# [重复]
【发布时间】:2015-07-12 22:33:23
【问题描述】:

大家好,我想在 c# 的同一行生成 6 个不同的数字,但我面临的问题是一些数字在同一行重复。这是我的代码

var rand = new Random();
List<int> listNumbers = new List<int>();
int numbers = rand.Next(1,49);
for (int i= 0 ; i < 6 ;i++)
    {
         listNumbers.Add(numbers);
         numbers = rand.Next(1,49);
    }

我的输出在哪里

17 23 23 31 33 48

【问题讨论】:

  • 唯一性不是随机性的属性。 “随机”意味着数字不是确定性的。你要问的是这个数字是由前面的状态决定的。
  • 将数字 1 到 49 放入一个列表中,然后随机选择一个并在完成后将其删除,重复直到你够了.. 或者将它们洗牌并选择前六个。只要你说随机和唯一,随机就在垃圾箱中......

标签: c#


【解决方案1】:

对照之前的数字检查您生成的每个数字:

List<int> listNumbers = new List<int>();
int number;
for (int i = 0; i < 6; i++)
{
  do {
     number = rand.Next(1, 49);
  } while (listNumbers.Contains(number));
  listNumbers.Add(number);
}

另一种方法是创建一个可能的数字列表,并从列表中删除您选择的数字:

List<int> possible = Enumerable.Range(1, 48).ToList();
List<int> listNumbers = new List<int>();
for (int i = 0; i < 6; i++)
{
  int index = rand.Next(0, possible.Count);
  listNumbers.Add(possible[index]);
  possible.RemoveAt(index);
}

【讨论】:

  • 为什么投反对票?如果你不解释你认为错的地方是什么,它就无法改进答案。
  • 我没有否决您的答案,但您的第一个解决方案似乎有点混乱。虽然它会起作用,但我认为最好将 for 循环更改为 while 循环,如 my answer.
  • @ZoharPeled:这只是两种不同的方法。两者都不比另一个更好。
  • @Guffa 我不同意。我认为没有充分的理由将 while 循环嵌套在 for 循环中。在这种情况下,我认为在性能方面我们的两个建议可能是等效的,但我认为只有 while 循环更具可读性。
  • @ZoharPeled:尝试将创建尚未使用的数字的代码部分重构为函数,您应该明白我的意思。
【解决方案2】:
listNumbers.AddRange(Enumerable.Range(1, 48)
                               .OrderBy(i => rand.Next())
                               .Take(6))

【讨论】:

  • 通过随机数排序的洗牌不是一个很好的方法,你应该使用 Fisher-Yates 洗牌。它恰好在这种情况下起作用,因为 LINQ 缓存了它从谓词中获取的值,但对于其他排序实现,它不会正常工作。
【解决方案3】:

创建一个HashSet并生成一个唯一的随机数

public List<int> GetRandomNumber(int from,int to,int numberOfElement)
{
    var random = new Random();
    HashSet<int> numbers = new HashSet<int>();
    while (numbers.Count < numberOfElement)
    {
        numbers.Add(random.Next(from, to));
    }
    return numbers.ToList();
}

【讨论】:

    【解决方案4】:

    使它成为一个while循环并将整数添加到哈希集中。当你有六个整数时停止循环。

    【讨论】:

    • 这是一个有趣的想法,但是没有很好的方法可以从哈希集中获取值。哈希集中项目的顺序未定义,因此您可能会按照取决于值的顺序而不是添加它们的顺序来获取它们。
    • 如果生成的顺序很重要,则将每个数字添加到返回列表中,因为它们会添加到哈希中。
    • 顺序绝对重要。如果项目根据值重新排列,则列表不再是随机的。只需将数字添加到列表中就意味着该列表可能包含重复项。您需要检查该数字是否存在于哈希集中以确定是否应将其添加到列表中。
    • 是的,当您将它们添加到哈希中时,您会得到一个 true/false 来指示添加是否成功。无需查看哈希。
    • 对,你可以这样检查,我没想到。 :)
    【解决方案5】:

    您应该使用 HashSet,而不是使用 List。 HashSet 禁止多个相同的值。 Add 方法返回一个布尔值,表示元素是否已添加到列表中,请在下面找到示例代码。

    public static IEnumerable<int> GetRandomNumbers(int count)
    {
    HashSet<int> randomNumbers = new HashSet<int>();
    
    for (int i = 0; i < count; i++) 
        while (!randomNumbers.Add(random.Next()));
    
    return randomNumbers;
    }
    

    【讨论】:

      【解决方案6】:

      此类任务的最佳方法(在 CPU 时间方面)是创建一个包含所有可能数字的数组并从中取出 6 个项目,同时从数组中删除您刚刚取出的项目。 示例:

      const int min = 1, max = 49;
      List<int> listNumbers = new List<int>();
      int[] numbers = new int[max - min + 1];
      int i, len = max - min + 1, number;
      
      for (i = min; i < max; i++) numbers[i - min] = i;
      for (i = 0; i < 6; i++) {
          number = rand.Next(0, len - 1);
          listNumbers.Add(numbers[number]);
          if (number != (len - 1)) numbers[number] = numbers[len - 1];
          len--;
      }
      

      【讨论】:

        【解决方案7】:

        我已经用 do...while 循环切换了你的 for 循环,并将列表计数上的停止条件设置为小于 6。 这可能不是最好的解决方案,但它最接近您的原始代码。

        List<int> listNumbers = new List<int>();
        do
            {
                int numbers = rand.Next(1,49);
                if(!listNumbers.Contains(number)) {
                    listNumbers.Add(numbers);
                }
            } while (listNumbers.Count < 6)
        

        【讨论】:

        • 这不是最接近原始代码。检查我的答案以获得更接近原始代码的解决方案。
        • 好吧,你让我到了那里:-)
        【解决方案8】:

        如果您不担心最小值、最大值和范围,那么您可以使用它。

         var nexnumber = Guid.NewGuid().GetHashCode();
                if (nexnumber < 0)
                {
                    nexnumber *= -1;
                }
        

        【讨论】:

          【解决方案9】:

          您所做的是每次在循环中生成一个随机数。当然,下一个随机数可能与前一个相同。只需添加一项检查以确保当前随机数不存在于序列中。您可以使用 while 循环,例如:while (currentRandom not in listNumbers): generateNewRandomNumber

          【讨论】:

            【解决方案10】:
               public partial class Form1 : Form
            {
                public Form1()
                {
                    InitializeComponent();
                }
            
                private void button1_Click(object sender, EventArgs e)
                {
                    int[] que = new int[6];
                    int x, y, z;
                    Random ran = new Random();            
                    for ( x = 0; x < 6; x++)
                    {
                        que[x] = ran.Next(1,49);
                        for (y = x; y >= 0; y--)
                        {
                            if (x == y)
                            {
                                continue;
                            }
                            if (que[x] == que[y])
                            {
                                que[x] = ran.Next(1,49);
                                y = x;
                            }
            
            
                        }
                    }
                    listBox1.Items.Clear();
                    for (z = 0; z < 6**strong text**; z++)
                    {
                        listBox1.Items.Add(que[z].ToString());
                    }
                }
            }
            

            【讨论】:

            • 请编辑你的答案,解释你做了什么以及为什么
            【解决方案11】:

            将以下内容粘贴到类中作为新方法

                public int randomNumber()
                {
                    var random = new Random();
                    int randomNumber = random.Next(10000, 99999);
                    return randomNumber;
                }
            

            并在需要时在测试中的任何地方使用以下内容

            var RandNum = randomNumber();
            
            driver.FindElement(By.CssSelector("[class='test']")).SendKeys(**RandNum**);
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2012-12-17
              • 1970-01-01
              • 2018-07-03
              • 2012-08-30
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多