首页 > 其他分享 >01 - Rust 猜数字游戏

01 - Rust 猜数字游戏

时间:2023-09-26 23:01:49浏览次数:56  
标签:guessing guess 01 游戏 rand number game println Rust

目录
对于任何编程语言在实例中学习效果都要比空洞的直接学习概念好。正所谓“talk is cheap, show me code.”是也。

本篇,以猜数字游戏为例,对 rust 语言中涉及到的概念进行讲解,尽可能做到深入浅出。

1. 猜数字游戏的逻辑

  1. 程序将会随机生成一个 1 到 100 之间的随机整数。
  2. 接着请玩家猜一个数并输入。
  3. 提示猜测是大了还是小了。如果猜对了,它会打印祝贺信息并退出。

2. 创建新项目

主要通过

cargo new guessing_game
cargo run

来创建新的项目,运行结果如下:

➜  tmp git:(master) ✗ cargo new guessing_game  
     Created binary (application) `guessing_game` package
➜  tmp git:(master) ✗ ls
guessing_game
➜  tmp git:(master) ✗ cd guessing_game       
➜  guessing_game git:(master) ✗ cargo run              
   Compiling guessing_game v0.1.0 (/home/ak3/wspaces/dev/tmp/guessing_game)
    Finished dev [unoptimized + debuginfo] target(s) in 0.30s
     Running `target/debug/guessing_game`
Hello, world!

3. 猜数字游戏实现

拆分为以下三个步骤来实现,具体概念穿插讲解,在最后再进行总结。

3.1 获取用户输入并打印

a. 标准库引入

获取用户输入的功能,需要引入标准库内容来完成,如下:

use std::io;

标准读写库文档 就能看到从控制台读写的案例
代码如下:

use std::io;

fn main() -> io::Result<()> {
    let mut input = String::new();

    io::stdin().read_line(&mut input)?;

    println!("You typed: {}", input.trim());
    Ok(())
}

执行如下:

➜  guessing_game git:(master) ✗ cargo run
   Compiling guessing_game v0.1.0 (/home/ak3/wspaces/dev/tmp/guessing_game)
    Finished dev [unoptimized + debuginfo] target(s) in 0.22s
     Running `target/debug/guessing_game`
11
You typed: 11

b. println! 宏

println! 是一个在屏幕上打印字符串的

c. 可变与不可变 变量

上面的input 变量使用了可变变量的定义。Rust中默认定义的变量具有不可变性,可变变量需要显示用 let mut来定义。

d. string::new 与io::stdin().read_line(&mut input)

3.2 生成指定范围内的随机数

Rust 标准库中尚未包含随机数功能。然而,Rust 团队还是提供了一个包含上述功能的 rand crate。

crates.io 搜索rand 得到 rand crate的相关信息,然后在执行如下命令添加 rand crate

cargo add rand

对比执行上述命令前后差异,是在 Cargo.toml中增加了一行

rand = "0.8.5"

rand右侧进入其rand documention

在原来代码基础上新增 如下代码

use rand::Rng;

let secret_number = rand::thread_rng().gen_range(1..=100);

    println!("The secret number is: {secret_number}");

执行 cargo run 显示如下:

  Downloaded libc v0.2.148
  Downloaded getrandom v0.2.10
  Downloaded 3 crates (748.2 KB) in 29.36s
   Compiling libc v0.2.148
   Compiling cfg-if v1.0.0
   Compiling ppv-lite86 v0.2.17
   Compiling getrandom v0.2.10
   Compiling rand_core v0.6.4
   Compiling rand_chacha v0.3.1
   Compiling rand v0.8.5
   Compiling guessing_game v0.1.0 (/home/ak3/wspaces/dev/tmp/guessing_game)
    Finished dev [unoptimized + debuginfo] target(s) in 30.82s
     Running `target/debug/guessing_game`
The secret number is: 66
12
You typed: 12

在执行cargo run的过程中,会下载 rand 相关的 crate lib.

3.3 随机数与猜测数的比较

这部分的主要是循环读取用户输入,与随机数比较给出输出直至猜中结束游戏。

a. 字符串转数字

由于从控制台输入的数据最先取得的都是字符串,需要将字符串转换为相应类型,才能进行对应的操作。

// 此处guess 覆盖了上面的 guess ,Rust 允许同名覆盖变量,隐藏 (Shadowing) guess 之前的值
let guess: u32 = guess.trim().parse().expect("Please type a number!");

parse 方法返回一个 Result 类型。像之前 “使用 Result 类型来处理潜在的错误” 讨论的 read_line 方法那样,再次按部就班的用 expect 方法处理即可。如果 parse 不能从字符串生成一个数字,返回一个 Result 的 Err 成员时,expect 会使游戏崩溃并打印附带的信息。

b. 数字比较大小

use std::cmp::Ordering;

增加 use 声明,从标准库引入了一个叫做 std::cmp::Ordering 的类型到作用域中。 Ordering 也是一个枚举,不过它的成员是 Less、Greater 和 Equal。这是比较两个值时可能出现的三种结果。

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

使用一个 match 表达式,根据对 guess 和 secret_number 调用 cmp 返回的 Ordering 成员来决定接下来做什么。

一个 match 表达式由 分支(arms) 构成。一个分支包含一个 模式(pattern)和表达式开头的值与分支模式相匹配时应该执行的代码。Rust 获取提供给 match 的值并挨个检查每个分支的模式。

c. 循环处理多次猜想

直接通过 loop 关键字进行循环读入比较,正确则推出(break 关键字退出循环)。
代码如下:

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

