- 玩法一 数字一笔:规则库、求解器、26 关、竖屏触摸 Web 原型、测试 - 玩法二 连连气球:连消畅玩版核心、Web 原型、Cocos 球槽组件与导出脚本 - 玩法三 六边一笔:规则库、求解器、10 关 + 转墙实验包、Web 原型、测试 - 产品文档、UI 设计规范、各玩法 GDD / HANDOFF - 文档移除全部外部参考作引用;删除玩法二 v0 旧稿
6.5 KiB
6.5 KiB
玩法三 · 六边一笔
六边形上一笔画走遍;墙贴在边上,挡住那一条邻接;线索数字必须踩在对应步号。
本目录自包含:规格、关卡、规则代码、求解器、生成器和 Web 原型。不 import 玩法一的矩形模型,也不把墙做成玩法一的后期关。壳的约定见 docs/PRODUCT.md。
几何锁六边形,墙是边不是格。关卡、资源、文案全部原创,不使用第三方题库或素材。
状态
M1/M2 已达:竖屏触摸 Web 原型可玩,10 关全部经求解器断言「唯一解 + 墙参与唯一性 + 无冗余墙」,存档、提示、音效、振动齐全。另有 转墙 实验包 9 关(GDD 附录 A)。下一步 M4 迁 Cocos。
目录
| 路径 | 用途 |
|---|---|
docs/GDD.md |
本玩法规格(权威) |
docs/HANDOFF.md |
交接文档:实现了什么、怎么实现、与 GDD 的偏差、待办与 Cocos 迁移顺序 |
levels/pack-1-tutorial.json |
第一包 10 关 |
levels/pack-2-spinner.json |
第二包(实验):转墙 9 关 |
src/ |
纯 TS 规则层,零 DOM / 零 Cocos 依赖。Web 与 Cocos 共用 |
web/ |
浏览器原型:DOM / Canvas / PointerEvent / localStorage 粘合层 |
tools/ |
求解器命令行:全关卡校验、关卡设计辅助、随机生成器 |
tests/ |
规则层单元测试(node:test) |
src/ 分层:
types.ts 关卡 JSON 结构(轴坐标 + 墙边)
board.ts HexBoard:轴坐标六邻接、墙、转墙(按步号判定)、几何邻接 / 可走邻接、连通性
game.ts 对局状态机:Command → GameEvent(start/append/undo/release/resume/reset;含 wallHit)
input.ts 手势语义:按下/移动/松手 + “当前压在哪个格” → Command
solver.ts 枚举满足线索的哈密顿路径、唯一解、墙有效性、提示(下一步 / 退回分叉)
geom.ts 纯几何:圆角多边形、凸裁剪、斜纹带
layout.ts 六边形布局:轴坐标 ↔ 像素、命中测试(带死区)、共用边、桥、墙带
view.ts HexBoardView:格/桥/数字/墙/冲突/提示/过关动效,只调用 Painter
painter.ts 绘制原语接口(多边形、线、圆、居中文字)
theme.ts 配色
progress.ts 存档(KeyValueStore 抽象,桶 mode:03-hex-walls)
levels.ts 关卡包解析
运行
cd modes/03-hex-walls
npm install
npm run dev # 起本地服务(默认 8100)+ 监听改动,终端会打印手机可访问的局域网地址
npm run build # 打包到 web/dist/app.js,之后可直接双击 web/index.html
npm run check # 类型检查(含 src/ 无 DOM 校验)+ 单元测试 + 全关卡校验
?dev=1 解锁全部关卡并暴露 window.__hexWalls 调试句柄(自动化手势测试用)。
关卡工具:
npm run validate # 每关:连通、恰好 1 解、第 3 关起去墙后不唯一、无冗余墙、转墙不可换静态墙
npm run validate -- 1-7 # 只看某关,并打印解
npm run design -- 1-7 --minimize # 当前线索里哪些可删
npm run design -- 1-7 --walls # 哪些墙可删
npm run design -- 1-7 --suggest 3 --path a,b,c,... # 给作者解找最少线索
npm run generate -- --shape hex2 --holes 2 --walls 3 --clues 3 --seed 7 --count 5 # 出候选盘
npm run generate -- --shape rect4x2 --walls 0 --spinners 1 --clues 2 --seed 212 # 带转墙的候选
第一包 · 10 关
每关只加一个旋钮(GDD §7)。「去墙解」= 拿掉全部墙后满足线索的解数,> 1 才说明墙在干活。
| 关 | N | 教什么 | 墙 | 线索 | 去墙解 |
|---|---|---|---|---|---|
| 1-1 | 3 | 滑动,邻格自动出步号 | 0 | 1 | – |
| 1-2 | 5 | 必须走完所有格 | 0 | 1, 5 | – |
| 1-3 | 4 | 第一堵墙:看起来相邻,滑不过去 | 1 | 1, 4 | 2 |
| 1-4 | 7 | 墙贴在 1 旁边,第一步只剩一个方向 | 1 | 1, 7 | 2 |
| 1-5 | 8 | 中段线索:3 在 1 旁边却要绕一步 | 1 | 1, 3, 8 | 2 |
| 1-6 | 11 | 空洞 + 两堵墙 | 2 | 1, 9 | 7 |
| 1-7 | 12 | 先想再画:旁边那格是陷阱 | 2 | 1, 9 | 8 |
| 1-8 | 12 | 综合:3 墙 3 线索 | 3 | 1, 6, 12 | 13 |
| 1-9 | 15 | 走廊:墙把一侧切成单向通道 | 3 | 1, 11, 15 | 16 |
| 1-10 | 19 | 小考:满花盘 4 墙 | 4 | 1, 10, 14 | 26 |
第二包 · 转墙(实验)
绕顶点转的墙,每走一格顺时针转 120°,轴心那端有圆点。规则与铁律见 GDD 附录 A。
| 关 | N | 教什么 | 静态墙 | 转墙 | 线索 | 去墙解 |
|---|---|---|---|---|---|---|
| 2-1 | 7 | 起手后墙正好挡住直觉的第一步,绕回来时它已转开 | 0 | 1 | 1, 7 | 2 |
| 2-2 | 8 | 用线索 4 算拍子:绕两格到 4,再往左时墙刚好开 | 0 | 1 | 1, 4 | 6 |
| 2-3 | 12 | 静态墙 + 转墙综合 | 1 | 1 | 1, 12 | 9 |
| 2-4 | 7 | 两个转墙,轴心相邻 | 0 | 2 | 1, 2 | 8 |
| 2-5 | 10 | 三角盘,两个转墙分居两端 | 0 | 2 | 1, 6 | 8 |
| 2-6 | 12 | 三个转墙围着中心格 | 0 | 3 | 1, 11 | 20 |
| 2-7 | 15 | 三个转墙挤在右侧 + 一堵静态墙 | 1 | 3 | 1, 7 | 49 |
| 2-8 | 17 | 三个转墙分布三处 | 0 | 3 | 1, 10 | 52 |
| 2-9 | 19 | 满花盘,四个转墙 | 0 | 4 | 1, 8, 17 | 41 |
交互(已实现)
- 有线索
1只能从它起手,点别处1抖一下。 - 按住滑到相邻、无墙、未走格 → 追加(弹一下、桥长出来、步号淡入、音高随步号上升)。
- 滑向有墙的邻格 → 墙闪白 + 红描边 + 轻推、短振动、闷响;不追加,指针逻辑上仍在末端。撞转墙同样反馈。
- 每追加 / 撤销一格,转墙做 120° 旋转动画。
- 滑回上一格 → 撤销。不相邻 / 已走且非上一格 → 忽略。
- 松手保留;从末端继续;点前一格撤销;点末端旁的空格直接追加。
- 线索踩错 → 红底 + 角标写应有步号,不中断手势。走完且全对 → 提亮、扫光、自动下一关。
- 提示:起点 / 下一步 / 退回分叉(压暗要退的段)/ 起手错(重开按钮脉冲)。
移植到 Cocos Creator
见 docs/HANDOFF.md §4.2 D。要点:src/ 整目录拷进 assets/modes/03-hex-walls/scripts/ 不改一行;写 GraphicsPainter(Graphics.moveTo/lineTo/close/fill/stroke + Label 池);触摸事件转节点坐标后喂 hitTest → PointerInput;sys.localStorage 实现 KeyValueStore。