1)新建一个文件并打开
(1)使用cargo new 新建文件夹
(2)使用cd 打开
cargo new guessing_game
cd guessing_game
(3)使用vs code 打开文件
2)编写代码
use std::io;
fn main() {
println!("Guess the number!");
println!("input your guess.");
let mut guess = String::new();
io::stdin().read_line(&mut guess)
.expect("Failed to read line");
println!("You guessed: {}", guess);
}
3)代码分析
3.1)为了使用标准输入,我们在函数之前使用了标准库的io,具体语法:
use std::io;
io::stdin().read_line(&mut guess)
.expect("Failed to read line");
代码的下一部分,.read_line(&mut guess)
,调用 read_line
方法从标准输入句柄获取用户输入。我们还向 read_line()
传递了一个参数:&mut guess
,&表示引用,允许多处代码访问统一数据而无需多次拷贝,并且默认是不可变的,需要在加上mut保证它的可变性
并且,当使用.method_name()语法调用方法时,最佳做法是通过换行加缩进来把长行拆开
3.2)使用关键字let定义变量, 如变量前面加mut,表示变量值可变,否则不可变
let mut apple = 5;可变变量
let banana = 6;不可变变量
在上述程序中,我们将绑定了类型的关联函数赋值给了变量guess
let mut guess = String::new();
3.3)String::new()
String::new会返回一个string类型,其中::语法表示new()是string类型的一个关联函数,关联函数是针对具体类型而实现的,这个例子中就是string
3.4) 使用Result类型来处理潜在的错误
继续前面的分析,我们给read_line方法传递了一个引用类型的参数,它会返回Result结果,而Result类型是个枚举,通常写作enums,枚举中持有固定集合的值,它们被称为成员variants。这里的Result包含两个成员,OK和Err,并且Result 拥有expect方法,如果Result实例是Err,expect会导致程序崩溃,并传递错误信息,如果是Ok,则会返回原输入值
3.5 {}
println!("You guessed: {}", guess);
{} 代表要打印的变量,若需打印多个变量值,那罗列多个{}即可
3.6)测试代码:使用cargo run即可查看结果
> Executing task: C:\Users\xxx\.cargo\bin\cargo.exe run --package guessing_game --bin guessing_game <
Finished dev [unoptimized + debuginfo] target(s) in 0.07s
Running `target\debug\guessing_game.exe`
Guessing the number!
input your guess.
34
You guessed: 34
小结:以上是一个简单的程序,我们引出了变量、函数、creates、方法、实例、错误处理等概念,这些概念我们在后面都会更详细的讲到
1.生成神秘数字
1)生成神秘数字的前期准备
因为Rust标准库中尚未包含成随机数功能,所以我们无法直接调用标注库实现我们的目标,但是Rust构建了一个rand crate, 类似于其他语言中的“package”概念,里面包含了可以被其他程序使用的代码。同样的,关于crate的跟朵内容我们在后面会讲到,这个先挖个坑。在使用它之前,我们必须引入rand依赖,并且使用cargo build 构建,具体操作如下:
在cargo.toml文件中指定rand
[dependencies]
rand = "0.8.3"
使用cargo build在终端中构建
cargo build
2)编写代码
use std::io;
use rand::Rng;
fn main() {
println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1..101);
println!("The secret number is: {}", secret_number);
println!("Please input your guess.");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Failed to read line");
println!("You guessed: {}", guess);
}
3)代码分析
use rand::Rng;
我们在第二行引入一个crate rand,其中Rng是一个trait,类似其它语言中的接口
rand::thread_rng
函数提供实际使用的随机数生成器,接下来,调用随机数生成器的 gen_range
方法,gen_range
方法接受一个范围表达式作为参数,并在该范围内生成一个随机数
代码的其他部分我们就不过多赘述了,前面都讲过
2.比较猜测的数字和神秘的数字
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..101);
println!("The secret number is: {}", secret_number);
println!("Please input your guess.");
let mut guess = String::new();
io::stdin().read_line(&mut guess)
.expect("Failed to read line");
let guess:u32 = guess.trim().parse()
.expect("Please type a number!");
println!("You Guessed number,{}",guess);
match guess.cmp(&secret_number) {
Ordering::Less=>println!("Too small!"),
Ordering::Greater=>println!("Too big!"),
Ordering::Equal=>println!("You win!"),
}
}
2)代码分析
2.1)Rust 语言在创建时有个shadow特性,意思是后创建的同名变量会shadow前面的变量,比如:
let mut guess = String::new();
let guess:u32 = guess.trim().parse()
.expect("Please type a number!");
第二个同名变量中,我们将变量绑定到了一个表达式,trim()方法会去掉字符串开头和结尾的空白字符,而且parse()方法会将字符串解析成数字,expect()方法照例是对错误的处理方法
2.3)为了比较我们猜测的数字和神秘的随机数,我们需要引入并且使用标准库中的Ordering类型
match guess.cmp(&secret_number) {
Ordering::Less=>println!("Too small!"),
Ordering::Greater=>println!("Too big!"),
Ordering::Equal=>println!("You win!"),
}
match由多个分支构成,如果匹配正确,则执行后面的语句(这一点和if语句比较像)
3.使用循环来允许多次猜测
1)编写代码
把输入和比较嵌入loop循环体
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..101);
println!("The secret number is: {}", secret_number);
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 = guess.trim().parse()
.expect("Please type a number!");
println!("You Guessed number,{}",guess);
match guess.cmp(&secret_number) {
Ordering::Less=>println!("Too small!"),
Ordering::Greater=>println!("Too big!"),
Ordering::Equal=>println!("You win!"),
}
}
}
loop是一个限循环
4.猜测正确后退出
1)编写代码
match guess.cmp(&secret_number) {
Ordering::Less=>println!("Too small!"),
Ordering::Greater=>println!("Too big!"),
Ordering::Equal=>{
println!("You win!");
break;
}
}
当条件满足时退出程序:只需要在相应的语句后面添加break语句即可
5.处理无效输入
1)如果是无效输入,让程序不奔溃而是继续运行
let guess:u32 = match guess.trim().parse(){
Ok(num)=>num,
Err(_)=>continue,
};
2)最后一步,让我们把下列语句删掉。完全依靠用户猜测;
println!("The secret number is: {}", secret_number);
3)猜数游戏的完整代码
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..101);
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 number,{}",guess);
match guess.cmp(&secret_number) {
Ordering::Less=>println!("Too small!"),
Ordering::Greater=>println!("Too big!"),
Ordering::Equal=>{
println!("You win!");
break;
}
}
}
}
小结:我们通过实现”猜数游戏“这个项目了解了了let
、match
、方法、函数、使用外部 crate 等等,接下来的几章,我们会继续深入学习这些概念(挖了好多坑)