RSS

 

RSS


 今回は、麻雀ゲームを作るときに発生するかもしれないプ:「配牌バリエーション少なくね?」という問題点の解決方法を提示。

 前回のやりかたのままだと、136!種類あるはずの山のうちのほんのちょっと、(10の200乗)分の1ほどしかバリエーションがない。

 これを解決するのは、難しいことではなく・・・。

■解決法1

//  初期化で一旦配ったら
 //  まず0~135を行儀よくつめて
void init()
{
  for(i=0;i<136;i++){
    table[i]=i;
  }
}

//  前回のtableの内容は残しておいて毎回シャッフル

 //  基本どおり丁寧にシャッフル。
void nokoshite_kubari()
{
   for
(int i=0; i<136; i++) {
     int nokori=136-i;
     int pos= i +  (rand30000.Next() % nokori );
     swap(i, pos); // box[i]とbox[pos]の内容を交換
   }
}

////////////////////////////

全体の流れ

 //  最初に初期化したら、半荘が終わっても2度と呼ぶ必要なし。
 init(); 

 nokoshite_kubari();
  対局();  // 1局目

  nokoshite_kubari();
  対局();  // 2局目

  nokoshite_kubari();
  対局();  // 3局目

 ・・・・・・

とすればよい。「なぁんだ、当たり前ジャン」という話。これで136!に手が届いた。時間等での乱数の揺らしを時々入れてあげて完成。

 これができてない場合。乱数側をちょっと弄って、例えば、64ビット数4個使用などとしても、(10の*00乗)分の1レベルからは脱却していない。また、それに気づいていないところが重要な問題

■解決法2

 解決法1とは効果的には似てるけど、別な方法を提示。それは、tableの中を前回の捨て牌の順で詰めて行くという方法。その後でシャッフル。

 これは電動卓や手積み卓をシミュレートしているカタチ。ある意味、一番すなお。

 また、解決法1の「時間等の乱数の揺らしを時々入れてあげる」という部分を「捨て牌を使う」というところまで拡大したという見方もできる。


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

コメント

ダイレクトな解決法で、メルセンヌ・ツイスターを使うのはどうでしょう。
周期2^19937-1>10^6000

#Cソース
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/mt.html

  • Posted by かっちゃん
  • at 2008/08/02 20:53:21

・コメントありがとうございます。メルセンヌ・ツイスター、良さそうです。勉強になります。
・但し、「時間等での揺すり方」を間違わないようにする必要はあります。

・今回の記事の方法は「周期30000の擬似乱数」でも大丈夫という方法でした。
・メルセンヌ・ツイスタでの大きい「内部ベクトル」のかわりに、アプリ側で既に用意されているtableを流用しているカタチともとれます。

  • Posted by いわいまさか
  • at 2008/08/03 08:36:05