# 鸿蒙 HarmonyOS 应用开发实战(第26期)|石头剪刀布(Rock-Paper-Scissors)— 游戏逻辑与胜负判定精讲

发布时间:2026/9/14 23:22:33

# 鸿蒙 HarmonyOS 应用开发实战(第26期)|石头剪刀布(Rock-Paper-Scissors)— 游戏逻辑与胜负判定精讲 一、应用概述石头剪刀布Rock-Paper-Scissors是一款经典的人机对战游戏用户与电脑进行石头剪刀布对决。应用提供了直观的图形化选择按钮✊✌️️玩家点击选择后电脑随机出拳系统根据规则判定胜负并实时更新比分。应用基于 HarmonyOS 的 ArkTS 语言和声明式 UI 框架构建完美展示了 Record 字典胜负表、Type 类型别名、枚举约束、计分追踪、以及状态驱动的胜负反馈等核心技术的综合运用。对于鸿蒙开发者而言石头剪刀布是一个展示游戏逻辑编码的经典案例——它让你在约87行代码中同时掌握类型安全、字典查找表、随机选择算法、计分系统四大核心能力这些能力广泛适用于猜拳、棋牌、回合制游戏等场景。1.1 功能特性三种出拳选择石头✊、剪刀✌️、布️电脑随机出拳使用 Math.random() 随机选择胜负规则判定基于字典查找表快速判定结果实时比分追踪分别记录玩家和电脑的得分胜负状态反馈不同结果使用不同颜色和文字提示比分重置功能一键清除历史比分记录1.2 适用场景休闲娱乐小游戏决策时作为随机辅助概率统计教学演示儿童逻辑思维训练二、技术架构2.1 整体架构概览┌─────────────────────────────────────────┐ │ 数据层 │ │ Choice 类型 (石头|剪刀|布) │ │ EMOJI / RULES / CHOICES 常量字典 │ ├─────────────────────────────────────────┤ │ 状态管理层 │ │ State playerChoice / computerChoice │ │ State result / playerScore / │ │ computerScore / played │ ├─────────────────────────────────────────┤ │ 业务逻辑层 │ │ play(choice) —— 出拳 判定 计分 │ │ reset() —— 重置比分 │ ├─────────────────────────────────────────┤ │ UI 表示层 │ │ 电脑区域 / 结果显示 / 玩家区域 / │ │ 选择按钮 / 比分板 / 重置按钮 │ └─────────────────────────────────────────┘2.2 游戏流程用户点击选择石头/剪刀/布 ↓ playerChoice 用户选择 computerChoice 随机选择 ↓ 查询 RULES[playerChoice][computerChoice] ↓ 胜负判定 → 更新比分 ↓ UI 重新渲染 → 显示结果和出拳三、核心代码深度分析3.1 完整的页面源码import { router } from kit.ArkUI; type Choice 石头 | 剪刀 | 布; const EMOJI: RecordChoice, string { 石头: ✊, 剪刀: ✌️, 布: ️ }; const RULES: RecordChoice, RecordChoice, string { 石头: { 石头: 平局, 剪刀: 你赢了, 布: 电脑赢了 }, 剪刀: { 石头: 电脑赢了, 剪刀: 平局, 布: 你赢了 }, 布: { 石头: 你赢了, 剪刀: 电脑赢了, 布: 平局 }, }; const CHOICES: Choice[] [石头, 剪刀, 布]; Entry Component struct index26 { State playerChoice: Choice 石头; State computerChoice: Choice 石头; State result: string 选择你的出拳; State playerScore: number 0; State computerScore: number 0; State played: boolean false; play(choice: Choice) { this.playerChoice choice; this.computerChoice CHOICES[Math.floor(Math.random() * 3)]; this.result RULES[this.playerChoice][this.computerChoice]; if (this.result 你赢了) this.playerScore; else if (this.result 电脑赢了) this.computerScore; this.played true; } reset() { this.playerScore 0; this.computerScore 0; this.result 选择你的出拳; this.played false; } build() { Column() { Row() { Text(‹ 返回).fontSize(16).fontColor(#0077FF).onClick(() router.back()) Text(✊ 石头剪刀布).fontSize(18).fontWeight(FontWeight.Bold) Blank() }.width(92%).padding({ top: 16, bottom: 8 }) Column() { // 电脑区域 Text(电脑).fontSize(16).fontColor(#888) Text(EMOJI[this.computerChoice]).fontSize(64) if (this.played) Text(this.computerChoice).fontSize(16) // 结果 Text(this.result).fontSize(22).fontWeight(FontWeight.Bold) .fontColor(this.result 你赢了 ? #4CAF50 : this.result 电脑赢了 ? #F44336 : #FF9800) .margin(16) // 玩家区域 Text(EMOJI[this.playerChoice]).fontSize(64) Text(你).fontSize(16).fontColor(#888) if (this.played) Text(this.playerChoice).fontSize(16) // 选择按钮 Row({ space: 12 }) { ForEach(CHOICES, (c: Choice) { Button() { Column() { Text(EMOJI[c]).fontSize(32) Text(c).fontSize(14).fontColor(#fff) } }.width(90).height(90).borderRadius(16).backgroundColor(#0077FF) .onClick(() this.play(c)) }) }.margin({ top: 16 }) // 比分板 Row({ space: 20 }) { Text(你: ${this.playerScore}).fontSize(18).fontWeight(FontWeight.Bold) .fontColor(#4CAF50) Text(电脑: ${this.computerScore}).fontSize(18).fontWeight(FontWeight.Bold) .fontColor(#F44336) }.margin({ top: 12 }) // 重置按钮 Button(重置比分).width(120).height(40).borderRadius(20) .backgroundColor(#9E9E9E).margin({ top: 8 }) .onClick(() this.reset()) } .layoutWeight(1).justifyContent(FlexAlign.Center) } .width(100%).height(100%).backgroundColor(#f8f8f8) } }3.2 Type 类型别名与类型安全type Choice 石头 | 剪刀 | 布;type是 ArkTS 中定义类型别名的关键字。这里定义了一个联合类型Union TypeChoice只能是三个字符串字面量之一。使用类型别名的好处编译期类型检查任何不符合Choice类型的赋值都会在编译时报错代码自文档化清晰地表达了这个变量的取值范围只有三种IDE 智能提示在编码时获得准确的自动补全和类型提示类型别名在整个应用中被多处使用const EMOJI: RecordChoice, string { ... }; // 键类型为 Choice const RULES: RecordChoice, RecordChoice, string { ... }; // 双层嵌套 const CHOICES: Choice[] [石头, 剪刀, 布]; // 数组元素类型为 Choice play(choice: Choice) { ... } // 参数类型为 Choice这种类型约束确保了数据的一致性和安全性是 ArkTS 类型系统的核心优势。3.3 胜负判定表的设计const RULES: RecordChoice, RecordChoice, string { 石头: { 石头: 平局, 剪刀: 你赢了, 布: 电脑赢了 }, 剪刀: { 石头: 电脑赢了, 剪刀: 平局, 布: 你赢了 }, 布: { 石头: 你赢了, 剪刀: 电脑赢了, 布: 平局 }, };这是一个二维查找表Lookup Table是游戏开发中实现规则判定的经典模式电脑出拳 石头 剪刀 布 玩家出拳 石头 平局 你赢了 电脑赢了 剪刀 电脑赢了 平局 你赢了 布 你赢了 电脑赢了 平局第一维外层 Record 的键玩家的出拳第二维内层 Record 的键电脑的出拳值判定结果字符串这种设计比使用if-else链式判断更清晰、更易维护// ❌ 难以维护的链式判断 if (player 石头 computer 剪刀) return 你赢了; if (player 石头 computer 布) return 电脑赢了; // ... 需要写9个条件分支 // ✅ 优雅的查找表 return RULES[player][computer]; // 一行搞定查找表的优势O(1) 时间复杂度直接索引查找无需条件分支易于扩展增加新规则只需修改表结构可读性强表格形式直观展示所有规则3.4 游戏主逻辑play(choice: Choice) { this.playerChoice choice; // 1. 记录玩家选择 this.computerChoice CHOICES[Math.floor(Math.random() * 3)]; // 2. 电脑随机选择 this.result RULES[this.playerChoice][this.computerChoice]; // 3. 查询胜负 if (this.result 你赢了) this.playerScore; // 4. 玩家得分 else if (this.result 电脑赢了) this.computerScore; // 5. 电脑得分 this.played true; // 6. 标记已开始 }六行代码完成了完整的游戏逻辑电脑随机选择this.computerChoice CHOICES[Math.floor(Math.random() * 3)];Math.random()生成 [0,1) 浮点数乘以3得到 [0,3) 区间Math.floor()取整得到 0、1、2 三个整数索引对应CHOICES数组中的三个选项。胜负判定this.result RULES[this.playerChoice][this.computerChoice];通过二维查找表一行代码完成胜负判定。计分逻辑if (this.result 你赢了) this.playerScore; else if (this.result 电脑赢了) this.computerScore;注意这里没有为平局做处理因为平局不计分。3.5 状态驱动的胜负反馈Text(this.result).fontSize(22).fontWeight(FontWeight.Bold) .fontColor(this.result 你赢了 ? #4CAF50 : this.result 电脑赢了 ? #F44336 : #FF9800)结果的文字颜色根据胜负状态动态变化结果颜色含义你赢了#4CAF50绿色积极、胜利电脑赢了#F44336红色消极、失败平局#FF9800橙色中性、提示这种状态驱动的视觉反馈让玩家一眼就能判断胜负无需仔细阅读文字内容。四、HarmonyOS 特性深度解析4.1 Button 内容插槽与复合按钮Button() { Column() { Text(EMOJI[c]).fontSize(32) Text(c).fontSize(14).fontColor(#fff) } }.width(90).height(90).borderRadius(16).backgroundColor(#0077FF)HarmonyOS 的Button组件支持内容插槽Content Slot允许在按钮内部嵌入任意 UI 布局。这里使用Column垂直排列 Emoji 图标和文字标签创建了复合按钮——比单纯的文字按钮更直观、更有吸引力。每个按钮的布局┌──────────────┐ │ ✊ │ ← 32px Emoji │ 石头 │ ← 14px 文字 └──────────────┘这种设计在游戏类应用中尤为常见兼顾了视觉直观性和操作准确性。4.2 条件渲染的出拳信息显示Text(EMOJI[this.computerChoice]).fontSize(64) if (this.played) Text(this.computerChoice).fontSize(16)played标志位控制是否显示文字版本的出拳信息。在游戏开始前playedfalse只显示默认的 Emoji石头不显示文字标签。游戏开始后playedtrue在 Emoji 下方补充显示文字描述让用户确认电脑的出拳。这种渐进式的信息披露设计让界面在初始状态下保持简洁在游戏过程中提供更完整的信息。4.3 比分板的视觉设计Row({ space: 20 }) { Text(你: ${this.playerScore}).fontSize(18).fontWeight(FontWeight.Bold) .fontColor(#4CAF50) Text(电脑: ${this.computerScore}).fontSize(18).fontWeight(FontWeight.Bold) .fontColor(#F44336) }比分板使用对称布局玩家分数用绿色代表积极电脑分数用红色代表消极。space: 20的间距确保两个分数清晰可辨不会相互干扰。五、UI/UX 设计模式5.1 对战式布局┌─────────────────────────────────┐ │ 电脑区域 │ │ 电脑 (灰色标签) │ │ ✊ (64px Emoji) │ │ 石头 (出拳名称) │ ├─────────────────────────────────┤ │ ★ 胜负结果 ★ │ ← 居中彩色显示 ├─────────────────────────────────┤ │ 玩家区域 │ │ ✊ (64px Emoji) │ │ 你 (灰色标签) │ │ 石头 (出拳名称) │ ├─────────────────────────────────┤ │ 选择按钮 (✊✌️️) │ ├─────────────────────────────────┤ │ 比分板 重置按钮 │ └─────────────────────────────────┘这种上下对称的布局清晰地展示了玩家 vs 电脑的对战关系结果展示在中间形成视觉焦点。5.2 交互流程初始状态: 显示默认出拳提示选择你的出拳 │ │ 用户点击选择按钮 ▼ 游戏进行: 显示双方出拳展示胜负结果更新比分 │ │ 用户再次点击 ▼ 继续游戏: 新的出拳和结果比分累加 │ │ 用户点击重置比分 ▼ 重置: 分数归零恢复到初始提示5.3 色彩心理学应用元素颜色心理效应选择按钮#0077FF蓝色信任、可靠、可点击玩家分数#4CAF50绿色积极、成长、优势电脑分数#F44336红色警告、劣势、警惕胜利结果#4CAF50绿色成功、喜悦失败结果#F44336红色失败、警示平局结果#FF9800橙色中性、等待六、最佳实践与经验总结6.1 类型别名 vs 枚举本应用使用type类型别名而非enum枚举来定义 Choice// 类型别名方式本应用使用 type Choice 石头 | 剪刀 | 布; // 枚举方式另一种选择 enum Choice { 石头 石头, 剪刀 剪刀, 布 布 }类型别名的优势更简洁无需定义枚举值到字符串的映射与 JSON 兼容直接使用字符串值便于序列化更灵活可以组合其他类型6.2 查找表的优势使用Record字典作为查找表比if-else或switch-case有明显的优势// ❌ if-else 方式 if (player 石头 computer 石头) result 平局; else if (player 石头 computer 剪刀) result 你赢了; // ... 需要9个分支 // ❌ switch-case 方式 switch (player) { case 石头: switch (computer) { case 石头: result 平局; break; // ... } break; // ... } // ✅ 查找表方式 (推荐) result RULES[player][computer];查找表是声明式编程的体现——你声明规则是什么而非如何判断代码更简洁、更易维护。6.3 状态重置的最佳实践reset() { this.playerScore 0; this.computerScore 0; this.result 选择你的出拳; this.played false; }重置函数应同时恢复所有相关状态到初始值包括比分、结果文字和游戏状态标记。遗漏任何一个变量的重置可能导致 UI 显示异常。6.4 游戏扩展建议对于更完整的石头剪刀布游戏可以考虑多局制实现三局两胜或五局三胜的赛制动画过渡出拳时添加 Emoji 切换动画出拳历史显示最近几局的出拳记录音效反馈集成 HarmonyOS 的音效 API联机对战通过分布式能力实现远程对战AI 策略根据玩家历史出拳模式调整电脑策略七、总结石头剪刀布应用在约87行代码中完美展示了 ArkTS 声明式 UI 开发的多个核心概念Type 类型别名联合类型的类型安全约束Record 查找表O(1) 时间复杂度的规则判定状态驱动的视觉反馈胜负结果的颜色编码Button 内容插槽复合按钮的灵活构建计分系统简单的累加计分逻辑条件渲染played 标志位控制信息显示这个应用以石头剪刀布这一经典游戏为切入点展示了如何在 ArkTS 中构建交互式游戏应用。清晰的代码结构、优雅的查找表设计和类型安全的编程风格使其成为学习 HarmonyOS 游戏开发的优秀入门案例。
延伸阅读

