数字华容道:用最少的移动把 15 块数字归位
数字华容道最折磨人的不是不会拼,而是拼到一半才发现棋盘是无解的。这个工具默认为你按「合法移动」洗牌,保证每一局都一定能归位;点击与空格相邻的数字块即可滑动,步数和计时自动记录,胜利时逐块弹跳加彩带,3×3 / 4×4 / 5×5 三档难度随时切换。先看成品,再讲怎么用华为云 CodeArts 码道 WebUI 一段话把它做出来、部署上线。
这个工具做什么
它把「数字华容道」做成一个零依赖的单页小游戏:
- 保证有解:洗牌不是随意打乱,而是从已解状态做数百次随机合法移动,杜绝「拼到绝望才发现无解」。
- 三档难度:3×3 / 4×4 / 5×5 一键切换,棋盘大小和洗牌步数随之变化。
- 步数与计时:首次点击开始计时,移动步数实时统计,归位后显示「用时 + 步数」。
- 可移动高亮:与空格相邻的数字块会亮起提示,避免瞎点。
- 归位反馈:数字回到正确位置后变色标记,一眼看出还差哪几块。
- 胜利动画:逐块弹跳 + 彩带特效 + 成功浮层,完成时明确告诉你这局拿下。
- 洗牌 / 重置:洗牌重开一局,重置回到本局初始打乱态。
- 响应式布局:手机、电脑都适配,深色渐变 UI。

码道开通(免费体验版)
开始之前,先免费开通码道体验版。不需要装任何软件,浏览器就能用:
https://developer.huaweicloud.com/codeartsco.html?source=dmzntgwsf&sourcead=dmzntgwwbwz
开通后有三种使用方式:WebUI(浏览器对话)、TUI(终端命令行)和桌面 IDE(IDE 插件)。本文用 WebUI 版演示。
进入 AI 开发者空间
- 浏览器打开 https://devstation.developer.huaweicloud.com/aidevspace?utm_source=opcsfsq&utm_medium=wbwz
- 弹窗「请选择要进入的版本」→ 点击 体验版
- 首次使用会跳到华为云登录页,扫码登录一次,后续浏览器会话复用
- 弹窗「临时凭据自动配置」→ 点击 同意,沙箱自动创建
进入 AI 开发者空间主界面后,先等左侧菜单加载出来,再找到 CodeArts,点击它右侧的浏览器图标,打开码道 WebUI 对话窗口:

打开后码道 WebUI 会先和你打招呼,下方就是需求输入框:

小贴士:体验版沙箱 3 小时后自动重置,生成完记得把
index.html下载保存。
任务描述
在码道 WebUI 输入框粘贴以下需求,回车发送:
开发一个「数字华容道」单文件网页应用:4×4 棋盘随机打乱 1~15 数字和一个空格,点击相邻数字块滑动到空格,目标是按顺序归位;支持 3×3/4×4/5×5 难度切换、步数统计、计时、胜利动画、重置和洗牌按钮,界面美观简洁,手机和电脑都能用,所有代码写在一个 index.html 里。完成后用部署功能部署成可访问的网页应用,生成一个公网可访问的分享链接,并告诉我访问地址。

