Files
NumberSwipe_New/modes/01-number-stroke/README.md
T
cabinw 8026e4628d 初始提交:三玩法 Web 原型与设计文档
- 玩法一 数字一笔:规则库、求解器、26 关、竖屏触摸 Web 原型、测试
- 玩法二 连连气球:连消畅玩版核心、Web 原型、Cocos 球槽组件与导出脚本
- 玩法三 六边一笔:规则库、求解器、10 关 + 转墙实验包、Web 原型、测试
- 产品文档、UI 设计规范、各玩法 GDD / HANDOFF
- 文档移除全部外部参考作引用;删除玩法二 v0 旧稿
2026-09-16 14:30:59 +08:00

11 KiB
Raw Blame History

玩法一 · 数字一笔

按数字顺序,一笔画走完盘面上每一格。大格只计一步。

本目录自包含:规格、关卡、规则代码、求解器和 Web 原型。不要依赖 modes/02 或 modes/03。壳需要的东西通过 shared/ 的玩法入口对接,见 docs/PRODUCT.md。

关卡、资源、文案全部原创,不使用第三方题库或素材。

状态

M1/M2 已达:竖屏触摸 Web 原型可玩,三包 26 关全部经求解器断言唯一解,含 6 关「奇与偶」体验包;存档、补数字 / 指路双提示、音效、振动齐全。68 个单元测试通过。下一步为试玩调校与 M4 迁 Cocos。

目录

路径 用途
docs/GDD.md 本玩法规格(权威)
docs/HANDOFF.md 交接文档:实现了什么、怎么实现、与 GDD 的偏差、待办与 Cocos 迁移顺序
../../docs/design.md UI 设计规范(色彩 / 字阶 / 组件 / 动效)。web/style.css :root 与 src/theme.ts 由 tests/theme.test.ts 校验一致
levels/pack-1-tutorial.json 第一包 10 关(教学)
levels/pack-2-advanced.json 第二包 10 关(进阶,生成器产出 + 人工过目)
levels/pack-3-parity.json 第三包 6 关(奇与偶,每条奇偶线索都参与唯一性)
src/ 纯 TS 规则层,零 DOM / 零 Cocos 依赖。Web 与 Cocos 共用
web/ 浏览器原型:DOM / Canvas / PointerEvent / localStorage 粘合层
tools/ 求解器命令行:全关卡校验、关卡设计辅助
tests/ 规则层单元测试(node:test)

src/ 分层:

types.ts     关卡 JSON 结构
board.ts     Cell / Board:单位网格、四向邻接、共享边
clue.ts      数字 / 奇偶线索统一判定与显示文字
game.ts      对局状态机:Command → GameEvent(含 rewind 多步回退、reveal 补数字)
input.ts     手势语义:按下/移动/松手 + “当前压在哪个格” → Command
solver.ts    枚举满足线索的哈密顿路径、唯一解、提示(下一步 / 退回分叉)
clue-hint.ts 在尚未解开的数字区间补中间数,不替玩家画路线
layout.ts    盘面适配、格矩形、桥矩形、命中测试(带死区)
view.ts      BoardView:格/桥/数字/冲突/提示/过关动效,只调用 Painter
painter.ts   绘制原语接口(圆角矩形、圆、居中文字)
theme.ts     配色
progress.ts  存档(KeyValueStore 抽象,桶 mode:01-number-stroke)
levels.ts    关卡包解析

运行

cd modes/01-number-stroke
npm install
npm run dev        # 起本地服务 + 监听改动,终端会打印手机可访问的局域网地址
npm run build      # 打包到 web/dist/app.js,之后可直接双击 web/index.html
npm run build:standalone  # 导出项目根目录 releases/数字一笔-试玩版.html
npm run check      # 类型检查(含 src/ 无 DOM 校验)+ 单元测试 + 全关卡唯一解校验

?dev=1 解锁全部关卡并暴露 window.__numberStroke 调试句柄(自动化手势测试用)。 直接体验奇偶:http://localhost:8000/?dev=1&level=3-1。level 跳关参数仅在开发模式下生效;不清空已有存档。

