1. 引言
    随着 HarmonyOS NEXT 正式商用,ArkTS + 原生 ArkUI 声明式开发 已成为鸿蒙应用开发的主流技术体系。相较于传统移动端命令式开发,鸿蒙声明式 UI 以数据驱动视图为核心,大幅简化视图更新逻辑、降低代码耦合度,也是入门开发者必须掌握的核心能力。
    在鸿蒙入门学习阶段,轻量交互式小游戏是综合练习布局、状态管理、事件响应、动画效果、随机算法的最优载体。本文选择骰子小游戏作为实战案例,基于最新 HarmonyOS NEXT API 12 进行开发,全程使用系统原生 API,无任何第三方依赖。
    本文不仅提供可直接编译运行的完整工程代码,还从原理、编码、排错、优化、拓展多个维度进行深度讲解,同时遵循华为官方编码规范与工程化设计思想。无论是日常技术学习、高校课程实训、课程设计,还是面试项目演示,本案例都具备极高的参考价值。
    技术栈清单
    开发语言:ArkTS(静态强类型,兼容 TS 语法)
    UI 框架:ArkUI 声明式布局
    核心能力:@State 响应式状态管理、组件点击事件、属性动画、弹性布局、随机数算法
    适配版本:HarmonyOS NEXT API 12
  2. 开发环境搭建与版本规范
    2.1 环境配置要求
    本项目严格适配 HarmonyOS NEXT API 12,低版本 SDK 会出现语法报错、API 不存在等问题,推荐环境配置如下:
    表格
    工具名称 推荐版本 用途说明
    DevEco Studio 4.0 及以上正式版 鸿蒙官方集成开发环境,负责代码编写、编译、调试、真机 / 模拟器运行
    HarmonyOS SDK API 12 目标编译版本,适配 HarmonyOS NEXT 系统特性
    运行设备 鸿蒙模拟器 / 鸿蒙真机 模拟器用于快速迭代调试,真机用于最终兼容性与体验测试
    2.2 环境校验流程
    打开 DevEco Studio,点击 Create Project,选择模板 Empty Ability;
    编程语言选择 ArkTS,Compile SDK 选定为 API 12;
    项目创建完成后,打开 File -> Project Structure,再次确认模块 SDK 版本;
    启动模拟器,确认系统镜像为 HarmonyOS NEXT,保证运行环境统一。
    重要说明:API 12 对早期版本的语法、组件属性做了标准化调整,本文代码为新版标准写法,不兼容 API 9/10/11 旧版本。
  3. 技术核心:声明式 UI 与数据驱动思想
    理解鸿蒙开发的核心设计理念,是写出高质量代码的前提。本节对比传统开发与鸿蒙开发的差异,并详解本项目核心装饰器 @State。
    3.1 命令式 UI VS 声明式 UI
    传统命令式开发(Android /iOS)
    开发者需要主动获取视图实例,手动修改控件样式、内容。当业务数据发生变化时,必须编写额外代码主动刷新 UI,数据与视图高度耦合,代码冗余量大,维护成本高。
    鸿蒙 ArkUI 声明式开发
    开发者仅需描述页面结构、样式、数据绑定关系,框架内部自动监听数据变化。数据更新时,框架主动刷新对应视图,开发者无需操作 DOM / 视图实例,解耦数据与 UI,开发效率与可维护性显著提升。
    3.2 @State 响应式状态原理
    @State 是 ArkUI 最基础、使用频率最高的状态装饰器,也是本项目的核心:
    被 @State 修饰的变量,会被 ArkUI 框架纳入响应式托管,自动建立「数据 - 视图」绑定关系;
    变量数值发生变更时,框架会精准定位依赖该变量的组件,执行局部刷新,而非全局重绘,渲染性能优异;
    作用域仅限当前自定义组件,适用于组件内部私有动态数据管理。
    本项目中,骰子点数、投掷次数、统计数据、动画状态等所有动态变量,均使用 @State 进行管理。
  4. 项目架构与编码规范
    为保证代码可读性、可维护性与可扩展性,本项目采用分层架构设计,同时统一编码规范,符合企业级鸿蒙开发标准。
    4.1 四层分层架构
    视图层(View):由 Column、Row、Text、Button 等基础组件构成,仅负责页面结构、样式、布局,不编写业务逻辑;
    状态层(State):通过 @State 统一管理全部动态数据,作为视图与业务逻辑的中间桥梁;
    业务逻辑层(Logic):封装随机数生成、点数统计、数据重置、状态控制等核心逻辑,实现逻辑与视图解耦;
    交互层(Event):绑定按钮点击事件,监听状态变化,触发动画与业务流程,处理人机交互。
    4.2 编码规范约定
    变量、方法统一使用小驼峰命名,命名语义化,做到见名知意;
    核心业务方法添加注释,复杂逻辑增加行内说明;
    固定逻辑、资源映射统一封装为独立方法,遵循单一职责原则;
    区分静态数据与动态状态,仅将会改变的数据使用 @State 修饰。
  5. 需求分析与功能设计
    5.1 核心功能
    摇骰子交互:点击按钮触发摇骰子动作,通过随机算法生成 1~6 随机点数;
    动画效果:骰子切换点数时添加旋转过渡动画,提升视觉体验;
    防重复点击:摇骰子过程中锁定按钮,避免连续点击造成数据异常;
    数据统计:实时统计总投掷次数、1~6 每个点数的出现频次;
    数据重置:一键清空所有统计数据与运行状态,恢复应用初始效果;
    设备适配:基于弹性布局实现全机型自适应,兼容手机、平板等设备。
    5.2 界面模块划分
    页面整体分为四大模块:标题区、骰子展示区、操作按钮区、数据统计区,结构清晰,层级简单。
  6. 完整源码实现
    文件路径:entry/src/main/ets/pages/Index.ets
    新建 API12 空白 ArkTS 项目后,直接替换该文件全部代码,即可一键编译运行。
