01 - Rust 猜数字游戏
对于任何编程语言在实例中学习效果都要比空洞的直接学习概念好。正所谓“talk is cheap, show me code.”是也。
本篇,以猜数字游戏为例,对 rust
语言中涉及到的概念进行讲解,尽可能做到深入浅出。
1. 猜数字游戏的逻辑
- 程序将会随机生成一个 1 到 100 之间的随机整数。
- 接着请玩家猜一个数并输入。
- 提示猜测是大了还是小了。如果猜对了,它会打印祝贺信息并退出。
2. 创建新项目
主要通过
cargo new guessing_game cargo run
来创建新的项目,运行结果如下:
➜ tmp git:(master) ✗ cargo new guessing_game Created binary (application) `guessing_game` package ➜ tmp git:(master) ✗ ls guessing_game ➜ tmp git:(master) ✗ cd guessing_game ➜ guessing_game git:(master) ✗ cargo run Compiling guessing_game v0.1.0 (/home/ak3/wspaces/dev/tmp/guessing_game) Finished dev [unoptimized + debuginfo] target(s) in 0.30s Running `target/debug/guessing_game` Hello, world!
3. 猜数字游戏实现
拆分为以下三个步骤来实现,具体概念穿插讲解,在最后再进行总结。
3.1 获取用户输入并打印
a. 标准库引入
获取用户输入的功能,需要引入标准库内容来完成,如下:
use std::io;
在 标准读写库文档 就能看到从控制台读写的案例
代码如下:
use std::io; fn main() -> io::Result<()> { let mut input = String::new(); io::stdin().read_line(&mut input)?; println!("You typed: {}", input.trim()); Ok(()) }
执行如下:
➜ guessing_game git:(master) ✗ cargo run Compiling guessing_game v0.1.0 (/home/ak3/wspaces/dev/tmp/guessing_game) Finished dev [unoptimized + debuginfo] target(s) in 0.22s Running `target/debug/guessing_game` 11 You typed: 11
b. println! 宏
println! 是一个在屏幕上打印字符串的宏
c. 可变与不可变 变量
上面的input
变量使用了可变变量的定义。Rust
中默认定义的变量具有不可变性,可变变量需要显示用 let mut
来定义。
d. string::new 与io::stdin().read_line(&mut input)
3.2 生成指定范围内的随机数
Rust 标准库中尚未包含随机数功能。然而,Rust 团队还是提供了一个包含上述功能的 rand crate。
在 crates.io 搜索rand 得到 rand crate的相关信息,然后在执行如下命令添加 rand crate
cargo add rand
对比执行上述命令前后差异,是在 Cargo.toml中增加了一行
rand = "0.8.5"
在 rand右侧进入其rand documention
在原来代码基础上新增 如下代码
use rand::Rng; let secret_number = rand::thread_rng().gen_range(1..=100); println!("The secret number is: {secret_number}");
执行 cargo run
显示如下:
Downloaded libc v0.2.148 Downloaded getrandom v0.2.10 Downloaded 3 crates (748.2 KB) in 29.36s Compiling libc v0.2.148 Compiling cfg-if v1.0.0 Compiling ppv-lite86 v0.2.17 Compiling getrandom v0.2.10 Compiling rand_core v0.6.4 Compiling rand_chacha v0.3.1 Compiling rand v0.8.5 Compiling guessing_game v0.1.0 (/home/ak3/wspaces/dev/tmp/guessing_game) Finished dev [unoptimized + debuginfo] target(s) in 30.82s Running `target/debug/guessing_game` The secret number is: 66 12 You typed: 12
在执行cargo run的过程中,会下载 rand 相关的 crate lib.
3.3 随机数与猜测数的比较
这部分的主要是循环读取用户输入,与随机数比较给出输出直至猜中结束游戏。
a. 字符串转数字
由于从控制台输入的数据最先取得的都是字符串,需要将字符串转换为相应类型,才能进行对应的操作。
// 此处guess 覆盖了上面的 guess ,Rust 允许同名覆盖变量,隐藏 (Shadowing) guess 之前的值 let guess: u32 = guess.trim().parse().expect("Please type a number!");
parse 方法返回一个 Result 类型。像之前 “使用 Result 类型来处理潜在的错误” 讨论的 read_line 方法那样,再次按部就班的用 expect 方法处理即可。如果 parse 不能从字符串生成一个数字,返回一个 Result 的 Err 成员时,expect 会使游戏崩溃并打印附带的信息。
b. 数字比较大小
use std::cmp::Ordering;
增加 use 声明,从标准库引入了一个叫做 std::cmp::Ordering 的类型到作用域中。 Ordering 也是一个枚举,不过它的成员是 Less、Greater 和 Equal。这是比较两个值时可能出现的三种结果。
match guess.cmp(&secret_number) { Ordering::Less => println!("Too small!"), Ordering::Greater => println!("Too big!"), Ordering::Equal => println!("You win!"), }
使用一个 match 表达式,根据对 guess 和 secret_number 调用 cmp 返回的 Ordering 成员来决定接下来做什么。
一个 match 表达式由 分支(arms) 构成。一个分支包含一个 模式(pattern)和表达式开头的值与分支模式相匹配时应该执行的代码。Rust 获取提供给 match 的值并挨个检查每个分支的模式。
c. 循环处理多次猜想
直接通过 loop
关键字进行循环读入比较,正确则推出(break
关键字退出循环)。
代码如下:
use std::io; use rand::Rng; use std::cmp::Ordering; fn main(){ let secret_number = rand::thread_rng().gen_range(1..=100); // println!("The secret number is: {secret_number}"); loop { let mut guess = String::new(); println!("Please input your guess."); io::stdin().read_line(&mut guess); // 此处guess 覆盖了上面的 guess ,Rust 允许同名覆盖变量,隐藏 (Shadowing) guess 之前的值 let guess: u32 = guess.trim().parse().expect("Please type a number!"); match guess.cmp(&secret_number) { Ordering::Less => println!("Too small!"), Ordering::Greater => println!("Too big!"), Ordering::Equal => { println!("You win!"); break; // 跳出循环,结束游戏。 } } } }
至此,我们的猜数字游戏完成了。但也存在一些对输入数据异常的 case 处理。
在后续学习中逐步完善。
4. 总结
虽然猜数字游戏较小,但从中能看到一些 rust
的特性:
- 使用
use
关键字引入库。 - println! 是宏。
- match 表达式。
- Result 枚举类型。
更多详情,且看后续笔记。
本文参考 Rust 程序设计语言:写个猜数字游戏
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)