发给朋友测试:运行 npm run build:standalone,发送生成的 数字一笔-试玩版.html 一个文件即可。脚本、样式、26 关数据与合成音效全部内置,无需安装或启动服务,可离线用浏览器打开。全部 26 关直接可选,无需解锁或添加参数;通关记录仍保存在试玩者的浏览器中。

关卡工具:

npm run validate            # 每关:连通、恰好 1 条满足线索的哈密顿路径
npm run validate -- 1-7     # 只看某关,并打印解
npm run design -- 1-7 --minimize          # 当前线索里哪些可删
npm run design -- 1-7 --suggest 3 --path a,b,c,...   # 给作者解找最少线索
npm run generate -- --seed 3 --out levels/pack-2-advanced.json   # 随机铺盘+作者解+挑线索,批量产关

选关页按包分区渲染,跨包线性解锁(2-1 需先过 1-10);web/main.ts 顶部的 packs 数组登记包文件,加新包时往数组里加 import 即可。

第一包 · 10 关

每关只加一个旋钮(GDD §7)。线索数已按 §4.6 收到教学所需的最少。

关 N 教什么 大格 线索
1-1 3 滑动,邻格自动出步号 – 1
1-2 4 必须走完所有格 – 1, 4
1-3 5 走错可以退(第一次死路) – 1, 3
1-4 4 大格只算一步 2×2 1, 3
1-5 7 中段线索 – 1, 4
1-6 9 空洞:隔洞不相邻,先看终点再起手 – 1, 9
1-7 12 先推再画:三处分叉各需一次推理 – 1, 4, 8
1-8 11 2×2 当枢纽:6 个出口只能选远角 2×2 1, 8
1-9 11 横长条:b 紧挨 1 却是第 6 步,只能从长条下边进上边出 2×1 1, 6
1-10 14 小考:顶行直走只有 5 步,要借 2×2 垫一步;竖长条收尾 2×2 + 1×2 1, 6

GDD §7.1 的 12 关教学梯度压缩到 10 关:竖长条与“两个大格”并入 1-10;无线索 1 的关按 §7 留在第 13 关之后,本包不含。

第二包 · 10 关(进阶)

tools/generate.ts 自动生成(seed=43)+ 人工过目。面向已经会玩的人,三个设计原则(来自试玩反馈,已写进 GDD §4/§7/§8.2):

  • 难度的主旋钮是相邻线索的步号差。每关开局固定「线索 1 + 4~7 步内的引导线索」,玩家先有起手方向;难度靠后面的差距拉开(包内最大差从 8 升到 16)。
  • 大连块高频出现:每关 2~3 个多单位格,2×2 在 7 关出现,3×3 在 2-2、2-4 出现。大连块只计 1 步但出口多,是推理的主战场。
  • 格子可以是俄罗斯方块式异形(L/I/S/T,随机旋转镜像)。异形格占 2~4 个单位格、仍只计 1 步,凹口让邻接关系更不规则;渲染上拼块连成一整块(单位矩形 + 延展接缝),与 2×2 观感一致。
关 N 大连块与异形 空洞 线索 步号差
2-1 16 异形×2 + 2×2 – 1, 7, 14 6/7/2
2-2 14 3×3 + 异形 – 1, 4, 12 3/8/2
2-3 18 异形×2 1 1, 4, 8, 16 3/4/8/2
2-4 15 3×3 1 1, 6, 15 5/9/0
2-5 16 2×2×2 + 异形 – 1, 6, 15 5/9/1
2-6 18 2×2×2 1 1, 4, 8 3/4/10
2-7 21 2×2 + 条 – 1, 7, 17 6/10/4
2-8 19 异形×2 – 3, 5, 15, 17 2/10/2/2
2-9 21 2×2 + 条 – 1, 7, 20 6/13/1
2-10 21 2×2 + 条 – 1, 5, 21 4/16/0

2-8 无线索 1(全游戏第一关):起点也要自己找。

每关 JSON 里的 teach 字段存了生成参数与作者解(剧透,永不渲染)。想换一批:npm run generate -- --seed <新种子> --out levels/pack-2-advanced.json,然后 npm run check。

第三包 · 6 关(奇与偶)

「奇」要求走到该格时的步数为 1、3、5…,「偶」要求 2、4、6…。整块仍只计一步,数字与奇偶条件要同时满足。走过后显示实际步号并保留奇偶标记;走错可撤回,提示也考虑奇偶要求。

