zoukankan      html  css  js  c++  java
  • Rust 入门 (二)

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


    先简单介绍一个这个游戏的内容:游戏先生成一个1到100之间的任意一个数字,然后我们输入自己猜测的数字,游戏会告诉我们输入的数字太大还是太小,然后我们重新输入新的数字,直到猜到游戏生成的数字,然后游戏结束。

    创建项目

    制作游戏的第一步先创建项目,创建方法和上一节一样,使用 cargo 来创建一个名为 guessing_game 的项目。

    cargo new guessing_game && cd guessing_game
    

    项目创建完成,可以运行一下,如果程序打印出 Hello, World! 则证明程序创建完成,运行命令如下:

    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.把读取的数字再打印到控制台。

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


    测试一下这段程序:

    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 文件:

    [dependencies]
    
    rand = "^0.3.14"
    

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

    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,代码如下:

    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
    恭喜您,猜对了!
    

    可以看到我们的游戏制作完成了~~

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

  • 相关阅读:
    《Python 学习手册4th》 第十一章 赋值、表达式和打印
    《Python 学习手册4th》 第十章 Python语句简介
    视图
    表约束
    表值参数
    表操作
    MSSQL数据批量插入优化详细
    SQL Server表分区
    表分区中的分区交换
    maven命令和maven插件
  • 原文地址:https://www.cnblogs.com/shanpengfei/p/11945047.html
Copyright © 2011-2022 走看看