奥赛罗Minimax算法

时间:2016-06-29 18:11:58

标签: algorithm artificial-intelligence

我正在尝试使用Minimax算法为奥赛罗实施人工智能播放器。电脑播放得体,但不是很好。我是否在以下代码中正确实现了它?

Coordinate bestCoordinate = null;
public int minimax(MyButton[][] gameBoard, int depth, boolean maximizingPlayer) {
    if (depth == 0) {
        return evaluateBoard(gameBoard);
    }

    if (maximizingPlayer) {
        int bestValue = Integer.MIN_VALUE;
        LinkedList<Coordinate> moves = generateMoves(gameBoard);
        for (Coordinate move : moves) {
            MyButton[][] newBoard = cloneBoard(gameBoard);
            processMove(newBoard, newBoard[move.getxCoordinate()][move.getyCoordinate()]);
            int v = minimax(newBoard, depth - 1, !maximizingPlayer);
            if (v > bestValue) {
                bestValue = v;
                bestCoordinate = move;
            }
        }
        return bestValue;
    }
    else {
        int bestValue = Integer.MAX_VALUE;
        LinkedList<Coordinate> moves = generateMoves(gameBoard);
        for (Coordinate move : moves) {
            MyButton[][] newBoard = cloneBoard(gameBoard);
            processMove(newBoard, newBoard[move.getxCoordinate()][move.getyCoordinate()]);
            int v = minimax(newBoard, depth - 1, !maximizingPlayer);
            if (v < bestValue) {
                bestValue = v;
                bestCoordinate = move;
            }
        }
        return bestValue;
    }
}

此外,这是我的评估功能:

public int evaluateBoard(MyButton[][] gameBoard) {

    int blackPieces = 0;
    int whitePiecess = 0;

    for (MyButton[] array : gameBoard) {
        for (MyButton button : array) {
            if (button.getBackground().equals(Color.black)) {
                blackPieces++;
            } else if (button.getBackground().equals(Color.WHITE)) {
                whitePiecess++;
            }
        }
    }

    int cornerBonus = 10;
    if (gameBoard[0][0].getBackground().equals(Color.BLACK)) {
        blackPieces += cornerBonus;
    }
    if (gameBoard[0][getBoardWidth() - 1].getBackground().equals(Color.BLACK)) {
        blackPieces += cornerBonus;
    }
    if (gameBoard[getBoardHeight() - 1][0].getBackground().equals(Color.BLACK)) {
        blackPieces += cornerBonus;
    }
    if (gameBoard[getBoardHeight() - 1][getBoardWidth() - 1].getBackground().equals(Color.BLACK)) {
        blackPieces += cornerBonus;
    }
    if (gameBoard[0][0].getBackground().equals(Color.WHITE)) {
        whitePiecess += cornerBonus;
    }
    if (gameBoard[0][getBoardWidth() - 1].getBackground().equals(Color.WHITE)) {
        whitePiecess += cornerBonus;
    }
    if (gameBoard[getBoardHeight() - 1][0].getBackground().equals(Color.WHITE)) {
        whitePiecess += cornerBonus;
    }
    if (gameBoard[getBoardHeight() - 1][getBoardWidth() - 1].getBackground().equals(Color.WHITE)) {
        whitePiecess += cornerBonus;
    }
    return whitePiecess - blackPieces;
}

(电脑总是白色,人是黑色)。 我主要不确定,因为尽管他们给出了奖励积分,但计算机似乎并没有保护角落。我的代码/逻辑有什么问题吗?

2 个答案:

答案 0 :(得分:0)

您正在更新每个深度的最佳动作。在函数之外创建一个名为SEARCH_DEPTH的常量,每次调用该函数时都会使用该常量并执行if检查:

if(depth == SEARCH_DEPTH) {
    bestCoordinate = move;
}

另外,假设您是最大化玩家,您只想在if(maximizingPlayer)区块中设置移动。

答案 1 :(得分:0)

我没有亲自测试您的代码,但这是minimax算法,它似乎编写正确(假设您的辅助函数正确实现)。我的一些观点可能会为您提供有关代理商为何无法发挥最佳作用的见解:

  1. 我看到您的目标函数是代理人拥有的棋子数减去对手的棋子数,再加上角球数的加成。这似乎是最好的策略,但我会仔细阅读奥赛罗球员的出色举动。通常,他们会尽量只翻动一件,直到比赛后期,因为这样有更多的机会。
  2. Minimax不一定会返回导致捕捉角点的动作,即使您权衡得太重,也可能会因为对手选择的动作而被破坏。例如,假设您的算法比计算机的转弯提前3圈,因此它首先查看的状态是捕获具有高目标函数的角。但是,您的对手将选择使目标功能最小化的路线,因此,由于存在风险,计算机不会将捕获角点的动作视为最佳。我不知道这有多容易,但是如果您能以某种方式可视化该树,则可能可以弄清楚是否是这种情况。