上一节我们写到了随便猜一个数字在shell
控制台都会打印出结果,但是这样的程序逻辑是不正确的,然后我们继续完善这个功能。
1. 生成秘密数字
在生成秘密数字的时候我们需要用到,rand crate
这个库,然而这个库是我们0.8.6
才发布的所以我们需要统一一下版本。
1.2 更新箱子以获取新版本
这里我们需要将版本确定一下,就需要修改Cargo.toml
文件,修改为如下内容:
ini
[package]
name = "guessing_game"
version = "0.1.0"
edition = "2024"
[dependencies]
rand = "0.8.5"
[dependencies] rand = "0.8.5"
是我们需要修改的内容,目的是为了和教程中的rand
版本一致,因为Rust
也有很多版本,随着时间的增长而更新。就好比我们的node现在都二十多的版本了。这里表示任何至少为 0.8.5 但低于 0.9.0 的版本. 紧接着我们需要构建一下代码,用来同步版本库。在DOC
命令行输入:
cargo build

3. 生成随机数
这里我们需要用到一个库,他就是rand::Rng
,这里我们可以使用这个库生成随机数字,使用如下:
css
let secret_number = rand::thread_rng().gen_range(1..100);
其中上面的.gen_range()
是限制我们的取值范围,1..100
是说我们的随机数字就在1~100
这个取值范围。
4.将猜测数字与秘密数字进行比较
在这里比较就相对来说容易理解了,如下所示:
ini
match guess.cmp(&secret_number){
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => println!("You win!");
}
上面的guess
是我们输入的数字,再经过格式转换等操作,然后和我们自己生成的秘密数字secret_number
作比较。大括号里面的内容就相当于js
中的大于小于和等于了,这一点很好理解,主要说一下Ordering
,这个是什么东东,他从哪里来?
Ordering
是我们另外一个库use std::cmp::Ordering
,这里我们直接将这一行放到文件第一行引入这个库。Ordering::Less
这是小于,Ordering::Greater
这是大于,Ordering::Equal
这个是等于。这里我们注意要将输入的变量放在.cmp
之前而不是放在后面的()
里面。
5. 使用循环允许多次猜测
这里使用循环就比较简单了,就是使用一个loop
将重复使用的代码包起来,如下:
rust
loop {
match guess.cmp(&secret_number){
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => println!("You win!");
}
}
这里我们发现一个问题,怎么可以一直比较一直循环,如何跳出循环呢,那我们看下面。
6.处理比较两个数字的可能返回值
没错,这里跳出循环同样使用break
,Ordering::Less =>
这里的箭头,有点像js中的箭头函数,可以放一句话也可以放一个方法。所以代码如下。
ini
match guess.cmp(&secret_number){
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
break;
};
}
也就是说当输入的数字和生成的神秘数字一样了,就提示你胜出了。然后跳出循环。
7.处理无效输入
当然了,假如有人乱输入,比如输入一大堆字符串不输入数字我们怎么办,就需要处理用户输入的数据了,代码如下:
scss
let guess: u32 = match guess.trim().parse(){
Ok(num)=>num,
Err(_)=>continue,
};
u32
是指的guess
类型,用来限定类型相当于TypeScript
的类型限定,这里是说类型为无符号 32 位数字。并且加了个判断,判断将用户输入的内容处理的程序是否出错guess.trim().parse()
,这里处理的内容就是先将两边的空格去除,然后再按照u32
的格式化,出错的话就跳出这一次循环Err(_)=>continue
,继续重新输入。
最后贴上最终的代码,供大家测试把玩。
rust
use std::io;
use rand::Rng;
use std::cmp::Ordering;
fn main() {
println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1..100);
loop{
println!("Please input your guess.");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Failed to read line");
let guess: u32 = match guess.trim().parse(){
Ok(num)=>num,
Err(_)=>continue,
};
println!("You guessed: {guess}");
match guess.cmp(&secret_number){
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
break;
}
}
}
}
感谢大家观看,我们下次见