news 2026/9/2 2:29:20

Minmax算法实战:从井字棋到五子棋AI的本地部署

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Minmax算法实战:从井字棋到五子棋AI的本地部署

之前接触过一个博弈类项目,当时为了给棋类对战加一个“有点水平”的电脑对手,我尝试了随机落子、贪心评分、蒙特卡洛模拟,效果都不理想。后来把算法换成 Minmax,配合 Alpha-Beta 剪枝后,AI 的棋力直接从“乱走”提升到“能预判两三步”。最近看到社区里有人在讨论 minmax 以及 minmax h3 本地部署,很多初学者对“Minmax 到底是什么、怎么落地、怎么优化”还没建立完整认知。本文就围绕 Minmax 展开,从算法原理讲到完整实战,再讲如何把 AI 封装成本地可调用的服务,全程附上可运行的代码和排错思路。

本文适合有 Python 基础、想入门博弈搜索算法,或者想在本地服务器/开发机上部署 AI 对战服务的开发者。学完后你可以:写出一个井字棋 AI、一个可调搜索深度的五子棋 AI,并且能把它们封装成 HTTP 服务,供前端或客户端调用。代码均以常见 Python 环境为例,版本差异会在文中说明。

1. 什么是 Minmax 算法

1.1 从博弈场景理解 Minmax

Minmax(极大极小算法)是博弈论和人工智能中的经典搜索算法,常用于零和博弈场景,例如井字棋、五子棋、国际象棋、围棋等。所谓“零和博弈”,简单说就是一方得分增加,另一方必然损失相同分数,不存在“双赢”局面。

在棋类游戏中,Minmax 的核心思想是:当前玩家落子时,假设对手和自己一样聪明,双方都会选择对自己最有利、对对方最不利的一步。于是 AI 在搜索未来的棋局时,会交替使用“取最大值”和“取最小值”的思路。轮到 AI 行棋时,它从所有候选走法中选择评估分数最高的一步;轮到对手行棋时,它假设对手会选择让 AI 分数最低的一步。

这种“我下一步,你下一步”的思考方式,本质上是在一棵博弈树上做深度优先搜索。树的根节点是当前棋局,每个分支代表一步走法,叶子节点代表游戏结束或达到搜索深度上限。Minmax 就是从叶子节点向上回溯,逐层计算出每个节点的“理论最优值”。

需要注意的是,Minmax 假设双方都是理性且信息完全的。如果对手水平不高,AI 可能“过度防御”,导致它面对弱手时表现并不激进。这是算法本身的特性,不是代码 bug。

1.2 极大极小值的数学直觉

用数学方式描述 Minmax 的话,可以这样看:假设当前局面是 S,玩家 A 是 Max 方,玩家 B 是 Min 方。轮到 Max 走时,它会选择让评估函数值最大的走法;轮到 Min 走时,它会选择让评估函数值最小的走法。

用伪代码表示就是:

function minmax(node, depth, maximizingPlayer): if depth == 0 or node is terminal: return evaluate(node) if maximizingPlayer: maxValue = -infinity for child in node.children(): maxValue = max(maxValue, minmax(child, depth-1, False)) return maxValue else: minValue = +infinity for child in node.children(): minValue = min(minValue, minmax(child, depth-1, True)) return minValue

这个递归过程会一直进行到游戏结束或达到设定的搜索深度。搜索深度越深,AI 的“远见”越强,但计算量也越大。如果没有 Alpha-Beta 剪枝等优化手段,Minmax 的时间复杂度是 O(b^d),其中 b 是分支因子(平均可选走法数),d 是搜索深度。

1.3 Minmax 的适用边界

Minmax 不是万能的。它适合状态空间相对可控、评估函数容易定义的场景。对于井字棋这样棋盘只有 3x3 的游戏,Minmax 可以直接搜索到终局,AI 能做到不败。对于五子棋,棋盘 15x15,搜索深度稍微加深,计算量就会指数增长,必须依赖评估函数和剪枝。

对于围棋这类状态空间极大的棋类,纯 Minmax 基本不可行,通常要结合蒙特卡洛树搜索(MCTS)和神经网络。因此,本文的实战部分会选择井字棋和五子棋两个落地场景,让你清晰看到 Minmax 的能力边界在哪里。

2. 环境准备与版本说明