fn main(){
    

    let secret_number = rand::thread_rng().gen_range(1..=100);

    // println!("The secret number is: {secret_number}");

    loop {
        let mut guess = String::new();
        println!("Please input your guess.");
        io::stdin().read_line(&mut guess);
        
        // 此处guess 覆盖了上面的 guess ,Rust 允许同名覆盖变量,隐藏 (Shadowing) guess 之前的值
        let guess: u32 = guess.trim().parse().expect("Please type a number!");

        match guess.cmp(&secret_number) {
            Ordering::Less => println!("Too small!"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => {
                println!("You win!");
                break;  // 跳出循环,结束游戏。
            }
        }
    }

}

至此,我们的猜数字游戏完成了。但也存在一些对输入数据异常的 case 处理。
在后续学习中逐步完善。

4. 总结

虽然猜数字游戏较小,但从中能看到一些 rust 的特性:

  1. 使用 use 关键字引入库。
  2. println! 是宏。
  3. match 表达式。
  4. Result 枚举类型。

更多详情,且看后续笔记。

本文参考 Rust 程序设计语言:写个猜数字游戏

标签:guessing,guess,01,游戏,rand,number,game,println,Rust
From: https://www.cnblogs.com/jfunny/p/17731479.html

相关文章

  • Rust 日志记录库 tracing
    Rust日志记录库tracing​#2023-09-26#​#日志#​#tracing#一个好用的日志跟踪系统,可以帮助我们很快的定位程序中的bug。tracing不仅仅可以作为一个日志库去使用,还可以作为一个程序追踪库,帮助我们分析程序中存在的问题。tracing-Rusttracing各个模块​tracing​​:......
  • 多线程Review-926-01
    一、进程与线程1、进程:①电脑管家等软件我们运行的应用程序②在内存中正在运行的程序2、线程:①进程中的一个最小执行单元。一个进程最少得有一个线程②软件中的每一个功能,如电脑管家中的清理垃圾、杀毒、软件搜索二、线程的创建方式1、继承Thread类  :优点——代码......
  • Adobe全家桶2015-2024全套Win+Mac最新爱国版软件吐血整理(含AI绘画版本)
    爆肝整理,最全的设计类软件大全切记!!!先转存,随时都有可能被和谐。Windows系统版本截图:Mac系统版本截图:网盘下载:切记!!!先转存,随时都有可能被和谐。链接:https://pan.quark.cn/s/3a964f54ea82提取码:ZHYMAdobe全家桶软件目录、最新版本号(部分未及时更新,请进网盘查看):Adobe20......
  • 文心一言 VS 讯飞星火 VS chatgpt (101)-- 算法导论9.3 7题
    七、用go语言,设计一个O(n)时间的算法,对于一个给定的包含n个互异元素的集合S和一个正整数k≤n,该算法能够确定S中最接近中位数的k个元素。文心一言:要设计一个O(n)时间的算法来找到集合S中最接近中位数的k个元素,我们可以使用快速选择算法(QuickSelect)。该算法基于快速排......
  • 文心一言 VS 讯飞星火 VS chatgpt (101)-- 算法导论9.3 7题
    七、用go语言,设计一个O(n)时间的算法,对于一个给定的包含n个互异元素的集合S和一个正整数k≤n,该算法能够确定S中最接近中位数的k个元素。文心一言:要设计一个O(n)时间的算法来找到集合S中最接近中位数的k个元素,我们可以使用快速选择算法(QuickSelect)。该算法基于快速排序的......
  • P6344 [CCO2017] Vera 与现代艺术 题解
    在\(V\timesV\)的平面上,\(n\)次修改,每次给定\(x,y,v\),令\(a,b\)为不超过\(x,y\)的最大的\(2\)的整数次幂,则所有\((x+pa,y+qb)(p,q为自然数)\)都加上\(v\),最后有\(m\)次单点询问一个位置的值。\(1\lex,y,V\le10^{18},1\lev,n,m\le2\times10^5\)我们可以......
  • P4099 [HEOI2013] SAO
    原题今天我刚知道一个很逆天的事:\(DAG\)的拓扑序方案数不可做!!!,目前能做到的最优方法好像是状压我们考虑这题怎么做,对于一个限制,我们关心的是他俩在拓扑序中的相对排名,而这题恰好是一个树形结构,因此我们考虑树形\(dp\)我们设\(dp_{i,j}\)表示以\(i\)为根的子树,\(i\)在拓......
  • NOI2015酱油记
    这么一想我好像破掉了两个flag。。。一个是Ag的flag……(Wc、Ctsc、Apio都是Ag另一个是二试被翻的flag……(NOIP,省选,Ctsc,各种二试被####DAY-1报到日从长春坐一晚上火车到北京然后坐高铁到杭州。。。一下车一股热气真爽~下了车看到好多人……黄学长居然和我们一趟线?黄学长:......
  • 移动应用的构件—[译]2011年移动开发者经济学报告(七)
    如何利用平台特性第三部分移动应用的构件掌握移动开发移动开发的掌握主要通过时间和精力投入,投入多寡取决于所学的平台,不同平台不一样。Android和QT(注:原文如此,右图中黑莓以微弱优势取胜QT)是最容易学习的平台,受访者平均不到6个月就可以掌握。相反,JavaME和Symbian是最难学的平台,平......
  • Buuctf——[GXYCTF2019]BabySQli
    本题目是一道联合注入进入页面后发现只有一个登录框。知识点unionselect联合查询union拼接的两个查询语句查询字段数必须一样多当其中一个查询结果为空时,不影响另外一个语句的查询结果联合注入核心是使用拼接的select语句同时使原查询语句结果为空来覆盖原查询结果,从而实......