# 鸿蒙 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 游戏开发的优秀入门案例。

相关新闻

如何5分钟快速部署Sunshine游戏串流服务器:打造家庭云游戏终极解决方案

如何5分钟快速部署Sunshine游戏串流服务器:打造家庭云游戏终极解决方案

如何5分钟快速部署Sunshine游戏串流服务器:打造家庭云游戏终极解决方案 【免费下载链接】Sunshine Self-hosted game stream host for Moonlight. 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine 你是否曾梦想过在家中的任何设备上流畅玩转高性…

2026/10/17 8:46:55 阅读更多 →
行空板M10集成百度与讯飞双语音引擎:嵌入式AI语音交互实践

行空板M10集成百度与讯飞双语音引擎:嵌入式AI语音交互实践

1. 项目概述:当行空板M10遇上双语音引擎最近在折腾行空板M10,一个想法冒了出来:能不能让这块板子同时“听懂”百度,又能“开口说”讯飞?听起来像是给一个设备装了两个“大脑”,一个负责听,一个负…

2026/10/19 5:38:24 阅读更多 →
3D打印与激光切割融合制造:从设计到实战的混合制造指南

3D打印与激光切割融合制造:从设计到实战的混合制造指南

1. 从“加法”到“减法”:一次偶然发现的融合契机那天在工作室里,我正对着一个刚出炉的3D打印件发愁。这是一个为户外电源设计的外壳原型,功能上没问题,但外观上总差点意思——打印支撑留下的疤痕、层纹,还有几个需要高…

2026/10/18 10:32:54 阅读更多 →

最新新闻

MCP协议深度解析:从设计思路到实战落地,智能体工具集成不再难

MCP协议深度解析:从设计思路到实战落地,智能体工具集成不再难

1. 为什么这一讲值得单独拿出来精讲MCP,全称 Model Context Protocol,是近两年在智能体工程圈子里被反复讨论的一个协议规范。如果你正在做 AI 应用开发,尤其是涉及工具调用、多智能体协作、外部数据源接入这类场景,那 MCP 基本是…

2026/10/19 5:38:26 阅读更多 →
OpenClaw requireApproval 插件:生产环境 AI 代理的人工审批闸门

OpenClaw requireApproval 插件:生产环境 AI 代理的人工审批闸门

OpenClaw 跑得越顺,我心里反而越没底。这句话听起来有点反直觉,但凡是把 OpenClaw 从个人实验搬到团队生产环境的人,多半能对上这个感觉:代理的执行力越强,越没人敢给它在生产环境里完全放开手脚。OpenClaw v2026.3.28…

2026/10/19 5:38:26 阅读更多 →
Agent上下文管理选型:流水式与汉堡式架构对比及混合方案实践

Agent上下文管理选型:流水式与汉堡式架构对比及混合方案实践

1. 从一次上下文溢出事故说起去年冬天,我接手了一个内部知识库问答助手的调优工作。上线第一周就出了状况:用户连续追问七八轮之后,Agent 开始答非所问,甚至把三轮之前已经确认过的订单编号又当成新信息重新询问。日志里最扎眼的一…

2026/10/19 5:38:26 阅读更多 →
PSO-BiLSTM与SHAP可解释性分析:多步时序回归的完整实践

PSO-BiLSTM与SHAP可解释性分析:多步时序回归的完整实践

上个月我手头有一个多步超前回归需求:一段工业设备运行监测数据,十几个连续采集的变量,要用过去24个时刻的观测预报未来三个时刻的一项关键质量指标。业务方提出三个硬性要求——预报要准,模型结果要能解释“到底哪些变量在起作用…

2026/10/19 5:38:26 阅读更多 →
OpenClaw基础版扩展指南:理解skills机制与必备技能清单

OpenClaw基础版扩展指南:理解skills机制与必备技能清单

装完OpenClaw基础版的第一天,很多人都会对着终端界面发愣——程序确实起来了,也能对话了,但让它干点正事,比如整理个文件、抓个网页信息、定时提醒你开会,它却总是回一句"我没有这个能力"。这不奇怪。OpenCl…

2026/10/19 5:38:26 阅读更多 →
AI开发工程师面试全解析:从简历到系统设计的高频考点与备战方法

AI开发工程师面试全解析:从简历到系统设计的高频考点与备战方法

面试这件事,最微妙的地方在于:你以为你在展示自己,面试官却往往在60分钟内只做一件事——验证“如果把这个项目交点给我,我能放心吗”。作为一个面过别人、也被别人面过的AI开发工程师,我见过太多准备充分却答偏的候选…

2026/10/19 5:37:25 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →