// 指す手を決める。 Othello::Coord place(const Othello::Board & board){ SimulatedBoardList candidates_me, candidates_opponent; // 自分が置ける場所をすべて試し、結果をdequeとして返す enum_possible_placements(gi_.my_color(), board, candidates_me); // そのそれぞれに対して、相手が置ける場所をすべて試す std::size_t max_pieces_m = 0; Othello::Coord max_pieces_m_place; for(SimulatedBoardList::iterator it_m = candidates_me.begin(); it_m != candidates_me.end(); ++it_m){ // 相手が置ける場所を列挙する enum_possible_placements(gi_.my_color(), it_m->board, candidates_opponent); // 相手が置いた結果の、自分の残る石の数。 // 相手が置く前の数で初期化しておく。 std::size_t min_pieces_o = (it_m->board.pieces())[gi_.my_color()]; // 相手が置ける場所のうち、 // 自分の石が最も少なくなるときの個数を数える // (相手が置ける場所がなければ、上記「相手が置く前の数」が使われる) for(SimulatedBoardList::iterator it_o = candidates_opponent.begin(); it_o != candidates_opponent.end(); ++it_o){ const std::size_t pieces = (it_o->board.pieces())[gi_.my_color()]; if(pieces < min_pieces_o) min_pieces_o = pieces; } // 相手の手によって「自分の石が一番少なくなる」ようにされた // 結果において、自分の石が他の候補よりも多くなるのであれば、 // その手を選ぶ if(min_pieces_o > max_pieces_m){ max_pieces_m = min_pieces_o; max_pieces_m_place = it_m->coord; } } // 置く場所を返す return max_pieces_m_place; }
// 指す手を決める。 Othello::Coord place(const Othello::Board & board){ // 置ける場所のうち、(各分類において)石を最も多く裏返せるときの // 数ならびに場所。 // [0]: 角のマス(優先度最高) // [1]: それ以外 // [2]: 角に隣接するマス(優先度最低) std::size_t max_flipped[3]; Othello::Coord max_flipped_place[3]; for(std::size_t i = 0; i < 3; ++i){ max_flipped[i] = 0; } for(int i = 0; i < board.rows(); ++i){ for(int j = 0; j < board.cols(); ++j){ // 盤面のインスタンスを複製しておく Othello::Board board_tmp = Othello::Board(board); // 石を置いてみる const std::size_t flipped = board_tmp.put_and_flip(i, j, gi_.my_color()); // 今まで試した中で一番多く石を裏返せていたら、 // その座標を max_flipped_place に保存しておく if((i == 0 || i == board.rows() - 1) && (j == 0 || j == board.cols() - 1)){ // 角。優先して置く if(flipped > max_flipped[0]){ max_flipped[0] = flipped; max_flipped_place[0] = Othello::Coord(i, j); } }else if((i <= 1 || i >= board.rows() - 2) && (j <= 1 || j >= board.cols() - 2)){ // 角の隣。優先度最低 if(flipped > max_flipped[2]){ max_flipped[2] = flipped; max_flipped_place[2] = Othello::Coord(i, j); } }else{ // その他 if(flipped > max_flipped[1]){ max_flipped[1] = flipped; max_flipped_place[1] = Othello::Coord(i, j); } } } } // 置く場所を返す if(max_flipped_place[0].is_valid()) return max_flipped_place[0]; if(max_flipped_place[1].is_valid()) return max_flipped_place[1]; return max_flipped_place[2]; }
// 置ける場所の候補を列挙する void enum_possible_placements(Othello::Color color, const Othello::Board & board, SimulatedBoardList & result){ result.clear(); for(int i = 0; i < board.rows(); ++i){ for(int j = 0; j < board.cols(); ++j){ // 盤面のインスタンスを複製しておく SimulatedBoard simboard; simboard.coord = Othello::Coord(i, j); simboard.board = Othello::Board(board); // 石を置いてみる if(simboard.board.put_and_flip(simboard.coord, gi_.my_color()) > 0){ // 1か所でも裏返せるとわかったら候補に加える result.push_back(simboard); } } } }