Rust 入门 (二)

我认为学习计算机语言,应该先用后学,这一节,咱们来实现一个猜数字的小游戏。


先简单介绍一个这个游戏的内容:游戏先生成一个1到100之间的任意一个数字,而后咱们输入本身猜想的数字,游戏会告诉咱们输入的数字太大仍是过小,而后咱们从新输入新的数字,直到猜到游戏生成的数字,而后游戏结束。git

建立项目

制做游戏的第一步先建立项目,建立方法和上一节同样,使用 cargo 来建立一个名为 guessing_game 的项目。函数

cargo new guessing_game && cd guessing_game

项目建立完成,能够运行一下,若是程序打印出 Hello, World! 则证实程序建立完成,运行命令以下:oop

cargo run

读取猜想的数字

正式写游戏的第一步,让游戏先读取咱们猜想的数字。咱们能够先把打印语句换成提示咱们输入数字的提示语句。学习

use std::io;

fn main() {
    println!("猜想数字游戏,请输入您猜想的数字。");

    let mut guess = String::new();

    io::stdin().read_line(&mut guess).expect("读取数字失败!");

    println!("您猜想的数字是:{}", guess);
}

这段代码包含了大量的信息,咱们一行一行地过一遍。
1.由于咱们须要读取用户的输入,而后把它做为结果打印出来,因此须要把 标准库(被称做 std )中的 io 依赖引入当前做用域。
2.在主函数中写方法体,首先是打印提示语,不说了。
3.而后建立一个用于保存即将输入的字符串的 String 类型的变量 guess。
4.把控制台输入的数字读取到变量 guess 中,若是读取失败,则打印 “读取数字失败!” 的字符串。
5.把读取的数字再打印到控制台。测试

注:这段程序的细节暂时先不深究了,后续文章会一一解释清楚。


测试一下这段程序:ui

cargo run                                    
   Compiling guessing_game v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/guessing_game)
    Finished dev [unoptimized + debuginfo] target(s) in 1.01s
     Running `target/debug/guessing_game`
猜想数字游戏,请输入您猜想的数字。
2
您猜想的数字是:2

生成随机数

咱们的游戏须要建立一个随机数,供咱们去猜想,这个数字要求每次启动游戏时都是不相同的,这样游戏才更加有意思。接下来咱们在游戏中生成一个1到100的随机数。可是 rust 没有在它的标准库中提供生成随机数的方法,不过不要紧,它提供了生成随机数的名为 rand 的 crate。咱们来引入一下生成随机数的 crate,修改 Cargo.toml 文件:spa

[dependencies]

rand = "^0.3.14"

只须要在 [dependencies] 下面添加须要的 crate 便可。此次添加的 crate 名字是 rand,版本号 0.3.14, 而 ^ 的意思是兼容 0.3.14 版本的任何版本均可以。而后咱们编译一下程序,就会自动下载引入的依赖:debug

cargo build                                      
    Updating crates.io index
   Compiling libc v0.2.65
   Compiling rand v0.4.6
   Compiling rand v0.3.23
   Compiling guessing_game v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/guessing_game)
    Finished dev [unoptimized + debuginfo] target(s) in 1m 13s

引入了生成随机数和 crate 后,咱们来生成一下须要的 crate,代码以下:code

use std::io;
use rand::Rng;

fn main() {
    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("生成的随机数字是:{}", secret_number);

    println!("猜想数字游戏,请输入您猜想的数字。");

    let mut guess = String::new();

    io::stdin().read_line(&mut guess).expect("读取数字失败!");

    println!("您猜想的数字是:{}", guess);
}

能够看到咱们在前面代码的基础上添加了三行代码:
1.第一行是引入生成随机数的依赖。
2.第二行是生成一个随机数,随机数的范围是 [1, 101),区间是左闭右开,说人话就是1到100。
3.第三行是打印生成的随机数。
而后咱们测试一下添加的随机数是否生效:游戏

cargo run                                    
   Compiling guessing_game v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/guessing_game)
    Finished dev [unoptimized + debuginfo] target(s) in 0.45s
     Running `target/debug/guessing_game`
生成的随机数字是:79
猜想数字游戏,请输入您猜想的数字。
6
您猜想的数字是:6

比较随机数和猜想数

如今咱们能够输入本身猜想的数字,也能够生成随机数字了,那么接下来就是比较两者的大小了。可是在比较以前还有个问题,控制台输入的数字是 string 类型的,而随机生成的数字是无符号32位整型(u32),两者不类型不一致,不能做比较,所以,在比较以前,咱们应该先把控制台输入的 string 类型的数字转成u32类型的,代码以下:

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("生成的随机数字是:{}", secret_number);

    println!("猜想数字游戏,请输入您猜想的数字。");

    let mut guess = String::new();

    io::stdin().read_line(&mut guess).expect("读取数字失败!");

    let guess: u32 = guess.trim().parse().expect("请输入一个数字!");

    println!("您猜想的数字是:{}", guess);

    match guess.cmp(&secret_number) {
        Ordering::Less => println!("您猜想的数字过小了!"),
        Ordering::Greater => println!("您猜想的数字太大了!"),
        Ordering::Equal => println!("恭喜您,猜对了!"),
    }
}

