RSS

 

RSS


 「配牌バリエーション少なくね?」について説明。具体的な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,r0,r1,r2・・・・

3.配る
   山配りルーチンにそれ自体は問題のないプ:乱数で順列を作る方法を使う。一局の頭で以下のルーチンを呼ぶ。
######################################
void kubari1()
{
     //  まず0~135を行儀よくつめて
  for(i=0;i<136;i++){
      table[i]=i;
   }
  //  基本どおり丁寧にシャッフル。
    for(int i=0; i<136; i++) {
     int nokori=136-i;
     int pos= i +  (rand30000.Next() % nokori );
     swap(i, pos); // box[i]とbox[pos]の内容を交換
   }
}
######################################

4.バリーエション少な!
 わかるだろうか? 3.のままだと生成される山の状態がrand30000()の内部状態の数にあわせて30000種類しかないことを。   
 例えばr1000から始まったら、r1000,r1001,r1002,・・・r1135を使うことは一本道。
 3.65904288 × (10^232)のうちの30000は少なすぎ。この麻雀ゲームでは「天和は出ることはない」「この配牌は前もやったことある」という悲しい状況。

5.時間でも使って乱数を揺らせてやればいい?
   乱数を使う前にシードを時間で揺らしてあげるとどうなるか?
######################################
void kubari2()
{
  r30000.SetSeed(time());
  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.解決策
  「 一気に内部状態を表すビット数を増やして・・・」という方法でいいのか? 解決策は難しくないけど、次回へ続く。


  • コメント (0)
  • トラックバック (0)
トラックバックURL :
http://www.iwai-masaka.jp/tb.cgi/52311