我意识到使用random不会产生真正的随机数,但我不明白为什么这段代码不能用来防止重复。目标是从0到44之间(不包括)导出8个唯一数字。运行代码时没有任何错误,但确实会发生重复:
//Loop Begins Within Main
for (int i = 0; i < 8; i++)
{
//Begins Recursion
int x = Unique8(rndm, num8);
num8[i] = x;
}
//Recursion Takes Place Outside of the Main with Static Declarations
static Random rndm = new Random();
static int[] num8 = new int[8];
static int Unique8 (Random rndm, int[] num8)
{
int x = rndm.Next(1, 43);
//Seeks if Number is Repeated
if (num8.Contains(x))
{
//If So, Recursion Takes Place
Unique8(rndm, num8);
}
//Returns Value to Original Loop to be Assigned to Array
return x;
}
如果Random因算法而重新生成数字,为什么它们会通过递归?为什么这不会成为一个无限循环?
我已经找到了一个很好的解决方案,类似于一个牌组的洗牌和从顶部拉出牌。创建原始的排序数组很简单,但我不明白它是如何“改组”的。你如何扰乱C#中的数组
答案 0 :(得分:9)
见
//If So, Recursion Takes Place
Unique8(rndm, num8);
你没有做任何有关返回值的事情 - 你应该可以将其更改为
x = Unique8(rndm, num8);
答案 1 :(得分:2)
如果您运气不好,您的代码可能会导致 stackoverflow 。这是使用改组获得8个唯一数字的另一种方法。
int[] array = new int[43];
for (int i = 0; i < array.Length; i++) array[i] = i+1;
FisherYatesShuffle(array);
int[] newArray = array.Take(8).ToArray();
public static void FisherYatesShuffle<T>(T[] array)
{
Random r = new Random();
for (int i = array.Length - 1; i > 0; i--)
{
int j = r.Next(0, i + 1);
T temp = array[j];
array[j] = array[i];
array[i] = temp;
}
}
答案 2 :(得分:0)
一种方法是使用Fisher Yates shuffle,因为L.B已经发布了。我过去做过的另一种方法是使用所有可能的值填充列表,然后通过生成0到列表计数之间的随机数从该列表中随机绘制。然后使用List.RemoveAt删除刚刚绘制的数字:
List<int> myList = new List<int>(43);
for (int i = 0; i < array.Length; i++) myList.Add(i+1);
for (int j = 0; j < 8; j++)
{
int idx = rndm.Next(myList.Count);
num8[i] = myList[idx];
myList.RemoveAt(idx);
}