可见,咱们在三个位置添加了代码:
1.从标准库中添加了比较的依赖。
2.把输入的数字类型成u32类型,若是输入的不是数字,则转换失败,打印出错误信息。
3.最后一部分就是比较一下两者的大小,并打印出比较的结果。
好了,咱们先测试一下吧,这里咱们只测正确的输入:

cargo run                                     101 ↵
   Compiling guessing_game v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/guessing_game)
    Finished dev [unoptimized + debuginfo] target(s) in 0.42s
     Running `target/debug/guessing_game`
生成的随机数字是:53
猜想数字游戏,请输入您猜想的数字。
4
您猜想的数字是:4
您猜想的数字过小了!

添加循环

咱们发现,咱们只输入了一次,游戏就结束了,这显然不符合咱们的预期。咱们的预期是,咱们能够一直猜一直猜,直到猜中才让游戏结束,那应该怎么修改一下呢?添加一个循环,代码以下:

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("生成的随机数字是:{}", secret_number);

    loop {

        println!("猜想数字游戏,请输入您猜想的数字。");

        let mut guess = String::new();

        io::stdin().read_line(&mut guess).expect("读取数字失败!");

        let guess: u32 = guess.trim().parse().expect("请输入一个数字!");

        println!("您猜想的数字是:{}", guess);

        match guess.cmp(&secret_number) {
            Ordering::Less => println!("您猜想的数字过小了!"),
            Ordering::Greater => println!("您猜想的数字太大了!"),
            Ordering::Equal => println!("恭喜您,猜对了!"),
        }
    }
}

这里修改得比较简单,只须要添加一个名叫 loop 的关键字,而后把须要循环的内容放在 {} 中便可,而后咱们测试一下:

cargo run                                    
   Compiling guessing_game v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/guessing_game)
    Finished dev [unoptimized + debuginfo] target(s) in 0.38s
     Running `target/debug/guessing_game`
生成的随机数字是:71
猜想数字游戏,请输入您猜想的数字。
50
您猜想的数字是:50
您猜想的数字过小了!
猜想数字游戏,请输入您猜想的数字。
71
您猜想的数字是:71
恭喜您,猜对了!
猜想数字游戏,请输入您猜想的数字。
45
您猜想的数字是:45
您猜想的数字过小了!
猜想数字游戏,请输入
t
thread 'main' panicked at '请输入一个数字!: ParseIntError { kind: InvalidDigit }', src/libcore/result.rs:1165:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

咱们的游戏能够屡次输入了,可是有没有发现一些问题呢?
1.游戏直接告诉咱们生成的数字了,那就不用猜了,直接输入就行了。
2.当咱们猜对后,游戏没有结束。
3.当咱们输入的内容不是数字的时候,才会结束游戏,并且不只打印了咱们预期的错误信息,还打印了其它信息。
接下来,咱们把这些问题依次修改,代码以下:

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    let secret_number = rand::thread_rng().gen_range(1, 101);

    // println!("生成的随机数字是:{}", secret_number);

    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(&secret_number) {
            Ordering::Less => println!("您猜想的数字过小了!"),
            Ordering::Greater => println!("您猜想的数字太大了!"),
            Ordering::Equal => {
                println!("恭喜您,猜对了!");
                break;
            }
        }
    }
}

这三处错误的修改方式依次是:
1.把打印随机数的代码注释掉。
2.在作类型转换时,使用 match 关键字做判断,若是转化成功,则返回转化后的结果,若是转化失败,无论由于什么缘由失败,都直接跳出本次循环。
3.在作二个数字大小判断时,若是判断相等,则结束循环。
咱们来测试一下修改的结果:

cargo run                                    
   Compiling guessing_game v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/guessing_game)
    Finished dev [unoptimized + debuginfo] target(s) in 0.38s
     Running `target/debug/guessing_game`
猜想数字游戏,请输入您猜想的数字。
50
您猜想的数字是:50
您猜想的数字过小了!
猜想数字游戏,请输入您猜想的数字。
r
猜想数字游戏,请输入您猜想的数字。
75
您猜想的数字是:75
您猜想的数字过小了!
猜想数字游戏,请输入您猜想的数字。
87
您猜想的数字是:87
您猜想的数字太大了!
猜想数字游戏,请输入您猜想的数字。
81
您猜想的数字是:81
恭喜您,猜对了!

能够看到咱们的游戏制做完成了~~

欢迎阅读单鹏飞的学习笔记

相关文章
相关标签/搜索