4

このメソッドがカードのデッキをシャッフルしたかどうかをテストして確認する必要があります。ここでは、実際のシャッフル部分のコードを示します。

 public void randomShuffle () {
               for (int i = 0; i < DECK_SIZE; i++) {
                   int place = (int)((Math.random()*(51-i))+i);
                   Card temp = this.cardAt(i);
                   this.cardList[i] = this.cardAt(place);
                   this.cardList[place] = temp;
           }
       }

シャッフルされたかどうかをテストする際の問題は、2 枚のカードしか切り替えることができず、シャッフルされたと見なされることです。ランダムシャッフルのテストのために私がこれまでに持っているものは次のとおりです。

static void randomShuffleTest () {
       Deck deck1 = Deck.newDeckOf52();
       Deck deck2 = Deck.newDeckOf52();
       deck2.randomShuffle();           

       assert false == deck1.equals(deck2);
    }

それで、私の質問は、何かが十分にシャッフルされているかどうかをどのようにテストするのですか?

4

7 に答える 7

6

単一のサンプルでこれを行うことはできません。しかし、あなたできることは、シャッフルされた多数のデッキの統計分析を実行して、非ランダム性の兆候を探すことです.

math.stackexchange.com でこれを聞いたほうがいいと思います...頭のいい人がたむろしている場所です。「数学」を簡単な言葉で説明できれば (あなたや私のような愚かな IT 関係者向け)、Java でテストをコーディングできるはずです。


私が「あなたはこれを行うことはできません」と言うとき...明らかに、デッキがまったくシャッフルされていないかどうか、またはシャッフルによってデッキが破損していないかどうかをテストできます. しかし、これらはどちらもあなたの基準に対する信頼できるテストではありません...「十分にシャッフルされました」。

于 2011-02-17T10:02:55.587 に答える
4

できません。理論的には、シャッフルによって正しい順序でデッキが作成される可能性があるため、デッキがシャッフルされているかどうかを判断することは不可能です。

于 2011-02-17T09:50:40.067 に答える
4

正確なテストはできません。アルゴリズムを信頼してください。または使用Collections.shuffle()

于 2011-02-17T09:51:56.840 に答える
2

1 つの方法として、シャッフルされたデックを並べ替えて、何回の「操作」が行われたかを確認することが考えられます。明らかに、この尺度はソートアルゴリズムに依存します。

別の方法として、http: //en.wikipedia.org/wiki/Randomness_testsのどこかで統計的尺度を見つけることができます。

于 2011-02-17T10:04:39.673 に答える
2

マーク バイヤーズが言ったように、シャッフル アルゴリズムは正確に順序どおりのデッキを生成する可能性があります。しかし、連続して実行するたびにそうするなら、それは間違いなく悪いアルゴリズムです! したがって、シャッフルの適切なアルゴリズムは、i 番目の位置でのカードの分布が均一になるように一連のカードを作成する必要があります。iS(i)={c(1)(i),c(2)(i),...,c(54)(i)}番目のシーケンス (アルゴリズムの i 番目の結果) とします。次に、(i) に関する c(j)(i) は、(ほぼ) 一様分布に従う必要があります。それが成り立つかどうかを確認するには、アルゴリズムを数千回実行し、各位置 j=1,2,...,54 で、それぞれの異なるカードが出現する頻度を数えます。数値はほぼ同じである必要があります。理想的には、アルゴリズムを 54000 回実行すると、各カードが各位置に 1000 回表示されるはずです。私はこれが当てはまるかどうかを強く疑っていますMath.random(). java.util.Randomより良い結果を得るために使用します。Random を使用する方法は次のとおりです。

final java.util.Random random = new java.util.Random(seed);

そして、ランダムな倍精度が必要になるたびに:

random.nextDouble();

メソッドCollections.shuffle();はまさにそれを行います。Java の Random 実装よりも優れた RNG が必要な場合は、おそらく独自の実装を進める必要があります。

于 2011-02-17T10:13:01.643 に答える
1

まず、この質問が好きです(面白い)。

  • まず、「十分にシャッフルされていますか?」というあなたの定義を知りたいです。測ってもいいですか?これに関するガイドラインはありますか?たとえば、少なくとも 5 枚のカードを別の場所に配置する必要がありますか? カードの数または別の場所を検証するテストを簡単に作成できますが、これで十分でしょうか?
  • また、元のデッキを模倣したシャッフル デッキを作成することについて、マークが正しいと思います (確率が非常に低いとは思えませんが)。したがって、それをテストするのは非常に困難であり、シャッフルされたデッキがオリジナルを模倣している場合は破棄することもできます. そうすれば、テストで十分です
  • Collections.shuffle()さらに、自分で何かを書く代わりに、おそらくジガーの言及を使用する必要があると思いますか?
于 2011-02-17T10:03:13.697 に答える
1

これをテストするために私が見つけた最良の方法は、1,000回ほど異なる回数をテストし、テストが成功するたびに記録することです. 最終的には、テストが 98 ~ 99% の確率で機能することを本当に知りたいので、結果が ~99% +/- 1% である限り、テストは常に成功するはずです。

  • シャッフルされた手はオリジナルと同じであってはなりません。
  • 両方の長さは同じでなければなりません。
  • すべてのカードの合計が同じ (または類似) である必要があります。

迅速なコード例:

func testShuffled() {
    var hand1 = [3,4,5,6,7,1,2,8,9,10,11,12,2,3,4,5,6,7,8,9,10,11,12]
    var count =  0

    for _ in 0..<1000 {
        let hand2 = hand1.shuffled()

        if (hand1 != hand2 && hand1.count == hand2.count &&
            hand1.reduce(0, combine: +) == hand2.reduce(0, combine: +)) {
            count += 1
        }
        hand1 = hand2
    }
    let result = Double(count) / 1000.00
    XCTAssertEqualWithAccuracy(result, 1, accuracy: 0.02)
}
于 2016-04-28T18:21:29.857 に答える