我的学习总结
cargo new guess_number
cd guess*
code .
2. 构造项目
cargo build
3. 处理用户输入
use std::io;
fn main() {
println!("---猜数字游戏---");
println!("请输入你猜的数字: ");
//生成一个String类型的字符串
let mut guess=String::new();
io::stdin().read_line(&mut guess).expect("输入错误\n");
println!("你输入的数字是: {}",guess);
}
解析:
cargo run
接下来,需要生成一个秘密数字,好让用户来猜。秘密数字应该每次都不同,这样重复玩才不会乏味;范围应该在 1 到 100 之间,这样才不会太困难。Rust 标准库中尚未包含随机数功能。然而,Rust 团队还是提供了一个包含上述功能的 :rand
rand下载地址
导入rand扩展包:
在Cargo.toml文件的下面,添加这样一行信息:(表示我们要下载rand的扩展包的0.8.5版本,当然你可以根据网站的信息来下载最新的)
rand=“0.8.5”
我们来重新构建一下
cargo build
稍微等待一下,就可以根据你填写的版本,下载rand扩展包,此时构建完成之后,Cargo.lock文件里就会生成rand的相关信息配置,此时我们的rand就配置成功了,如果你想修改版本,直接在Cargo.toml里面修改rand的版本号就可以,然后重新执行 cargo build 来构建它。
下面我们来生成一个随机数字:
use rand::Rng;
//生成一个随机数字
let secret_number=rand::thread_rng().gen_range(1..101);
注意我们生成的随机数字是不变的,所以不用给它声明为mut,后面照抄就可以(以后再讲),注意gen_raneg的括号里面的格式:
1…101;表示生成一个左闭右开的区间: [1,101) ;
1…=101:表示生成一个左闭右闭的区间,[1,101]
use std::io;
use rand::Rng;
fn main() {
println!("---猜数字游戏---");
//生成一个随机数字
let secret_number=rand::thread_rng().gen_range(1..101);
println!("请输入你猜的数字: ");
//生成一个String类型的字符串
let mut guess=String::new();
io::stdin().read_line(&mut guess).expect("输入错误\n");
println!("你输入的数字是: {}",guess);
println!("随机数字是:{}",secret_number);
}
cargo run
你可能认为,if else可以轻松的解决这个问题,但是在rust里面我们无法使用if else(就我目前而言不知道),我们要了解一个新的东西: macth(匹配)
导入一个叫做cmp的东西
use std::cmp::Ordering;
//匹配 guess和secret_number是什么类型
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small.\n"),
Ordering::Greater => println!("Too big.\n"),
Ordering::Equal => println!("Equal.\n"),
}
但是现在我们还不能编译他,会出错,我们先了解以下这个结构:
但是我们忘记了一个很重要的东西:
先试着来编译以下:
cargo run
String不是整形,不能和随机生成的数字相比较,类型不匹配,所以我们必须试着转换类型。
guess 是 String类型
secret_number是i32类型
我们可以使用rust提供的一个新概念:隐藏(shadow)
//shadow隐藏
let guess:u32=guess.trim().parse().expect("转换失败!\n");
简单来说,当我们在下文创建一个同名的变量时,会自动隐藏上一个同名的变量,我们把以前的这个String类型转换为 u32类型。需要显示指定类型。
之后我们的guess就从String变成了 u32类型,同时上一个guess的String类型就会消失
这时我们就用match同时对两个 u32类型的数进行比较了。
注意:match的cmp会自动强制转化两个变量为同一类型:
secret一开始是 i32类型,生成的随机数,是有符号整型,会自动转换为和guess一样的类型: u32
然后就可以比较了,运行如下:
cargo run
我们已经完成了这个程序的大部分,猜数字还应该持续的比较下去,直到你猜到了随机数字:使用loop循环来进行游戏重复进行:
类似于 while(1) 注意,它是无限循环,需要指定游戏的退出
loop {
println!("请输入你猜的数字: ");
//生成一个String类型的字符串
let mut guess=String::new();
io::stdin().read_line(&mut guess).expect("输入错误\n");
//shadow隐藏
let guess:u32=guess.trim().parse().expect("转换错误!\n");
println!("你输入的数字是: {}",guess);
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small.\n"),
Ordering::Greater => println!("Too big.\n"),
Ordering::Equal => break, //游戏结束
}
}
注意要在比较时相等的情况下,指定它退出loop循环,即break
别忘了隐藏随机数字,不打印出来随机数字。
运行程序如下:
cargo run
我们还剩最后一步,我们如果在输入数字时出现了字母或者其他字符该怎么办?
程序就会直接退出,报错
在变量隐藏和强制转换的时候,指定出错误时需要干的事情:即重新读取
//shadow隐藏
let guess:u32=match guess.trim().parse()
{
Ok(num) => num,
Err(_) => continue,
};
别忘了parse的返回类型是Result类型,是一个枚举类型,返回Ok,或者Err
最后我们再来运行一下程序:
cargo run
这样我们就算输入字符也会提示我们重新输入
这样我们的猜数字游戏就完成了
use std::io;
use rand::Rng;
use std::cmp::Ordering;
fn main() {
println!("---猜数字游戏---");
//生成一个随机数字
let secret_number=rand::thread_rng().gen_range(1..101);
loop {
println!("请输入你猜的数字: ");
//生成一个String类型的字符串
let mut guess=String::new();
io::stdin().read_line(&mut guess).expect("输入错误\n");
//shadow隐藏
let guess:u32=match guess.trim().parse()
{
Ok(num) => num,
Err(_) => continue,
};
println!("你输入的数字是: {}",guess);
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small.\n"),
Ordering::Greater => println!("Too big.\n"),
Ordering::Equal => break, //游戏结束
}
}
}
这一期只是先了解一下rust语言,如果有什么不懂的函数或者其他的东西,其实我也不懂,今后我们将一步步来讲解这些东西
下期预告:常见rust编程概念: 基本变量和标量函数注释