这轮码道具体做了什么
不是复述通用 AI 能力,而是它在这次项目里的实际动作:
- 在
/workspace/huarongdao下创建单文件index.html,把棋盘渲染、移动判定、计时器和胜利动画全部写进一个文件,无第三方依赖。 - 探测空闲端口并用
python3 -m http.server启动服务,curl自检 HTTP 200 后给出内部预览地址。 - 用 DevBridge 创建公网隧道并验证可访问性,最后给出 8 小时有效的公网分享链接。
代码亮点
以下是 index.html 里值得关注的设计思路和实现细节。
1. 洗牌靠「合法移动」,不靠「随机打散」
直接随机把数字塞进棋盘,很容易出现无解局面。shuffleByMoves 从完整状态出发,每一步都把空格和相邻数字块交换,做了足够多次数后又用 isSolved 兜底重洗,保证每局可解:
function shuffleByMoves(n, steps) {
var arr = solvedArray(n);
var empty = arr.indexOf(0);
var last = -1;
for (var s = 0; s < steps; s++) {
var neighbors = [];
var er = Math.floor(empty / n), ec = empty % n;
if (er > 0) neighbors.push(empty - n);
if (er < n - 1) neighbors.push(empty + n);
if (ec > 0) neighbors.push(empty - 1);
if (ec < n - 1) neighbors.push(empty + 1);
var candidates = neighbors.filter(function (x) { return x !== last; });
if (candidates.length === 0) candidates = neighbors;
var pick = candidates[Math.floor(Math.random() * candidates.length)];
arr[empty] = arr[pick];
arr[pick] = 0;
last = empty;
empty = pick;
}
return arr;
}
函数里 last 用来记录上一步空格位置,优先排除「刚退回去」的那一步,让洗牌更有随机感,而不是来回抖动。
2. 曼哈顿距离一眼判断「能不能点」
只有和空格上下左右相邻的数字块才允许移动,isAdjacent 用行列坐标差之和是否等于 1 来判断:
function isAdjacent(a, b, n) {
var ra = Math.floor(a / n), ca = a % n;
var rb = Math.floor(b / n), cb = b % n;
return (Math.abs(ra - rb) + Math.abs(ca - cb)) === 1;
}
每次移动后调用 refreshMovable,给可移动的数字块加上 movable class 做高亮提示。
3. 一维数组存棋盘,渲染只改 left / top
棋盘状态就是一个一维数组 state.tiles,空位用 0 表示。layout 按 state.tiles.indexOf(v) 反推行列坐标,再把每个数字块的 left / top 直接写进 style,交给 CSS 的过渡动画完成滑动:
function layout() {
var n = state.size;
var bw = board.clientWidth;
var gap = n >= 5 ? 6 : 8;
var tileSize = (bw - gap * (n + 1)) / n;
var fontSize = Math.max(16, Math.floor(tileSize * 0.42));
for (var v = 1; v < n * n; v++) {
var el = tileEls[v];
if (!el) continue;
var idx = state.tiles.indexOf(v);
var r = Math.floor(idx / n), c = idx % n;
el.style.width = tileSize + "px";
el.style.height = tileSize + "px";
el.style.fontSize = fontSize + "px";
el.style.left = (gap + c * (tileSize + gap)) + "px";
el.style.top = (gap + r * (tileSize + gap)) + "px";
}
}
这套写法把「状态」和「视图」分得很干净:逻辑只改数组,视图只跟着数组重排即可。
4. 归位不仅判断输赢,还实时标色
isSolved 检查数列是否已经是 1..n²-1, 0;refreshOk 则对已经回到正确位置的数字块加 ok class,让玩家随时看到进度:
function isSolved(arr) {
var n = state.size;
for (var i = 0; i < arr.length - 1; i++) {
if (arr[i] !== i + 1) return false;
}
return arr[arr.length - 1] === 0;
}
function refreshOk() {
var n = state.size;
for (var v = 1; v < n * n; v++) {
var idx = state.tiles.indexOf(v);
var el = tileEls[v];
if (!el) continue;
if (idx === v - 1) el.classList.add("ok");
else el.classList.remove("ok");
}
}
直接下载试玩
本次生成的项目就是单文件 index.html,没有第三方依赖,把文件保存到本地后双击用浏览器打开即可运行。源码同步到公开 Demo Park 仓库:
- Demo Park 仓库:https://atomgit.com/deli007/demo_park
- 本案例目录:https://atomgit.com/deli007/demo_park/tree/main/codearts-sliding-puzzle
总结
数字华容道把「可玩性」压回两个关键设计:洗牌用随机合法移动保证有解,视图层只改 left / top 让逻辑和渲染解耦。棋盘是一维数组、空位用 0 表示,移动判定靠行列坐标的曼哈顿距离,胜利则用 isSolved 全量比对。最快的一局几秒就能完成,三档难度也足够给想要挑战的人加码。后续可以继续加「最少步数提示」「历史最佳记录」,或把洗牌动画做得更顺滑。
如果还没用过码道,可以免费开通体验版:https://developer.huaweicloud.com/codeartsco.html?source=dmzntgwsf&sourcead=dmzntgwwbwz
- 点赞
- 收藏
- 关注作者
评论(0)