2.1 运行环境

本文示例代码使用 Python 3 编写,不依赖第三方游戏引擎。为了让 AI 服务化,会用到 Flask。版本需要根据你的实际环境调整,本文以常见环境为例,重点演示配置思路。

项目建议环境
操作系统Windows 10/11、Ubuntu 20.04+、macOS
Python3.8 及以上
依赖库Flask 2.x
调用测试curl 或 Postman

安装 Flask 的命令如下:

pip install flask

如果使用虚拟环境,可以这样初始化:

python -m venv venv # Windows venv\Scripts\activate # Linux/macOS source venv/bin/activate pip install flask

2.2 关于 minmax h3 本地部署的说明

在社区讨论里,“minmax h3 本地部署”中的 H3 并没有统一定义,有的场景指轻量级开发设备型号,有的场景指某种三层部署结构。本文不依赖任何特定硬件或平台,只要你的本机具备 Python 运行环境,就能完成演示。

如果你手上的设备型号正好叫 H3,部署思路完全一致:先在设备上安装 Python,再把代码放到指定目录,最后启动 Flask 服务即可。注意不要因为设备架构是 ARM 或 x86 不同而担心,Python 的跨平台特性可以让你直接运行本文代码。

2.3 项目结构

为了保持代码清晰,建议按下面的目录结构组织项目:

minmax-tutorial/ ├── tictactoe.py # 井字棋 AI 实现 ├── gomoku.py # 五子棋 AI 实现 ├── server.py # Flask 服务入口 └── requirements.txt # 依赖清单

requirements.txt 内容如下:

flask==2.3.3

后续所有代码都按这个结构编写,方便你对照文件路径查找。

3. Minmax 算法核心原理拆解

3.1 博弈树与胜负评估

博弈树是 Minmax 搜索的“地图”。以井字棋为例,一盘对局从空棋盘开始,双方轮流落子,每一步都会产生新的局面。把所有可能局面按先后手关系连接起来,就形成了一棵博弈树。

树的节点存储棋盘状态,边代表一次落子。搜索时,我们需要一个评估函数,用来给某个局面打分:

  • 正数表示当前 AI 方占优。
  • 负数表示当前 AI 方处于劣势。
  • 0 表示势均力敌。

如果是终端局面,比如 AI 获胜,评估分数可以设为 +1000;对手获胜设为 -1000;平局设为 0。如果搜索没有到达终局,就需要根据棋子分布设计一个“启发式评估”,在 5.1 节会展开。

3.2 递归实现 Minmax

了解原理后,先来看一个最基础的 Minmax 递归实现。这个版本不包含剪枝,逻辑最直白,适合理解算法骨架。

# 文件路径:minmax-tutorial/minmax_basic.py import math def minmax(board, depth, is_maximizing): """ board 是当前局面(列表表示), is_maximizing 为 True 表示当前轮到 Max 方。 """ winner = check_winner(board) if winner == "X": return 10 - depth elif winner == "O": return depth - 10 elif is_full(board): return 0 if is_maximizing: best = -math.inf for move in empty_cells(board): board[move] = "X" best = max(best, minmax(board, depth + 1, False)) board[move] = None return best else: best = math.inf for move in empty_cells(board): board[move] = "O" best = min(best, minmax(board, depth + 1, True)) board[move] = None return best

这里使用深度因子调整胜负分数,意味着越快获胜的路径分数越高,越快输掉的路径分数越低。下面解释几个关键点:

  1. check_winner(board)判断是否有人获胜。
  2. is_full(board)判断棋盘是否下满,用于识别平局。
  3. board[move] = None是回溯操作,恢复棋盘状态,让下一次递归搜索不受干扰。

3.3 负极大值 Negamax 简化实现

Minmax 的代码需要区分 Max 方和 Min 方,逻辑有些冗余。Negamax(负极大值算法)利用“一方的最优值等于另一方最优值的相反数”的性质,用同一套逻辑处理双方节点,让代码更简洁。

# 文件路径:minmax-tutorial/negamax_basic.py import math def negamax(board, depth, player): winner = check_winner(board) if winner == player: return 10 - depth elif winner == opponent(player): return depth - 10 elif is_full(board): return 0 best = -math.inf for move in empty_cells(board): board[move] = player value = -negamax(board, depth + 1, opponent(player)) board[move] = None best = max(best, value) return best

