数字华容道:用最少的移动把 15 块数字归位

举报
deli007 发表于 2026/09/14 16:09:38 2026/09/14
【摘要】 数字华容道:用最少的移动把 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 开发者空间

  1. 浏览器打开 https://devstation.developer.huaweicloud.com/aidevspace?utm_source=opcsfsq&utm_medium=wbwz
  2. 弹窗「请选择要进入的版本」→ 点击 体验版
  3. 首次使用会跳到华为云登录页,扫码登录一次,后续浏览器会话复用
  4. 弹窗「临时凭据自动配置」→ 点击 同意,沙箱自动创建

进入 AI 开发者空间主界面后,先等左侧菜单加载出来,再找到 CodeArts,点击它右侧的浏览器图标,打开码道 WebUI 对话窗口:

AI 开发者空间主界面

打开后码道 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 表示。layoutstate.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, 0refreshOk 则对已经回到正确位置的数字块加 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 仓库:

总结

数字华容道把「可玩性」压回两个关键设计:洗牌用随机合法移动保证有解,视图层只改 left / top 让逻辑和渲染解耦。棋盘是一维数组、空位用 0 表示,移动判定靠行列坐标的曼哈顿距离,胜利则用 isSolved 全量比对。最快的一局几秒就能完成,三档难度也足够给想要挑战的人加码。后续可以继续加「最少步数提示」「历史最佳记录」,或把洗牌动画做得更顺滑。

如果还没用过码道,可以免费开通体验版:https://developer.huaweicloud.com/codeartsco.html?source=dmzntgwsf&sourcead=dmzntgwwbwz

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。