Rust第三天,编写一个猜数字游戏(第二部分)

上一节我们写到了随便猜一个数字在shell控制台都会打印出结果,但是这样的程序逻辑是不正确的,然后我们继续完善这个功能。

1. 生成秘密数字

在生成秘密数字的时候我们需要用到,rand crate这个库,然而这个库是我们0.8.6才发布的所以我们需要统一一下版本。

1.2 更新箱子以获取新版本

这里我们需要将版本确定一下,就需要修改Cargo.toml文件,修改为如下内容:

ini 复制代码
[package]
name = "guessing_game"
version = "0.1.0"
edition = "2024"

[dependencies]
rand = "0.8.5"

[dependencies] rand = "0.8.5"是我们需要修改的内容,目的是为了和教程中的rand版本一致,因为Rust也有很多版本,随着时间的增长而更新。就好比我们的node现在都二十多的版本了。这里表示任何至少为 0.8.5 但低于 0.9.0 的版本. 紧接着我们需要构建一下代码,用来同步版本库。在DOC命令行输入:

复制代码
cargo build

3. 生成随机数

这里我们需要用到一个库,他就是rand::Rng,这里我们可以使用这个库生成随机数字,使用如下:

css 复制代码
let secret_number = rand::thread_rng().gen_range(1..100);

其中上面的.gen_range()是限制我们的取值范围,1..100是说我们的随机数字就在1~100这个取值范围。

4.将猜测数字与秘密数字进行比较

在这里比较就相对来说容易理解了,如下所示:

ini 复制代码
match guess.cmp(&secret_number){
            Ordering::Less => println!("Too small!"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => println!("You win!");
}

上面的guess是我们输入的数字,再经过格式转换等操作,然后和我们自己生成的秘密数字secret_number作比较。大括号里面的内容就相当于js中的大于小于和等于了,这一点很好理解,主要说一下Ordering,这个是什么东东,他从哪里来?

Ordering是我们另外一个库use std::cmp::Ordering,这里我们直接将这一行放到文件第一行引入这个库。Ordering::Less这是小于,Ordering::Greater这是大于,Ordering::Equal这个是等于。这里我们注意要将输入的变量放在.cmp之前而不是放在后面的()里面。

5. 使用循环允许多次猜测

这里使用循环就比较简单了,就是使用一个loop将重复使用的代码包起来,如下:

rust 复制代码
loop {
    match guess.cmp(&secret_number){
            Ordering::Less => println!("Too small!"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => println!("You win!");
    }
}

这里我们发现一个问题,怎么可以一直比较一直循环,如何跳出循环呢,那我们看下面。

6.处理比较两个数字的可能返回值

没错,这里跳出循环同样使用break,Ordering::Less =>这里的箭头,有点像js中的箭头函数,可以放一句话也可以放一个方法。所以代码如下。

ini 复制代码
match guess.cmp(&secret_number){
            Ordering::Less => println!("Too small!"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => {
                println!("You win!");
                break;
            };
}

也就是说当输入的数字和生成的神秘数字一样了,就提示你胜出了。然后跳出循环。

7.处理无效输入

当然了,假如有人乱输入,比如输入一大堆字符串不输入数字我们怎么办,就需要处理用户输入的数据了,代码如下:

scss 复制代码
let guess: u32 = match guess.trim().parse(){
            Ok(num)=>num,
            Err(_)=>continue,
        };

u32是指的guess类型,用来限定类型相当于TypeScript 的类型限定,这里是说类型为无符号 32 位数字。并且加了个判断,判断将用户输入的内容处理的程序是否出错guess.trim().parse(),这里处理的内容就是先将两边的空格去除,然后再按照u32的格式化,出错的话就跳出这一次循环Err(_)=>continue,继续重新输入。

最后贴上最终的代码,供大家测试把玩。

rust 复制代码
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..100);
   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: {guess}");
       match guess.cmp(&secret_number){
           Ordering::Less => println!("Too small!"),
           Ordering::Greater => println!("Too big!"),
           Ordering::Equal => {
               println!("You win!");
               break;
           }
       }
   }
}

感谢大家观看,我们下次见

相关推荐
文艺理科生6 小时前
Nginx 路径映射深度解析:从本地开发到生产交付的底层哲学
前端·后端·架构
千寻girling6 小时前
主管:”人家 Node 框架都用 Nest.js 了 , 你怎么还在用 Express ?“
前端·后端·面试
南极企鹅6 小时前
springBoot项目有几个端口
java·spring boot·后端
Luke君607976 小时前
Spring Flux方法总结
后端
define95276 小时前
高版本 MySQL 驱动的 DNS 陷阱
后端
忧郁的Mr.Li6 小时前
SpringBoot中实现多数据源配置
java·spring boot·后端
暮色妖娆丶7 小时前
SpringBoot 启动流程源码分析 ~ 它其实不复杂
spring boot·后端·spring
Coder_Boy_7 小时前
Deeplearning4j+ Spring Boot 电商用户复购预测案例中相关概念
java·人工智能·spring boot·后端·spring
Java后端的Ai之路7 小时前
【Spring全家桶】-一文弄懂Spring Cloud Gateway
java·后端·spring cloud·gateway
野犬寒鸦7 小时前
从零起步学习并发编程 || 第七章:ThreadLocal深层解析及常见问题解决方案
java·服务器·开发语言·jvm·后端·学习