Rust入门系列:04、猜数字游戏,引入rand随机数模块
上一篇文章我们使用 Rust 编程语言创建一个猜数字游戏, 仅仅只能打印出来用户的输入,我们这一小节会引入更多的功能。
首先,我们希望系统给我们生成一个随机数,我们也输入一个数字,然后和系统生成的随机数来进行比较,通常情况下会有三种可能:
- 比随机数小
- 比随机数大
- 和随机数相等
要实现这个功能,我们首先要在程序中引入rand
模块,因为在rust原生类库中,并不包含随机数模块。
rand模块简介
rand
是一个 Rust 语言的库模块,它提供了一系列功能,用于生成随机数以及处理各种随机数相关的任务。这个库非常重要和常用,特别是在需要随机性的程序中。以下是 rand
库的一些主要用途和功能:
- 生成随机数:
rand
提供多种方式生成不同类型的随机数,比如整数、浮点数、布尔值等。 - 不同分布的随机数:除了基本的随机数生成,它还支持多种概率分布(如均匀分布、正态分布、指数分布等)来生成特定分布的随机数。
- 随机工具: 提供随机选择元素、洗牌数组等实用功能。
- 随机数生成器(RNG): 支持多种随机数生成器。如:
ThreadRng
:基于当前线程,非常适合普通应用,提供很好的性能和安全性。StdRng
:使用加密安全的随机数生成器,适合需要高随机性的场景。 -SmallRng
:更高效但随机性较低,不适用于加密安全需要的场景。 - 线程安全性:
rand
考虑到多线程使用的需要,大部分RNG实现都是线程安全的,或者像ThreadRng
这样专为线程本地使用优化。 - 加密安全: 对于需要加密安全的应用,
rand
提供了适合这类用途的 RNGs,例如,OsRng
直接使用操作系统提供的加密安全的随机数生成器。 在具体应用中,例如游戏、模拟、安全性测试、科学研究等场合,
rand
库提供了方便和强大的工具来满足随机性需求。使用 rand
库可以帮助开发者简化代码,同时保障了随机数的质量和应用的可靠性。
我们本小节主要使用的是随机数生成器的能力。
代码示例:
use std::cmp::Ordering;
use std::io;
use rand::Rng;
fn main() {
println!("猜数游戏,包含随机数!");
let secret_number = rand::thread_rng().gen_range(1..101);
println!("神秘数字是:{}", secret_number);
println!("猜测一个数");
let mut guess = String::new();
io::stdin().read_line(&mut guess).expect("无法读取行信息");
let guess_to_string:u32 = guess.trim().parse().expect("please type a number!");
match guess_to_string.cmp(&secret_number) {
Ordering::Less => println!("Too small!!"),
Ordering::Greater => println!("Too big!!"),
Ordering::Equal => println!("You win!!"),
}
println!("你猜测的数字是:{}",guess)
}
详细解释
- 导入库模块
use std::cmp::Ordering;
use std::io;
use rand::Rng;
这几行代码导入所需的库。Ordering
用于比较大小,io
用于输入输出操作,rand::Rng
用于生成随机数。
- 程序入口
fn main() {
println!("猜数游戏,包含随机数!");
程序从 main
函数开始执行。首先输出一个欢迎信息,告诉玩家这是一个猜数游戏。
- 生成随机数
let secret_number = rand::thread_rng().gen_range(1..101);
使用 rand::thread_rng()
获取当前线程的随机数生成器,并调用 gen_range(1..101)
生成一个1到100之间的随机数(左闭右开区间),也就是包含1,但是不包含101。
- 输出随机数(调试用)
println!("神秘数字是:{}", secret_number);
这行代码打印神秘数字。通常在发布游戏时,你应该注释或删除这一行,否则会暴露游戏答案。
- 读取用户猜测
println!("猜测一个数");
let mut guess = String::new();
io::stdin().read_line(&mut guess).expect("无法读取行信息");
-
- 首先提示用户输入一个数字。
guess
初始化为一个新的字符串;- 使用
io::stdin().read_line(&mut guess)
从标准输入中读取一行到guess
中,.expect("无法读取行信息")
是错误处理,如果发生IO错误,则程序会输出错误信息并退出。
- 将字符串转换为数字
let guess: u32 = guess.trim().parse().expect("please type a number!");
-
- 使用
guess.trim()
去除字符串前后的空白字符。 .parse()
尝试将修剪后的字符串转换为一个32位无符号整数(u32
)。如果转换失败(例如,如果字符串包含非数字字符),程序将显示错误信息并退出。
- 使用
- 比较猜测与神秘数字
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!!"),
Ordering::Greater => println!("Too big!!"),
Ordering::Equal => println!("You win!!"),
}
-
- 使用
cmp
方法比较guess
和secret_number
。 cmp
返回一个Ordering
枚举,它可以是Less
、Greater
或Equal
。match
语句根据cmp
的结果来执行相应的分支。
- 使用
- 输出用户的猜测
println!("你猜测的数字是:{}", guess);
在游戏结束时输出用户最终的猜测。
总结相关知识点
这个简单的猜数字游戏包括生成一个随机数、读取用户输入、将输入转换为整数、比较数字、并给出用户猜测的反馈。
- 使用标准库和第三方库:
-
- 使用
rand
库生成随机数。 - 使用标凈输入输出(
std::io
)处理输入和输出。
- 使用
- 变量和可变性:
-
- 使用
let
声明变量。 - 使用
mut
关键字来声明可变变量。
- 使用
- 基本数据类型:
-
- 整数(如:
i32
,u32
)。 - 字符串处理,例如
String
。
- 整数(如:
- 控制流:
-
- 使用
match
表达式来处理包含多个分支的逻辑,如比较猜测的数字与实际数字。
- 使用
- 错误处理:
-
- 使用
Result
类型处理可能的错误。 - 使用
expect
或unwrap
方法处理Result
类型,特别是在读取用户输入时。
- 使用
- 输入输出:
-
- 使用
println!
宏打印输出到控制台。 - 使用
std::io::stdin().read_line()
读取用户输入。
- 使用
- 类型转换:
-
- 将输入的字符串转换为数字时使用
str::parse()
方法。
- 将输入的字符串转换为数字时使用
转载自:https://juejin.cn/post/7382775817581559808