@Entry
@Component
struct DiceGame {
  // ========== 响应式状态变量 ==========
  // 当前骰子点数(1-6)
  @State currentDiceNum: number = 1;
  // 总投掷次数
  @State totalCount: number = 0;
  // 各点数出现次数(索引0未使用,1-6对应点数1-6)
  @State countList: number[] = [0, 0, 0, 0, 0, 0, 0];
  // 是否正在摇骰子(控制动画状态)
  @State isRolling: boolean = false;

  build() {
    Column() {
      // 标题区域
      Column() {
        Text('🎲 骰子小游戏')
          .fontSize(24)
          .fontWeight(FontWeight.Bold)
          .margin({ bottom: 8 })
        Text('趣味摇骰子,随机点数挑战')
          .fontSize(14)
          .fontColor('#666666')
      }
      .width('100%')
      .alignItems(HorizontalAlign.Center)
      .margin({ top: 20, bottom: 20 })

      // 骰子显示区域
      Column() {
        // 用Text组件模拟骰子(也可以用Image组件加载骰子图片)
        Text(this.getDiceText(this.currentDiceNum))
          .fontSize(120)
          .fontColor('#000000')
          .rotate({ angle: this.isRolling ? 360 : 0 })
          .animation({
            duration: 500,
            curve: Curve.EaseOut
          })

        // 本次结果提示
        Text(`本次摇出点数:${this.currentDiceNum}`)
          .fontSize(18)
          .fontColor('#34A853')
          .fontWeight(FontWeight.Medium)
          .margin({ top: 30 })
      }
      .width('100%')
      .height(300)
      .backgroundColor('#F5F5F5')
      .borderRadius(16)
      .justifyContent(FlexAlign.Center)
      .margin({ bottom: 30 })

      // 操作按钮区域
      Row() {
        Button('🎲 摇骰子')
          .width(150)
          .height(50)
          .fontSize(16)
          .backgroundColor('#34A853')
          .onClick(() => {
            if (this.isRolling) return;
            this.rollDice();
          })

        Button('🔄 重置数据')
          .width(150)
          .height(50)
          .fontSize(16)
          .backgroundColor('#EA4335')
          .margin({ left: 20 })
          .onClick(() => {
            this.resetData();
          })
      }
      .margin({ bottom: 30 })

      // 统计数据区域
      Column() {
        Text(`总投掷次数:${this.totalCount}`)
          .fontSize(16)
          .fontWeight(FontWeight.Medium)
          .margin({ bottom: 15 })

        // 点数统计列表
        Column() {
          ForEach([1, 2, 3, 4, 5, 6], (num: number) => {
            Text(`${num}点:${this.countList[num]}`)
              .fontSize(14)
              .fontColor('#666666')
              .margin({ top: 5 })
          })
        }
        .alignItems(HorizontalAlign.Center)
      }
      .width('100%')
      .padding(20)
      .backgroundColor('#F8F8F8')
      .borderRadius(12)

    }
    .width('90%')
    .padding(20)
    .backgroundColor('#FFFFFF')
    .borderRadius(16)
    .justifyContent(FlexAlign.Start)
    .height('100%')
    .alignItems(HorizontalAlign.Center)
    .backgroundColor('#FFFFFF')
  }

