无效的数组洗牌器

发布于 2024-09-30 01:27:38 字数 483 浏览 0 评论 0原文

我正在尝试对数组进行洗牌,但我这样做的方式大约每五次才有效。如果有人能解释为什么它不能正常工作并可能提出调整,我将不胜感激。

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;
}

I am attempting to shuffle an array, but the way I am doing it only works about every fifth time. I would greatly appreciate if someone could explain why it is not working properly and perhaps propose a tweak.

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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

爱的故事 2024-10-07 01:27:38

将以下行移到循环之外:

Random rand = new Random();

System.Random 使用的默认种子基于 Environment.TickCount。在紧密循环中,滴答计数在连续迭代之间可能不会改变,因此它最终可能会一遍又一遍地使用相同的种子。因此,循环将重复交换相同两个元素,直到滴答计数发生变化(在循环完成之前可能不会这样做)。要验证这是否是问题所在,您可以尝试在循环内添加 Thread.Sleep(100) 或类似内容;然后你应该能够看到随机播放正常工作(尽管非常慢)。

您还应该注意您正在使用的技术 排列数组是有偏差的;并非所有排列的可能性都相同。您可能想要使用已知无偏的洗牌算法,例如 Fisher -耶茨洗牌

或者,您可以使用一种非常简单的技术来洗牌。它效率稍低,但不偏不倚:

var rand = new Random();
return buttons.OrderBy(button => rand.Next()).ToArray();

Move the following line outside the loop:

Random rand = new Random();

The default seed used by System.Random is based on Environment.TickCount. In a tight loop, the tick-count may not change between successive iterations, so it may end up using with the same seed over and over. Consequently, the loop will repeatedly swap the same two elements until the tick-count changes (it may not do so before the loop completes). To verify that this is the issue, you can try adding a Thread.Sleep(100) or similar inside the loop; you should then be able to see the shuffle working correctly (albeit very slowly).

You should also note that the technique you're using to permute the array is biased; not every permutation is equally likely. You might want to use a shuffling algorithm that is known to be unbiased, such as the Fisher-Yates shuffle.

Alternatively, you can use a really simple technique to shuffle. It's slightly inefficient, but unbiased:

var rand = new Random();
return buttons.OrderBy(button => rand.Next()).ToArray();
来世叙缘 2024-10-07 01:27:38

问题是您在循环的每次迭代中创建 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;
}

The problem is that you're creating the Random() object in each iteration of your loop. As the Random object uses a seed during initialization you'll find that most values will be identical and not random.

You can fix the problem by declaring the Random class as static outside the method body.

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;
}
む无字情书 2024-10-07 01:27:38

您的问题已得到解答,但我想分享一个使用 LINQ 和 Guid 打乱集合的好小技巧。这将创建一个随机排序的列表,其中的值分布良好。

private Button[] scrambleBoard(Button[] buttons)
{
    return buttons.OrderBy(b => Guid.NewGuid()).ToArray();
}

Your question has been answered, but I thought I'd share a nice little trick for shuffling a collection using LINQ and Guid. This creates a randomly ordered list with a nice spread of values.

private Button[] scrambleBoard(Button[] buttons)
{
    return buttons.OrderBy(b => Guid.NewGuid()).ToArray();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文