关 格数 内容
3-1 4 「偶」入门,借 2×2 调整步数
3-2 6 「奇」写在 3×3 上,整块只计一步
3-3 11 用奇数条件决定绕行方向
3-4 16 异形格上的「偶」+「奇」+数字线索
3-5 18 双异形、奇偶与中段数字共同推理
3-6 18 两个 2×2、两个「奇」,仅固定起点 1

3-2 为新盘,其余复用既有关卡的几何并重新设计线索(来源及作者解记在 teach)。每关唯一解;逐条删去任意奇偶条件都会出现多解,确保新规则有实际作用。此包先用于体验规则,难度手感仍待真人试玩。

关卡中写 "parity": "odd" / "parity": "even",与同格 clue 互斥;可与 shape 或 3×3 共用。npm run design -- 3-4 --minimize 会同时检查数字和奇偶线索。现有随机生成器仍产出数字关,奇偶包采用人工配线索并用求解器筛选。

交互(已实现,对齐 GDD §5)

  • 有线索 1 时只能从它起手,点别处 1 抖一下
  • 按住滑到相邻未走格追加;点按或滑到任意已走格,直接撤掉该格之后的路径,不松手就能换方向继续画
  • 松手保留路径;从末端按下继续;点末端旁的空格仍可追加;不相邻的空格忽略
  • 快速滑动在两帧之间插值采样,避免漏掉中间格;直接落到历史格时优先回退。触屏死区收至 8%,鼠标维持 14%;只跟踪一个指针
  • 踩错线索,或第 n 步走到预定数字 n 所在格以外的位置,立即让该格变红并轻晃,连接线保持紫色,不加叉号;本格要求不符时仍显示原数字 / 奇偶要求。原始数字与补出的数字都生效;退回后清除冲突。死路当前格抖动,不弹失败
  • 补数字:优先当前尚未解开的数字区间,1~9 补 5;每次只给一个确定数字,遵守原来的奇偶规则。重开保留补数,退出重进则恢复原关卡
  • 指路:无路径指起点;是解的前缀给下一步;已偏离则高亮分叉格并压暗错段,点高亮格即可直接回退
  • 过关:路径提亮、按步序扫光,约 0.9s 后自动下一关;最后一关回选关

移植到 Cocos Creator

技术选型就是为这一步做的:

  1. src/ 原样拷进 assets/modes/01-number-stroke/scripts/。 它用 tsconfig.src.json(lib: ["ES2020"],无 DOM)编译通过;import 全部无后缀,符合 Cocos 模块规范(Cocos 不允许 import './foo.ts')。
  2. Painter 换实现。 web/canvas-painter.ts 对应一个 GraphicsPainter:fillRoundRect/strokeRoundRect/fillCircle 用 Graphics,text 用一组按需复用的 Label 节点。BoardView.draw() 不用改。Cocos 的 y 轴向上,在 Painter 里翻一次 y 即可。异形格不用新原语:layout.cellShapeRects() 把拼块拆成单位矩形 + 接缝矩形,复用同一套 fillRoundRect。
  3. 输入换事件源。 Node.on(TOUCH_START/MOVE/END) 把触点转成 Canvas 节点局部坐标 → layout.hitTest() → PointerInput.down/move/up()。插值采样那几行照搬 web/main.ts。
  4. 存档换 store。 Progress 接收 KeyValueStore,Cocos 用 sys.localStorage 包一层。
  5. 关卡 JSON 放 resources/,resources.load 成 JsonAsset 后走同一个 parsePack/loadPack。
  6. HUD / 选关是 UI 节点。 对应 web/index.html 里那几个元素:顶栏(返回、关号、剩余格)、字幕、底栏(重开、补数字、指路)、选关网格。
  7. 音效:web/audio.ts 是 WebAudio 合成;Cocos 用 AudioSource 播 4 段短音(step / conflict / cleared / reject),接口一致。
  8. 每帧:view.update(dt) 放 update(dt),view.draw(painter) 在 isAnimating 为真时清空 Graphics 重画。

不搬进 Cocos 的东西:web/、tools/、tests/(测试可以继续在 Node 跑,它们只依赖 src/)。