Negamax 代码比 Minmax 更短,但需要理解“负号取反”的含义:对对手有利的局面,对当前玩家一定是不利的,所以取负值即可。

3.4 Alpha-Beta 剪枝优化

Minmax 最严重的问题是效率低。井字棋还好,五子棋每层可能有几十个分支,搜索深度稍微加深就会卡死。Alpha-Beta 剪枝能在不影响最终结果的前提下,剪掉大量“没必要搜索”的分支。

剪枝思路可以这样记忆:

  • Alpha 表示 Max 方当前已经确保的最低分数。
  • Beta 表示 Min 方当前已经确保的最高分数。
  • 在搜索过程中,如果某个节点的分数已经比 Alpha 更差,Max 方不会选择它;如果比 Beta 更好,Min 方不会允许它出现。

一旦出现 Alpha >= Beta,就可以停止搜索当前节点。

# 文件路径:minmax-tutorial/alphabeta.py import math def alphabeta(board, depth, alpha, beta, is_maximizing): winner = check_winner(board) if winner == "X": return 10 - depth elif winner == "O": return depth - 10 elif is_full(board): return 0 if is_maximizing: best = -math.inf for move in empty_cells(board): board[move] = "X" best = max(best, alphabeta(board, depth + 1, alpha, beta, False)) board[move] = None alpha = max(alpha, best) if beta <= alpha: break return best else: best = math.inf for move in empty_cells(board): board[move] = "O" best = min(best, alphabeta(board, depth + 1, alpha, beta, True)) board[move] = None beta = min(beta, best) if beta <= alpha: break return best

Alpha-Beta 剪枝的搜索效率与节点排列顺序强相关。如果优先搜索“比较好的走法”,剪枝效果会更明显,这一点在 8.2 节会继续讨论。

4. 实战:井字棋 AI 的完整实现

4.1 棋盘状态设计与胜负判断

井字棋棋盘是一个包含 9 个位置的列表,索引 0-8 对应 3x3 棋盘的九个格子。玩家为 “X”,AI 为 “O”,空格用 None 表示。

# 文件路径:minmax-tutorial/tictactoe.py import math def check_winner(board): lines = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6] ] for a, b, c in lines: if board[a] is not None and board[a] == board[b] == board[c]: return board[a] return None def is_full(board): return all(cell is not None for cell in board) def empty_cells(board): return [i for i, cell in enumerate(board) if cell is None]

这里的胜负判断覆盖了所有横、竖、对角线的三连情况。is_full用 all() 判断所有格子是否非空,逻辑简洁。

4.2 评估函数

评估函数的作用是把局面转换为数值。井字棋可以直接用胜负结果作为评估值,因为搜索深度到达终端局面时,结果已经确定。

在递归函数中,设定:

  • AI(“O”)获胜返回depth - 10,越小越好?这里要注意:我们最终取最小值还是最大值,取决于谁在搜索。
  • 玩家(“X”)获胜返回10 - depth
  • 平局返回 0。

由于搜索函数使用统一的分数方向,我们直接把谁轮到谁走作为参数传入,确保 AI 会尽量选择“自己获胜”且“越快越好”的路径。

4.3 Minmax 搜索核心代码

这里采用 Negamax 风格实现,便于简化双方逻辑:

# 文件路径:minmax-tutorial/tictactoe.py def opponent(player): return "X" if player == "O" else "O" def evaluate(board, depth, player): winner = check_winner(board) if winner == player: return 10 - depth elif winner == opponent(player): return depth - 10 return 0 def negamax(board, depth, player, alpha, beta): score = evaluate(board, depth, player) if score != 0 or is_full(board): return score best = -math.inf for move in empty_cells(board): board[move] = player value = -negamax(board, depth + 1, opponent(player), -beta, -alpha) board[move] = None best = max(best, value) alpha = max(alpha, value) if alpha >= beta: break return best

这里把 Alpha-Beta 剪枝与 Negamax 合在了一起。注意在递归调用时,alphabeta要取相反数并交换位置,这是 Negamax 写剪枝的常用方式。

4.4 人机对战入口

为了让玩家和 AI 对战,需要实现一个函数来选择 AI 的最佳落子位置。

