繁体   English   中英

Java中的miniMax算法

[英]miniMax algorithm in Java

我目前对我正在编程的 AI 不满意。 AI 应该在 3x3 棋盘 (TicTacToe) 中的每一步都获得最高分。

可能的分数是 -1(输)、0(平)和 1(赢)。

首先调用方法makeTurn() ,然后调用包含 miniMax 算法的方法。

public void makeTurn(Button[][] currentBoard) {                                                 // Calculating best move using miniMax algorithm
        AIcheck = new Check(currentBoard);
        int bestScore = Integer.MIN_VALUE;
        int[] bestMove = new int[2];
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (currentBoard[i][j].getText().equals("")) {
                    currentBoard[i][j].setText("O");
                    int score = calcScore(currentBoard, 0, false);
                    System.out.println(score);
                    currentBoard[i][j].setText("");
                    if (score > bestScore) {
                        bestScore = score;
                        bestMove = new int[]{i, j};

                    }
                }
            }
        }
        Board.getInstance().getField(bestMove[0], bestMove[1]).performClick();
    }

private int calcScore(Button[][] currentBoard, int depth, boolean isMax) {                      // MiniMax Algorithm, calculating score for each branch via recursive execution
        int score;
        if (AIcheck.checkWin()) {
            return (Util.getInstance().getTurnCounter() % 2) == 0 ? 1 : -1;
        } else if (AIcheck.checkTie()) {
            return 0;
        }
        int bestScore = isMax ? Integer.MIN_VALUE : Integer.MAX_VALUE;
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (currentBoard[i][j].getText().equals("")) {
                    if (isMax) {
                        currentBoard[i][j].setText("O");
                    } else {
                        currentBoard[i][j].setText("X");
                    }
                    score = calcScore(currentBoard, depth + 1, !isMax);
                    currentBoard[i][j].setText("");
                    bestScore = isMax ? Math.max(bestScore, score) : Math.min(bestScore, score);
                }
            }
        }
        return bestScore;
    }

我正在使用isMax来确定是否轮到最大化器,还使用turnCounter % 2来确定轮到哪个玩家,因为他们轮流。

然而,人工智能并没有阻止我的胜利,它更像是从一个领域到下一个领域,而不是选择最佳领域。 我怎样才能正确实现 miniMax 算法? 非常感谢!

例子:

[]|[]|[]

[]|[]|[]

[X]|[]|[]


[O]|[]|[]

[]|[]|[]

[X]|[]|[]


[O]|[]|[]

[]|[]|[]

[X]|[]|[X]


[O]|[O]|[]

[]|[]|[]

[X]|[]|[X]


[O]|[O]|[X]

[]|[]|[]

[X]|[]|[X]


[O]|[O]|[X]

[O]|[]|[]

[X]|[]|[X]


[O]|[O]|[X]

[O]|[X]|[] 我赢了,这也显示了 AI 似乎只是占据了下一个位置(从左到右)

[X]|[]|[X]

我认为问题在于您如何确定谁在calcScore中获胜。 您使用Util.getInstance().getTurnCounter() ,但您似乎没有在递归调用中更新计数器。 您可以改为使用depth % 2isMax

if (AIcheck.checkWin()) {
    return isMax ? -1 : 1;
}

我认为问题是calcScore()中的这一行

if (currentBoard[i][j].getText().equals("")) {

如果板子是空的,你只计算分数,但你总是在调用 function 之前将它设置为“0”,所以 if 的代码块永远不会被执行。

makeTurn()类似,但我猜你是在转弯之间清理木板? 如果不是,您还需要更新它。

编辑:在主要 function 中:

                    currentBoard[i][j].setText("O");
                    int score = calcScore(currentBoard, 0, false);

在计算分数中:

// this will always evaluate to false
if (currentBoard[i][j].getText().equals("")) {

您的bestScore作业有问题。 对于每个空框,您都这样做:

int bestScore = isMax ? Integer.MIN_VALUE : Integer.MAX_VALUE;

如果你这样计算,你总是会得到相同的分数,这可能是它只选择下一个空框的原因。 在极小极大算法中,您需要一种方法来为每个动作分配不同的得分值,以便您可以通过比较找到最佳动作。 在国际象棋游戏或类似的游戏中,这些分数通常是通过一些启发式给出的。 由于您的游戏要简单得多,这应该更容易。 一个简单的解决方案可能是为每个板子 state 分配不同的分数,您可以简单地 select 导致此所需 state 的移动。 您可以轻松地做到这一点,因为这些状态的数量在您的游戏中非常有限。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM