我为什么要重复?

时间:2014-04-27 09:03:47

标签: c# arraylist duplicates

我已经构建了一个基诺游戏,它从一个arraylist中选择了20个随机数,NumbersToPickFrom。我生成一个随机数,然后检查该数字当前是否可以从中挑选。如果是,我将它添加到我将用作彩票号码的数字arraylist,randomPicks,然后我从可用的数字中删除它。如果它不在列表中,那意味着它已被选中,我需要一个新号码。我用goto重新开始。我认为它工作正常,但似乎我一直在重复。我使用ArrayList.Remove函数错了吗?如果它被删除,我不应该在我的随机选择的最终列表中得到重复。如果有人能看到我错过的地方,那将会有所帮助。下面的代码只是我正在谈论的代码。

private void GeneratePicks()
    {
        for (int i = 1; i <= 20; )
        {
        Retry:
            int rInt = GenerateRandomPick();
            if (NumbersToPickFrom.Contains(rInt))
            {
                RandomPicks.Add(rInt);

                NumbersToPickFrom.Remove(rInt);
                i++;
                //PickBox.Text += rInt + " ,";
                RandomPicks.Sort();
            }
            else
            {
                goto Retry;
            }
        }

    }

    private int GenerateRandomPick()
    {
        int rInt = rand.Next(1,81);
        return rInt;
    }

    private void initializeArray()
    {
        for (int i = 1; i <= 80; i++)
        {
            NumbersToPickFrom.Add(i);
        }
    }

4 个答案:

答案 0 :(得分:3)

我运行了你的代码,并没有得到任何重复。

尽管如此,重复选择随机数并与缩小列表进行比较的方法并不是最好的方法。

请改为尝试:

RandomPicks =
    Enumerable
        .Range(1, 80)
        .OrderBy(n => rand.Next())
        .Take(20)
        .OrderBy(n => n)
        .ToList();

答案 1 :(得分:2)

我发现你的代码工作正常。

我添加了以下公共变量以使其工作(在我的机器上)

   List<int> NumbersToPickFrom = new List<int>();
   List<int> RandomPicks = new List<int>();
   Random rand = new Random();

虽然在第二次运行中,我发现RandomPicks中的项目数量增加了一倍并且也有重复项,所以我更改了 initializeArray(),如下所示

   private void initializeArray()
   {
       for (int i = 1; i <= 80; i++)
       {
           NumbersToPickFrom.Add(i);
       }

       RandomPicks.Clear();    // Added this to clear the existing values in the list.
   }

答案 2 :(得分:0)

如果你想这样做&#34;旧学校&#34;并实际观察发生的事情,将GeneratePicks()方法更改为:

private void GeneratePicks()
{
    RandomPicks = new List<int>();
    initializeArray();
    for (int i = 0; i < 20; ++i)
    {
        int randomIndex = rand.Next(1, 80 - i);
        int randomPick = NumbersToPickFrom[randomIndex];
        RandomPicks.Add(randomPick);
        NumbersToPickFrom[randomIndex] = NumbersToPickFrom[80 - i - 1];
    }
    RandomPicks.Sort();
}

这将完成20次,并保证不重复。

答案 3 :(得分:0)

我无法在您的代码中看到任何错误,并通过运行代码测试您的代码100000次,并且没有任何重复。

然而,有更好的方法来获取随机数。一个简单的改进是从NumbersToPickFrom列表中随机选择一个数字,而不是仅仅选择一个数字,然后你不需要内循环。

有一种更好的选择彩票号码的方法。您可以遍历数字并计算每个数字应该被选中的概率。挑选数字的概率为PicksLeft / NumbersLeft,例如,数字1被挑选的概率为20 / 80,然后概率根据选择的数字而变化:

private void GeneratePicks() {
  int pick = 20;
  for (int n = 1; pick > 0; n++) {
    if (rand.Next(81 - n) < pick) {
      RandomPicks.Add(n);
      pick--;
    }
  }
}

由于这些数字是按顺序挑选的,因此您甚至不必对数字进行排序,而且您不需要NumbersToPickFrom列表。