跳到正文
← 作品

案例 · LK-002

西库扑克

随时随地,开一桌。西库是柬埔寨本地三人或四人的牌戏,搬进 Telegram;牌、回合和账本都由服务端持有。

角色
产品、设计、开发
范围
端到端,三个运行时
技术栈
Flutter · Java 25 · Spring Boot · PostgreSQL · Valkey
年份
2026
西库扑克封面:墨色背景上的大厅、牌桌和结算三屏。
01

背景

三五好友,几台手机,没有实体牌。

西库是柬埔寨本地牌戏:52 张牌,三到四人,手里 8 张凑成四副对子;红牌算钱,钱在人和人之间走,不进程序。朋友本来就会打。问题不在规则,在牌桌:有人没带牌,或者牌要重新洗。任务不是发明另一种牌戏,而是让原来那张牌桌,在 Telegram 里、在三到四台手机上成立。

02

模型

规则先变成状态机。

能起争议的东西全部放在服务端:牌墙、四家手牌、轮次、倒计时、抢胡窗口。客户端只渲染发给自己的快照,再把出牌、摸牌、吃、胡、过发回去;它不判牌。每张弃牌都走同一条顺序:先看谁能胡,开 15 秒响应窗;没人胡,再看下家吃不吃;不吃就摸牌。吃进后必须打一张,新的弃牌重新走一遍。抢胡按座次,不按谁先点——先点先得奖励的是网速,不是牌技。判牌是纯函数:8 张拆 4 副对子,穷举验证全部 C(52,8) = 752,538,150 手。1,731 行规则写在代码之前。后面的工作才立得住。

03

构建

三个运行时,一张牌桌。

玩家端是 Telegram Mini App 里的 Flutter Web,原生壳留给以后。服务端是 Java 25 + Spring Boot 4.1.1:REST 管大厅,WebSocket 管牌桌;PostgreSQL 18.6 存会员、房间、已结算的局和转账;Valkey 9.1.2 存会话、进桌票据和还在打的牌。Vue 3 管理后台看会员、房间和账本。整套在 Docker + nginx 后面。好友桌和机器人桌共用同一个引擎,只换座位、结束规则和账本标题。客户端、服务端、后台合计 11.9k 行,另有 2.3k 行服务端测试。规则文档和测试决定了代码能做什么。

04

结果

一张能打的牌桌,不是演示。

v1 有好友房:3 或 4 人、邀请链接可重复使用、房主开局、中途要停须全员同意;机器人房一个人也能打;断线留 15 秒;账本把一局净额压成最少几笔转账。三语:中文、English、ខ្មែរ;高棉语字体随包走,避免组合符号错位。没有匹配、没有观战、没有钱包、没有广告。在 Telegram 里通过 @sikhu_bot 打开。

05

复盘

规则先于代码。

做对的是:先把规则和边界写死,再做界面;服务端权威;好友桌和机器人桌共用一套引擎;判牌穷举;账本和钱分开。会改的是:补 UI 自动化,不只单测;在更多真实 Telegram WebView 上看高棉语整形;把原生壳发出去;再给机器人一个难度档。1,731 行规则和测试,才是它没散架的原因。

3–4名玩家
7.525 亿手牌穷举验证
1.19 万行应用代码
3种语言

2.3k 行服务端测试 · 7 个数据库迁移 · 13 个 Java 测试类,2 个 Flutter 测试文件。