2.2.0. 本篇知识点
在本篇中,你将学到:
- 外部Crate的搜索与下载
- Cargo依赖项管理
- 基于语义化版本的升级规则
rand
随机数生成器- …
2.2.1. 游戏目标
- 生成一个1到100间的随机数(本篇会涉及)
- 提示玩家输入一个猜测
- 猜完之后,程序会提示猜测是太大了还是太小了
- 循环询问,如果猜测正确,那么打印一个庆祝信息,程序退出
2.2.2. 代码实现
Step 1:寻找外部库
虽然Rust标准库内并没有提供与生成随机数相关的函数,但rust团队开发了具有这个功能的外部库,在Rust官方crates管理平台(Rust 编程语言的官方包管理平台和生态系统)中搜索rand即可以找到这个外部库,这个网页提供了非常详细的对这个库的介绍。
Rust的crate一共分为两种:
-
库 Crate(Library Crate):库 crate 是一个提供功能、逻辑模块的库,没有
main
函数,不能单独运行。它通常用于与其他代码共享功能,其用途是提供可重用的功能模块。rand
这个crate就属于库crate。 -
二进制 Crate(Binary Crate):二进制 crate 是一个可执行的程序,包含一个
main
函数,编译后生成可运行的二进制文件。其用途是构建独立的、可运行的 Rust 应用程序。
Step 2:把这个外部Crate写入Cargo依赖项
接下来就需要把这个外部库写入Cargo依赖项(有关Cargo的介绍在1.3. Rust Cargo一文中就已提及,这里不再重复)以供程序调用。
打开项目中的Cargo.toml
文件,在dependencies
下面添加依赖项,格式为依赖项名 = "依赖项版本"
(Crates网页的右上角Install
这一栏下就有这一行的写法)。这个程序需要rand
这个依赖项,并且使用0.8.5这个版本,就应该写rand = "0.8.5"
。如果这个依赖项有其他的依赖项,那Cargo就会自动在编译时下载它们。
实际上0.8.5
这种版本号写法是一种简写,其完整写法为^0.8.5
,表示任何与0.8.5
版本公共API所兼容的版本都可以。比如有一个依赖项的版本是1.2
,那么就意味着允许升级到 1.2.0
以上的任意版本,但不会升级到 2.0.0
或更高版本。
Cargo会一直使用你指定的依赖项版本,直到你手动指定其他版本。
如果某个项目的依赖项的更新会破坏基于老版本依赖项的代码,那么在重新build后会发生什么呢?答案在Cargo.lock
文件中,在build时,Cargo会查看时候已经生成了Cargo.lock
文件,如果有,那就使用这个文件里指定的版本,这样就避免了兼容问题。
如果想在当前标准下更新版本,只需要在控制台中使用cargo update
指令,具体步骤如下:
- 复制Cargo项目所在的文件夹路径,打开终端,输入命令
cd Cargo项目路径
- 输入命令
cargo update
这个命令会忽略cargo.lock
,通过更新的注册表来找到符合在Cargo.toml
中要求的最新版本依赖项,但Cargo.toml
中所写下的版本是不会动的。举个例子,假如说有一个依赖项在Cargo.toml
中声明的版本是1.2
,它就可以通过cago update
升级到最新的1.x.x
版本,但不会升级到 2.0.0
或更高版本,同时Cargo.toml
中写下的这个依赖项的版本依然是1.2
Step 3:在代码中使用这个依赖项
在程序开头需要使用关键字use
来引用依赖项,具体为:
use rand::Rng
rand::Rng
是一个trait
,trait
类似于其他语言中的接口(如 Java 的接口或 C++ 的纯虚基类),用于规定一组类型必须实现的函数和方法。rand::Rng
就是定义了一些随机数随机数生成器所需要的一些方法。
接下来在main
函数中使用这个trait
来生成随机数,具体代码如下:
let range_number = rand::thread_rng().gen_range(1..101);
PS:使用低于0.8的rand版本时写为gen_range(1,101)
let rang_number
:声明了一个叫做range_number
的不可变变量=
:赋值rand::thread_rng
:返回ThreadRng
类型,这个类型就是一个随机数生成器。这个随机数生成器位于本地线程空间,通过操作系统获得这个随机数的种子。.gen_range(1,101)
:rand::thread_rng
上的一个方法,它有两个参数:最小值和最大值,在这里就是1和101,它就会在1到101间生成随机数,这个范围包括1但不包括101。
最后再打印出这个随机数(println!
的使用在上一篇文章已作介绍,不再阐述):
println!("神秘数字是 The secret number is: {}", range_number);
2.2.3. 代码效果
这是完整的代码:
use std::io;
use rand::Rng;
fn main() {
let range_number = rand::thread_rng().gen_range(1..101);
println!("猜数游戏 Number Guessing Game");
println!("猜一个数 Guess a number");
let mut guess = String::new();
io::stdin().read_line(&mut guess).expect("无法读取行 Could not read the line");
println!("你猜测的数是The number you guessed is:{}", guess);
println!("神秘数字是 The secret number is: {}", range_number);
}
运行效果如下: