4

私は小規模なポーカー プログラムを行っており、デッキがどれだけうまくシャッフルされているかを判断したいと考えています。52 枚のカードを含むリストがあり、シャッフル アルゴリズムを実行して、デッキがある程度の規模でシャッフルされているかどうかを判断できるようにしたいと考えています。誰かがこれを行う方法を知っていますか? ありがとう

編集:うわー。たくさんの反応。すべて良いですが、まさに私が探していたものではありません。それは、私の質問をこれ以上特定しなかった私のせいです。でも、サランは私が実際に望んでいるものに最も近いと思います. 指定させてください。

すぐに「完璧な」シャッフルはしたくありません。私はすでにそれを読み、Fisher-Yatesを実装しました。それは「完璧な」シャッフルをするのが得意です。私がやろうとしているのは、友人がテキサス ホールデムをプレイしている現実世界の状況をシミュレートすることです。ディーラーはデッキを取り、他のシャッフルと混合したリフル シャッフルを使用してシャッフルします。最後に、私が欲しいのは、現実世界のシャッフルの違いを測定する方法です。

例。デッキは常に新鮮であると仮定します (エースからキングのスーテッド、次に 4 つのスーツすべての次のスーツのエースからキング)。ジョーはデックを取り、間に 1 つのカットを入れて 2 つのリフル シャッフルを行います。ピーターはストリッピング シャッフルを 5 回行います。どちらがデッキを「より良く」シャッフルするかを確認する方法を見つけたい.

考えれば考えるほど、決定するのは非常に難しいと思います。

再度、感謝します。

編集 23.10.2013

サランのアイデアと私のアイデアを組み合わせて、私が思いついた方法は次のとおりです。

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

シャッフルされていないデッキから始めて、リフル シャッフル メソッドを 5 回実行すると、70、33、28、5、10 が得られます。シャッフルされていないデッキから始めて、ダーステンフェルド シャッフル メソッドを 5 回実行すると、5,0,7,11,7 が得られます。

これらの結果は、私が期待するものです。

誰かがこの方法で何か問題を見つけた場合は、コメントしていただければ幸いです:)ありがとう

4

4 に答える 4

7

希望を得るには、常に同じ最初のデッキから始めて、シャッフル プログラムを何度も実行し、結果を比較する必要があります。

それが完全に公平である場合、シャッフル後に特定のカードが 52 分の 1 の確率で任意の場所に配置されることが予想されます。

偏りがある場合は、特定の場所で他の場所よりも頻繁に発生することがわかります。

もちろん、理想的な 1/52 からの多少の変動は予想されます。
許容可能な変動量は、統計とさまざまな信頼区間によって予測できます。(95%? 97%?)

そして、たとえ完璧な分布を得たとしても、それはあなたのシャッフルがランダムであることを意味しません.
(連続するシャッフルごとにデッキを 1 枚ずつカードを回転させるシャッフル アルゴリズムを想像してみてください.... 52 分の 1 の完全な結果が得られますが、まったくランダムにはなりません)

探すべきもう 1 つの側面は、カード間の相関関係です。
たとえば、スペードのエースとスペードのキングの最終的な位置は、完全に相関していない必要があります。
シャッフル アルゴリズムが悪いと、これら 2 枚のカードが一緒に移動され、相関が高くなる可能性があります。すべてのカードと他のすべてのカードとの相関関係をチェックすることは、計算コストが高くなりますが、単純なアルゴリズムである必要があります。

最終結果は、アルゴリズムが公平/良いシャッフルであることを証明できないということだと思います。さまざまなテストを設定して、「悪い」シャッフル (不均一な分布、またはカード位置の高い相関) を探すことしかできません。悪いシャッフルのすべてのテストに合格しても、テストでカバーされなかった他の方法でアルゴリズムに欠陥がないことを意味するわけではありません。
しかし、それはあなたにますます自信を与えます。

ランダム性をテストするさらに良い方法があるかもしれませんが、計算上不可能です。

Coding Horror ブログのエントリが指摘しているように、アルゴリズムを非常に小さなカード デッキ (この記事では 3 枚のカード デッキを使用) に対して実行し、それらの結果を慎重に評価する方がはるかに優れている可能性があります。カードが 3 枚しかないため、すべての経路をたどり、すべての結果が同じように発生する可能性があるかどうかを確認するのがはるかに簡単になるはずです。

于 2013-10-17T19:03:20.580 に答える
3

ここにいくつかの情報があります: Randomness tests。シャッフルがそのようなすべてのテストに「合格」した場合、シャッフルが本当にランダムである可能性があることを示しているだけであることに注意してください。ただし、疑似乱数ジェネレーターを使用している場合は、そうではないことが既にわかっています。

于 2013-10-17T19:05:11.823 に答える
1

このための 1 つのアイデアは、リストを取得して整数値 (カードごとに 1 つの整数) を入力することです。int 値を受け取り、それをカード値に変換する別のコード セットを作成して、どのカードがどの数字に属しているかを保持します。整数のリストをランダム化し、リストの各行をループして、一連の範囲内または前の数値から 1 ~ 2 個の整数の 1 つの範囲内にいくつあるかをマークします。最後に、悪い、良い、素晴らしいなどのパーセンテージスケールのセットを設定します...

これは最善の解決策ではないかもしれませんが、リストがどの程度広がっているかを把握することができます。

于 2013-10-17T19:15:34.613 に答える
1

すべてのカードの組み合わせの可能性は等しいため、単一のデッキがどれだけうまくシャッフルされているかを測定することはできません。

ただし、シャッフル アルゴリズムが実際にどの程度優れているかを測定することはできます。Jeff Atwood には、この特定の問題に関するいくつかの投稿があります。

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

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

于 2013-10-17T19:05:24.667 に答える