# 文件路径:minmax-tutorial/tictactoe.py def best_move(board, player): best_score = -math.inf move = None for cell in empty_cells(board): board[cell] = player score = -negamax(board, 1, opponent(player), -math.inf, math.inf) board[cell] = None if score > best_score: best_score = score move = cell return move def print_board(board): symbols = [cell if cell is not None else " " for cell in board] for row in range(3): print("|".join(symbols[row * 3: row * 3 + 3])) if row != 2: print("-----") def play_game(): board = [None] * 9 human = "X" ai = "O" current = human while True: print_board(board) if check_winner(board): print("获胜方:", check_winner(board)) break if is_full(board): print("平局") break if current == human: try: cell = int(input("请输入落子位置(0-8): ")) if board[cell] is not None: print("该位置已有棋子,请重新输入") continue board[cell] = human except (ValueError, IndexError): print("输入不合法,请输入 0-8 之间的整数") continue else: cell = best_move(board, ai) board[cell] = ai print("AI 落子:", cell) current = opponent(current) if __name__ == "__main__": play_game()

4.5 运行与验证

在项目目录下运行:

python tictactoe.py

效果如下:

| | ----- | | ----- | | 请输入落子位置(0-8): 0 AI 落子: 4 X| | ----- |O| ----- | |

AI 会选择中心位置,这是井字棋中最优的开局应对方式。如果你继续测试,会发现无论如何都不会输,最多平局。这是因为井字棋的状态空间很小,Minmax 配合 Alpha-Beta 剪枝可以在毫秒级完成全深度搜索。

5. 升级实战:五子棋 AI 与评估函数

5.1 五子棋评估思路

五子棋的棋盘比井字棋大得多,15x15 棋盘有 225 个交叉点,不可能搜索到终局。因此需要设计一个启发式评估函数,在搜索深度受限时对局面打分。

常见做法是“连线评分”:对每个位置,分别检查四个方向(横、竖、两个对角线),统计以该位置为起点的连续同色棋子数量,以及两端是否被堵住。比如:

  • 活四:两端都开放的四个连续棋子,评分最高。
  • 冲四:一端被堵的四个连续棋子,评分很高。
  • 活三:两端都开放的三个连续棋子,评分较高。
  • 眠三:一端被堵的三个连续棋子,评分较低。

评估函数会计算 AI 所有方向的分数总和,再减去对手所有方向的分数总和,得到一个相对优势值。这种“自己进攻分数减去对手进攻分数”的思路,能让 AI 既会进攻又会防守。

5.2 搜索层数与性能

五子棋每个节点的平均可选分支数大约有几十个,如果搜索深度设为 4,计算量可能在数万到数十万级别,配合 Alpha-Beta 剪枝,单步可在可接受时间内完成。

建议先把搜索深度设为 2,验证 AI 是否具备基本防守能力,再逐步增加到 4。如果发现响应太慢,可以优先优化走法排序,把评估分数高的走法排在前面搜索,剪枝效率会显著提升。

5.3 核心代码

下面是一个简化版五子棋 AI 的核心代码,重点展示评估函数和搜索框架。

# 文件路径:minmax-tutorial/gomoku.py import math SIZE = 15 EMPTY = 0 BLACK = 1 # AI WHITE = 2 # 玩家 def init_board(): return [[EMPTY for _ in range(SIZE)] for _ in range(SIZE)] def in_board(x, y): return 0 <= x < SIZE and 0 <= y < SIZE def get_line_score(board, x, y, dx, dy, player): count = 1 blocked = 0 for sign in (1, -1): for step in range(1, 5): nx, ny = x + sign * step * dx, y + sign * step * dy if not in_board(nx, ny): blocked += 1 break if board[nx][ny] == player: count += 1 elif board[nx][ny] == EMPTY: break else: blocked += 1 break return count, blocked def evaluate_position(board, x, y, player): score = 0 opponent_player = WHITE if player == BLACK else BLACK for dx, dy in [(1, 0), (0, 1), (1, 1), (1, -1)]: count, blocked = get_line_score(board, x, y, dx, dy, player) if blocked == 0: if count >= 5: score += 10000 elif count == 4: score += 1000 elif count == 3: score += 100 elif count == 2: score += 10 else: if count >= 5: score += 8000 elif count == 4: score += 500 elif count == 3: score += 50 # 对手同样位置的威胁,AI 需要防守 count2, blocked2 = get_line_score(board, x, y, dx, dy, opponent_player) if blocked2 == 0: if count2 >= 4: score -= 9000 elif count2 == 3: score -= 500 else: if count2 >= 4: score -= 4000 return score def evaluate_board(board, player): total = 0 for x in range(SIZE): for y in range(SIZE): if board[x][y] == EMPTY: total += evaluate_position(board, x, y, player) return total

