「配牌バリエーション少なくね?」について説明。具体的なrand30000
の例を示すところから始めて。
麻雀ゲームの作り方によっては、配牌(山配り)時に起こりうる現象。
1.麻雀の山を配ることは全部の牌が違うものと考えると int table[136]の配列に0~135の数字を一個づつ詰める順列を求めるのと同じ。
場合の数は136!個で、googleで計算すると。
136 ! = 3.65904288 × (10^232)
2.擬似乱数 rand30000 を考えて。
参考:プ:擬似乱数って。
rand30000は、内部状態が30000個ある擬似乱数。返す値は30000周期でループ。
・・・,r0,r1,r2,r3,・・・,r29998,r29999,
3.配る
山配りルーチンにそれ自体は問題のないプ:乱数で順列を作る方法を使う。一局の頭で以下のルーチンを呼ぶ。
###############
void kubari1()
{
// まず0~135を行儀よくつめて
for(i=0;i<136;i+
table[i]=i;
}
// 基本どおり丁寧にシャッフル。
for(int i=0; i<136; i++) {
int nokori=136
int pos= i + (rand30000.Next
swap(i, pos); // box[i]とbox[pos]の内容を交換
}
}
###############
4.バリーエション少な!
わかるだろうか? 3.のままだと生成される山の状態がrand30000()の内部状態の数にあわせて30000種類しかないことを。
例えばr1000から始まったら、r1000,r1001,r10
3.65904288 × (10^232)のうちの30000は少なすぎ。この麻雀ゲームでは「天和は出ることはない」「この配牌は前もやったことある」という悲しい状況。
5.時間でも使って乱数を揺らせてやればいい?
乱数を使う前にシードを時間で揺らしてあげるとどうなるか?
###############
void kubari2()
{
r30000.SetSeed(
kubari1();
}
###############
こんなことしてもバリエーションは30000のまま。
6.もっとグショグショに・・・
かなりグチャグチャですが、「配ってる途中で時間を参照する」ようにすると、バリエーションが30000×30000とか30000×300000×300000程度に増えるかも。それでも
(30 000 × 30 000 × 30 000) / (136 !) = 7.37897884 × (10^ -220)
と麻雀の山の可能性に比べると全然少ない。しかも、だんだん、乱数じゃなくなっているかもしれないし。
7.ビット数増やす?
乱数の内部状態を増やして64ビット変数2個で表すようにしても
(2^(64×2)) / (136 !) = 9.29976439 × (10^ -195)
と まだまだ、気の遠くなるような少なさ。
8.解決策
「 一気に内部状態を表すビット数を増やして・・・」という方法でいいのか? 解決策は難しくないけど、次回へ続く。