【复刻微信小程序 系列】2. 数字华容道
数字华容道滑块 水管一个小游戏塞了两种玩法起因这次做的是「数字华容道」就是小时候玩的那种——一堆数字方块在格子里滑来滑去把顺序拼对就赢了。做完之后觉得不过瘾又加了个水管模式把管道拼通也算一种玩法。为啥选这个因为够纯粹。不用找素材不用搞物理碰撞一个 Canvas 从头画到尾就行玩家要么滑一下要么点两下交互极其简单。不过真写起来发现事儿还不少——怎么打乱才保证一定能解开屏幕适配为啥点不准水管拼对了为啥不给过一个一个来。两个模式都支持 3×3 到 7×7 五个难度下面说说怎么做的。先说说这俩模式经典模式就是最传统的数字华容道——一个 N×N 的格子里面有数字方块和一个空位用手指把方块滑到空位那边去全部按顺序排好就赢了。会记你花了多长时间走了多少步还给你存个最佳纪录。3×3 随便玩玩7×7 就得认真想想了。水管模式这个是自己瞎琢磨的玩法——棋盘上散着一堆水管碎片直的和弯的还有一些空位。起点在左上角顶部终点在右下角底部你要做的就是点两个格子让它们互换位置把管道拼成一条通路。管子方向是固定的不能转只能挪位置。拼通了之后会有个蓝色水流从头流到尾的动画挺有成就感的。选择模式的界面长这样怎么做的跟 AI 对需求动手之前先跟 AI 把需求聊清楚了。我大概描述了想做什么它帮我把方案细化成了一张表——页面结构、核心玩法、技术要点、技术栈全列出来了。基本就是经典模式手势滑动、扁平化视觉、本地存档、打乱保证有解。有了这个方案就可以直接开干了。代码怎么组织的没用框架原生 Canvas但是懒得手写 就直接用workbuddy的skill【weixin-minigam-helper】去实现了场景管理器思路很朴素每个页面就是一个场景注册进去要切换就 switchTo每个场景自己管渲染和触摸事件。所有场景共用一块 canvas主循环每帧问一下当前场景该画啥。踩过的几个坑第一个画面和手指对不上一跑起来发现两个毛病——画面糊、按钮点不中。我把这个情况发给 AI 看它马上就定位了canvas 用的物理像素1170×2532但手指触摸事件给的是逻辑像素390×844。我把按钮画在 y1393 的位置但手指最远就能摸到 y844当然点不着。解决方法就是加一行setTransform让绘制也用逻辑像素坐标。之后所有绘制代码直接用逻辑坐标390×844跟触摸坐标自然就对上了。以后做小游戏 Canvas 项目开头就加这个省得后面到处改。第二个打乱出来可能无解数字华容道有个经典问题随机排列之后可能无解。网上说可以算逆序数判断但奇数阶和偶数阶的规则还不一样写对了心里也没底。跟 AI 讨论之后用了个更稳的办法——从正确答案开始随机合法移动很多步。因为每一步都是合法移动倒着走回去一定能还原所以打乱出来的局面 100% 有解。笨是笨了点但绝对不会翻车。第三个滑动方向搞反了手指往上滑应该是把空格下面的方块拉上来——不是把上面的方块推下去。这个一开始老搞混想通了就好但第一次写的时候确实愣了一会儿。水管模式怎么搞的这块比经典模式复杂多了花了大部分时间。路径怎么生成用 DFS深度优先搜索随机走出一条从左上到右下的路。难度越高路越长——第一关走最短路径之后每关路径多拐两步。但 DFS 不一定能找到刚好那么长的路所以做了个降级策略先尝试 200 次找精确长度找不到就放宽一点再找不到就直接走最短路径算了。管子类型怎么定路径生成完看每个格子的前一格和后一格在什么方位就知道该放什么管子了。总共就 6 种——左右通、上下通、上右弯、下右弯、下左弯、上左弯。起点从顶部进水终点从底部出水中间每个格子看看前后邻居在哪个方向就能推出来放什么管子。通关判断的坑——不能只对答案这个坑是玩着玩着发现的。第一版判通关很偷懒——直接看棋盘跟标准答案是不是一模一样。然后翻车了我拼出了一条跟原始答案不一样但确实是通的路径结果不给过。这哪行啊水管游戏本来就可能有多种解法。把这个情况截图发给 AI讨论之后改成了真正去追踪管道连通性——从起点出发一路顺着管子走能走到终点就算赢。不管你怎么拼的只要水能从头流到尾就通关。水流动画也是沿着实际检测出来的路径播的。画管子的细节——别让线条溢出格子这又是个视觉上的问题。Canvas 画粗线条线宽是往两边扩的如果端点贴着格子边缘画线条就会溢出去L形弯管尤其明显。跟 AI 聊了这个情况之后的方案是把端点往里缩一点半个线宽3像素管子也画细一点从格子宽度的 30% 收到 22%。L 形弯管就是从一个端点画到格子中心再折到另一个端点只要端点缩进来了就不会溢出。空格也得能换一开始设计的是只有有管子的格子才能选、只有两个有管子的格子才能互换。玩了两把就觉得不对劲——我明明想把管子挪到旁边的空位去凭啥不让太难受了。跟 AI 反馈了这个体验问题索性改成随便哪两个格子都能换有管子的和没管子的也能换。自由度一下就上来了玩起来舒服很多。返回按钮的小事最早用这个字符当返回箭头结果不同手机上渲染出来长得不一样有的偏上有的偏胖。后来直接用 Canvas 画了个箭头——三根线段拼个 V 形圆角收边所有设备上看起来都一样。小事但值得做。最后的成品东西怎么搞的画面Canvas 2D requestAnimationFrame页面切换AI写的场景管理器经典操作手势滑动也支持点击水管操作点两个格子互换判通关路径连通追踪水流动画一段一段蓝色渐变填上去存档wx.setStorageSync屏幕适配setTransform(dpr)配色方面浅灰打底、蓝色主色调、绿色通关色方块白底圆角带点阴影水管灰色外壁蓝色水流。做完的感受屏幕适配这个东西canvas 宽高设物理像素、画画用逻辑像素一个 setTransform 搞定。下次闭着眼睛写。打乱算法别花里胡哨从正确答案随机走就完事了保证有解比啥都重要。判通关不能偷懒尤其是有多个正确答案的游戏得真的去验证连通性不能光比对答案。画粗线条记得端点往里缩不然线宽会溢出格子边界视觉上很丑。交互限制越少越好空格能换、任意两格能换看着是小改动玩起来舒服很多。还没做的事方块滑动加个过渡动画现在是直接蹦过去的加点音效分享功能和排行榜水管旋转模式又一种新玩法卡关了给个提示下次试试复刻一个 肉鸽小游戏溜了溜了