The Rust Programming Language - 第2章 Programming a Guessing Game

2 Programming a Guessing Game

2.1 猜数

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、方法、实例、错误处理等概念,这些概念我们在后面都会更详细的讲到

2.2 猜数游戏:生成神秘数字

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.比较猜测的数字和神秘的数字

  1. 编写代码
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;
            }
        }
    }
}

小结:我们通过实现”猜数游戏“这个项目了解了了letmatch、方法、函数、使用外部 crate 等等,接下来的几章,我们会继续深入学习这些概念(挖了好多坑)

你可能感兴趣的:(#,Rust,rust,游戏)