这里把 AI 的进攻威胁和对手的防守威胁都纳入评估,避免 AI 只进攻不防守。

搜索函数与井字棋类似,只是把empty_cells替换为“候选落子列表”。为了减少搜索范围,通常只考虑已有棋子周围 2 格内的空位。

# 文件路径:minmax-tutorial/gomoku.py def get_candidates(board): candidates = set() for x in range(SIZE): for y in range(SIZE): if board[x][y] != EMPTY: for dx in (-1, 0, 1): for dy in (-1, 0, 1): nx, ny = x + dx, y + dy if in_board(nx, ny) and board[nx][ny] == EMPTY: candidates.add((nx, ny)) if not candidates: return [(SIZE // 2, SIZE // 2)] return list(candidates) def negamax_gomoku(board, depth, player, alpha, beta): if depth == 0: return evaluate_board(board, player) candidates = get_candidates(board) # 走法排序,优先评估分数高的走法 scored_moves = [] for x, y in candidates: board[x][y] = player score = evaluate_position(board, x, y, player) board[x][y] = EMPTY scored_moves.append((score, x, y)) scored_moves.sort(reverse=True) best = -math.inf for _, x, y in scored_moves[:20]: board[x][y] = player value = -negamax_gomoku(board, depth - 1, WHITE if player == BLACK else BLACK, -beta, -alpha) board[x][y] = EMPTY best = max(best, value) alpha = max(alpha, value) if alpha >= beta: break return best

5.4 运行效果

如果你在本地执行主循环,AI 会优先占据中心或靠近已有棋子的位置。搜索深度为 2 时,AI 能挡住明显的三连;深度为 4 时,AI 会主动创造“双活三”之类的杀招。实际项目里可以根据机器性能动态调整深度。

6. 把 Minmax AI 本地部署为 HTTP 服务

6.1 为什么封装成服务

棋类 AI 通常是独立程序,但如果要嵌入 Web 前端、小程序或游戏客户端,更好的方式是封装成 HTTP 服务。前端只负责显示棋盘和收集玩家操作,AI 决策交给后端,这样算法逻辑可以复用,也能方便地扩展成多人对战。

本地部署服务的另一个好处是:无需把模型或算法代码暴露给前端。敏感的业务逻辑、评估函数、搜索参数都可以留在服务端,客户端只拿到“推荐落子位置”这个结果。

6.2 Flask 服务代码

下面用一个 Flask 服务封装五子棋 AI。客户端只需要提交当前棋盘状态和 AI 执子颜色,服务端返回落子坐标。

# 文件路径:minmax-tutorial/server.py from flask import Flask, request, jsonify from gomoku import init_board, get_candidates, negamax_gomoku, evaluate_board app = Flask(__name__) SEARCH_DEPTH = 2 def convert_board(data): board = init_board() for cell in data: x = int(cell["x"]) y = int(cell["y"]) value = int(cell["value"]) board[x][y] = value return board @app.route("/api/bestmove", methods=["POST"]) def best_move(): data = request.get_json() board = convert_board(data["board"]) player = int(data["player"]) candidates = get_candidates(board) if not candidates: return jsonify({"error": "棋盘已满"}), 400 best_score = float("-inf") best_move_pos = None alpha = float("-inf") beta = float("inf") opponent_player = 2 if player == 1 else 1 scored_moves = [] for x, y in candidates: board[x][y] = player score = evaluate_board(board, player) board[x][y] = 0 scored_moves.append((score, x, y)) scored_moves.sort(reverse=True) for _, x, y in scored_moves[:20]: board[x][y] = player score = -negamax_gomoku(board, SEARCH_DEPTH - 1, opponent_player, -beta, -alpha) board[x][y] = 0 if score > best_score: best_score = score best_move_pos = (x, y) alpha = max(alpha, best_score) if best_move_pos is None: return jsonify({"error": "没有可用落子"}), 500 return jsonify({"x": best_move_pos[0], "y": best_move_pos[1], "score": best_score}) if __name__ == "__main__": app.run(host="0.0.0.0", port=8000, debug=False)

