HarmonyOS 数独:ArkTS 实现 9×9 棋盘实时行列宫冲突校验

举报
yd_266360277 发表于 2026/11/06 23:31:57 2026/11/06
【摘要】 结合鸿蒙开发实践中心的数独小游戏案例,讲清 ArkTS 9×9 棋盘实时行列宫冲突校验的做法:二维数组存盘、@State 驱动刷新、Math.floor(row/3)*3 定位 3×3 宫,以及用文件直读做通关进度持久化。

今天在华为云鸿蒙开发实践中心看了一个纯端侧数独小游戏案例:9×9 棋盘、54 道分级题库、填数实时校验、通关进度本地保存,全程不联网。把其中最核心的“实时冲突校验”梳理一下,这也是写一个能玩的数独最先要解决的问题。

1. 棋盘用什么数据结构

用一个 9×9 的二维数组存当前棋盘,0 表示空格;再用一个集合记录冲突格,键写成 “行,列” 的形式:

@State board: number[][] = [] // 9×9,0 = 空格
@State conflictCells: Set<string> = new Set() // 冲突格 "row,col"

@State 是 ArkTS 的状态装饰器,数据一变,声明式 UI 自动重渲染,不用手动刷新界面。棋盘、数字面板、进度卡片都可以拆成 @Builder 构建函数或子组件,用 @Prop 把状态往下传。

2. 冲突校验:只查三处

每次往 (row, col) 填入数字 num,依次查三处:同一行、同一列、所在的 3×3 宫。宫的定位是关键一行代码:

const boxRow = Math.floor(row / 3) * 3
const boxCol = Math.floor(col / 3) * 3

行号 0/1/2 映射到 0,3/4/5 映射到 3,6/7/8 映射到 6,列同理;再从 (boxRow, boxCol) 扫描 9 格即可。行、列、宫都只要线性扫一遍,9×9 的规模下成本可以忽略,完全可以做到每次填数都实时算。

3. 填数时的联动

填数不是只校验当前格,要把结果写回 UI 状态:

function onCellInput(row: number, col: number, num: number) {
  board[row][col] = num
  if (checkConflict(row, col, num)) {
    conflictCells.add(`${row},${col}`) // 标红
  } else {
    conflictCells.delete(`${row},${col}`) // 清除标记
  }
}

注意一个细节:改掉一个格子可能让原来冲突的格子恢复正常,所以更稳妥的做法是每次填数后全盘重算冲突集合,而不是只处理当前格。棋盘只有 81 格,全盘重算的开销完全可以接受,逻辑也更不容易漏。

4. 题库:确定性生成

案例的 54 道题不是手写死数据,而是由一道基准解经确定性变换(mulberry32 种子随机数)生成,同一输入得到同一题库,方便复现和测试。需要说明的是:题目由合法解盲挖空格得到,没有做唯一性校验,同一题可能存在多套合法终盘;通关判定只校验“填满且无行列宫冲突”,不与内置答案逐格比对。

5. 进度持久化:直接读文件

通关进度只存在应用沙箱的 sudoku_progress.json(filesDir 目录)里,用 @ohos.file.fs 读写,卸载即清除。案例里特意选了“每次直接读文件”的方式,而不是依赖跨页面缓存的值,目的是规避“返回首页读到旧进度”的缓存一致性问题——首页返回时重新读一遍文件,进度计数自然就对了。

小结

一个能玩的端侧数独,核心就四件事:二维数组存盘、@State 驱动刷新、行列宫三重实时校验、文件直读做持久化。验证环境是 DevEco Studio,compatibleSdk 6.1.0(23),compileSdk 与 targetSdk 6.1.1(24)。这套“棋盘渲染 + 实时校验 + 本地存档”的组合,照搬到扫雷、华容道、记忆翻牌这类游戏同样成立。

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

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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