5

寻找洗牌四个变量(试图改变它们出现在多项选择列表中的顺序)。

我已经摸索了一段时间,但我无法完全理解逻辑,并且在过去的问题中查找随机洗牌给出了超出我的新手技能的超详细算法(以及我对这个程序的需求)我想写,我只想做一个多选图像选择器)。

理想情况下,我想要遵循这个伪代码的东西:

// int Answer1 = Random(min1 max4)

// int Answer2 = Random(min1 max4)

// int Answer3 = Random(min1 max4)

// int Answer4 = Random(min1 max4)

// If Answer 1 equals ANY of the other three, re-randomize Answer1 and loop.

// Loop through this cycle for all answers.

我会发布我当前的常规代码,但坦率地说,这是垃圾。:( 这似乎是一个足够简单的问题,但我就是做错了。

提前致谢!

4

4 回答 4

8

洗牌 - http://www.codinghorror.com/blog/archives/001008.html

不过,不要使用 guid,而是使用随机数:

//create only once, please
static readonly Random random = new Random();

接着:

var numbers = Enumerable.Range(1, 4);
var shuffle = numbers.OrderBy(a => random.NextDouble());
于 2010-01-06T05:24:04.343 回答
5

我喜欢这种扩展方法:

static class IListExtensions {
    public static void Shuffle<T>(this IList<T> list, Random rg) {
        for (int i = list.Count; i > 1; i--) {
            int k = rg.Next(i);
            T temp = list[k];
            list[k] = list[i - 1];
            list[i - 1] = temp;
        }
    }
}

然后:

Random rg = new Random();
List<int> list = Enumerable.Range(1, 4).ToList();
list.Shuffle(rg);

现在list是洗牌{1, 2, 3, 4}

我在这里使用的算法是Fisher-Yates shuffle

于 2010-01-06T05:27:06.087 回答
5

好吧,从技术上讲,谁在乎它是否只是 400 个数字中的 4 个数字。您应该使用Fisher-Yates shuffle 的实现。但是,为了更容易理解:

var possibleNumbers = new List<int>(Enumerable.Range(1, 4));
var result = new List<int>(4);
var rnd = new Random();
while (possibleNumbers.Count > 0) {
    int r = rnd.Next(possibleNumbers.Count);
    result.Add(possibleNumbers[r]);
    possibleNumbers.RemoveAt(r);
}

上面演示的算法基本上是 Fisher-Yates shuffle。在实践中,您不会使用两个不同的列表来保存内容。您只需从尚未修复的数组部分中选择一个随机元素并将其移动到它的位置。单个列表的开头将是固定元素,而结尾将是可能性。

于 2010-01-06T05:25:19.670 回答
0
        Random rand = new Random();
        List<int> choices = new List<int>() { 1, 2, 3, 4 };

        while (choices.Count > 0)
        {
            int index = rand.Next() % choices.Count;
            int choice = choices[index];
            Console.WriteLine(choice);
            choices.RemoveAt(index);
        }

编辑-您显然可以将它们添加到新列表中,而不仅仅是打印数字。

于 2010-01-06T05:25:23.600 回答