Minimax功能不适用于连接4

时间:2015-04-05 21:39:50

标签: java algorithm minimax game-theory

我正在尝试使用minimax算法在java中实现connect 4的计算机AI版本。对于任务,我创建了一个“Node”类,它以单个板状态开始,然后递归地创建更多节点,直到指定的深度。然后,它将每个节点评分为1作为赢取0作为绘制或最大深度。最后,我使用minimax algorithem来选择在函数“getColumn()”中使用哪个移动。这是我的代码

package ai;

import java.util.ArrayList;
import java.util.Arrays;

public class Node {
    public ArrayList < Node > nodeList = new ArrayList < Node > ();
    private int[][] board; // Represents board, 0 is empty space, 1 is player 1, 2 is computer
    private int turn; // Current turn, 1 is player, 2 is computer

    // Node constructor, creates tree of possible game states
    public Node(int[][] board, int depth, int turn) {
        this.board = board;
        this.turn = turn;

        if (depth > 0 && result(turn) == -1) {
            int[][] copy = new int[7][6];

            for (int i = 0; i < 7; i++)
            copy[i] = board[i].clone();

            int[] cols = getAvailCols(board);

            for (int col: cols) {
                int y = placeBlock(col, turn, copy);
                nodeList.add(new Node(copy, depth - 1, turn == 1 ? 2 : 1));
                copy[col][y] = 0;
            }
        }
    }

    // Returns 0 for draw, 1 for win, -1 for no result
    private int result(int currTurn) {
        int horCount = 1;
        int verCount = 1;
        int ldiaCount = 1;
        int rdiaCount = 1;

        for (int x = 0; x < 7; x++) {
            for (int y = 0; y < 6; y++) {
                for (int countX = x + 1; countX < 7; countX++) {
                    if (board[countX][y] == currTurn) horCount++;
                    else break;
                }

                for (int countX = x - 1; countX >= 0; countX--) {
                    if (board[countX][y] == currTurn) horCount++;
                    else break;
                }

                for (int countY = y + 1; countY < 6; countY++) {
                    if (board[x][countY] == currTurn) verCount++;
                    else break;
                }

                for (int countY = y - 1; countY >= 0; countY--) {
                    if (board[x][countY] == currTurn) verCount++;
                    else break;
                }

                for (int countX = x + 1, countY = y + 1; countX < 7 && countY < 6; countX++, countY++) {
                    if (board[countX][countY] == currTurn) rdiaCount++;
                    else break;
                }

                for (int countX = x - 1, countY = y - 1; countX >= 0 && countY >= 0; countX--, countY--) {
                    if (board[countX][countY] == currTurn) rdiaCount++;
                    else break;
                }

                for (int countX = x + 1, countY = y - 1; countX < 7 && countY >= 0; countX++, countY--) {
                    if (board[countX][countY] == currTurn) ldiaCount++;
                    else break;
                }

                for (int countX = x - 1, countY = y + 1; countX >= 0 && countY < 6; countX--, countY++) {
                    if (board[countX][countY] == currTurn) ldiaCount++;
                    else break;
                }

                if (horCount >= 4 || verCount >= 4 || ldiaCount >= 4 || rdiaCount >= 4) {
                    return 1;
                }

                for (int i = 0; i < 7; i++) {
                    for (int j = 0; j < 6; j++) {
                        if (board[i][j] == 0) return -1;
                    }
                }
            }
        }

        return 0;
    }

    // Puts chip into a column
    private int placeBlock(int x, int turn, int[][] checkboard) {
        int y = 0;

        while (y < 5 && checkboard[x][y + 1] == 0)
        y++;

        checkboard[x][y] = turn;
        return y;
    }

    // Gets the score of a node
    private int score() {
        int result = result(turn);

        if (result == 0) return 0;
        else if (result == 1) return Integer.MAX_VALUE;
        else if (nodeList.size() > 0) {
            int score = Integer.MIN_VALUE;

            for (Node node: nodeList)
            score = Math.max(score, -node.score());

            return score;
        } else {
            return 0;
        }
    }

    public int[] getAvailCols(int[][] checkboard) {
        ArrayList < Integer > list = new ArrayList < Integer > ();

        for (int i = 0; i < 7; i++) {
            if (checkboard[i][0] == 0) list.add(i);
        }

        int[] cols = new int[list.size()];

        for (int i = 0; i < list.size(); i++) {
            cols[i] = (int) list.get(i);
        }

        return cols;
    }

    // Only called for top node tell whichmove ai should take
    public int getColumn() {
        int[] cols = getAvailCols(board);
        int index = 0;
        int maxScore = Integer.MIN_VALUE;

        for (int i = 0; i < cols.length; i++) {
            if (nodeList.get(i).score() > maxScore) {
                maxScore = nodeList.get(i).score();
                index = i;
            }
        }

        return cols[index];
    }
}

在棋盘阵列中:

  • 0是空格
  • 1是玩家筹码
  • 2是ai的筹码

我已经运行了很多测试但是计算机似乎总是选择最左边的列,即使其他玩家即将获胜也是如此。任何人都可以解释如何解决这个或问题是什么。我目前正在为游戏使用7的深度。

0 个答案:

没有答案