0

我正在尝试使用 minimax 算法在 java 中实现连接 4 的计算机 AI 版本。对于该任务,我创建了一个“节点”类,它以单个板状态开始,然后递归地创建更多节点,直至指定深度。然后它给每个节点打分,1 分表示胜利,0 分表示平局或最大深度。最后,我使用极小极大算法来选择要在函数“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];
    }
}

在板阵列中:

  • 0s 是空白空间
  • 1s 是玩家的筹码
  • 2s是ai的筹码

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

4

0 回答 0