私はちょっとしたレクリエーションホリデーコンピューティングをやっています。私のミニプロジェクトは、イタリアの「トンボリ」ゲームのシミュレーションでした。重要な構成要素は、次のプロセスのシミュレーションでした。
ゲームは、1から90までの番号が付けられた90個のビー玉のバッグを持った男性によって制御されます。彼は、プレーヤーにビー玉の番号を呼び出すたびに、バッグからランダムにビー玉を1つずつ引き出します。
少し考えた後、このビルディングブロック用に次のコードを作成しました。
// NBR marbles, numbered 1...NBR are in a bag. Simulate randomly
// pulling them from the bag, one by one, until the bag is empty
void bag( int random_sequence[NBR] )
{
int i;
// Store each marble as it is pulled out
int *store = random_sequence;
// Array of marbles still in the bag
int not_yet_pulled[NBR];
for( i=0; i<NBR; i++ )
not_yet_pulled[i] = i+1; // eg NBR=90; 1,2,3 ... 90
// Loop pulling marbles from the bag, one each time through
for( i=NBR; i>=1; i-- )
{
int x = rand();
int idx = x%i; // eg i=90 idx is random in range 0..89
// eg i=89 idx is random in range 0..88
// ...
// eg i=1 idx is random in range 0..0
// (so we could optimize when i=1 but not worth the bother)
*store++ = not_yet_pulled[idx];
// Replace the marble just drawn (so it cannot be pulled again)
// with the last marble in the bag. So;
// 1) there is now one less marble in the bag
// 2) only marbles not yet pulled are still in the bag
// If we happened to pull the last marble in the *current subarray*, this is
// not required but does no harm.
not_yet_pulled[idx] = not_yet_pulled[i-1];
}
}
乱数を使用したゲームシミュレーションには、いたるところに微妙な点や罠があることを知っています。そのため、コードにはかなり満足していますが、自信は100%弱です。だから私の質問は;
1)私のコードに何か問題がありますか?
2)[1)の答えが「いいえ」の場合]私は無意識のうちに標準のシャッフルアルゴリズムを使用していますか?
3)[2)の答えが「いいえ」の場合]私のアルゴリズムは標準的な代替アルゴリズムとどのように比較されますか?
編集 答えてくれたすべての人に感謝します。フィッシャー-イェーツアルゴリズムを再発見し、それが問題の核心になっていることを明らかにしたので、エイダンカリーの答えを受け入れるつもりです。もちろん、事前に調査を行うことで時間と労力を節約できたのも当然です。しかし一方で、それは楽しい趣味のプロジェクトでした。シミュレーションの残りの部分は日常的なものでした。これは最も興味深い部分でした。私は自分で行かなくても、楽しみを奪っていただろう。さらに、私はバッグからビー玉を取り出す男性をシミュレートしようとしていましたが、状況がカードのシャッフルとまったく同じであることに気付いたのは、作品のかなり遅い段階でした。
もう1つの興味深い点は、Kenによって特定された小さな欠陥があることです。この欠陥は、頻繁に繰り返されるパターンrand()%Nは、0..N-1の範囲から乱数を選択するための実際には良い方法ではないことを指摘しています。
最後に、私のバージョンのフィッシャー-イェーツには、シャッフルという優れた特性を備えたエレガントなトリックが欠けています。その結果、私のアルゴリズムは、同じようにランダムですが逆のシャッフルになります。