当前位置: 首页 > news >正文

Rust 学习笔记 2:猜数字游戏

上一篇:Rust 学习笔记 1:编译运行环境的构建

文章目录

  • 1. 前言
  • 2. 背景
  • 3. 猜数字游戏
    • 3.1 概述
    • 3.2 实现
  • 4. 参考资料

1. 前言

限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。

2. 背景

本文基于 Rust 文档 Programming a Guessing Game 翻译整理而成。

3. 猜数字游戏

3.1 概述

程序随机生成一个数字,并告知用户数据所处区间范围;用户根据区间范围随意输入一个数字,程序读取用户输入的数字,将其和目标数字对比,并提示数字是大了还是小了;然后用户根据提示继续输入,直到猜中目标数字为止。

从前面的描述可以看到,猜数字游戏,程序需要处理:

  • 随机数字生成
  • 读取用户输入
  • 数字比较
  • 输出提示信息
  • 循环逻辑

3.2 实现

首先,我们给出一个初始版本,这个版本没有随机生成目标数字、以及进行数字比较的功能,它仅仅是打印用户输入的数字。先用 Cargo 构建一个代码工程:

$ cargo new guessing_gameCreated binary (application) `guessing_game` package

然后对代码文件 guessing_game/src/main.rs 进行编辑,其内容如下:

