○×ゲームを作る (5) 思考ルーチンを賢く

前回までで、勝敗判定ができるようにしました。今回は、コンピュータ側の思考ルーチン(コンピュータ側の戦略や方策)をもう少し賢くしていきましょう。

今回のゲームでは、コンピュータ側は後攻です。後攻は言わば守りになるため、先攻とはちょっと違った戦略をとらなければいけません。仮に以下の戦略をとることにしましょう。

  1. turn 1:角が取られたら真ん中をとる。それ以外の場合は角をとる
  2. turn 3以降:自分がリーチの場合優先してリーチのマスをとる。プレイヤーがリーチの場合、リーチを防ぐ。それ以外はランダム

必ずしも turn の値によって場合分けする必要はないのですが、このようにすることで無駄な計算を省くことができます。例えばturn が1 のときは、プレイヤーもコンピュータもリーチになることはないので、その計算をする必要はありません。では、上記の流れでコードにしてみましょう。

まず、リーかどうかを判定する関数 reach() を作成します。今回の関数は、リーチであれば True、そうでなければ False を返す Boolean型とします。こうすることで、「もしリーチだったら」ということを if (reach) と端的に表すことができます。リーチの場合は True、そうでない場合は False になるので、このように if 文の条件式として使用することができます。またこの関数では、リーチの場合にリーチになっているマスの X, Y の値も書き換えておくこととします。reachタブを作成して以下のコードを記述します。

boolean reach(){
  int line = 1;

  // vertical reach
  for (X = 0; X < 3; X++){
    for (Y = 0; Y < 3; Y++){
      line *= map[Y][X];
    }
    if(line == 9){
      for (Y = 0; Y < 3; Y ++){
        if(map[Y][X] == 1)  return true;
      }
    } else if(line == 4){
      for (Y = 0; Y < 3; Y ++){
        if(map[Y][X] == 1)  return true;
      }
    }
  }

  //horizontal reach
  line = 1;
  for (Y = 0; Y < 3; Y++){
    for (X = 0; X < 3; X++){
      line *= map[Y][X];
    }
    if(line == 9){
      for (X = 0; X < 3; X ++){
        if(map[Y][X] == 1)  return true;
      }
    } else if (line == 4){
      for (X = 0; X < 3; X ++){
        if(map[Y][X] == 1)  return true;
      }
    } 
  }

  // cross reach (right-down)
  line = map[0][0] * map[1][1] * map[2][2];
  if(line == 9){
    for(int i = 0; i < 3; i++){
      if(map[i][i] == 1) {
        X = i;
        Y = i;
        return true;
      }
    }
  } else if (line == 4){
    for(int i = 0; i < 3; i++){
      if(map[i][i] == 1) {
        X = i;
        Y = i;
        return true;
      }
    }
  } 

  // cross reach (right-up)
  line = map[2][0] * map[1][1] * map[0][2];
  if(line == 9){
    for(int i = 0; i < 3; i++){
      if(map[2-i][i] == 1) {
        X = i;
        Y = 2 - i;
        return true;
      }
    }
  } else if(line == 4){
    for(int i = 0; i < 3; i++){
      if(map[2-i][i] == 1) {
        X = i;
        Y = 2 - i;
        return true;
      }
    }
  }
  
  return false;
}

最初のブロック(まとまり)で縦の 3 列を、次のブロックで横 3 列、続いて斜めでリーチになっているか判定しています。リーチになっていれば、そのマスの X, Y を保存して True を return 文で返しています。

続きは次回~

Leave a Reply

Your email address will not be published. Required fields are marked *