C# - 检查彩票计划中的重复项

时间:2015-05-19 02:16:27

标签: c#

我必须写一个抽奖程序,它产生1到40之间的6个数字并检查重复项。我生成随机数没有问题,但它是检查我遇到问题的算法。除了下面的错误,代码似乎工作(我已经多次运行该程序,并且从未得到任何数字作为重复(除了零,见下文)。

这些是错误。

  1. 我偶尔会得到两个零作为最后两个数字。
  2. 偶尔会出现一个零作为最后一个数字(但除了错误#1之外,其他任何地方都没有。
  3. 以下是源代码:

    using System;
    using System.Linq;
    
    namespace LottoV2Program
    {
        class LottoV2
        {
             static void Main(string[] args)
            {
                //declare variables
                 int[] lottoNumbers = new int[6];
                Random rand = new Random();
                int temp = 0;
                int count = 0;
    
                //fill array with lottery numbers
                 for (int i = 0; i < lottoNumbers.Length; i++)
                {
                    temp = rand.Next(1, 41);//generate random number
    
                     //check to see whether number has already been picked
                    while (lottoNumbers.Contains(temp) == false)
                    {
                        lottoNumbers[count] = temp;
                        count++;
                    }
    
                }
    
                //display numbers on screen, one per line
                foreach (int i in lottoNumbers)
                {
                    Console.WriteLine(i);
                }
    
                //pause
                Console.ReadLine();
            }//end mm
    

5 个答案:

答案 0 :(得分:2)

你似乎有一些逻辑逆转。这样:

 //check to see whether number has already been picked
 while (lottoNumbers.Contains(temp) == false)
 {
     lottoNumbers[count] = temp;
     count++;
 }
只要lottoNumbers不包含值temp

就会循环播放。

现在想象一下,i = 3lottoNumbers = { 20, 15, 0, 0, 0, 0 }和新绘制的值temp20

在这种情况下lottoNumbers.Contains(temp) == true,它不会进入while循环代码块,并且不会向lottoNumbers添加任何值,但i会递增。因此,经过6次迭代(绘制)后,您将在count数组的末尾留下小于6的0和至少一个lottoNumbers的值。

你应该颠倒逻辑,以便继续绘制一个数字,直到你得到一个尚未绘制的数字:

temp = rand.Next(1, 41); // generate random number

// check to see whether number has already been picked
while (lottoNumbers.Contains(temp) == true)
    temp = rand.Next(1, 41); // already drawn, try again

// unique number drawn, add it.
lottoNumbers[i] = temp;

注意,奖励积分

要以统计上负责任的方式做到这一点(即没有大的抽样误差),你应该通过生成所有数字来防止能够绘制数字两次,执行“Fisher-Yates Shuffle”随机化他们的顺序,以及以前6名。

var rand = new Random();
var lottoNumbers = Enumerable
    .Range(1, 40)              // number 1 - 40
    .OrderBy(x => rand.Next()) // randomly shuffled
    .Take(6)                   // we only need 6
    .ToArray();                // as an array please.

答案 1 :(得分:1)

而不是检查数字是否已经被选中,为什么不做每个数字的列表,1到40,然后随机选择一个,完成时将它放在列表的末尾并减少随机最大值。

类似这样的事情

class Program
{
    static void Main(string[] args)
    {
        const int retrieve = 6;
        const int maxNumber = 40;
        const int maxLine = 20;

        var numbers = Enumerable.Range(1, maxNumber).ToArray();
        var rnd = new Random();
        int[] result = new int[retrieve];
        int pos;

        for (int j = 0; j < maxLine; ++j)
        {
            int number = numbers.Length;

            for (int i = 0; i < retrieve; ++i)
            {
                pos = rnd.Next(0, number);
                result[i] = numbers[pos];
                number--;
                numbers[pos] = numbers[number];
                numbers[number] = result[i];
            }

            Console.WriteLine(string.Join(", ",result.OrderBy (x => x).Select(x => x.ToString("00")).ToArray()));
        }

        Console.ReadKey(false);
    }
}

答案 2 :(得分:0)

  1. 生成随机数
  2. 如果已生成该号码,请返回第一步
  3. 将数字添加到当前位置并跳转到下一个

        for (int i = 0; i < lottoNumbers.Length; i++)
        {
            do
            {
                temp = rand.Next(1, 40);
            }
            while (lottoNumbers.Contains(temp));
    
            lottoNumbers[i] = temp;
        }
    
  4. 建议:你的问题不明确,只是简单地说'#34;这是我的代码,这是错误的错误&#34;是不是很优雅,说话。欢迎大家参加StackOverflow,但请更好地了解社区。我邀请你take the tour

答案 3 :(得分:0)

使用List而非普通array尝试以下操作。你不会得到零或任何重复。

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        const int MAX_LOTTO_NUMBERS = 6;

        Random r = new Random();
        List<int> lotteryNumbers = new List<int>();

        while (lotteryNumbers.Count < MAX_LOTTO_NUMBERS)
        {
            int lottoNumber = r.Next(1, 41); // Generate random number from 1 - 40
            if (!lotteryNumbers.Contains(lottoNumber))
            {
                lotteryNumbers.Add(lottoNumber);
            }
        }

        Console.WriteLine(String.Join(", ", lotteryNumbers.ToArray()));
    }
}

结果:

  

9,6,25,36,16,29

请参阅此处的代码:https://dotnetfiddle.net/EF7Ndc

答案 4 :(得分:0)

我不是C#家伙。但逻辑很容易阅读。我认为你正在获得零,因为你正在为lottoNumbers运行循环。长度= 6.如果存在重复,则不执行任何操作。

示例:

  • i = 0 temp = 21 =&gt; lottoNumber [0] = 21
  • i = 1 temp = 4 =&gt; lottoNumber [1] = 4
  • i = 2 temp = 21 =&gt;已存在,请跳过
  • i = 3 temp = 10 =&gt; lottoNumber [2] = 21(注意数组索引尚未更新)
  • i = 4 temp = 6 =&gt; lottoNumber [3] = 6
  • i = 5 temp = 30 =&gt; lottoNumber [4] = 30

Loop已在这里结束。 lottoNumber [5]未设置。因此,当您打印时,空数组值可能会被打印为0