更多相关文章

2026/9/14 0:56:07

大语言模型在智能系统架构设计中的挑战与实践

1. 项目概述:大语言模型在智能系统架构设计中的应用挑战去年参与某金融风控系统升级时,我们首次尝试将大语言模型(LLM)引入决策链路。在架构评审会上,一位资深架构师提出的质询让我记忆犹新:"当模型响…

2026/9/14 23:21:14

Paimon数据湖删除操作问题解析与解决方案

1. 问题背景与现象定位最近在使用Paimon进行数据湖管理时,遇到了一个棘手问题:合并引擎(merge-engine)无法按分区或主键删除数据。具体表现为执行DELETE操作后,目标数据仍然存在于表中,或者出现部分数据残留…

2026/9/14 23:21:14

IEEE 39节点系统建模与仿真平台选型指南

1. IEEE 39节点系统概述与建模意义IEEE 39节点系统是电力系统分析中最具代表性的标准测试系统之一,这个由IEEE电力工程学会发布的基准模型包含了39个母线节点、10台同步发电机和19条负荷支路。作为新英格兰电力系统的简化版本,它完整保留了实际电网的拓扑…

2026/9/14 23:21:14

AI辅助Windows内存优化实战:8GB旧笔记本从94%降到64%

开机先等两分钟,打开浏览器再开个 Office 文档,风扇就开始狂转,鼠标指针都开始飘——这就是我手里这台用了快六年的 8GB 内存旧笔记本年初的真实状态。任务管理器里的内存占用长期停在 94% 附近,别说跑大型软件,连正常…

