我必须写一个抽奖程序,它产生1到40之间的6个数字并检查重复项。我生成随机数没有问题,但它是检查我遇到问题的算法。除了下面的错误,代码似乎工作(我已经多次运行该程序,并且从未得到任何数字作为重复(除了零,见下文)。
这些是错误。
以下是源代码:
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
答案 0 :(得分:2)
你似乎有一些逻辑逆转。这样:
//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次迭代(绘制)后,您将在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)
将数字添加到当前位置并跳转到下一个
for (int i = 0; i < lottoNumbers.Length; i++)
{
do
{
temp = rand.Next(1, 40);
}
while (lottoNumbers.Contains(temp));
lottoNumbers[i] = temp;
}
建议:你的问题不明确,只是简单地说'#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.如果存在重复,则不执行任何操作。
示例:
Loop已在这里结束。 lottoNumber [5]未设置。因此,当您打印时,空数组值可能会被打印为0