一、为什么需要"简易数字猜谜游戏"?
在 OpenHarmony 的教育、娱乐与认知训练场景中,简单的互动游戏具有独特价值:
- 儿童数学启蒙(理解大小、范围、逻辑推理);
- 老年人认知锻炼(短期记忆、数字敏感度);
- 开发者调试 UI 交互流程的模板。
而"猜数字"作为经典编程入门题,具备以下优势:
- 规则极简:无需教程,直觉可玩;
- 反馈即时:每次猜测都有明确方向提示;
- 计算轻量:仅需一次随机生成与整数比较;
- 无副作用:不保存数据,不联网,关闭即重置。
更重要的是,它完美展示了 "状态 → 用户输入 → 反馈 → 状态更新" 的闭环交互模型,是学习响应式 UI 的理想范例。
本文将构建一个极简页面:「简易数字猜谜游戏」。它包含:
- 一个数字输入框(限制整数输入);
- 一个"提交"按钮;
- 一行动态提示(如 "50 太大了!");
- 一行显示"已尝试:3 次"。
游戏目标:在最少次数内猜中系统生成的 1--100 随机整数。
二、完整可运行代码
dart
// lib/main.dart
import 'package:flutter/material.dart';
import 'dart:math';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '猜数字',
debugShowCheckedModeBanner: false,
theme: ThemeData(useMaterial3: true, colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue)),
home: const NumberGuessingGame(),
);
}
}
class NumberGuessingGame extends StatefulWidget {
const NumberGuessingGame({super.key});
@override
State<NumberGuessingGame> createState() => _NumberGuessingGameState();
}
class _NumberGuessingGameState extends State<NumberGuessingGame> {
final TextEditingController _controller = TextEditingController();
final int _target = Random().nextInt(100) + 1; // 1 到 100
String _message = '我想了一个 1 到 100 的数字,猜猜看?';
int _attempts = 0;
void _submitGuess() {
final input = _controller.text.trim();
if (input.isEmpty) return;
int? guess = int.tryParse(input);
if (guess == null || guess < 1 || guess > 100) {
setState(() {
_message = '请输入 1 到 100 之间的整数';
});
return;
}
_attempts++;
if (guess == _target) {
setState(() {
_message = '🎉 恭喜你!$guess 猜对了!';
});
} else if (guess < _target) {
setState(() {
_message = '$guess 太小了!';
});
} else {
setState(() {
_message = '$guess 太大了!';
});
}
_controller.clear();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('数字猜谜游戏')),
body: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: _controller,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
labelText: '输入你的猜测',
hintText: '1 - 100',
),
onSubmitted: (_) => _submitGuess(),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _submitGuess,
child: const Text('提交'),
),
const SizedBox(height: 30),
Text(_message, style: const TextStyle(fontSize: 18)),
const SizedBox(height: 10),
Text('已尝试:$_attempts 次', style: const TextStyle(fontSize: 16, color: Colors.grey)),
],
),
),
);
}
}
三、核心机制:一次初始化,多次反馈
本游戏的核心状态包括:
_target:目标数字(在initState前通过字段初始化完成);_message:当前提示信息;_attempts:尝试次数;_controller.text:用户当前输入。
关键设计在于:_target 在页面创建时即固定 ,不会因重建而改变。这是通过在 State 类中直接初始化实现的:
dart
final int _target = Random().nextInt(100) + 1; // 1 到 100
由于 _target 是 final 字段,在 State 对象构造时赋值一次,后续 build 或 setState 均不会修改它,确保游戏公平性。
四、安全输入解析与范围校验:
我们首先看用户提交逻辑:
dart
void _submitGuess() {
final input = _controller.text.trim();
if (input.isEmpty) return;
int? guess = int.tryParse(input);
if (guess == null || guess < 1 || guess > 100) {
setState(() {
_message = '请输入 1 到 100 之间的整数';
});
return;
}
_attempts++;
// ... 比较逻辑
}