6.3 启动与调用

启动服务:

python server.py

用 curl 测试:

curl -X POST http://127.0.0.1:8000/api/bestmove \ -H "Content-Type: application/json" \ -d '{"board": [], "player": 1}'

空棋盘时,预期返回棋盘中心位置附近的结果:

{"score": 30, "x": 7, "y": 7}

如果前端已经运行到中盘,提交的 board 数组会包含已落子的坐标和颜色,服务端会返回下一步推荐位置。

需要注意:host="0.0.0.0"意味着服务会监听本机所有网络接口。如果设备处于局域网,其他机器也能访问。若只是在本地调试,改为host="127.0.0.1"更安全。

6.4 在 H3 本地设备上部署的注意事项

如果你的 H3 设备是 ARM 架构或性能有限的开发板,部署时要注意以下几点:

  1. 确认 Python 版本。部分开发板自带 Python 3.7 或更旧版本,建议升级到 3.8+,避免语法兼容问题。
  2. 调整搜索深度。性能不足时,把SEARCH_DEPTH降为 1 或 2,保证响应时间。
  3. 使用debug=False,避免调试模式在局域网环境下暴露交互式调试器。
  4. 如果希望在系统启动时自动运行服务,可以用 systemd 或 supervisor 托管 Flask 进程,避免手动启动。

7. 常见问题与排查思路

问题现象常见原因解决思路
AI 执行速度很慢搜索深度过大、候选走法过多降低搜索深度、限制候选走法数量、优化走法排序
AI 总是应对迟缓,不主动进攻评估函数中防守权重过高调整进攻分数的权重比例,让进攻威胁得分更高
服务启动后外部无法访问监听地址不是 0.0.0.0,或防火墙拦截修改 host 参数,检查防火墙和端口
curl 返回 400请求 JSON 格式错误,或 board 字段缺失检查 JSON 结构,确认board字段是数组
服务响应不稳定没有做超时控制,请求量过大增加超时参数、限制并发数,或使用队列机制
落子坐标非法后端未校验棋盘边界在服务端增加in_board校验,返回 400 提示

如果遇到递归深度报错RecursionError,大概率是搜索深度设置过大,或者递归终止条件没有覆盖到游戏结束状态。检查is_full和胜负判断是否在所有分支上生效。

8. 最佳实践与工程建议

8.1 评估函数决定 AI 的上限

Minmax 搜索只是“框架”,真正决定 AI 棋力上限的是评估函数。建议把评估函数拆成独立的模块,方便调整权重和测试。参考的评分策略如下:

  • 进攻分数和防守分数分开统计。
  • 优先考虑“连五”和“活四”这样的直接胜负手。
  • 对双方威胁做差,让 AI 在进攻与防守之间动态平衡。

8.2 走法排序是性能优化的重要杠杆

Alpha-Beta 剪枝的效果对走法顺序非常敏感。如果每次先搜索“当前评估分数最高”的走法,剪枝可以在很早阶段发生,搜索量大幅缩减;如果先搜索烂走法,剪枝效果会大打折扣。所以每次搜索前,对候选位置按评估分数预排序是很有必要的。

8.3 服务端必须做输入校验

HTTP 服务暴露出去后,不能假设客户端传来的数据总是合法。必须校验坐标范围、棋子类型、棋盘长度等,否则可能出现越界访问。建议在接口入口统一做一层校验,非法输入直接返回 4xx 错误。

8.4 安全与最小权限原则

如果服务要部署到生产环境,注意以下几点:

  • 不要用 root 用户运行 Flask 服务。
  • 监听地址按需绑定,仅本地使用时用 127.0.0.1。
  • 如果服务需要暴露到公网,前面对接 Nginx 等反向代理,并做好访问控制。
  • 不要在服务端暴露不必要的调试信息。

8.5 日志与监控

给 AI 服务增加日志是必要的,尤其是生产环境。每次请求记录棋盘摘要、搜索深度、响应耗时和返回结果即可。问题出现时,能极大缩短排查时间。如果响应时间突然变长,优先关注搜索深度或候选走法数量是否异常。

9. 总结与下一步学习方向

