こんにちは。


 おかげさまで、制作中のゲームのシステムは8割以上完成してきました。



 さて、今日は戦闘処理への複線として、ルーレット選択を実装しましょう。英語では"roulette wheel selection"といいます。



 ルーレット選択自体に余り馴染みのない方のために説明すると、ルーレット選択はそれぞれに比重がある複数項目のうちからランダムに一つを選び出す方法で、概念的には賭博場にあるあの玉を転がすルーレット(roulette wheel)を想像していただければ良いです。このとき、ルーレットの枠の大きさは、項目それぞれの比重にあたります。



 ルーレット選択は遺伝的アルゴリズム(GA)等にもよく使われる方法で、ゲームを制作する際には非常に有用です。


 では、関数の実装に入ります。


public int rouletteChoice(int[] rate){
  int max = 0;
  for(int i = 0;i < rate.length ;i++ )
    max += rate[i];
  int temp = rand.nextInt(max);
  for(int i = 0;i < rate.length ;i++ ){
    temp -= rate[i];
  if(temp < 0)
    return i;
  }

  System.out.println("予期しないエラー@ルーレット選択");
  return -1;
}


 実装自体は非常に簡単です。引数rate[]はそれぞれの起こる「比重」であり、合計が100であると分かりやすいですが、100である必要はありません。randはjava.util.Randomクラスのオブジェクトです。




 では、使用例を挙げてみましょう。今、明日の天気が晴れ50%、曇り20%、雨30%であるとします。このとき引数たるrateを


int[] tommorow_rate = {50,20,30};


として初期化し、


int result = rouletteChoice(tommorow_rate);


とします。resultが0となる確率は50%、1、2となる確率はそれぞれ20、30%であることが分かると思います。前述の通り、int[] tommorow_rate = {5,2,3};としても挙動は変わりません。



 実装の際考慮した点としては、値の評価ですかね。簡単のために合計が100である場合を挙げると、確率50に該当するケースは乱数が0~49のときです(50個)。すなわち、乱数<50の場合に該当します。乱数=<50の場合ではないということです。




 この関数を用意すれば、乱数発生は格段に楽になると思います。次からは戦闘について簡単に書いていきたいと思います。