主题
给游戏站加了 3 款逻辑谜题:自研的理由,和「谜题为什么必须用求解器验证」
先说结论:游戏站从 5 款扩到 8 款,新增黑白棋、数织(Nonogram)、星之战(Star Battle),全部自研,零外部依赖;28 个谜题关卡逐个用求解器验证过。

地址:https://games.cosmocat.dev/games/reversi/ · /nonogram/ · /starbattle/
为什么加的是「谜题」
之前 5 款(2048、扫雷、俄罗斯方块、数独、五子棋)里,只有数独是纯逻辑推理。用起来会形成一个很明显的空档:
- 想动脑,但不想动手速——俄罗斯方块、2048 都吃手速和反应;
- 想玩 3-10 分钟的一局,不想被人机对战拖着走;
- 想「卡住的时候能想明白」,而不是靠概率赌。
所以这次补的三款,标准很明确:零手速、纯推理、单局可长可短。
| 游戏 | 核心机制 | 为什么选它 |
|---|---|---|
| 黑白棋 | 8×8 夹击翻转,人机对战 | 和五子棋互补:规则一分钟学会,但中盘全是位置价值判断 |
| 数织 | 行列数字线索填格 | 最「纯粹」的排除法;题目可验证唯一解 |
| 星之战 | 每行/列/区域星数相同 + 星不相邻 | 纯约束满足,推理链长,适合 10×10 的 2 星局 |
为什么不引开源仓库,选自研
之前 5 款都是 MIT 开源镜像,走的是「找仓库 → vendor → 补移动端适配」。这次换路线,原因是三个具体成本:
第一,谜题类游戏的质量命门不在代码,在题目。 开源实现给你一套引擎,但题库往往只有寥寥几关,或者关卡来源不明(不知道是不是唯一解)。自己写生成器,才能批量产出并验证。
第二,依赖和 CDN 是移动端的隐形税。 很多开源谜题项目引了 jQuery、Vue CDN、字体;在手机上要么慢、要么断网就废。自研是单文件内联 JS,零请求。
第三,AI 要自己调。 黑白棋如果直接用随机走子,一盘就劝退。自己写搜索,才能分出「简单/普通/困难」三档,让新手能赢、老手有压力。
代价当然有:代码要自己写、自己要测。但三个游戏的逻辑都不复杂,换来的是可控性和题库质量。
实现一:黑白棋的 AI,三档不是摆设

棋盘 8×8,初始四子交叉,夹住对方即翻转。规则部分半小时能写对,真正花时间的是 AI:
- 简单:位置权重表 + 翻转数 + 一点随机扰动。会犯错,适合第一次玩。
- 普通:两层搜索(negamax),能看穿「你翻我一片、我反手翻回来」。
- 困难:四层搜索 + α-β 剪枝 + 走法排序(先试角位)。
评估函数里三样东西加权:位置分(角 100、角邻 -50)、行动力差(双方可落点数之差 ×6)、子数差(×2)。
一个反直觉的点:子数差权重故意压得很低。黑白棋新手最常见的输法就是「翻得爽」,中盘领先一堆散子,残局被连翻。如果评估函数偏爱子数,AI 也会犯同样的错。
实现二:数织的题目,用求解器验证「唯一解」

数织(Nonogram)的规则一句话:行列两侧的数字是这一行/列连续填充段的长度序列。
难点在出题。手工出题很容易出三种坏题:
- 多解——两个不同图案满足同一组线索,玩家永远不知道错在哪;
- 无解——自己算漏了一个约束;
- 只能猜——有唯一解,但推理路径需要「试一步再看」,体验极差。
我的做法是先设计图案,再由程序反推线索,然后用回溯求解器数解的数量:
- 对每行生成所有满足行线索的填充组合(位掩码);
- 按行 DFS,每放一行就检查每列的前缀是否仍是该列线索的合法前缀(不合法立刻剪枝);
- 数到第 2 个解就停——只要不是 1,这题就淘汰。
16 关跑下来,8 个 5×5 + 8 个 10×10 全部唯一解。这个验证步骤不能省:我第一版设计的图案里有 3 个是多解的,肉眼完全看不出来。
实现三:星之战,生成 + 可解验证

星之战规则:N×N 分 N 个区域,每行、每列、每个区域恰好 K 颗星,任意两星不能相邻(含斜对角)。
出题的难点是「区域划分」:随机划出来的区域,绝大多数要么多解、要么解得很丑。我试过纯随机的区域生成:
- 8×8 1 星局,40 次随机区域划分,15 个有解,但全部有 3 个以上解;
- 10×10 2 星局更极端,唯一解出现的概率低到没法用。
所以最后把标准改成**「保证可解 + 提供参考解」**(玩家只要找到一个满足全部约束的布局就算通关),生成流程变成:
- 多源均衡生长,把棋盘划成 N 个各 N 格的连通区域;
- 回溯求解器按行放置星(每行选 K 列组合,检查列容量、区域容量、相邻冲突、前瞻剪枝);
- 找到第一个解就收,把它作为「提示」的数据源。
这里有个诚实的取舍:星之战的多解在体验上并不致命(不像数织,多解会让「我差一格」变成永远过不去)。所以没有强求唯一解,而是用「提示一星」兜底。
验收:不是「能打开」,而是「能玩」
上线前跑了真 Firefox 的验收:13 个页面(首页 + 5 旧游戏 + 3 新游戏 + 攻略目录 + 3 篇新攻略)全部无控制台错误,另外做了三项交互实测:
- 黑白棋:点一个合法空位 → 玩家棋子 4 颗、AI 应手 1 颗(翻转逻辑生效);
- 数织:点格子 → 正确进入「填色」状态;
- 星之战:点格子 → 正确进入「★」状态。
顺手修了两个旧问题:验收脚本里俄罗斯方块和数独的选择器早就过时了(页面改版后 DOM 变了),导致每次验收都误报 FAIL——这次一起校准了。
还有一个真 bug 是在写这篇文章、回头截真机图时才暴露的:黑白棋的 AI 从第 1 局起就没落过子。玩家落子后 turn 没切到白方,AI 拿着黑方的合法步在算、再用白子去落,全部落空;界面上白子始终是初始那两颗,最后直接按「黑方子多」判终局。修法是落子后立即切换回合,并把「无步跳过」收成一个独立函数(双方都无步才终局)。截图里那盘黑 5 : 白 5,才是 AI 真的在走。
现在的形态
- 3 款新游戏,每款 1 篇中文玩法攻略(进阶/游戏史后续补);
- 首页 8 款卡片、攻略目录 23 篇、sitemap 37 条;
- PWA 缓存升到 v2,装到主屏的三款新游戏同样支持离线打开。
链接再放一次:
- 黑白棋:https://games.cosmocat.dev/games/reversi/
- 数织:https://games.cosmocat.dev/games/nonogram/
- 星之战:https://games.cosmocat.dev/games/starbattle/
下一个要补的不是游戏,是「进阶攻略」——谜题类的乐趣有一半在「学会一个推理套路」,这部分内容现在还欠着。