随机数字发生器没有重复
基本上我创build一个程序,随机生成6个独特的彩票号码,所以没有重复在同一行,这里是我到目前为止的代码…
//Generate 6 random numbers using the randomiser object int randomNumber1 = random.Next(1, 49); int randomNumber2 = random.Next(1, 49); int randomNumber3 = random.Next(1, 49); int randomNumber4 = random.Next(1, 49); int randomNumber5 = random.Next(1, 49); int randomNumber6 = random.Next(1, 49); textBox1.Text = randomNumber1.ToString(); textBox2.Text = randomNumber2.ToString(); textBox3.Text = randomNumber3.ToString(); textBox4.Text = randomNumber4.ToString(); textBox5.Text = randomNumber5.ToString(); textBox6.Text = randomNumber6.ToString(); }
我得到随机数字,但有时在同一行上有相同的数字,我如何使每个数字独特?
提前致谢
你需要将它们存储在一个集合中,每次你select一个新的号码,你需要确保它不存在,否则你需要生成一个新的号码,直到find一个唯一的号码。
而不是这个,我会产生一个1
到49
之间的序列,将它们洗牌并从序列中选出6个数字,例如:
var rnd = new Random(); var randomNumbers = Enumerable.Range(1,49).OrderBy(x => rnd.Next()).Take(6).ToList();
你不能。 您只指定每个数字是从1到49的随机数字,而不是它不应该匹配任何重复。
既然你有一个相对较小的数字,最好的办法就是画出随机数字,把它们放进一个HashSet,然后如果你需要更多的话,多拉一下。 像这样的东西:
HashSet<int> numbers = new HashSet<int>(); while (numbers.Count < 6) { numbers.Add(random.Next(1, 49)); }
在这里你正在利用HashSet消除重复。 这不会与列表或其他收集工作。
使用这种扩展方法进行油藏采样 :
public static IList<T> TakeRandom<T>( this IEnumerable<T> source, int count, Random random) { var list = new List<T>(count); int n = 1; foreach (var item in source) { if (list.Count < count) { list.Add(item); } else { int j = random.Next(n); if (j < count) { list[j] = item; } } n++; } return list; }
你可以像这样对你的collections进行采样:
var random = new Random(); var numbers = Enumerable.Range(1, 49).TakeRandom(6, random); numbers.Shuffle(random);
请注意,返回的numbers
将从{1,2,…,49}中的一组6个数字中的所有(49个select6个)可能性中统一抽样,但它们既不会保持秩序也不会被统一洗牌。 如果您想要订单也是随机的,那么您可以轻松地做一个标准的Fisher-Yates随机洗牌 。
public static void Shuffle<T>(this IList<T> list, Random random) { for (int i = 0; i < list.Count; i++) { int j = random.Next(i, list.Count); T temp = list[j]; list[j] = list[i]; list[i] = temp; } }
请注意,在这个答案中可以findFisher-Yates shuffle更加优化的版本: Randomize List <T>
为了使发生器满足必要的随机性统计特性,返回重复值是必需的:绘制数字的概率不依赖于先前绘制的数字。
您可以在1到49范围内对整数进行混洗 ,并返回前6个元素。 请参阅http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle了解更多关于这样的洗牌机的细节。;
不过,我认为你这样做会带来轻微的统计偏差。
最好的方法是使用random.Next(1, 49);
并拒绝任何重复。 这将不受统计偏差的影响,而且您只需要从49个可能性中select6个,碰撞次数不会显着减慢algorithm。
List<int> aux = new List<int>(); while(aux.Count < 6) { int rnd = random.Next(1,49); if(!aux.Contains(rnd))aux.add(rnd); }
如果你把所有的Texbox放在同一个面板上,你可以做到这一点
int j = 0; foreach(Control x in MyPanel.Controls) { if(x is TexBox) { x.Text = aux[j].toString(); j++; } }
看看使用数组来保存你的6个数字。
每次生成一个时,循环访问数组以确保它不在那里。 如果是,则再次生成另一个&循环,直到你有一个不匹配。
数组和OOP(面向对象编程)非常简单。 在开始之前,您必须将Linq(使用System.Linq)库添加到您的项目中。
Random random = new Random(); int[] array = new int[6]; int number; for (int i = 0; i < 6; i++) { number = random.Next(1, 50); if (!array.Contains(number)) //If it's not contains, add number to array; array[i] = number; else //If it contains, restart random process i--; } for (int i = 1; i < 7; i++) { foreach (Control c in this.Controls) //Add random numbers to all Textboxes { if (c is TextBox && c.Name.EndsWith(i.ToString())) { c.Text = array[i - 1].ToString(); } } }
一个function性的方法可能是产生一个无限序列的随机数字,过滤出非唯一的数字,并采取你需要的唯一数字的数量。
例如:
private IEnumerable<int> RandomDigitStream(int seed) { Random random = new Random(seed); while (true) { yield return random.Next(DIGIT_MIN, DIGIT_MAX); } } private List<int> GenerateUniqueRandomNumbers(int seed, int count) { // Assert that DIGIT_MAX - DIGIT_MIN > count to ensure // algorithm can finish return RandomDigitStream(seed) .Distinct() .Take(count) .ToList(); }
这个algorithm的效率主要取决于.NET团队如何实现Distinct
。 它的内存使用量会随着您所需的数字位数和随机函数产生的数字范围而增加。 它也具有不可预测的运行时间,因为它取决于随机函数的概率分布。 事实上,如果随机algorithm产生的数字范围小于您需要的位数,则该algorithm可能陷入无限循环。
但实际上看,它应该是less量的数字的罚款,但如果你正在看大量(100 +),你可能想看看其他方法。
如果没有使用查找表,甚至有可能创build一个只能产生唯一数字的随机algorithm会更有效率。
这是我的解决scheme:生成数组的数组
/// <summary> /// auto generate a array with number element and max value is max /// </summary> /// <param name="number">number element of array</param> /// <param name="max">max value of array</param> /// <returns>array of number</returns> public static int[] createRandomArray(int number, int max) { List<int> ValueNumber = new List<int>(); for (int i = 0; i < max; i++) ValueNumber.Add(i); int[] arr = new int[number]; int count = 0; while (count < number) { Random rd = new Random(); int index = rd.Next(0,ValueNumber.Count -1); int auto = ValueNumber[index]; arr[count] = auto; ValueNumber.RemoveAt(index); count += 1; } return arr; }
是。 使用数组。 循环多less次你想要的:生成一个随机数,循环数组和全部比较所产生的数字。 如果有一场比赛再循环,直到没有匹配。 然后存储它。
完成:)