本小节目标
通过循环完成完整的猜数游戏.
代码
当前的代码与上节相比有较大改动, 请复制到本地, 稍后讲解:
rust
use rand::random_range;
use std::{cmp::Ordering, io};
fn main() {
println!("请猜测一个数");
let secret_num = random_range(1..=100);
println! ("{}", loop {
let mut guess = String::new();
io::stdin().read_line(&mut guess).unwrap();
let guess = guess.trim();
let result = match guess.cmp(&secret_num.to_string()) {
Ordering::Less => "太小了",
Ordering::Greater => "太大了",
Ordering::Equal => "猜对了",
};
println!("你猜的是: {}, {}.", guess, result);
if result == "猜对了" {
break "结束猜测.";
}
})
}loop 循环
代码中出现了新的关键字 loop, 使用语句
rust
loop {
/* 山有扶苏, 隰有荷华. */
}将会一遍一遍地顺序运行大括号定界的语句块. 代码中, 我们通过 loop 循环实现让用户重复猜测数字并判断比较情况.
loop 循环可被 break 关键字跳出. 此外虽然本处代码未提及, 但还有一个类似的关键字 continue, 将会仅跳过本次循环的剩余部分而进入下一次循环, 而非直接跳出循环体.
所有语句都是表达式
我们在循环体内定义了 result 为将要打印的提示信息, 通过 match 模式匹配根据不同的比较结果返回不同的结果, 此处
rust
match guess.cmp(&secret_num.to_string()) {
Ordering::Less => "太小了",
Ordering::Greater => "太大了",
Ordering::Equal => "猜对了",
}的返回值类型就是 &str, 之后会知道这就是字符串字面量的类型. 将这团东西看做一个黑盒 some_function_about(&guess, &secret_num), 那么我们的定义赋值语句就可以视作
rust
let result = some_function_about(&guess, &secret_num);这么看待的目的在于末尾的分号 ;: 模式匹配的大括号结束时, 赋值语句并未关闭, 而额外通过一个 ; 关闭.
再来看 break 关键字后跟随的一个字符串字面量:
rust
break "结束猜测.";loop 循环体同样拥有返回值, 其内容就决定以 break 关键字. 在当前代码中, 除非被 .unwrap() 截胡, 否则 loop 循环结束时总会由 break 返回字符串字面量 "结束猜测.".
进一步说明
除了后面跟着某个值, break 关键字同样可以直接以 ; 关闭:
rust
loop {
break;
}此时并不是说 loop 循环体没有返回值, 而是说其返回值类型为空, 写作 (). 这并非某种特例, 事实上, 所有以分号 ; 结尾的表达式, 或者叫做语句, 均返回 () 类型.