2026/9/14 23:21:14

本体论:企业智能化转型的核心引擎与知识铸造流水线

做企业智能化咨询这几年,我发现一个特别普遍的现象:不少企业花了大价钱上了数据中台、训练了大模型,最后却卡在一个看不见摸不着的地方——数据口径对不上。销售部的“客户”和财务部的“往来单位”明明说的是同一个实体,系统里却…

2026/9/14 23:21:14

Spring Boot整合Mybatis:高效Java后端开发实践

1. Spring Boot整合Mybatis的核心价值Spring Boot和Mybatis的组合堪称Java后端开发的"黄金搭档"。我经历过从SSH到Spring MVC再到Spring Boot的技术演进,这套组合拳真正实现了开发效率与运行性能的平衡。Spring Boot的自动配置机制让Mybatis集成变得异常简…

2026/9/14 23:16:13

C语言文件操作函数详解与实战技巧

1. C语言文件操作函数全景解析作为一名在嵌入式领域摸爬滚打多年的老码农,我至今记得第一次用fopen()操作传感器数据文件时踩过的坑。C语言的文件操作就像瑞士军刀——看似简单但暗藏玄机,用好了能处理各种I/O需求,用不好轻则数据丢失&#x…

2026/9/14 2:17:50

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/14 0:03:22

KCF目标跟踪算法与OTB工程实现:毕业设计实战解析

简介:这是一份基于KCF核相关滤波算法、融合尺度池与抗遮挡处理的目标检测跟踪MATLAB完整源码,主要面向计算机相关专业准备毕业设计、课程设计或期末大作业的学生,也适合需要项目实战练习的初学者。源码在OTB数据集上完成验证,能够…

2026/9/14 0:03:22

语音情感识别实战:Keras实现LSTM、CNN、SVM与MLP多模型对比

简介:面向语音情感识别入门与进阶开发者,这份基于Keras的项目源码完整实现了LSTM、CNN、SVM、MLP四种模型,兼容Python3.8与Keras/TensorFlow2环境。压缩包内含49个文件,大小约70.31MB,主体包括Python脚本、yaml/json配…

2026/9/14 11:59:31

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/14 13:53:59

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/14 11:22:57

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码