c# - 确定一副牌洗牌的程度

标签 c# random entropy

我正在做一个小型扑克程序,我想确定一副牌的洗牌情况。 我有一个包含 52 张牌的列表,然后运行我的洗牌算法,我希望能够确定一副牌在某种程度上的洗牌情况。 有人知道如何做到这一点吗? 谢谢

编辑: 哇。很多回应。一切都很好,但不完全是我想要的。那是我没有进一步说明我的问题的错。但我认为 Saran 最接近我真正想要的。让我具体说明。

我不想立即进行“完美”洗牌。我已经阅读了相关内容并实现了 Fisher-Yates。那一个非常擅长提供“完美”的洗牌。我想做的是模拟一个真实世界的情况,在这个情况下, friend 们正在玩德州扑克,庄家拿走一副牌,并使用混杂着其他洗牌的浅滩洗牌来洗牌。 最后,我想要的是一种衡量现实世界洗牌之间差异的方法。

一个例子。假设这副牌总是新鲜的(A 到 K 同花,然后下一个花色 A 到 K,所有四套花色)。乔接过一副牌,进行了 2 次浅滩洗牌,中间有 1 次洗牌。彼得进行 5 次脱衣洗牌。我想找到一种方法来查看哪个洗牌“更好”。

我越想越觉得这很难确定。

再次感谢。

编辑 23.10.2013

这是我想出的方法,将 Sarans 的想法与我的结合起来:

 public int checkShuffle(List<Card> cardDeckToCheck,int[] previousOrder)
    {
        // Higher is worse? Sure.
        int score = 0;

        for (int i = 0; i < cardDeckToCheck.Count; i++)
        {
            Card cardToCheck = cardDeckToCheck[i];
            Card cardToLeft = null;
            Card cardToRight = null;

            // Should cost more since the card has not moved at all.
            // For this I need an array that shows me the arangement of the deck before shuffling.
            if(cardToCheck.index == previousOrder[i])
            {
                score += 3;
            }

            if (i == 0)
            {
                Console.WriteLine("i == 1");
                cardToRight = cardDeckToCheck[i+1];
                // if the card we are checking is one lower or one higher than the card to the right
                if(Math.Abs(cardToCheck.index - cardToRight.index) == 1)
                {
                    score++;
                }
                continue;
            }

            else if (i == cardDeckToCheck.Count-1)
            {
                Console.WriteLine("i == carddecktocheck.count-1");
                cardToLeft = cardDeckToCheck[i - 1];
                // if the card we are checking is one lower or one higher than 
                if (Math.Abs(cardToCheck.index - cardToLeft.index) == 1)
                {
                    score++;
                }
                continue;
            }

            else
            {
                cardToLeft = cardDeckToCheck[i - 1];
                cardToRight = cardDeckToCheck[i + 1];
                // if the card we are checking is one lower or one higher than 
                if (Math.Abs(cardToCheck.index - cardToLeft.index) == 1)
                {
                    score++;
                }
                if (Math.Abs(cardToCheck.index - cardToRight.index) == 1)
                {
                    score++;
                }
                continue;
            }

        }
        return score;
    }

我首先将牌组的外观记录到一个 int 数组中,然后我洗牌,然后我用洗牌后的牌组和牌组的先前顺序运行此方法。 像这样:

int[] previousOrder = getCurrentOrder(deck.getDeck());
deck.setDeck(riffleShuffle2(3));
textBoxShuffleness.Text = "" + checkShuffle(deck.getDeck(), previousOrder);
displayDeck(deck);

当我从一副未洗牌的牌开始并运行 riffle shuffle 方法 5 次时,我得到 70、33、28、5、10。 当我从一副未洗牌的牌开始并运行 Durstenfeld 洗牌方法 5 次时,我得到 5,0,7,11,7.

这些结果非常符合我的预期。

如果有人发现此方法有问题,那么如果您发表评论,我将不胜感激:) 谢谢

最佳答案

要有任何希望,您需要一遍又一遍地运行洗牌程序,始终从相同的初始牌组开始,然后比较结果。

如果完全公平,您预计任何给定的牌在洗牌后都有 52 分之一的机会出现在任何位置。

如果存在偏差,您会发现它最终出现在某些位置的频率高于其他位置。

当然,与理想的 1 比 52 存在一些差异是意料之中的。
可接受的变化量可以通过统计数据和各种置信区间来预测。 (95%?97%?)

即使你得到了完美的分布,也不意味着你的洗牌是随机的。
(想象一个洗牌算法,它只是在每次连续洗牌时将一副牌旋转一张牌……它会得到完美的 52 分之一的结果,但不会完全随机)

要寻找的另一个方面是卡片之间的相关性。
例如,黑桃 A 和黑桃 K 的最终位置应该完全不相关。
糟糕的洗牌算法可能会将这两张牌一起移动,从而导致高度相关。 检查每张卡片与其他所有卡片的相关性在计算上非常昂贵,但应该是一个简单的算法。

我认为最终结果是您无法证明您的算法是公平/良好的洗牌。 您只能设置各种测试来寻找“不良”洗牌(非均匀分布,或牌位高度相关)。如果您通过了所有关于坏洗牌的测试,并不意味着您的算法在测试未涵盖的其他方面没有缺陷。
但它确实让您更有信心。

可能有更好的方法来测试随机性,但它是 computationally impossible .

作为 Coding Horror Blog entry 指出,更好的方法可能是针对非常小的一副牌(本文使用 3 张牌的一副牌)运行你的算法,并仔细评估这些结果。只有 3 张卡片应该更容易追踪所有路径,并查看所有结果的可能性是否相同。

关于c# - 确定一副牌洗牌的程度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19434884/

相关文章:

c# - HttpContext.Current.User.Identity.Name 在 .ashx 处理程序中不起作用

c# - 如何通过 Web.Config 即时更改 Asp.net 主题

c# - 需要一个带有用户反馈的 ASP.NET MVC 长时间运行的进程

c# - 为什么我会收到此定义引用错误?

Java-单击按钮时更改标签文本

math - 随机数的算术会减少它的熵吗?

pandas - 将值插入随机行

algorithm - 在二叉树上实现随机过程

heroku - heroku 上有哪些熵源?

python - 我怎样才能修复熵产生的 nan?