|
|
|
@ -374,11 +374,11 @@ fn main() {
|
|
|
|
|
|
|
|
|
|
这里在顶部增加一行 `extern crate rand;` 通知 Rust 我们要使用外部依赖。这也会调用相应的 `use rand`,所以现在可以使用 `rand::` 前缀来调用 `rand` crate 中的任何内容。
|
|
|
|
|
|
|
|
|
|
接下来增加了另一行 `use`:`use rand::Rng`。`Rng` 是一个 trait,它定义了随机数生成器应实现的方法 ,想使用这些方法的话此 trait 必须在作用域中。第十章会详细介绍 trait。
|
|
|
|
|
接下来增加了另一行 `use`:`use rand::Rng`。`Rng` 是一个 trait,它定义了随机数生成器应实现的方法,想使用这些方法的话此 trait 必须在作用域中。第十章会详细介绍 trait。
|
|
|
|
|
|
|
|
|
|
另外,中间还新增加了两行。`rand::thread_rng` 函数提供实际使用的随机数生成器:它位于当前执行线程,并从操作系统获取 seed。接下来,调用随机数生成器的 `gen_range` 方法。这个方法由刚才引入到作用域的 `Rng` trait 定义。`gen_range` 方法获取两个数字作为参数,并生成一个范围在两者之间的随机数。它包含下限但不包含上限,所以需要指定 `1` 和 `101` 来请求一个 1 和 100 之间的数。
|
|
|
|
|
另外,中间还新增加了两行。`rand::thread_rng` 函数提供实际使用的随机数生成器:它位于当前执行线程本地,并从操作系统获取 seed。接下来,调用随机数生成器的 `gen_range` 方法。这个方法由刚才引入到作用域的 `Rng` trait 定义。`gen_range` 方法获取两个数字作为参数,并生成一个范围在两者之间的随机数。它包含下限但不包含上限,所以需要指定 `1` 和 `101` 来请求一个 1 和 100 之间的数。
|
|
|
|
|
|
|
|
|
|
知道 use 哪个 trait 和该从 crate 中调用哪个方法并不代表你 **知道** 如何使用。crate 的使用说明位于其文档中。Cargo 有一个很棒的功能是:运行 `cargo doc --open` 命令来构建所有本地依赖提供的文档,并在浏览器中打开。例如,假设你对 `rand` crate 中的其他功能感兴趣,`cargo doc --open` 并点击左侧导航栏中的 `rand`。
|
|
|
|
|
知道 use 哪个 trait 和该从 crate 中调用哪个方法并不是是你唯一会 **知道** 的。crate 的使用说明位于其文档中。Cargo 有一个很棒的功能是:运行 `cargo doc --open` 命令来构建所有本地依赖提供的文档,并在浏览器中打开。例如,假设你对 `rand` crate 中的其他功能感兴趣,`cargo doc --open` 并点击左侧导航栏中的 `rand`。
|
|
|
|
|
|
|
|
|
|
新增加的第二行代码打印出了秘密数字。这在开发程序时很有用,因为可以测试它,不过在最终版本中会删掉它。游戏一开始就打印出结果就没什么可玩的了!
|
|
|
|
|
|
|
|
|
@ -387,6 +387,7 @@ fn main() {
|
|
|
|
|
```text
|
|
|
|
|
$ cargo run
|
|
|
|
|
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
|
|
|
|
|
Finished dev [unoptimized + debuginfo] target(s) in 2.53 secs
|
|
|
|
|
Running `target/debug/guessing_game`
|
|
|
|
|
Guess the number!
|
|
|
|
|
The secret number is: 7
|
|
|
|
@ -434,9 +435,9 @@ fn main() {
|
|
|
|
|
println!("You guessed: {}", guess);
|
|
|
|
|
|
|
|
|
|
match guess.cmp(&secret_number) {
|
|
|
|
|
Ordering::Less => println!("Too small!"),
|
|
|
|
|
Ordering::Less => println!("Too small!"),
|
|
|
|
|
Ordering::Greater => println!("Too big!"),
|
|
|
|
|
Ordering::Equal => println!("You win!"),
|
|
|
|
|
Ordering::Equal => println!("You win!"),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
@ -449,9 +450,9 @@ fn main() {
|
|
|
|
|
|
|
|
|
|
```rust,ignore
|
|
|
|
|
match guess.cmp(&secret_number) {
|
|
|
|
|
Ordering::Less => println!("Too small!"),
|
|
|
|
|
Ordering::Less => println!("Too small!"),
|
|
|
|
|
Ordering::Greater => println!("Too big!"),
|
|
|
|
|
Ordering::Equal => println!("You win!"),
|
|
|
|
|
Ordering::Equal => println!("You win!"),
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
@ -459,7 +460,7 @@ match guess.cmp(&secret_number) {
|
|
|
|
|
|
|
|
|
|
[match]: ch06-02-match.html
|
|
|
|
|
|
|
|
|
|
一个 `match` 表达式由 **分支(arms)** 构成。一个分支包含一个 **模式**(*pattern*)和表达式开头的值与分支模式相匹配时应该执行的代码。Rust 获取提供给 `match` 的值并挨个检查每个分支的模式。`match` 结构和模式是 Rust 中强大的功能,它体现了代码可能遇到的多种情形,并帮助你没有遗漏的处理。这些功能将分别在第六章和第十八章详细介绍。
|
|
|
|
|
一个 `match` 表达式由 **分支(arms)** 构成。一个分支包含一个 **模式**(*pattern*)和表达式开头的值与分支模式相匹配时应该执行的代码。Rust 获取提供给 `match` 的值并挨个检查每个分支的模式。`match` 结构和模式是 Rust 中强大的功能,它体现了代码可能遇到的多种情形,并帮助你确保没有遗漏处理。这些功能将分别在第六章和第十八章详细介绍。
|
|
|
|
|
|
|
|
|
|
让我们看看使用 `match` 表达式的例子。假设用户猜了 50,这时随机生成的秘密数字是 38。比较 50 与 38 时,因为 50 比 38 要大,`cmp` 方法会返回 `Ordering::Greater`。`Ordering::Greater` 是 `match` 表达式得到的值。它检查第一个分支的模式,`Ordering::Less` 与 `Ordering::Greater`并不匹配,所以它忽略了这个分支的动作并来到下一个分支。下一个分支的模式是 `Ordering::Greater`,**正确** 匹配!这个分支关联的代码被执行,在屏幕打印出 `Too big!`。`match` 表达式就此终止,因为该场景下没有检查最后一个分支的必要。
|
|
|
|
|
|
|
|
|
@ -485,7 +486,6 @@ Could not compile `guessing_game`.
|
|
|
|
|
|
|
|
|
|
所以我们必须把从输入中读取到的 `String` 转换为一个真正的数字类型,才好与秘密数字进行比较。这可以通过在 `main` 函数体中增加如下两行代码来实现:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<span class="filename">文件名: src/main.rs</span>
|
|
|
|
|
|
|
|
|
|
```rust,ignore
|
|
|
|
@ -515,9 +515,9 @@ fn main() {
|
|
|
|
|
println!("You guessed: {}", guess);
|
|
|
|
|
|
|
|
|
|
match guess.cmp(&secret_number) {
|
|
|
|
|
Ordering::Less => println!("Too small!"),
|
|
|
|
|
Ordering::Less => println!("Too small!"),
|
|
|
|
|
Ordering::Greater => println!("Too big!"),
|
|
|
|
|
Ordering::Equal => println!("You win!"),
|
|
|
|
|
Ordering::Equal => println!("You win!"),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
@ -544,6 +544,7 @@ let guess: u32 = guess.trim().parse()
|
|
|
|
|
```text
|
|
|
|
|
$ cargo run
|
|
|
|
|
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
|
|
|
|
|
Finished dev [unoptimized + debuginfo] target(s) in 0.43 secs
|
|
|
|
|
Running `target/guessing_game`
|
|
|
|
|
Guess the number!
|
|
|
|
|
The secret number is: 58
|
|
|
|
@ -591,9 +592,9 @@ fn main() {
|
|
|
|
|
println!("You guessed: {}", guess);
|
|
|
|
|
|
|
|
|
|
match guess.cmp(&secret_number) {
|
|
|
|
|
Ordering::Less => println!("Too small!"),
|
|
|
|
|
Ordering::Less => println!("Too small!"),
|
|
|
|
|
Ordering::Greater => println!("Too big!"),
|
|
|
|
|
Ordering::Equal => println!("You win!"),
|
|
|
|
|
Ordering::Equal => println!("You win!"),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -634,7 +635,6 @@ error: Process didn't exit successfully: `target/debug/guess` (exit code: 101)
|
|
|
|
|
|
|
|
|
|
让我们增加一个 `break`,在用户猜对时退出游戏:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<span class="filename">文件名: src/main.rs</span>
|
|
|
|
|
|
|
|
|
|
```rust,ignore
|
|
|
|
@ -665,9 +665,9 @@ fn main() {
|
|
|
|
|
println!("You guessed: {}", guess);
|
|
|
|
|
|
|
|
|
|
match guess.cmp(&secret_number) {
|
|
|
|
|
Ordering::Less => println!("Too small!"),
|
|
|
|
|
Ordering::Less => println!("Too small!"),
|
|
|
|
|
Ordering::Greater => println!("Too big!"),
|
|
|
|
|
Ordering::Equal => {
|
|
|
|
|
Ordering::Equal => {
|
|
|
|
|
println!("You win!");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@ -693,7 +693,7 @@ let guess: u32 = match guess.trim().parse() {
|
|
|
|
|
|
|
|
|
|
如果 `parse` 能够成功的将字符串转换为一个数字,它会返回一个包含结果数字的 `Ok`。这个 `Ok` 值与 `match` 第一个分支的模式相匹配,该分支对应的动作返回 `Ok` 值中的数字 `num`,最后如愿变成新创建的 `guess` 变量。
|
|
|
|
|
|
|
|
|
|
如果 `parse` *不* 能将字符串转换为一个数字,它会返回一个包含更多错误信息的 `Err`。`Err` 值不能匹配第一个 `match` 分支的 `Ok(num)` 模式,但是会匹配第二个分支的 `Err(_)` 模式:`_` 是一个通配值,本例中用来匹配所有 `Err` 值,不管其中有何种信息。所以程序会执行第二个分支的动作,`continue` 意味着进入 `loop` 的下一次循环,请求另一个猜测。这样程序就有效的忽略了 `parse` 可能遇到的所有错误!
|
|
|
|
|
如果 `parse` *不* 能将字符串转换为一个数字,它会返回一个包含更多错误信息的 `Err`。`Err` 值不能匹配第一个 `match` 分支的 `Ok(num)` 模式,但是会匹配第二个分支的 `Err(_)` 模式:`_` 是一个通配符值,本例中用来匹配所有 `Err` 值,不管其中有何种信息。所以程序会执行第二个分支的动作,`continue` 意味着进入 `loop` 的下一次循环,请求另一个猜测。这样程序就有效的忽略了 `parse` 可能遇到的所有错误!
|
|
|
|
|
|
|
|
|
|
现在万事俱备,只需运行 `cargo run`:
|
|
|
|
|
|
|
|
|
@ -751,9 +751,9 @@ fn main() {
|
|
|
|
|
println!("You guessed: {}", guess);
|
|
|
|
|
|
|
|
|
|
match guess.cmp(&secret_number) {
|
|
|
|
|
Ordering::Less => println!("Too small!"),
|
|
|
|
|
Ordering::Less => println!("Too small!"),
|
|
|
|
|
Ordering::Greater => println!("Too big!"),
|
|
|
|
|
Ordering::Equal => {
|
|
|
|
|
Ordering::Equal => {
|
|
|
|
|
println!("You win!");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|