这段代码实现了健壮的用户输入处理。
- 空输入检查 :
trim()后若为空,直接返回,避免无效操作; - 整数解析 :
int.tryParse(input)尝试将字符串转为int?;- 若失败(如 "abc" 或 "12.5"),返回
null;
- 范围校验 :
- 即使解析成功,也需检查是否在 [1, 100] 区间;
- 超出范围视为无效输入,提示用户;
- 尝试计数 :
- 仅当输入有效时,
_attempts++; - 避免无效输入污染统计。
- 仅当输入有效时,
💡 此设计不阻止重复猜测(如多次猜 50),因不影响游戏逻辑,且可作为策略一部分。
五,反馈生成与状态更新:
再看核心比较逻辑:
dart
if (guess == _target) {
setState(() {
_message = '🎉 恭喜你!$guess 猜对了!';
});
} else if (guess < _target) {
setState(() {
_message = '$guess 太小了!';
});
} else {
setState(() {
_message = '$guess 太大了!';
});
}
_controller.clear();
这里展示了清晰的分支反馈机制。
- 相等判断 :
- 使用
==比较整数,精确可靠; - 成功时显示庆祝表情与数字,增强正向反馈;
- 使用
- 大小提示 :
- 明确告知"太大"或"太小",提供下一步方向;
- 显示用户输入的数字,确认识别无误;
- 输入清空 :
_controller.clear()清空输入框;- 方便用户连续输入,提升体验;
setState分离 :- 每个分支独立调用
setState,逻辑清晰; - 虽可合并,但分开更易读、易维护。
- 每个分支独立调用


📌 值得注意的是,未使用
switch或三元运算符 ,仅用if-else,确保最大兼容性。
六、UI 布局与交互优化:
最后看整体 UI 构建:
dart
TextField(
controller: _controller,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
labelText: '输入你的猜测',
hintText: '1 - 100',
),
onSubmitted: (_) => _submitGuess(),
),
ElevatedButton(onPressed: _submitGuess, child: const Text('提交')),
Text(_message, style: const TextStyle(fontSize: 18)),
Text('已尝试:$_attempts 次', style: const TextStyle(fontSize: 16, color: Colors.grey)),
此布局体现以用户为中心的设计:
- 输入优化 :
TextInputType.number弹出数字键盘;hintText: '1 - 100'提供范围提示;onSubmitted支持回车提交,提升效率;
- 按钮明确 :
- "提交"文案直观,无歧义;
- 信息分层 :
- 主提示
_message字体更大、居中; - 尝试次数用灰色弱化,避免干扰主反馈;
- 主提示
- 垂直居中 :
MainAxisAlignment.center使内容在屏幕中央,视觉聚焦。

💡 此设计不提供"重新开始"按钮------用户只需关闭再打开页面即可重置,符合轻应用理念。
七、为何这个游戏适合 OpenHarmony 场景?
1. 教育价值突出
- 帮助儿童建立数感与区间概念;
- 训练逻辑推理(二分法策略);
- 无广告、无内购,纯净学习环境。
2. 资源占用极低
- 无图片、无动画、无网络请求;
- 内存仅存几个整数和字符串;
- 适合手表、低端平板等资源受限设备。
3. 多端一致体验
- 在手机上:完整交互;
- 在手表上:大按钮便于点击;
- 在智慧屏上:作为家庭亲子互动小游戏。
4. 开发者友好
- 代码结构清晰,适合作为教学模板;
- 展示
StatefulWidget、TextField、Random的典型用法; - 无复杂依赖,易于调试。
八、工程注意事项
1. 随机数种子
Random()默认使用系统时间作为种子;- 在 OpenHarmony 模拟器中行为正常;
- 若需可复现(如测试),可传入固定种子:
Random(42),但本文未采用。
2. 输入边界处理
int.tryParse("100")返回 100,有效;int.tryParse("100.0")返回null(非整数),被拦截;- 负数、零、超大数均被范围校验过滤。
3. 可访问性
- 屏幕阅读器可朗读提示信息;
- 按钮有明确标签;
- 颜色非唯一信息载体(文字已说明大小)。
九、扩展与限制
可安全扩展的方向:
- 难度选择:1--50 / 1--100 / 1--1000;
- 历史记录:显示最近 5 次猜测;
- 最佳成绩 :用
SharedPreferences保存最少次数(但会引入依赖,违背本文原则)。
当前限制(有意为之):
- 不显示剩余机会(无限次猜测);
- 不提供提示(如"接近了");
- 不支持语音输入。
这些限制确保游戏聚焦核心玩法,无干扰元素。
十、结语:用简单规则,激发思考乐趣
本文的页面仅 68 行代码,却完整实现了一个有趣、公平、即时反馈的数字猜谜游戏。它没有华丽特效,没有社交功能,只有清晰的规则、确定的反馈、纯粹的乐趣。
在 OpenHarmony 构建的分布式智慧世界中,我们常被"智能"所吸引,但不应忘记:最好的互动,往往是那个让人愿意多试一次的那一个。
这个小小的猜谜游戏,正是对这一理念的践行------它不教你知识,但让你在猜测中学会思考。
🌐 欢迎加入开源鸿蒙跨平台社区 :
在这里,您将获得:
- OpenHarmony 轻量级互动应用设计指南;
- Flutter 游戏逻辑与状态管理模板;
- 无依赖实用组件开发经验。
用规则,点燃好奇。