Java Tic Tac Toe Minimax Bug

时间:2014-12-18 15:23:52

标签: java recursion tic-tac-toe minimax

已尝试调试我的MiniMax代码,但似乎无法在此处找到问题。主要方法是evalGame(),其中奖励为1,亏损为-1,领带为0。我在MiniMax算法中有任何明显的错误吗?

package tictactoe;

import static tictactoe.Player.*;

import java.util.Arrays;

public class MinimaxTTT {

    private Player[] board = new Player[9];
    private static Player player = X;

    public MinimaxTTT() {
        Arrays.fill(board, E);
        player = X;
    }

    public MinimaxTTT(Player[] b, Player p) {
        for(int i = 0; i < 9; i++) {
            board[i] = b[i];
        }
        player = p;
    }

    public static boolean checkWin(Player[] b, Player p) {
        if((b[0]==p&&b[1]==p&&b[2]==p) 
            || (b[0]==p&&b[3]==p&&b[6]==p)
            || (b[0]==p&&b[4]==p&&b[8]==p)
            || (b[0]==p&&b[1]==p&&b[2]==p)
            || (b[1]==p&&b[4]==p&&b[7]==p)
            || (b[0]==p&&b[1]==p&&b[2]==p)
            || (b[2]==p&&b[4]==p&&b[6]==p)
            || (b[2]==p&&b[5]==p&&b[8]==p)
            || (b[0]==p&&b[3]==p&&b[6]==p)
            || (b[3]==p&&b[4]==p&&b[5]==p)
            || (b[0]==p&&b[4]==p&&b[8]==p)
            || (b[2]==p&&b[4]==p&&b[6]==p)
            || (b[3]==p&&b[4]==p&&b[5]==p)
            || (b[1]==p&&b[4]==p&&b[7]==p)
            || (b[2]==p&&b[5]==p&&b[8]==p) 
            || (b[3]==p&&b[4]==p&&b[5]==p)
            || (b[0]==p&&b[3]==p&&b[6]==p)
            || (b[2]==p&&b[4]==p&&b[6]==p)
            || (b[6]==p&&b[7]==p&&b[8]==p)
            || (b[6]==p&&b[7]==p&&b[8]==p)
            || (b[1]==p&&b[4]==p&&b[7]==p)
            || (b[2]==p&&b[5]==p&&b[8]==p)
            || (b[6]==p&&b[7]==p&&b[8]==p)
            || (b[0]==p&&b[4]==p&&b[8]==p)) {
            return true;
        }
        return false;
    }

    private static boolean checkTie(Player[] b) {
        for(int i = 0; i < 9; i++) {
            if(b[i] == E) {
                return false;
            }
        }
        return true;
    }

    private static boolean gameOver(Player[] b) {
        return checkTie(b) || checkWin(b, X) || checkWin(b, O);
    }

    private static int maxOfArray(int[] a) {
        int max = a[0];
        for (int i : a)
            if (max < i)
                max = i;
        return max;
    }

    private static int minOfArray(int[] a) {
        int min = a[0];
        for (int i : a)
            if (min > i)
                min = i;
        return min;
    }

    private static int getEmptyNumber(Player[] b) {
        int spaces = 0;
        for(int i = 0; i < 9; i++) {
            if(b[i] == E)
                spaces++;
        }
        return spaces;
    }

    private static int evalGame(Player[] b, Player p, Player currentP) {
        if(gameOver(b)) {
            if(checkWin(b, p)) {
                return 1;
            } else if(checkWin(b, p == X ? O : X)) {
                return -1;
            } else {
                return 0;
            }
        } else {
            int[] arrayEval = new int[getEmptyNumber(b)];
            for(int i = 0; i < getEmptyNumber(b); i++) {
                arrayEval[i] = evalGame(possibleBoards(b, currentP)[i], p, currentP == X ? O : X);
            }
            if(currentP == p) {
                return maxOfArray(arrayEval);
            } else {
                return minOfArray(arrayEval);
            }
        }
    }

    public static Player[][] possibleBoards(Player[] b, Player p) {
        Player[][] toReturn = new Player[getEmptyNumber(b)][9];
        int spaces = 0;
        for(int i = 0; i < 9; i++) {
            if(b[i] == E) {
                for(int j = 0; j < 9; j++) {
                    toReturn[spaces][j] = b[j];
                }
                toReturn[spaces][i] = p;
                spaces++;
            }
        }
        return toReturn;
    }

