当前位置: 首页 > 知识库问答 >
问题:

Tic-Tac-Toe中的Java Alpha-Beta修剪

马安邦
2023-03-14

我有一个Tic Tac Toe游戏,它使用了极大极小算法。我想通过添加alpha-beta修剪来改进这一点。然而,阿尔法-贝塔法似乎无法有效地计算移动。它只是把它的一块放在下一个可用的空间里,不管它是不是最佳的移动。我对极小极大法没有这个问题。我确信这是我一直忽略的一些简单的事情,所以请原谅我。我用这个教程来学习minimax,用这个教程来学习alpha-beta修剪。

这是极小极大类。它包括阿尔法-贝塔法:

public class Minimax {

    private Token playerToken;
    private EndStates endStates;
    private Token opponentToken;

    public Minimax(Token playerToken, EndStates endStates) {
        this.playerToken = playerToken;
        this.endStates = endStates;
        opponentToken = makeOpponentToken();
    }

    public Token makeOpponentToken() {
        if (playerToken == Token.O) {
            return Token.X;
        }
        else {
            return Token.O;
        }
    }

    public Token getOpponentToken() {
        return opponentToken;
    }

    public int evaluate(Cell[] board) {
        //rows across
        if (endStates.checkWinByRow(board, playerToken) || endStates.checkWinByColumn(board, playerToken) || endStates.checkWinByDiagonal(board, playerToken)) {
            return 10;
        }
        else if (endStates.checkWinByRow(board, opponentToken) || endStates.checkWinByColumn(board, opponentToken) || endStates.checkWinByDiagonal(board, opponentToken)) {
            return -10;
        }

        return 0;
    }

    public boolean hasCellsLeft(Cell[] board) {
        for (int i=0; i<board.length; i++) {
            if (board[i].getToken() == Token.EMPTY) {
                return true;
            }
        }
        return false;
    }

    int MAX = 1000;
    int MIN = -1000;

    public int alphaBeta(Cell[] board, int depth, boolean isMax, int alpha, int beta) {
        int score = evaluate(board);
        if (score == 10) {
            return score;
        }

        if (score == -10) {
            return score;
        }
        if (hasCellsLeft(board) == false) {
            return 0;
        }
        if (isMax) {
            int best = MIN;
            for (int i=0; i<board.length; i++) {
                if (board[i].getToken() == Token.EMPTY) {
                    board[i].setToken(playerToken);
                    int val = alphaBeta(board,depth+1, !isMax, alpha, beta);
                    best = Math.max(best, val);
                    alpha = Math.max(alpha, best);
                    board[i].resetMarker();
                }
                 if (best <= alpha) {
                    break;
                }
            }
            return best;
        }
        else {
            int best = MAX;
            for (int i=0; i<board.length; i++) {
                if (board[i].getToken() == Token.EMPTY) {
                    board[i].setToken(playerToken);
                    int val = alphaBeta(board, depth+1, isMax, alpha, beta);
                    best = Math.min(best, val);
                    beta = Math.min(beta, best);
                    board[i].resetMarker();
                }
                if (beta <= alpha) {
                    break;
                }
            }
            return best;
        }
    }

    public int minimax(Cell[] board,  int depth, boolean isMax) {
        int score = evaluate(board);
        int best;

        if (score == 10) {
            return score;
        }

        if (score == -10) {
            return score;
        }
        if (hasCellsLeft(board) == false) {
            return 0;
        }
        if (isMax) {
            best = -1000;
            for (int i=0; i<board.length; i++) {
                if (board[i].getToken() == Token.EMPTY) {
                    board[i].setToken(playerToken);
                    best = Math.max(best, minimax(board, depth+1, !isMax));
                    board[i].resetMarker();
                }
            }
            return best;
        }
        else {
            best = 1000;
            for (int i=0; i<board.length; i++) {
                if (board[i].getToken() == Token.EMPTY) {
                    board[i].setToken(opponentToken);
                    best = Math.min(best, minimax(board, depth+1, !isMax));
                    board[i].resetMarker();
                }
            }
            return best;
        }
    }

    public int findBestMove(Cell[] board) {
        int bestValue = -1000;
        int bestMove = -1;
        for (int i=0; i<board.length; i++) {
            if (board[i].getToken() == Token.EMPTY) {
                board[i].setToken(playerToken);
                //int moveValue = minimax(board, 0, false);
                int moveValue = alphaBeta(board, 0, true, -1000, 1000);
                board[i].resetMarker();
                if (moveValue > bestValue) {
                    bestMove = i;
                    bestValue = moveValue;
                }
            }
        }
        return bestMove;
    }
}

该板是一个由9组成的数组,其中包含Token的枚举值。空,但可以用Token替换。X或Token。O分别。

这是调用使用算法的类:

public class ComputerPlayer(Token token, Algorithm minimax ) {
   private Token playerToken;
   private Algorithm minimax;

    public ComputerPlayer(Token playerToken, Algorithm minimax) {
        this.playerToken = playerToken;
        this.minimax = minimax;
    }

    public Token getPlayerToken() {
        return playerToken;
    }

   public void makeMove(Cell[] board) {
        int chosenCell;
        chosenCell = minimax.findBestMove(board);
        board[chosenCell].setToken(playerToken);
        System.out.println("Player " + playerToken + " has chosen cell " + (chosenCell+1));
    }
}

共有1个答案

谭曦
2023-03-14

Alpha-Beta修剪需要一个好的评估函数,以使未完成的游戏状态有效。它应该能够评估一个玩家何时“更有可能”准确获胜。它将使用评估来删减看起来没有希望的变化。

现在,您的评估函数只区分游戏结束和游戏进行中,所以您将无法比min-max做得更好。

然而,如果你做得比min-max差,你肯定在其他地方也有bug。我建议您仔细检查一下代码,看看哪里出了问题。

 类似资料:
  • 首先,我是java的初学者,我正在尝试模拟TicTacToe游戏。我想使用游戏树为所有状态创建一个可能的树。树中的每个节点都将代表状态并使用此树来决定下一步要做的事情。我计划按如下方式进行, > 接口类包括表示单个移动所需的信息。 抽象/接口类包括以下方法: a、 返回一个新的状态对象,该对象表示应用该移动后游戏的状态。 B.如果当前状态代表其中一名玩家的胜利,则此游戏的获胜者ID。 c、 返回当

  • 我该怎么做? 下面是我的代码:

  • 对角线从右到左 在这里,支票中奖者代码结束。

  • 我一直在更新我在网上找到的一个有点过时的tic-tac-toe代码(好像它现在真的可以工作了:P)。我的代码几乎完成了,但我一直有一个相同的问题。tic tac趾板内的3x3按钮工作完美,除了一件事,它们被点击后的颜色始终是背景,我尝试过纠正这一点,但它所做的只是使按钮完全不改变颜色。这两种颜色是红色和绿色,我希望这样,当每个玩家点击一个按钮,它会改变他们的颜色。 主要游戏代码:

  • 我正在写一个井字游戏,“编码规则”的一部分是应该有一个“checkwin”函数来查看玩家是否赢了。我定义了两个名为“tttXArray”和“tttOArray”的变量,以查看一个玩家是否连续获得三个水平,垂直或对角线输入。这是以 tttXArray 为例放置的函数: Checkwin是time循环的一部分: 我得到的错误是: 问题是什么?