WRITING / 2025
2.1 猜数字游戏
题目
编写一个猜数字的小游戏程序,要求如下:
- 程序在启动时随机生成一个 1 到 100(包含)之间的整数作为目标数字。
- 程序不断提示用户输入一个猜测的数字。
- 如果用户输入的不是有效整数,程序应忽略该输入并重新提示。
- 每次用户输入有效数字后,程序应判断该数字与目标数字的大小关系:
- 如果相等,输出 “你赢了”,并结束程序;
- 如果大于目标数字,输出 “太大”;
- 如果小于目标数字,输出 “太小”。
- 游戏持续进行,直到用户猜中为止。
创建项目
我们使用Cargo创建项目,Cargo的具体使用方法在上一篇文章中。1.2 Hello, Cargo!
cargo new guessing_game
cd guessing_game
这里不做过多解释
逐行讲解
导入依赖
use rand::Rng;
- 作用:导入 rand crate(依赖)中的Rng trait(类似于接口)
- 解释:rand 中的 Rng 定义了生成随机数的方法(如 gen_range )。为了能调用这个方法需要先导入这个依赖。
use std::cmp::Ordering;
- 作用:导入 std (标准库)中的 Ordering 枚举类型。
- 解释:Ordering 有三个值:Less、Equal、Greater,用于表示两个之比较的结果。根 if 类似。
use std::io;
- 作用:导入标准输入输出模块 std::io。
- 解释 :用来处理用户的依赖。
主函数开始
fn main() {
- 作用:程序的入口点。所有 Rust 程序从 mian 函数开始执行。
println!(“猜数字!”);
- 作用:打印信息到控制台
let num = rand::thread_rng().gen_range(1..=100);
- 作用:生成一个1到100之间的随即整数给变量 num 。
- 解释 :
rand::thread_rng():获取一个线程本地的随机数生成器。.gen_range(1..=100):设置一个范围。1..=100是一个闭合区间,[1,100]1..100是一个左闭右开区间,[1,100)
loop {
- 作用:死循环,直到
break;推出循环。
println!("请输入一个数字");
- 作用:打印信息到控制台
let mut guess = String::new();
- 作用:创建一个可变的空字符串
guess,用于存储用户输入的内容。 - 解释 :
let是用于声明变量的关键字,声明的变量默认不可变。mut用于声明可变变量。String::new()是标准库中提供构造空字符串的方法。
io::stdin().read_line(&mut guess).expect("错误");
- 作用:获取一行文本,存入
guess。 - 解释 :
io::stdin()标准输入流的句柄。.read_line(&mut guess)将用户输入的内容追加到guess字符串中。会保留换行符\n。&mut guess是一个可变字符串的引用.expect("错误");用于在程序崩溃时,输出传入的错误分析。
println!("你的猜测是{guess}");
- 作用:打印信息到控制台
let guess: u32 = match guess.trim().parse() { Ok(num) => num, Err( ) => continue, };
- 作用:将用户输入的字符串改为
u32数字类型。 - 解释 :
.trim()去除字符串首尾的的空白字符(尤其是换行符)。.parse()将字符串转换为数字。match表达式处理两种情况。Ok(num):解析成功,将num赋值给guess(类型为u32)。Err(_):解析失败,则执行continue,跳过本次循环剩余部分,重新提示输入。
match guess.cmp(&num) {
- 作用:比较用户猜测的数字
guess和目标数字num。 - 解释 :
.cmp(&num)用于比较用者(guess) 和参数(&num)的大小。cmp的参数需要是引用(&T),因为它不需要获取参数的所有权。
Ordering::Equal => { println!("你赢了"); break; }
- 作用:如果相等,打印胜利信息,并用
break退出loop循环,程序结束。
Ordering::Greater => println!("太大"), Ordering::Less => println!("太小"),
- 作用:判断大小,进行相应输出,因为没有
break,所以会继续下一轮循环。
}} }
小tips: 如果你学过其他语言可能会好奇为什么不直接读取数字而是字符串?
完整程序
use rand::Rng;
use std::cmp::Ordering;
use std::io;
fn main() {
println!("猜数字!");
let num = rand::thread_rng().gen_range(1..=100);
loop {
println!("请输入一个数字");
let mut guess = String::new();
io::stdin().read_line(&mut guess).expect("错误");
println!("你的猜测是{guess}");
let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
match guess.cmp(&num) {
Ordering::Equal => {
println!("你赢了");
break;
}
Ordering::Greater => println!("太大"),
Ordering::Less => println!("太小"),
}
}
}