  // 生成骰子文本(也可以替换为Image组件加载不同点数的图片)
  getDiceText(num: number): string {
    const diceList = ['', '⚀', '⚁', '⚂', '⚃', '⚄', '⚅'];
    return diceList[num];
  }

  // 摇骰子核心逻辑
  rollDice() {
    this.isRolling = true;
    // 模拟动画效果,500ms后生成随机数
    setTimeout(() => {
      // 生成1-6的随机整数
      const newNum = Math.floor(Math.random() * 6) + 1;
      this.currentDiceNum = newNum;
      // 更新统计数据
      this.totalCount += 1;
      this.countList[newNum] += 1;
      this.isRolling = false;
    }, 500);
  }

  // 重置所有数据
  resetData() {
    this.currentDiceNum = 1;
    this.totalCount = 0;
    this.countList = [0, 0, 0, 0, 0, 0, 0];
    this.isRolling = false;
  }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  1. 核心代码深度拆解
    7.1 响应式状态定义
@State private currentDiceNum: number = 1;
@State private totalThrowCount: number = 0;
@State private pointStatistics: number[] = [0, 0, 0, 0, 0, 0, 0];
@State private isExecuting: boolean = false;

所有动态数据统一使用 @State 修饰,组件内部私有化,保证数据安全。
currentDiceNum:记录当前骰子点数,驱动 UI 展示与动画;
totalThrowCount:全局投掷总次数;
pointStatistics:数组存储各点数出现次数,索引与点数一一对应;
isExecuting:动作执行标记,实现按钮禁用、防重复点击。
7.2 资源映射方法

private getDiceEmoji(point: number): string {
  const emojiList: string[] = ['', '⚀', '⚁', '⚂', '⚃', '⚄', '⚅'];
  return emojiList[point];
}

将骰子表情统一封装为独立方法,实现资源与业务逻辑分离,后续如需替换图片、修改样式,仅需改动当前方法,拓展性更强。
7.3 随机数算法解析

const randomPoint: number = Math.floor(Math.random() * 6) + 1;

Math.random():生成 [0, 1) 区间浮点数;
乘以 6 后区间变为 [0, 6);
Math.floor() 向下取整,得到 0~5 整数;
末尾 +1,最终生成标准骰子点数 1~6。
7.4 业务逻辑方法
startThrowDice 封装完整摇骰子流程,resetAllData 统一重置所有状态,严格遵循单一职责原则,代码内聚性高、便于维护。
7.5 列表渲染 ForEach
使用 ForEach 循环渲染 1~6 点统计数据,避免重复编写组件代码,提升代码复用性。
8. 动画原理与交互优化
本项目采用 ArkUI 原生属性动画,由系统渲染层驱动,性能损耗极低,是鸿蒙官方推荐的轻量动画方案。

Text(...)
  .rotate({ angle: this.isExecuting ? 360 : 0 })
  .animation({ duration: 500, curve: Curve.EaseOut })

duration: 500:动画时长 500ms,符合移动端通用交互标准,节奏自然;
curve: Curve.EaseOut:先快后慢缓动曲线,模拟真实物理运动,优于线性动画;
rotate 旋转属性:结合 isExecuting 状态控制旋转角度,状态变化自动触发动画;
联动交互:动画执行期间按钮禁用,从交互层面规避异常操作。
9. 功能测试与设备适配
9.1 运行步骤
DevEco Studio 导入项目,确认 SDK 为 API 12;
启动模拟器或连接鸿蒙真机;
点击运行按钮,部署应用并开始测试。
9.2 功能测试用例
初始状态:骰子为 1 点,所有统计数据归零;
摇骰子:点击按钮,骰子旋转,随机生成点数,统计数据同步累加;
防重测试:连续快速点击按钮,按钮锁定,不会重复执行逻辑;
重置测试:点击重置,所有状态、数据恢复初始值;
适配测试:切换不同分辨率设备,页面布局无变形、元素无溢出。
10. 开发疑难问题汇总与解决方案
结合实操经验,整理开发本项目高频报错、异常问题,附根因与解决方案,帮助开发者避坑。
问题 1:数据更新后,UI 视图无变化
根因:动态变量未添加 @State 装饰,普通变量无法触发响应式刷新;
方案:所有驱动 UI 变化的变量,必须使用 @State 修饰。
问题 2:随机数出现 0,骰子展示异常
根因:随机算法缺少 +1,取值范围错误;
方案:固定写法 Math.floor(Math.random() * 6) + 1,保证取值 1~6。
问题 3:动画完全不触发
根因:动画依赖的状态变量未发生改变;
方案:保证动画组件绑定 @State 变量,交互过程中状态正常变更。
问题 4:连续点击按钮,统计数据错乱
根因:未做防重复点击处理,短时间多次触发业务逻辑;
方案:新增执行状态标记,动作执行期间禁用按钮。
问题 5:不同设备页面布局错乱
根因:大量使用固定宽高,未采用弹性布局;
方案:优先使用百分比、弹性布局,减少硬编码尺寸。
11. 性能优化与代码健壮性改造
11.1 性能优化
精简视图层级:页面布局扁平化,减少组件嵌套,降低渲染压力;
精准使用状态:仅动态数据使用 @State,静态内容不占用响应式资源;
动画优化:使用系统原生属性动画,避免自定义动画带来的性能损耗。
11.2 健壮性优化
状态闭环:所有状态变更都有对应的重置逻辑,避免状态残留;
交互拦截:通过 enabled 属性控制按钮可用性,拦截非法操作;
类型约束:ArkTS 强类型约束,编译阶段规避类型错误。
12. 功能拓展与二次开发思路
在现有基础功能之上,可根据学习需求拓展进阶功能,提升项目完整度:
多骰子模式:支持同时投掷 2 个 / 3 个骰子,计算点数总和;
图片资源替换:使用本地图片资源替代 Emoji,实现自定义骰子样式;
音频音效:接入鸿蒙音频 API,添加摇骰子、结果提示音效;
历史记录:使用数组存储每一局点数,实现对战日志功能;
趣味玩法:新增猜大小、猜点数等互动玩法;
数据可视化:结合图表组件,直观展示各点数出现概率。
13. 技术总结与进阶学习路线
13.1 知识点总结
通过本项目,我们综合掌握了以下鸿蒙核心知识点:
理解声明式 UI、数据驱动视图的设计思想,区分新旧开发模式;
熟练使用 @State 基础状态管理,掌握响应式局部刷新原理;
掌握 Column / Row 弹性布局,实现多设备自适应页面;
学会 ArkUI 属性动画的配置、触发逻辑与性能特点;
掌握随机数算法、按钮事件、列表渲染、数据统计等综合能力;
建立基础工程化思维,理解分层架构、代码解耦、健壮性优化。
13.2 后续进阶学习路线
进阶状态管理:学习 @Link、@Prop、@Provide 等跨组件状态装饰器;
自定义组件:拆分页面模块,实现组件复用,提升工程化能力;
页面路由:学习鸿蒙页面跳转,开发多页面应用;
资源访问:系统学习图片、音频、文件等本地资源调用;
高阶动画:探索显式动画、转场动画、矢量动画等复杂动效。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