1. 五子棋 AI 落子决策到底难在哪:从「随机下」到「会算棋」
五子棋规则一句话能讲完,但让程序真正「会下棋」是另一回事。我见过太多人写完棋盘渲染就卡住了:AI 要么随机落子,要么只会堵眼前一颗子,玩家下三颗连成一线它都看不见。问题不在 Canvas,而在落子决策这一层——你需要一个能评估局面、能往前推演、还能在有限时间里算完的搜索算法。
这篇要解决的就是这件事:用 Claude Code 生成一套可运行的五子棋,核心是 Minimax 搜索加 Alpha-Beta 剪枝,配合一个能识别活四、冲四、活三的评估函数,最后在 Canvas 上完成棋盘渲染和鼠标交互。适合谁看?写过一点 JavaScript、想搞明白「AI 怎么思考下一步」的人;或者你已经有一个五子棋 demo,但 AI 下得像傻子,想把它调聪明。
我试过把评估函数写得很粗糙,结果 AI 深度开到 3 还是乱下——因为它根本分不清「活三」和「眠三」的价值差。所以这篇的重点不是堆代码,而是把评估函数、剪枝逻辑、候选点筛选这三块讲透,让你能自己调参数、看效果。
核心检索词先摆出来:五子棋 Minimax Alpha-Beta 剪枝 AI 落子决策。下面从环境准备开始,一步步把可复制的配置和代码给你。
2. 用 TaoToken 接入 Claude Code 生成五子棋项目
2.1 为什么用 Claude Code 写这类算法代码
五子棋 AI 涉及递归搜索、边界判断、评分表设计,手写容易漏分支。Claude Code 的优势是能一次性生成结构完整的模块,你只需要把提示词写清楚,它会把棋盘状态、评估函数、搜索函数分层给你。但前提是 Claude Code 得先能正常调用模型。
2.2 配置 Base URL 与 API Key
TaoToken 提供的是兼容 Anthropic 的接口,Claude Code 通过环境变量读取。你需要三件套:Base URL、API Key、Model ID。Base URL 用https://taotoken.net/api,Key 在控制台生成。
先建项目目录:
mkdir -p gomoku && cd gomoku claude --version如果claude --version报 command not found,说明 Claude Code 没装好,先补安装。装好后配置环境变量,Linux/macOS 写进~/.zshrc或~/.bashrc:
export ANTHROPIC_BASE_URL="https://taotoken.net/api" export ANTHROPIC_API_KEY="sk-你的Key" export ANTHROPIC_MODEL="claude-sonnet-4-5-20250929"Windows PowerShell 用:
$env:ANTHROPIC_BASE_URL="https://taotoken.net/api" $env:ANTHROPIC_API_KEY="sk-你的Key" $env:ANTHROPIC_MODEL="claude-sonnet-4-5-20250929"Model ID 要填你账号里实际可用的,别照抄。填错会直接 404 或 model not found。
2.3 settings.json 配置片段
如果你用 Claude Code 的 settings 文件管理,路径通常在~/.claude/settings.json,写入:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-你的Key", "ANTHROPIC_MODEL": "claude-sonnet-4-5-20250929" } }注意 JSON 不能有注释,Key 别带多余空格。改完重启终端,让环境变量生效。
2.4 验证连通性
在项目目录里跑一句最简单的对话,确认链路通:
claude -p "只回复两个字:就绪"返回「就绪」说明 Base URL、Key、Model 三件套都对。如果卡住或报 401,先看第 5 节的排错。这一步过了,再让 Claude Code 生成代码,否则它连请求都发不出去。
3. 可复制的五子棋配置:评估函数、剪枝与 Canvas 渲染
3.1 项目结构与提示词
让 Claude Code 生成单文件 HTML,方便直接打开。提示词要具体到函数名和评分表,否则它给你的评估函数可能只有「连子数」没有「两端开放」判断。
claude -p "创建 gomoku/index.html,单文件包含:15x15 Canvas 棋盘、木纹背景、星位标记、黑白交替落子、径向渐变立体棋子、最后一手红点、五连检测并高亮连线、鼠标悬停半透明预览。AI 用 Minimax + Alpha-Beta 剪枝,评估函数区分活四/冲四/活三/眠三/活二,候选点只取已有棋子周围 2 格。给出完整可运行代码。"3.2 评估函数:棋型评分表
评估函数是 AI 的「眼睛」。核心是把每条线上的连续同色子按两端开放状态打分。下面这段可以直接用:
const SCORES = { FIVE: 100000, OPEN_FOUR: 10000, HALF_FOUR: 1000, OPEN_THREE: 1000, HALF_THREE: 100, OPEN_TWO: 100, HALF_TWO: 10, ONE: 1 }; function evaluateLine(cells, player) { let score = 0; for (let i = 0; i < cells.length; i++) { if (cells[i] !== player) continue; let count = 1; while (i + count < cells.length && cells[i + count] === player) count++; const leftOpen = i > 0 && cells[i - 1] === 0; const rightOpen = i + count < cells.length && cells[i + count] === 0; if (count >= 5) score += SCORES.FIVE; else if (count === 4) { if (leftOpen && rightOpen) score += SCORES.OPEN_FOUR; else if (leftOpen || rightOpen) score += SCORES.HALF_FOUR; } else if (count === 3) { if (leftOpen && rightOpen) score += SCORES.OPEN_THREE; else if (leftOpen || rightOpen) score += SCORES.HALF_THREE; } else if (count === 2) { if (leftOpen && rightOpen) score += SCORES.OPEN_TWO; else if (leftOpen || rightOpen) score += SCORES.HALF_TWO; } else if (count === 1 && leftOpen && rightOpen) { score += SCORES.ONE; } i += count - 1; } return score; }整盘评估时,四个方向都扫一遍,己方分减对方分乘 1.1,让 AI 优先防守:
function evaluateBoard(player) { const opp = player === 1 ? 2 : 1; let myScore = 0, oppScore = 0; const dirs = [[0,1],[1,0],[1,1],[1,-1]]; for (let r = 0; r < SIZE; r++) { for (let c = 0; c < SIZE; c++) { dirs.forEach(([dr, dc]) => { const line = []; for (let i = -1; i <= 5; i++) { const nr = r + dr * i, nc = c + dc * i; if (nr < 0 || nr >= SIZE || nc < 0 || nc >= SIZE) line.push(-1); else line.push(board[nr][nc]); } myScore += evaluateLine(line, player); oppScore += evaluateLine(line, opp); }); } } return myScore - oppScore * 1.1; }3.3 Alpha-Beta 剪枝配置
Minimax 递归时带上 alpha 和 beta,当 beta <= alpha 就 break。这段是性能关键:
function minimax(depth, alpha, beta, isMax, aiPlayer) { const opp = aiPlayer === 1 ? 2 : 1; if (depth === 0) return { score: evaluateBoard(aiPlayer) }; const candidates = getCandidates(); if (candidates.length === 0) return { score: 0 }; let bestMove = candidates[0]; if (isMax) { let maxScore = -Infinity; for (const { row, col } of candidates) { board[row][col] = aiPlayer; let score; if (checkWin(row, col, aiPlayer)) score = SCORES.FIVE * 10; else score = minimax(depth - 1, alpha, beta, false, aiPlayer).score; board[row][col] = 0; if (score > maxScore) { maxScore = score; bestMove = { row, col }; } alpha = Math.max(alpha, score); if (beta <= alpha) break; } return { score: maxScore, move: bestMove }; } else { let minScore = Infinity; for (const { row, col } of candidates) { board[row][col] = opp; let score; if (checkWin(row, col, opp)) score = -SCORES.FIVE * 10; else score = minimax(depth - 1, alpha, beta, true, aiPlayer).score; board[row][col] = 0; if (score < minScore) { minScore = score; bestMove = { row, col }; } beta = Math.min(beta, score); if (beta <= alpha) break; } return { score: minScore, move: bestMove }; } }3.4 候选点筛选
15x15 全盘 225 个点,深度 3 就是 225 的三次方,必须裁剪。只取已有棋子周围 2 格:
function getCandidates() { const set = new Set(); const range = 2; for (let r = 0; r < SIZE; r++) { for (let c = 0; c < SIZE; c++) { if (board[r][c] === 0) continue; for (let dr = -range; dr <= range; dr++) { for (let dc = -range; dc <= range; dc++) { const nr = r + dr, nc = c + dc; if (nr >= 0 && nr < SIZE && nc >= 0 && nc < SIZE && board[nr][nc] === 0) { set.add(nr * SIZE + nc); } } } } } if (set.size === 0) set.add(7 * SIZE + 7); return Array.from(set).map(idx => ({ row: Math.floor(idx / SIZE), col: idx % SIZE })); }3.5 Canvas 渲染与交互
棋盘用径向渐变画立体棋子,鼠标悬停用 globalAlpha 做半透明预览。落子后检查五连,命中就画红线。这部分 Claude Code 生成得比较稳,你重点核对坐标转换toGrid和toPixel是否对称,否则点击位置会偏。
4. 验证 AI 落子质量与性能
4.1 打开页面看基础功能
open gomoku/index.html检查清单:棋盘 15x15 木纹显示正常、五个星位可见、点击落子黑白交替、最后一手有红点、鼠标悬停有半透明预览、五连后红线高亮。
4.2 测 AI 是否识别活四
手动摆一个活四局面:让白棋(AI)形成_XXXX_,看它下一步是否直接连五获胜。再摆一个对手活四,看 AI 是否立刻堵。如果它不堵,说明评估函数里 OPEN_FOUR 权重不够或方向扫描漏了。
4.3 测剪枝性能
在aiMove里加计时:
function aiMove() { const depth = parseInt(document.getElementById('diffSelect').value); const t0 = performance.now(); const result = minimax(depth, -Infinity, Infinity, true, 2); console.log(`深度${depth} 耗时 ${(performance.now() - t0).toFixed(1)}ms`); if (result.move) placeStone(result.move.row, result.move.col); }实测参考:深度 1 小于 10ms,深度 2 约 50ms,深度 3 约 200ms,深度 4 约 1s。如果深度 3 超过 1s,检查候选点范围是不是开太大,或者评估函数里重复扫描太多。
4.4 对比剪枝前后节点数
在 minimax 里加一个全局计数器,每次进入函数加一。跑同一局面,注释掉if (beta <= alpha) break;对比。正常情况剪枝能减少 60% 以上节点。这个数字能直观告诉你剪枝有没有生效。
5. 常见报错排查:401、local proxy failed、reading choices
5.1 401 Unauthorized
最常见。原因三种:Key 复制时带了空格或换行;Key 已失效;Base URL 写成了带路径的地址。检查ANTHROPIC_API_KEY是否以sk-开头且无空格,Base URL 必须是https://taotoken.net/api,不要多加/v1。
5.2 local proxy failed
Claude Code 启动时连不上配置的地址。先echo $ANTHROPIC_BASE_URL确认变量生效,再curl https://taotoken.net/api看网络是否可达。如果公司网络有限制,换网络环境重试。注意别在配置里写任何本地代理地址。
5.3 reading choices 报错
通常是模型返回格式和 Claude Code 预期不一致,多半是 Model ID 填错。确认ANTHROPIC_MODEL是你账号实际可用的模型名,别用文档里的示例硬套。改完重启终端。
5.4 OAuth 相关报错
如果你之前登录过其他账号,本地可能残留 OAuth 凭证冲突。清掉~/.claude下的缓存文件,重新用 API Key 方式配置。三件套(Base URL + Key + Model ID)必须同时正确,缺一个都会报错。
5.5 AI 不落子或落子卡死
检查aiThinking标志位有没有在 setTimeout 回调里正确复位。如果 AI 一直显示「思考中」,多半是递归没退出——看depth === 0的终止条件,以及checkWin命中后有没有正确返回。
6. 把五子棋 AI 接到你的工作流里
这套代码跑通后,你可以做几件事继续深挖。第一,把评估函数的评分表调一调,比如把 OPEN_THREE 从 1000 提到 2000,看 AI 是不是更激进。第二,给候选点加排序,先搜高分点,剪枝效率会更高。第三,把深度做成滑块,实时感受搜索深度和响应速度的权衡。
如果你想把这类算法代码的生成、调试、重构流程固定下来,长期用 Claude Code 做编码和 Agent 任务,可以走 Coding Plan,把模型调用额度规划好,不用每次临时配 Key。需要生成新 Key 或管理多个项目的,去 API Keys 页面操作。接入文档里有完整的参数说明和示例,遇到配置问题先翻文档再排查。
模型对话入口适合快速验证某个评估函数片段或让模型解释一段递归逻辑,不用开完整项目。把五子棋当成一个练手靶子,评估函数、剪枝、候选点这三块吃透,换成象棋、围棋的简化版也是同一套思路。