确定甲板洗牌的程度

时间:2013-10-17 18:55:33

标签: c# random entropy

我正在做一个小型扑克计划,我想确定一个牌组的洗牌程度。 我有一张带有52张牌的List然后我运行我的洗牌算法,我希望能够确定牌组在某种程度上的洗牌程度。 有人知道怎么做吗? 感谢

编辑: 哇。很多回复。一切都很好,但不完全是我想要的。这是我没有进一步指出我的问题的错。但我认为Saran最接近我真正想要的。我来说明一下。

我不想马上进行“完美”的洗牌。我已经读完了,我实施了Fisher-Yates。那个人很擅长“完美”的洗牌。我想要做的是模拟一个真实世界的情况,朋友们正在玩德州扑克,经销商拿着套牌并使用混合其他洗牌的浅滩洗牌来洗牌。 最后,我想要的是一种衡量现实世界洗牌之间差异的方法。

一个例子。假设牌组总是新鲜的(对于所有四件套装来说,王牌适合王牌,然后是王牌王牌。)乔拿着甲板,做了2次浅口洗牌,其中一次切入。彼得做了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 shuffle方法5次我得到 5,0,7,11,7。

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

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

4 个答案:

答案 0 :(得分:7)

为了有任何希望,你需要一遍又一遍地运行你的洗牌程序,总是从同一个初始套牌开始,然后比较结果。

如果完全公平的话,你预计任何给定的牌在洗牌后有机会在任何位置结束。[/ p>

如果有偏见,你会发现它在某些地方比其他地方更频繁地结束。

当然,预计会有一些与理想的5-in-52有所不同 可接受的变化量可通过统计数据和各种置信区间来预测。 (95%?97%?)

即使你有完美的发行,但这并不意味着你的洗牌是随机的 (想象一下,一个随机算法,只需在每次连续的随机播放中将卡片旋转一张卡片......它将具有完美的1-in-52结果,但不会完全随机) < / p>

要寻找的另一个方面是卡之间的相关性 例如,黑桃王牌和黑桃王的最终位置应完全不相关。
一个糟糕的改组算法可以将这两张卡一起移动,从而产生高度相关性。 检查每张卡与每张其他卡的相关性在计算上是昂贵的,但应该是一个简单的算法。

我认为最终的结果是你不能证明你的算法是公平/好的洗牌。 您只能设置各种测试以查找“不良”混洗(非均匀分布或卡位置的高相关性)。如果你通过了所有的糟糕洗牌测试,这并不意味着你的算法没有以测试所覆盖的其他方式存在缺陷。
但它确实会让你增强信心。

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

正如Coding Horror Blog条目所指出的,更好的方法可能是针对非常小的卡片组运行您的算法(文章使用3张牌),并仔细评估这些结果。只有3张牌,跟踪所有路径应该更容易,并且看看所有结果是否同样可能。

答案 1 :(得分:3)

这里有一些信息:Randomness tests。值得注意的是,如果你的洗牌“通过”所有这些测试,那只是表明洗牌可能是真正随机的。但是,如果您使用的是伪随机生成器,则您已经知道它不是。

答案 2 :(得分:1)

你无法衡量单层牌组的洗牌程度,因为每张牌组合都是同样可能的。

但是,您可以衡量您的改组算法的真实程度。杰夫阿特伍德有一些关于这个特殊问题的帖子:

http://www.codinghorror.com/blog/2007/12/shuffling.html

http://www.codinghorror.com/blog/2007/12/the-danger-of-naivete.html

答案 3 :(得分:1)

这样做的一个想法是获取列表并用整数值填充它(每个卡1个int)。制作另一组带有int值的代码并将其转换为卡片值,这样您就可以保留哪些卡属于哪些卡片。随机化整数列表,然后循环遍历列表中的每一行,并标记一组范围内的数量或前一数字中1-2个整数的一个范围。然后,然后为穷人,好人,好人等设置一组百分比等等......

这可能不是最佳解决方案,但您可以了解列表的分布情况。