本文从 Minmax 算法的核心思想出发,解释了极大极小值、博弈树、评估函数的底层逻辑,并用井字棋和五子棋两个实战案例展示了算法落地过程。最后通过 Flask 把五子棋 AI 封装成 HTTP 服务,完成了一次典型的本地部署流程。如果你手上有 H3 设备或任何轻量级开发板,完全可以按相同思路把服务跑起来。

在实际项目中,我最想提醒你的一点是:不要试图把所有逻辑都塞进搜索函数。评估函数、走法生成、剪枝策略、服务接口应该是四个独立模块,这样才能逐步调优、单点排查。

下一步可以继续学习的方向包括:

  • 蒙特卡洛树搜索(MCTS):适合分支因子更大的棋类游戏。
  • 深度学习评估网络:用神经网络替代人工评估函数,进一步提升棋力。
  • 并行搜索:在多核设备上并行评估多个候选走法,减少响应时间。
  • 对局回放与性能分析:记录每步搜索耗时和搜索节点数,针对性优化。

如果你想在现有代码上继续练习,建议先调整五子棋评估函数的权重,看看 AI 风格会发生什么变化,再尝试增加“禁手”等规则,这会让你对算法设计和工程实现有更深的理解。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 2:28:36

GMSSL 2.5.4 Windows预编译包使用指南:国密算法开发与集成实践

简介&#xff1a;面向Windows平台国密应用开发者的国密SSL资源包&#xff0c;基于OpenSSL扩展支持SM2、SM3、SM4等国密算法&#xff0c;适合需要构建合规加密通信、密钥交换与证书管理能力的C/C项目。压缩包共128个文件&#xff0c;约13.7MB&#xff0c;包含109个头文件、8个静…

作者头像 李华
网站建设 2026/9/2 2:28:09

MQ事务消息实战:RocketMQ半消息、回查机制与最终一致性

面试问 MQ 事务消息&#xff0c;最怕不是背不出概念&#xff0c;而是只能回答一句“RocketMQ 支持事务消息”。真正拉开差距的是&#xff1a;你能不能把“半消息、本地事务、回查机制、最终一致性、幂等消费”这一条链路讲清楚&#xff0c;能不能现场写出一个订单与库存的示例&…

作者头像 李华
网站建设 2026/9/2 2:27:27

CSMC 0.5um PDK在Cadence中的安装与使用全攻略

简介&#xff1a;CSMC_0.5um_PDK.zip是面向集成电路设计工程师的0.5微米工艺设计套件&#xff0c;由中芯国际提供&#xff0c;适用于模拟/数字电路仿真、版图绘制、物理验证等前后端设计环节&#xff0c;能帮助设计师快速获取特定工艺的物理限制、电气性能与设计规则&#xff0…

作者头像 李华
网站建设 2026/9/2 2:27:26

明星资本转向硬科技投资:技术团队如何应对流量与技术的碰撞

这次我们来看一个很有意思的现象&#xff1a;明星投资风向的转变。过去几年&#xff0c;明星扎堆开火锅店、奶茶店、潮牌店&#xff0c;一度成为娱乐圈的“副业标配”。但现在&#xff0c;越来越多的明星投资人开始将目光投向硬科技领域&#xff0c;从消费赛道转向了芯片、人工…

作者头像 李华
网站建设 2026/9/2 2:27:21

嵌入式开发中继电器模块的深度解析:从原理到安全应用实践

最近在整理一个智能家居的小项目&#xff0c;发现一个挺有意思的现象&#xff1a;很多朋友在玩嵌入式&#xff0c;尤其是用树莓派、ESP32这类开发板做智能控制时&#xff0c;第一个想到的往往是点亮LED、驱动个舵机&#xff0c;但一提到要控制家里的台灯、风扇或者水泵这类“大…

作者头像 李华
网站建设 2026/9/2 2:25:52

WallSystem通用版部署实践:版本号解读、架构拆解与踩坑指南

简介&#xff1a;WallSystem 20190903通用版&#xff08;bc456&#xff09;是一款面向大屏幕显示系统管理人员的拼接控制软件&#xff0c;适用于监控中心、指挥中心及展览展示等场景&#xff0c;解决多屏拼接、信号切换与画面布局的统一管控问题。压缩包为7z格式&#xff0c;共…

作者头像 李华