You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java实现智能TicTacToe对手:求playSmart方法实现思路

Hey there! 作为Java初学者能搞定随机对手的井字棋,已经超棒了👏 其实实现playSmart方法不用一开始就想复杂,咱们可以从「基础逻辑」到「进阶智能」一步步来,我给你拆解清楚:

第一步:先保赢,再防输(最核心的基础逻辑)

这是智能对手最基础的判断逻辑,优先级最高:

  • 先检查自己能不能赢:遍历棋盘上所有空位,模拟自己落子,如果落子后能形成三子连线(横、竖、斜),直接选这个位置落子——这是赢的唯一机会,必须优先。
  • 再检查对手能不能赢:如果自己没机会赢,就模拟对手在每个空位落子,如果对手落子后能赢,立刻堵住这个位置——避免直接输掉游戏。

代码示例(核心片段)

首先你需要一个判断胜负的辅助方法:

// 判断指定玩家是否获胜
private boolean checkWin(char[][] board, char player) {
    // 检查横、竖、斜三个方向
    return (board[0][0] == player && board[0][1] == player && board[0][2] == player) ||
           (board[1][0] == player && board[1][1] == player && board[1][2] == player) ||
           (board[2][0] == player && board[2][1] == player && board[2][2] == player) ||
           (board[0][0] == player && board[1][0] == player && board[2][0] == player) ||
           (board[0][1] == player && board[1][1] == player && board[2][1] == player) ||
           (board[0][2] == player && board[1][2] == player && board[2][2] == player) ||
           (board[0][0] == player && board[1][1] == player && board[2][2] == player) ||
           (board[0][2] == player && board[1][1] == player && board[2][0] == player);
}

然后在playSmart里实现赢/防逻辑:

public int[] playSmart(char[][] board) {
    char self = 'X'; // 假设自己是X,对手是O,根据你的实际代码调整
    char opponent = 'O';

    // 1. 检查自己是否有必胜位置
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            if (board[i][j] == ' ') { // 空位
                board[i][j] = self;
                if (checkWin(board, self)) {
                    board[i][j] = ' '; // 回溯恢复棋盘
                    return new int[]{i, j}; // 返回必胜位置
                }
                board[i][j] = ' '; // 回溯
            }
        }
    }

    // 2. 检查对手是否有必胜位置,堵住它
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            if (board[i][j] == ' ') {
                board[i][j] = opponent;
                if (checkWin(board, opponent)) {
                    board[i][j] = ' ';
                    return new int[]{i, j}; // 返回堵位
                }
                board[i][j] = ' ';
            }
        }
    }

    // 后续逻辑往下加...
}
第二步:抢占关键位置(提升胜率的小技巧)

如果当前没有赢或输的紧急情况,就按优先级抢占井字棋里的「黄金位置」:

  • 中心位置:(1,1)(0索引),这个位置能参与4条连线(横、竖、两个斜),胜率最高,优先抢。
  • 四个角落:(0,0)、(0,2)、(2,0)、(2,2),每个角落能参与3条连线,优先级次之。
  • 边位:剩下的四个边中点,优先级最低。

代码续接

在刚才的playSmart方法里继续加:

// 3. 抢占中心位置
    if (board[1][1] == ' ') {
        return new int[]{1, 1};
    }

    // 4. 抢占四个角落
    int[][] corners = {{0,0}, {0,2}, {2,0}, {2,2}};
    for (int[] corner : corners) {
        if (board[corner[0]][corner[1]] == ' ') {
            return corner;
        }
    }

    // 5. 抢占边位
    int[][] edges = {{0,1}, {1,0}, {1,2}, {2,1}};
    for (int[] edge : edges) {
        if (board[edge[0]][edge[1]] == ' ') {
            return edge;
        }
    }

    // 如果棋盘满了(理论上不会走到这)
    return null;

到这一步,你的playSmart已经是一个相当不错的智能对手了,大部分情况下不会输,还能主动赢。

第三步:进阶智能——Minimax算法(实现完美对手)

如果想做一个永远不会输的完美对手,就可以用Minimax算法——这是博弈论里的经典算法,通过递归模拟所有可能的走法,评估每个走法的得分,选择最优解。

核心思路

  • 给每个棋盘状态打分:自己赢了得+10,输了得-10,平局得0。
  • 递归遍历所有可能的走法,自己(Max玩家)选择得分最高的走法,对手(Min玩家)选择得分最低的走法。
  • 可以加上Alpha-Beta剪枝优化,减少递归次数(初学者可以先实现基础版)。

代码示例(基础Minimax)

先加两个辅助方法:

// 判断棋盘是否已满
private boolean isBoardFull(char[][] board) {
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            if (board[i][j] == ' ') {
                return false;
            }
        }
    }
    return true;
}

// Minimax核心方法
private int minimax(char[][] board, boolean isMaximizing) {
    char self = 'X';
    char opponent = 'O';

    // 先判断当前状态的得分
    if (checkWin(board, self)) return 10;
    if (checkWin(board, opponent)) return -10;
    if (isBoardFull(board)) return 0;

    if (isMaximizing) {
        // 自己走,选最大得分
        int bestScore = Integer.MIN_VALUE;
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (board[i][j] == ' ') {
                    board[i][j] = self;
                    int score = minimax(board, false);
                    board[i][j] = ' '; // 回溯
                    bestScore = Math.max(score, bestScore);
                }
            }
        }
        return bestScore;
    } else {
        // 对手走,选最小得分
        int bestScore = Integer.MAX_VALUE;
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (board[i][j] == ' ') {
                    board[i][j] = opponent;
                    int score = minimax(board, true);
                    board[i][j] = ' ';
                    bestScore = Math.min(score, bestScore);
                }
            }
        }
        return bestScore;
    }
}

然后修改playSmart方法,调用Minimax选择最优位置:

public int[] playSmart(char[][] board) {
    char self = 'X';
    int bestScore = Integer.MIN_VALUE;
    int[] bestMove = null;

    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            if (board[i][j] == ' ') {
                board[i][j] = self;
                int score = minimax(board, false);
                board[i][j] = ' ';
                if (score > bestScore) {
                    bestScore = score;
                    bestMove = new int[]{i, j};
                }
            }
        }
    }
    return bestMove;
}

这样实现的对手就是完美的——要么赢,要么平局,永远不会输。

小提示

作为初学者,建议先把前两步的基础逻辑写通、测试好,再尝试Minimax算法,因为递归逻辑需要花点时间理解。

内容的提问来源于stack exchange,提问作者PCorral

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:02:49