use std::io;fn main() {println!("Guess the 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);
}

这里有几个需要了解的新知识点:

  • use std::io;
    这类似于 C 语言的 #includeJava、PythonimportPerluse,等等。
    总之,这就是 Rust 对其它库接口的导入方式。这里是导入了 Rust 标准 IO 库。
  • String::new();
    :: 在这里用来引用某个作用域内的接口。这里创建了一个空的字符串类型对象。
  • let mut guess = String::new();
    let 关键字用来定义变量,而 mut 是使得变量可以修改(mutable)
    默认情况下,let 定义的变量是不可修改的(immutable)
    我们注意到,Rust 定义变量,没有显式指定类型。
  • io::stdin()
    构建了一个 std::io::Stdin 实例对象。
  • io::stdin().read_line(&mut guess)
    调用 std::io::Stdin 实例对象的接口函数 read_line(),用于读取一行用户输入;
    read_line(&mut guess) 的参数加 & 表示使用 guess 的引用,但默认情况下,
    对象的引用是只读的,及 read_line() 无法通过 guess 的引用修改 guess
    这时候加上 mut 修饰,使得 read_line() 可以通过 guess 的引用修改 guess
  • io::stdin().read_line(&mut guess).expect(“Failed to read line”);
    std::io::Stdin 实例对象的接口函数 read_line() 返回一个 Result 类型的枚举值;
    Result 类型的枚举值可以是 OkErr:当为 Ok 时,调用 expect() 不做任何操
    作,而当为 Err 时,调用 expect() 将打印信息 Failed to read line

编译、运行:

$ cargo buildCompiling guessing_game v0.1.0 (/home/bill/Study/rust/guessing_game)Finished dev [unoptimized + debuginfo] target(s) in 4.42s
$ cargo runFinished dev [unoptimized + debuginfo] target(s) in 0.03sRunning `target/debug/guessing_game`
Guess the number!
Please input your guess.
8
You guessed: 8

到此,初始版本已经构建完毕。接下来,我们引入随机数模块,随机生成 [1,100] 的数字,并增加对用户输入数字的判定。Rust 的标准库不包含随机数模块,随机数模块是一个第三方库。Rust 引入第三方库的方式是通过编辑 Cargo 构建工程的 Cargo.toml 文件的 [dependencies] 段。按如下编辑 guessing_game/Cargo.toml[dependencies] 段引入 rand 库:

[dependencies]
rand = "0.8.5"

不改变任何代码,再次构建工程,会发现构建过程下载了 rand 库:

$ cargo build
warning: `/home/XXX/.cargo/config` is deprecated in favor of `config.toml`
note: if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`
warning: `/home/XXX/.cargo/config` is deprecated in favor of `config.toml`
note: if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`Updating `tuna` index
remote: Enumerating objects: 1102, done.
remote: Counting objects: 100% (292/292), done.
remote: Total 1102 (delta 292), reused 292 (delta 292), pack-reused 810
Receiving objects: 100% (1102/1102), 527.38 KiB | 0 bytes/s, done.
Resolving deltas: 100% (809/809), completed with 130 local objects.
From https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index* [new ref]                    -> origin/HEADDownloaded cfg-if v1.0.0 (registry `tuna`)Downloaded rand_core v0.6.4 (registry `tuna`)Downloaded rand_chacha v0.3.1 (registry `tuna`)Downloaded byteorder v1.5.0 (registry `tuna`)Downloaded quote v1.0.37 (registry `tuna`)Downloaded unicode-ident v1.0.12 (registry `tuna`)Downloaded zerocopy-derive v0.7.35 (registry `tuna`)Downloaded proc-macro2 v1.0.86 (registry `tuna`)Downloaded rand v0.8.5 (registry `tuna`)Downloaded zerocopy v0.7.35 (registry `tuna`)Downloaded syn v2.0.56 (registry `tuna`)Downloaded libc v0.2.158 (registry `tuna`)Downloaded 12 crates (1.5 MB) in 2m 57sCompiling proc-macro2 v1.0.86Compiling unicode-ident v1.0.12Compiling libc v0.2.158Compiling cfg-if v1.0.0Compiling byteorder v1.5.0Compiling quote v1.0.37Compiling syn v2.0.56Compiling getrandom v0.2.15Compiling rand_core v0.6.4Compiling zerocopy-derive v0.7.35Compiling zerocopy v0.7.35Compiling ppv-lite86 v0.2.20Compiling rand_chacha v0.3.1Compiling rand v0.8.5Compiling guessing_game v0.1.0 (/home/bill/Study/rust/guessing_game)Finished `dev` profile [unoptimized + debuginfo] target(s) in 3m 02s

如果你在国内,大概率会下载失败。如果遇到了这种情况,可参考下列链接配置 Crates.io 来解决问题:

  • 4.1. 配置 Cargo 国内镜像源
  • rsproxy.cn - 字节跳动新的 Rust 镜像源
  • Cargo设置

笔者使用的 ~/.cargo/config 内容如下,读者可作为参考:

[source.crates-io]
registry = "https://github.com/rust-lang/crates.io-index"replace-with = 'tuna'
#replace-with = 'ustc'
#replace-with = 'sjtu'
#replace-with = 'rsproxy'[source.tuna]
registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git"[source.ustc]
registry = "git://mirrors.ustc.edu.cn/crates.io-index"[source.sjtu]
registry = "https://mirrors.sjtug.sjtu.edu.cn/git/crates.io-index"[source.rsproxy]
registry = "https://rsproxy.cn/crates.io-index"[source.rustcc]
registry = "git://crates.rustcc.cn/crates.io-index"[net]
git-fetch-with-cli=true

另外,还需要将 rustc 安装为更新版本,系统自带的版本可能导致无法下载第三方库。好了,一切就绪,是时候修改代码引入目标数随机生成,以及用户输入数字比较判定功能了。修改后的代码如下:

use rand::Rng;
use std::io;
use std::cmp::Ordering;fn main() {println!("Guess the number!");let secret_number = rand::thread_rng().gen_range(1..=10);println!("The secret number is at range: [1, 10]");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!");let guess: u32 = match guess.trim().parse() {Ok(num) => num, // guess = numErr(_) => continue, // _ to match all};println!("You guessed: {}", guess);match guess.cmp(&secret_number) {Ordering::Less => println!("Too small!"),Ordering::Greater => println!("Too big!"),//Ordering::Equal => println!("You win!"),Ordering::Equal => {println!("You win!");break; // exit the loop}}}
}

编译、运行:

$ cargo build
warning: `/home/bill/.cargo/config` is deprecated in favor of `config.toml`
note: if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`
warning: `/home/bill/.cargo/config` is deprecated in favor of `config.toml`
note: if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`Compiling guessing_game v0.1.0 (/home/bill/Study/rust/guessing_game)Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.21s
bill@bill-virtual-machine:~/Study/rust/guessing_game$ cargo run
warning: `/home/bill/.cargo/config` is deprecated in favor of `config.toml`
note: if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`
warning: `/home/bill/.cargo/config` is deprecated in favor of `config.toml`
note: if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.01sRunning `target/debug/guessing_game`
Guess the number!
The secret number is at range: [1, 10]
Please input your guess.
5
You guessed: 5
Too small!
Please input your guess.
8
You guessed: 8
You win!

相对第一版代码,修改后的代码又引入了几个新的知识点,总结如下:

  • match 表达式
    这类似于 C 语言的 switch / case 组合,不难理解。
  • 同名变量覆盖
    代码里面两次定义了变量 guess,这有点类似 Python 的同名变量,它们彼此可以有不同的类型,后一变量定义会隐藏前一定义。
  • loop 循环
    loop 关键字,组织了循环结构,类似于其它语言的 while (1) { ... }

4. 参考资料

[1] The Rust Programming Language


http://www.mrgr.cn/news/7994.html

相关文章:

  • 【Linux篇】vim编译器
  • 仿Muduo库实现高并发服务器——EventLoop模块
  • mysql和oracle函数比较
  • Go语言Time包的使用
  • 深入浅出消息队列----【Broker 集群】
  • Go语言反射入门:理解类型与值的动态操作
  • Django 后端架构开发:存储层调优策略解析
  • Git 版本管理
  • 鸿蒙实现在图片上进行标注
  • git add . 报错 warning: LF will be replaced by CRLF in ******.vue.
  • 【分布式】分布式Session共享
  • Vue小玩意儿:vue3+express.js实现大文件分片上传
  • Python-Poc编写(6)
  • 鸿蒙服务卡片,点击事件,传值
  • Django 后端架构开发:文件云存储,从本地存储到腾讯COS桶集成
  • JDK17 隐藏类 Hidden Classes 介绍
  • 关于武汉芯景科技有限公司的RS232通信接口芯片XJ3243EEUI开发指南(兼容MAX3243EEUI)
  • mac 虚拟机PD19运行E-prime实验遇到E-prime unable to set display mode:0*80004001问题解决
  • QT Mainwindow下指定控件的setMouseTracking(true)和mousemoveevent函数失效-问题解决
  • 通信协议学习:CAN总线协议