首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >我的Tic Tac Toe AI怎么了?

我的Tic Tac Toe AI怎么了?
EN

Stack Overflow用户
提问于 2017-01-16 20:01:22
回答 2查看 170关注 0票数 1

我读了一篇关于minimax的教程,并尝试做一个tac tac toe AI。但由于某些原因,代码并不能以最佳方式工作,这一点我找不到。人工智能可以放置棋子,但它不是智能人工智能。我原以为它是无敌的。深度越高,ai变得越迟钝。“游戏”是我的另一个类,也就是真正的游戏。

代码语言:javascript
运行
复制
private Game game;
private Piece[][] board;
private Piece ai = Piece.CIRCLE;
private Piece player = Piece.CROSS;

public AI(Game game) {
    this.game = game;
    this.board = game.getBoard();

}

public int[] move() {
    int[] result = minimax(1, ai);

    return new int[] {result[1], result[2]};
}

private int[] minimax(int depth, Piece piece) {
    List<int[]> possibleMoves = generateMoves();

    int bestScore = (piece == ai) ? Integer.MIN_VALUE : Integer.MAX_VALUE;
    int currentScore;
    int bestRow = -1;
    int bestCol = -1;

    if (possibleMoves.isEmpty() || depth == 0) {
        // Game over or depth reached
        bestScore = evaluate();
    }
    else {
        for (int[] move : possibleMoves) {
            // Try this move for the player
            board[move[0]][move[1]] = player;
            if (piece == ai) { // ai is maximizing player
                currentScore = minimax(depth - 1, player)[0];

                if (currentScore > bestScore) {
                    bestScore = currentScore;
                    bestRow = move[0];
                    bestCol = move[1];
                }
            }
            else { // player is minimizing player
                currentScore = minimax(depth - 1, ai)[0];

                if (currentScore < bestScore) {
                    bestScore = currentScore;
                    bestRow = move[0];
                    bestCol = move[1];
                }
            }

            // Undo move
            board[move[0]][move[1]] = null;
        }
    }

    return new int[] {bestScore, bestRow, bestCol};
}

private List<int[]> generateMoves() {
    List<int[]> possibleMoves = new ArrayList<int[]>();

    // If game over
    if (game.getWinner() != null) {
        return possibleMoves; // return empty list
    }

    // Add possible moves to list
    for (int x = 0; x < 3; x++) {
        for (int y = 0; y < 3; y++) {
            if (game.getBoard()[x][y] == null) {
                possibleMoves.add(new int[] {x, y});
            }
        }
    }

    return possibleMoves;
}

private int evaluate() {        
    int score = 0;
    // Evaluate
    score += evaluateLine(0, 0, 0, 1, 0, 2); // row 0
    score += evaluateLine(1, 0, 1, 1, 1, 2); // row 1
    score += evaluateLine(2, 0, 2, 1, 2, 2); // row 2
    score += evaluateLine(0, 0, 1, 0, 2, 0); // col 0
    score += evaluateLine(0, 1, 1, 1, 2, 1); // col 0
    score += evaluateLine(0, 2, 1, 2, 2, 2); // col 0
    score += evaluateLine(0, 0, 1, 1, 2, 2); // diag 1
    score += evaluateLine(0, 2, 1, 1, 2, 0); // diag 2

    return score;
}

// Return +100, +10, +1 for 3-, 2-, 1-in-a-line for ai
// Return -100, -10, -1 for 3-, 2-, 1-in a line for player
// Else return 0
private int evaluateLine(int row1, int col1, int row2, int col2, int row3, int col3) {
    int score = 0;

    // First cell
    if (board[row1][col1] == ai) {
        score = 1;
    }
    else if (board[row1][col1] == player) {
        score = -1;
    }

    // Second cell
    if (board[row2][col2] == ai) {
        if (score == 1) { // board1 is ai
            score = 10;
        }
        else if (score == -1) { // board1 is player
            return 0;
        }
        else { // board1 is empty
            score = 1;
        }
    }
    else if (board[row2][col2] == player) {
        if (score == -1) { // board1 is player
            score = -10;
        }
        else if (score == 1) { // board1 is ai
            return 0;
        }
        else { // board1 is empty
            score = -1;
        }
    }

    // Third cell
    if (board[row3][col3] == ai) {
        if (score > 0) { // board1 and/or board2 is ai
            score *= 10;
        }
        else if (score < 0) { // board1 and/or board2 is player
            return 0;
        }
        else { // board1 and/or board2 is empty
            score = 1;
        }
    }
    else if (board[row3][col3] == player) {
        if (score < 0) { // board1 and/or board2 is player
            score *= 10;
        }
        else if (score > 1) { // board1 and/or board2 is ai
            return 0;
        }
        else { // board1 and/or board2 is empty
            score = -1;
        }
    }

    return score;
}
EN

回答 2

Stack Overflow用户

发布于 2017-01-16 21:19:31

我注意到了几件事:

  • ,循环中的第一行,经历了可能的移动,board[move[0]][move[1]] = player;说。这应该是piece而不是player,现在你的AI认为只有人类玩家的一部分才会出现在棋盘上。
  • Minimax应该很容易在不到一秒的时间内搜索完整的游戏树。因此,我建议允许搜索到它喜欢的深度,而不是限制搜索深度为1。这也消除了创建启发式评估函数的需要;您只需为获胜给出一个很大的分数,为平局给出0分,为输给一个非常负的分数。我建议这样做的主要原因是,我怀疑评估函数也可能有问题,尽管我不确定,因为我没有详细检查它。如果您确实坚持要提前终止搜索并使用启发式求值函数,则需要确保该函数是“对称的”。我的意思是,从一个玩家的角度评估棋盘应该总是导致从对手的角度评估同一棋盘的分数的-1倍。
票数 3
EN

Stack Overflow用户

发布于 2017-01-16 20:29:24

minimax根据行/列对返回移动,而不是分数。所以

代码语言:javascript
运行
复制
currentScore = minimax(depth - 1, player)[0];

这没有任何意义。它可能会导致移动到第3行的效果比移动到第1行或第2行的任何移动更好。

minmax需要亲自动手

除了最好的走法之外,后退一分。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41675984

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档