盤面評価/石の場所
また盤面評価です。前は石の数で評価していましたが、今回は石の場所で評価します。たとえば、角に石を打つのは有利だとか端に石を打つのが有利だとかをAIが考慮できるようにします。
各場所の価値
オセロを何回かやってると「4端や辺を取ると有利になる」ことに気づくと思います。今回はこのような場所の価値に関する知識をAIに実装します。人間に教えるときは「4端が有利だ」と言葉で教えられますが今のAIには無理です。AIに教えるには各場所の価値を数値で厳密に表す必要があります。
私自身はオセロが強いわけではないのでコンピュータリバーシ入門ですこし勉強してきました。このサイトでは各場所の価値として下の図のようなのを採用しています(この方法はあまりよくないようです)。
この評価は白石(AI)にとっての評価値です。隅はすごい価値が高く、辺も価値が高くなっています。また隅や辺のすぐ隣は低くなっています。AIクラスを見てください。上の評価値を二次元配列で実装しています。
// 盤面の各場所の価値 private static final int valueOfPlace[][] = { {120, -20, 20, 5, 5, 20, -20, 120}, {-20, -40, -5, -5, -5, -5, -40, -20}, { 20, -5, 15, 3, 3, 15, -5, 20}, { 5, -5, 3, 3, 3, 3, -5, 5}, { 5, -5, 3, 3, 3, 3, -5, 5}, { 20, -5, 15, 3, 3, 15, -5, 20}, {-20, -40, -5, -5, -5, -5, -40, -20}, {120, -20, 20, 5, 5, 20, -20, 120} };
評価値を計算するのは前回と同じくvalueBoard()メソッドです。
/** * 評価関数。盤面を評価して評価値を返す。盤面の場所の価値を元にする。 * * @return 盤面の評価値。 */ private int valueBoard() { int value = 0; for (int y = 0; y < MainPanel.MASU; y++) { for (int x = 0; x < MainPanel.MASU; x++) { // 打たれた石とその場所の価値をかけて足していく value += panel.getBoard(x, y) * valueOfPlace[y][x]; } } // 白石(AI)が有利なときは負になるので符合を反転する return -value; }
getBoard(x, y)は(x, y)の場所の石の種類を返します。石がないときはBLANK(0)、黒石のときはBLACK_STONE(1)、白石のときはWHITE_STONE(- 1)です。この値とvalueOfPlaceの値をかけます。たとえば、オセロの初期状態では
-1 * 3 + 1 * 3 + -1 * 3 + 1 * 3 = 0
となります。つまり、有利・不利はないってことですね。この方法でvalueを計算すると白が有利なとき負の値になります。白石(WHITE_STONE)を-1としたからです。ここでは白石(AI)が有利なほど正の値にしたいのでreturnするときに符号をひっくり返しています。実行してみてください。前回のよりさらに強くなったはずです。今度は隅が有利だということを知っているので積極的に隅や辺を狙うようになります。