少し考える思考ルーチン

開発目標

このページの目標は、思考ルーチンを賢くすることです。単にルール違反しないだけでなく、良い手を教えてあげましょう。

良い手を教える

思考ルーチンに良い手を教えるため、評価関数というシステムを導入します。要は、角に自分の石があったら150点、辺に相手の石があったらー10点のように、盤面に点数を付ける訳です。そして、点が最高になる差し手を最善手とします。また、最高点を出すためには何回か計算をしますが、1回の計算で盤面が変化してしまうので、次の計算のために盤面を元に戻す処理を加えます。

ReversiAI.java

//2011/09/25  by boco.hp3200.com
//--------------------------------------------------------------------------
package com.hp3200.boco.reversi;

public class ReversiAI {
    private final int WALL = -1;
    private final int BLANK = 0;
    private final int PLAYER = 1;
    private final int COM = 2;
    private final int[] MOVE = {-11, -10, -9, -1, 1, 9, 10, 11};
    private final int[] POINT_MAP = {    
        0,  0,  0, 0, 0, 0, 0,  0,  0,0,
        0,150,-20,20,10,10,20,-20,150,0,
        0,-20,-30,-5,-5,-5,-5,-30,-20,0,
        0, 20, -5,10, 5, 5,10, -5, 20,0,
        0, 10, -5, 5, 3, 3, 5, -5, 10,0,
        0, 10, -5, 5, 3, 3, 5, -5, 10,0,
        0, 20, -5,10, 5, 5,10, -5, 20,0,
        0,-20,-30,-5,-5,-5,-5,-30,-20,0,
        0,150,-20,20,10,10,20,-20,150,0,
        0,  0,  0, 0, 0, 0, 0,  0,  0,0
    };
    
    private int[] board = new int[100];
    private int bestPlace;

    //コンストラクタ
    public ReversiAI() {
    }

    //処 理:盤を初期化する
    //引 数:startBoard……初めの盤
    //戻り値:なし
    public void setBoard(int[] startBoard) {
        for(int i=0;i<100;i++) {
            board[i] = startBoard[i];
        }
    }

    //処 理:最善手を返す
    //引 数:なし
    //戻り値:最善手
    public int getPlace() {
        return bestPlace;
    }
    
    //処 理:最善手を考える
    //引 数:myCoin……PLAYER or COM
    //戻り値:なし
    public void think(int myCoin) {
        int i,j;
        int point;
        int bestPoint = -100000;
        int[] baseBoard = new int[100];
        
        for(i=0;i<100;i++) {
            baseBoard[i] = board[i];
        }
        
        for(i=11;i<=88;i++) {
            if(board[i]==BLANK) {
                if(reverse(myCoin,i)==true) {
                    point = evaluationFunction(myCoin);
                    if(bestPoint<point) {
                        bestPoint = point;
                        bestPlace = i;
                    }
                    for(j=0;j<100;j++) {
                        board[j] = baseBoard[j];
                    }
                }
            }
        }
    }

    //処 理:そこに置けるなら、置いて裏返す
    //引 数:myCoin……PLAYER or COM、p……置く場所
    //戻り値:置けなかったらfalse
    boolean reverse(int myCoin, int p) {
        …略…
    }
    
    //処 理:評価関数
    //引 数:myCoin……PLAYER or COM
    //戻り値:点数
    public int evaluationFunction(int myCoin) {
        int yourCoin = PLAYER;
        int i;
        int point = 0;
        
        //相手の石を設定
        if(myCoin==PLAYER) yourCoin = COM;
        
        //点数を計算
        for(i=11;i<=88;i++) {
            if(board[i]==myCoin) point += POINT_MAP[i];
            if(board[i]==yourCoin) point -= POINT_MAP[i];
        }

        //点数を返す
        return point;
    }

}

開発結果

これで思考ルーチンが少し賢くなりました。確認してみます。

まだまだ弱いですが、だいぶ良くなりました。次回は、さらに思考ルーチンを育てます。先の先を読むようになってくれます。