【Rust】——猜数游戏
🎃个人专栏:
🐬 算法设计与分析:算法设计与分析_IT闫的博客-CSDN博客
🐳Java基础:Java基础_IT闫的博客-CSDN博客
🐋c语言:c语言_IT闫的博客-CSDN博客
🐟MySQL:数据结构_IT闫的博客-CSDN博客
🐠数据结构:数据结构_IT闫的博客-CSDN博客
💎C++:C++_IT闫的博客-CSDN博客
🥽C51单片机:C51单片机(STC89C516)_IT闫的博客-CSDN博客
💻基于HTML5的网页设计及应用:基于HTML5的网页设计及应用_IT闫的博客-CSDN博客
🥏python:python_IT闫的博客-CSDN博客
🐠离散数学:离散数学_IT闫的博客-CSDN博客
🥽Linux:Linux_Y小夜的博客-CSDN博客
🚝Rust:Rust_Y小夜的博客-CSDN博客
欢迎收看,希望对大家有用!
目录
🎯简介
🎯过程
🚝创建文件并用vscode打开
🚝编写并分析猜测代码
🥽源码
🥽分析
🚝生成一个随机数
🥽引入rand
🥽代码分析
🚝比较随机数和所猜数字
🥽分析代码
🚝进行多次猜测
🎯总结
🎯简介
你将会学到
let
、match
、方法(method)、关联函数(associated function)、外部 crate 等知识!后续文章会深入探讨这些概念的细节。猜猜看游戏。它是这么工作的:程序将会随机生成一个 1 到 100 之间的随机整数。接着它会请玩家猜一个数并输入,然后提示猜测是大了还是小了。如果猜对了,它会打印祝贺信息并退出。
🎯过程
🚝创建文件并用vscode打开
$ cargo new guessing_game $ cd guessing_game $ code .
- 第一个命令,
cargo new
,它获取项目的名称(guessing_game
)作为第一个参数。- 第二个命令进入到新创建的项目目录。
- 第三个命令使用vscode打开文件夹。
🚝编写并分析猜测代码
🥽源码
use std::io;
fn main() {
println!("猜数游戏!");
println!("请输入你猜的数字:");
let mut guess = String::new();
io::stdin().read_line(&mut guess).expect("发生错误");
println!("你猜的数字是:{}",guess);
}
🥽分析
为了获取用户输入并打印结果作为输出,我们需要将
io
输入/输出库引入当前作用域。io
库来自于标准库,也被称为std
:use std::io;
如果你需要的类型不在预导入内容中,就必须使用
use
语句显式地将其引入作用域。std::io
库提供很多有用的功能,包括接收用户输入的功能。
fn main() {
fn
语法声明了一个新函数,小括号()
表明没有参数,大括号{
作为函数体的开始。提醒:
println!
是一个在屏幕上打印字符串的宏。
创建存储用户的输入:
let mut guess = String::new();
提醒:要使用关键字mut(后续文章会进行讲解)创建变量,只用let,创建是常量,变量默认是不可变的,这意味着一旦我们给变量赋值,这个值就不再可以修改了。
等号(
=
)告诉 Rust 我们现在想将某个值绑定在变量上。等号的右边是guess
所绑定的值,它是String::new
的结果,这个函数会返回一个String
的新实例。
::new
那一行的::
语法表明new
是String
类型的一个 关联函数(associated function)。关联函数是针对类型实现的,在这个例子中是String
,而不是String
的某个特定实例。一些语言中把它称为 静态方法(static method)。
new
函数创建了一个新的空字符串,你会发现很多类型上有new
函数,因为它是创建类型实例的惯用函数名。总的来说,
let mut guess = String::new();
这一行创建了一个可变变量,当前它绑定到一个新的String
空实例上。
io::stdin().read_line(&mut guess)
.read_line(&mut guess),调用read_line
方法从标准输入句柄获取用户输入。我们还将&mut guess
作为参数传递给read_line()
函数,让其将用户输入储存到这个字符串中。read_line
的工作是,无论用户在标准输入中键入什么内容,都将其追加(不会覆盖其原有内容)到一个字符串中,因此它需要字符串作为参数。这个字符串参数应该是可变的,以便read_line
将用户输入附加上去。
&(取地址符)
表示这个参数是一个 引用(reference),它允许多处代码访问同一处数据,而无需在内存中多次拷贝。引用是一个复杂的特性,Rust 的一个主要优势就是安全而简单的操纵引用。完成当前程序并不需要了解如此多细节。现在,我们只需知道它像变量一样,默认是不可变的。因此,需要写成&mut guess
来使其可变,而不是&guess
。(第四章会更全面的解释引用。)
.expect("发生错误");
用于报错处理。
println!("你猜的数字是:{}",guess);
将用户猜的数字打印出来,guess也可以写到{}里;
🚝生成一个随机数
🥽引入rand
在我们使用
rand
编写代码之前,需要修改 Cargo.toml 文件,引入一个rand
依赖。在Cargo.toml修改成以下代码:
[dependencies] rand="0.3.14"
在 Cargo.toml 文件中,标题以及之后的内容属同一个片段,直到遇到下一个标题才开始新的片段。
[dependencies]
片段告诉 Cargo 本项目依赖了哪些外部 crate 及其版本。可以用cargo update进行更新
提醒:一定要开启rust服务(可以点击ctrl+shift+p,在输入框里搜索rust)
🥽代码分析
use rand::Rng;
Rng
是一个 trait,它定义了随机数生成器应实现的方法,想使用这些方法的话,此 trait 必须在作用域中。
let secret_number = rand::thread_rng().gen_range(1,101);
rand::thread_rng
函数提供实际使用的随机数生成器:它位于当前执行线程的本地环境中,并从操作系统获取 seed。接着调用随机数生成器的gen_range
方法。这个方法由use rand::Rng
语句引入到作用域的Rng
trait 定义。gen_range
方法获取一个范围表达式(range expression)作为参数,并生成一个在此范围之间的随机数。这里使用的这类范围表达式使用了start,end
这样的形式,前闭后开提醒:新版的参数形式可以能做的改变,详情见官方文档,以官方为准。
🚝比较随机数和所猜数字
🥽分析代码
match guess.cmp(&num) { Ordering::Less => println!("Too small!"), Ordering::Greater => println!("Too big!"), Ordering::Equal => println!("You win!"), }
cmp
方法用来比较两个值并可以在任何可比较的值上调用。它获取一个被比较值的引用:这里是把guess
与secret_number
做比较。然后它会返回一个刚才通过use
引入作用域的Ordering
枚举的成员。一个
match
表达式由 分支(arms) 构成。一个分支包含一个 模式(pattern)和表达式开头的值与分支模式相匹配时应该执行的代码。Rust 获取提供给match
的值并挨个检查每个分支的模式。提醒:可能会出现类型不匹配的情况(guess默认为strng,而num默认为i32)
需要用
let guess: u32 = guess.trim().parse().expect("错误");
进行修改。
我们将这个新变量绑定到
guess.trim().parse()
表达式上。表达式中的guess
指的是包含输入的字符串类型guess
变量。String
实例的trim
方法会去除字符串开头和结尾的空白字符,我们必须执行此方法才能将字符串与u32
比较,因为u32
只能包含数值型数据。用户必须输入 enter 键才能让read_line
返回并输入他们的猜想,这将会在字符串中增加一个换行(newline)符。
parse方法将字符串转换成其他类型。这里用它来把字符串转换为数值。
所以我们要进行修改
let guess:u32=match guess.trim().parse(){ Ok(num)=>num, Err(_)=>continue, };
如果
parse
不能从字符串生成一个数字,返回一个Result
的Err
成员时,expect
会使游戏崩溃并打印附带的信息。如果parse
成功地将字符串转换为一个数字,它会返回Result
的Ok
成员,然后expect
会返回Ok
值中的数字。
🚝进行多次猜测
loop
关键字创建了一个无限循环。我们会增加循环来给用户更多机会猜数字:确保 loop 循环中的代码多缩进四个空格,再次运行程序。注意这里有一个新问题,因为程序忠实地执行了我们的要求:永远地请求另一个猜测,用户好像无法退出。
用户总能使用 ctrl-c 终止程序。不过还有另一个方法跳出无限循环。如果用户输入的答案不是一个数字,程序会崩溃。我们可以利用这一点来退出,
match guess.cmp(&num){ Ordering::Less=>println!("small"), Ordering::Greater=>println!("big"), Ordering::Equal=>{ println!("win"); break; } }
🎯总结
use std::{cmp::Ordering, io};
use rand::Rng;
fn main() {
println!("猜数!");
let num=rand::thread_rng().gen_range(1,101);
loop {
println!("猜一个数:");
let mut guess=String::new();
io::stdin().read_line(&mut guess).expect("无法读取行");
let guess:u32=match guess.trim().parse(){
Ok(num)=>num,
Err(_)=>continue,
};
println!("你猜测的数是:{}",guess);
match guess.cmp(&num){
Ordering::Less=>println!("small"),
Ordering::Greater=>println!("big"),
Ordering::Equal=>{
println!("win");
break;
}
}
}
}
程序将会随机生成一个 1 到 100 之间的随机整数。接着它会请玩家猜一个数并输入,然后提示猜测是大了还是小了。如果猜对了,它会打印祝贺信息并退出。