    public static void main(String[] args) {
        Player[] p = new Player[9];
        Arrays.fill(p, E);
        p[1] = X;
        System.out.println(evalGame(p, O, O));
    }

}

1 个答案:

答案 0 :(得分:0)

我查看了我的代码并意识到我在调试时犯了一个错误。对于任何有兴趣的人

,下面是有效的编辑代码
package tictactoe;

import static tictactoe.Player.*;

import java.util.Arrays;

public class MinimaxTTT {

    private Player[] board = new Player[9];
    private Player player = X;

    public MinimaxTTT() {
        Arrays.fill(board, E);
        player = X;
    }

    public MinimaxTTT(Player[] b, Player p) {
        for(int i = 0; i < 9; i++) {
            board[i] = b[i];
        }
        player = p;
    }

    public Player[] getBoard() {
        return board;
    }

    public void setBoard(Player[] b) {
        for(int i = 0; i < 9; i++) {
            board[i] = b[i];
        }
    }

    public void setSquare(int i, Player p) {
        board[i] = p;
    }

    public Player getPlayer() {
        return player;
    }

    public void setPlayer(Player p) {
        player = p;
    }

    public void switchPlayers() {
        player = player == X ? O : X;
    }

    public boolean checkWin(Player[] b, Player p) {
        if(b[0] == p && b[1] == p && b[2] == p 
            || b[3] == p && b[4] == p && b[5] == p
            || b[6] == p && b[7] == p && b[8] == p
            || b[0] == p && b[3] == p && b[6] == p
            || b[1] == p && b[4] == p && b[7] == p
            || b[2] == p && b[5] == p && b[8] == p
            || b[0] == p && b[4] == p && b[8] == p
            || b[2] == p && b[4] == p && b[6] == p) {
            return true;
        }
        return false;
    }

    public boolean checkTie(Player[] b) {
        for(int i = 0; i < 9; i++) {
            if(b[i] == E) {
                return false;
            }
        }
        return true;
    }

    public boolean gameOver(Player[] b) {
        return checkTie(b) || checkWin(b, X) || checkWin(b, O);
    }

    private int maxOfArray(int[] a) {
        int max = a[0];
        for (int i : a)
            if (max < i)
                max = i;
        return max;
    }

    private int minOfArray(int[] a) {
        int min = a[0];
        for (int i : a)
            if (min > i)
                min = i;
        return min;
    }

    private int getEmptyNumber(Player[] b) {
        int spaces = 0;
        for(int i = 0; i < 9; i++) {
            if(b[i] == E)
                spaces++;
        }
        return spaces;
    }

    private int findIndex(int[] is, int n) {
        for(int i = 0; i < is.length; i++) {
            if(is[i] == n)
                return i;
        }
        return 0;
    }

    private int[] evalGame(Player[] b, Player p, Player currentP, int depth) {
        int[] toReturn = new int[2];
        if(gameOver(b)) {
            if(checkWin(b, p)) {
                toReturn[1] = 10 + depth;
                return toReturn;
            } else if(checkWin(b, p == X ? O : X)) {
                toReturn[1] = depth - 10;
                return toReturn;
            } else {
                toReturn[1] = 0;
                return toReturn;
            }
        } else {
            depth += 1;
            int[] arrayEval = new int[getEmptyNumber(b)];
            for(int i = 0; i < getEmptyNumber(b); i++) {
                arrayEval[i] = evalGame(possibleBoards(b, currentP)[i], p, currentP == X ? O : X, depth)[1];
            }
            if(currentP == p) {
                int position = findIndex(arrayEval, maxOfArray(arrayEval));
                int base = 0;
                for(int i = 0; i < 9; i++) {
                    if(b[i] == E) {
                        if(base == position) {
                            toReturn[0] = i;
                            break;
                        } else {
                            base++;
                        }
                    }
                }
                toReturn[1] = maxOfArray(arrayEval);
                return toReturn;
            } else {
                toReturn[1] = minOfArray(arrayEval);
                return toReturn;
            }
        }
    }

    public Player[][] possibleBoards(Player[] b, Player p) {
        Player[][] toReturn = new Player[getEmptyNumber(b)][9];
        int spaces = 0;
        for(int i = 0; i < 9; i++) {
            if(b[i] == E) {
                for(int j = 0; j < 9; j++) {
                    toReturn[spaces][j] = b[j];
                }
                toReturn[spaces][i] = p;
                spaces++;
            }
        }
        return toReturn;
    }

    public Player[] move() {
        if(!gameOver(board)) {
            board[evalGame(board, player, player, 0)[0]] = player;
        }
        return board;
    }
}