c# -在彩票程序中检查重复
本文关键字:检查 程序 彩票 | 更新日期: 2023-09-27 17:49:42
我必须写一个彩票程序,它产生1到40之间的6个数字,并检查是否重复。我对生成随机数没有问题,但我遇到的问题是检查它们的算法。除了下面的错误,代码似乎可以工作(我已经运行了很多次程序,从来没有得到任何数字作为重复(除了0,见下文)。
这些是bug。
- 我偶尔得到两个零作为最后两个数字。
- 一个零偶尔会出现在最后一个数字(但除了错误#1之外,在其他任何地方都不会出现)。
源代码如下:
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
你似乎有些逻辑颠倒了。:
//check to see whether number has already been picked
while (lottoNumbers.Contains(temp) == false)
{
lottoNumbers[count] = temp;
count++;
}
将循环,只要lottoNumbers
不包含值temp
。
现在假设i = 3
, lottoNumbers = { 20, 15, 0, 0, 0, 0 }
,新绘制的值temp
为20
。
在这种情况下,lottoNumbers.Contains(temp) == true
不会进入while
循环代码块,并且lottoNumbers
不会增加任何值,但i
会增加。因此,在6次迭代(绘制)之后,您将得到一个小于6的count
,并且在lottoNumbers
数组末尾至少有一个0
的值。
你应该颠倒逻辑,这样你就可以一直画一个数字,直到你得到一个还没有画的数字:
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;
要以统计上负责任的方式做到这一点(即没有大的抽样误差),你应该通过生成所有数字,进行"费雪-叶茨洗牌"来随机化它们的顺序,并取前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到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);
}
}
- 生成随机数
- 如果号码已经生成,返回步骤1
-
将数字添加到当前位置并跳转到下一个
for (int i = 0; i < lottoNumbers.Length; i++) { do { temp = rand.Next(1, 40); } while (lottoNumbers.Contains(temp)); lottoNumbers[i] = temp; }
一个建议:你的问题不清楚,简单地说"这是我的代码,它有bug"是不够的…可以说是优雅的。StackOverflow非常欢迎你,但是请更好地了解这个社区。我邀请你来参观。
用List
代替正常的array
尝试以下操作。你不会得到0或任何重复项。
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
我不是c#爱好者。但逻辑很容易读懂。我认为你得到的是0因为你在运行lotttonnumbers的循环。长度= 6。如果有重复,你不做任何动作。
的例子:
- i=0 temp =21 => lottonnumber [0]=21
- i=1 temp =4 => lottonnumber [1]=4
- i=2 temp =21 =>已经存在,所以跳过
- i=3 temp =10 => lottonnumber[2]=21(注意数组索引没有更新)
- i=4 temp =6 => lottonnumber [3]=6
- i=5 temp =30 => lottonnumber [4]=30
循环在此结束。lottonnumber[5]未设置。因此,在打印时,空数组值可能打印为0