三目並べの盤面の評価の例
今回の記事は三目並べの盤面の評価してみようと思います
この記事は前回の続きです
盤面の評価方法
今回はシンプルに2つの石が隣り合っている時に点数を加算するようにします
実装例
⭕️❌ゲームに必要なクラスとして前回の記事で作成したFieldクラスに、盤面の判定を行うevaluate()
を追加作成します。
また、3x3マスでは読み切ってしまうので、盤面を8x8に拡張します
評価
まずは、コンストラクタで、評価に必要なビットボード(2つの石が並んでいるパターン)を生成し、evaluate()
でパターンに一致する個数(黒で一致した個数 - 白で一致した個数)
を評価として返却します
例として、横に2つ並んでいるパターンの場合、横に一つ移動したパターンは(1 + 0 * 8)個シフトして0x06(0b0110)となり、縦に一つ移動したパターンは(0 + 1 * 8)個シフトして0x300(0b001100000000)となります(※)
今回は8x8マスなのでBOARD_SIZEを8とします
※) 今回は8x8マスなので、以下のようにビットが立っていると解釈することができ、盤面が以下のパターンを含む場合に点数を獲得します
0x300(0b001100000000)の場合
00000000
00000000
00000000
00000000
00000000
00000000
00000011
00000000
0x180000(0b000110000000000000000000)(縦に2マス、横に3マス)の場合
00000000
00000000
00000000
00000000
00000000
00011000
00000000
00000000
constructor(/*省略*/){
//略
this.evalBoard = [];
for (let i = 0n; i < 7n; i++) {
for (let j = 0n; j < 7n; j++) {
//横
this.evalBoard.push(0x03n << (i + j * BigInt(BOARD_SIZE)));
//縦
this.evalBoard.push(0x09n << (i + j * BigInt(BOARD_SIZE)));
//斜め
this.evalBoard.push(0x201n << (i + j * BigInt(BOARD_SIZE)));
//斜め
this.evalBoard.push(0x102n << (i + j * BigInt(BOARD_SIZE)));
}
}
}
evaluate() {
let score = 0;
for (const board of this.evalBoard) {
if ((board & this.blackStones) == board) {
score++;
}
if ((board & this.whiteStones) == board) {
score--;
}
}
return score;
}
BigIntを使う理由
JavaScriptでは数値型は倍精度浮動小数点数であり64bitですが、ビット演算を行う際には32bit分しか演算されないという制約があるためBigIntに変換しています
動かしてみる
8x8マスに任意に石を配置して、評価を計算してみると以下のように盤面のスコアを評価できるようになりました
⬜︎⬜︎⬜︎⬜︎⬜︎⬜︎⬜︎⬜︎
⬜︎⬜︎⬜︎⬜︎⬜︎⬜︎⬜︎⬜︎
⬜︎⬜︎⬜︎❌⬜︎⬜︎⬜︎⬜︎
❌⬜︎⬜︎⬜︎❌⬜︎⬜︎⬜︎
❌⬜︎⭕️⬜︎⬜︎⬜︎⬜︎⭕️
⬜︎⬜︎⬜︎⬜︎⬜︎⬜︎⬜︎⬜︎
⬜︎⬜︎⬜︎⬜︎⬜︎⬜︎⬜︎⬜︎
⬜︎⬜︎⭕️⬜︎⬜︎⬜︎⬜︎⭕️
score: -2
まとめ
今回は盤面の評価について考えてみました
次回は探索と評価を組み合わせて、AIのようなものを作成してみたいと思います