我试图改组一个阵列,但我这样做的方式大约每五次一次。如果有人能解释为什么它不能正常工作并且可能提出调整,我将不胜感激。
private Button[] scrambleBoard(Button[] buttons)
{
for (int x = 100 * buttons.Count(); x > 0; x--)
{
Random rand = new Random();
int first = rand.Next(buttons.Count());
int second = rand.Next(buttons.Count());
Button temp = buttons[first];
buttons[first] = buttons[second];
buttons[second] = temp;
}
return buttons;
}
答案 0 :(得分:3)
将以下行移到循环外:
Random rand = new Random();
System.Random
使用的默认种子基于Environment.TickCount
。在紧密循环中,滴答计数在连续迭代之间可能不会改变,因此它可能会一遍又一遍地使用相同的种子。因此,循环将重复交换相同的两个元素,直到滴答计数发生变化(在循环完成之前可能不会这样做)。要验证这是否是问题,您可以尝试在循环内添加Thread.Sleep(100)
或类似内容;然后你应该能够看到shuffle正常工作(虽然非常缓慢)。
您还应该注意,排列数组的technique you're using 有偏见;不是每个排列都是同样可能的。您可能希望使用已知为无偏的混洗算法,例如Fisher-Yates shuffle。
或者,您可以使用非常简单的技术进行随机播放。它效率稍低,但没有偏见:
var rand = new Random();
return buttons.OrderBy(button => rand.Next()).ToArray();
答案 1 :(得分:1)
问题是你在循环的每次迭代中创建了Random()对象。由于Random对象在初始化期间使用种子,因此您会发现大多数值都是相同的而不是随机的。
您可以通过在方法体外声明Random类为静态来解决问题。
private static Random rand = new Random();
private Button[] scrambleBoard(Button[] buttons)
{
for (int x = 100 * buttons.Count(); x > 0; x--)
{
int first = rand.Next(buttons.Count());
int second = rand.Next(buttons.Count());
Button temp = buttons[first];
buttons[first] = buttons[second];
buttons[second] = temp;
}
return buttons;
}
答案 2 :(得分:0)
你的问题已得到解答,但我想我会分享一个很好的小技巧,用LINQ和Guid来改组一个集合。这会创建一个随机排序的列表,其中包含很好的值。
private Button[] scrambleBoard(Button[] buttons)
{
return buttons.OrderBy(b => Guid.NewGuid()).ToArray();
}