← 返回博客
架构2026-08-30 21:23:143 分钟 · 953 1

中国象棋实时对战系统:用 Webman + GatewayWorker + Phaser 搭一个攻擂台

一个业余项目怎么从零搭出"擂主 + 挑战者 + AI 替补"的实时对战。后端 PHP Webman 扛 WebSocket,前端 Vue3 + Phaser 画棋盘,棋局权威逻辑和 AI 全部收口在后端一个文件里。

这不是一个商业产品,是我个人的业余项目,但我打算把它写进简历——所以每一个模块都尽量做得经得起深挖。它要解决的核心问题只有一句话:让两个人在浏览器里实时下中国象棋,并且 AI 既能当擂主、也能当随时顶上的替补。这篇文章先把整体架构讲清楚,下两篇专门拆 AI 引擎。

一、攻擂模式:一个房间,三种角色

市面上大多数象棋小游戏是"你 vs 电脑"或者"你 vs 随机匹配的人"。我想做的不一样——擂台制:

  • 擂主:当前守在台上的人;
  • 挑战者:点"攻擂"进来挑战擂主的人,两人实时对弈;
  • AI 替补:擂主掉线 / 无人守擂时,AI 自动顶上,保证台子永远有人、访客随时能开局。

这带来一个架构上的硬约束:棋局的权威状态必须有一处唯一真相源。如果前端各自算棋,网络抖动一卡就出现"你看到我将被吃、我看到没被吃"的分裂。所以我让后端做唯一裁判。

二、整体拓扑

浏览器 (Vue3 + Vite + Phaser 画棋盘)
        │  WebSocket (GatewayWorker 长连)
        ▼
  Webman 1.6.14 业务进程
        │  棋局权威逻辑 + AI 引擎(都在 Events.php)
        ▼
     Redis(单 key 锁一局:擂主/挑战者/AI/当前棋盘)

几个选型理由:

  • Webman:常驻内存的 PHP 框架,不用每次请求重新 bootstrap,正好扛 WebSocket 长连接;
  • GatewayWorker:负责连接管理、房间广播,业务进程只管"这一步走得合不合法、AI 该回什么";
  • Phaser:前端渲染棋盘和棋子动画,比手写 Canvas 省事,Vue3 只管 UI 壳和状态;
  • Redis:一局棋的所有状态塞进一个 key,天然用单 key 的原子性避免并发写乱。

三、棋局权威为什么收口在后端一个文件

整个象棋规则校验、回合流转、胜负判定、AI 决策,全在后端 api/plugin/webman/gateway/Events.php 里(约 4400 行)。把权威逻辑放后端而不是前端,有两个实打实的好处:

  1. 防作弊:客户端只发"我想把车从 (x1,y1) 走到 (x2,y2)",合不合法由后端按完整规则判定;
  2. AI 与人对齐:AI 落子走的是同一套"生成合法走法 → 评估 → 选最优"的流程,不存在前端一套、AI 一套两套规则分叉的坑。

代价是 Events.php 越来越胖。对个人项目这是可接受的权衡——逻辑内聚、好调试;真要拆分也是下一步的事。

四、几个踩过的坑(先埋个伏笔)

这个项目早期交过不少学费,挑两个跟架构相关的:

  • 崩溃链:早期一个 warning 被框架转成 ErrorException,又被全局异常处理清掉了 Redis 里的对局状态,棋局直接卡死。根因是"服务端必须做唯一裁判,但裁判崩溃时要把状态收尾干净"。
  • 回合超时:AI 思考有预算,但挑战者可能发呆。靠 Redis 巡检在超时后强制流转回合,否则对方一卡,整局悬空。

这些修法都沉淀进了代码,后面讲 AI 时会顺带提到对应的收尾逻辑。

五、下集预告

架构就这么薄薄一层,真正有意思的是 AI。下一篇开始拆:一个 PHP 写的象棋 AI,怎么在 8 秒预算内决定下一步往哪走——Alpha-Beta 搜索、迭代加深、静态搜索、空着裁剪、置换表,一个一个讲。

相关推荐

本文为原创文章,采用CC BY-NC-SA 4.0协议授权,转载请保留署名与原文链接。原文链接:https://www.wxbuluo.com/article/156