对非重复随机数使用递归循环和整数数组

时间:2012-03-19 13:17:10

标签: c#

我意识到使用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#中的数组

3 个答案:

答案 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);
}