rust:猜数字小游戏

猜数字小游戏

我们来实现一个经典的入门级编程小游戏 ------ 猜谜游戏。具体玩法是这样的:程序会先在 1 到 100 之间随机选一个整数作为谜底。之后,它会让玩家输入自己的猜测数字。玩家输入后,程序会给出提示:如果猜的数字比谜底大,就说 "太高了";如果比谜底小,就说 "太低了"。一旦玩家猜对了数字,游戏就会弹出一条祝贺信息,然后结束运行。

新建项目

  1. 使用Cargo构建一个新项目

输入以下命令构建项目:

复制代码
cargo new guessing_game
  1. 用VSCode打开这个项目

项目结构

guessing_game/

├── Cargo.toml # 项目配置文件

└── src/

└── main.rs # 主程序文件

编写小游戏代码

首先玩家先猜测一个数字输入

Rust 复制代码
use std::io;

fn main() {
    println!("请猜一个数字");

    let mut guess = String::new();

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

    println!("您猜的数字是{guess}");
}
  • use std::io;

    引入 std::io 模块,这样我们就可以使用 io::stdin() 来读取用户输入。

  • fn main() { ... }

    程序的入口函数。

  • println!("请猜一个数字");

    向控制台输出提示信息。

  • let mut guess = String::new();

    • let:声明变量。

    • mut:表示这个变量是可变的(因为我们要往里面写入内容)。

    • guess:变量名。

    • String::new():创建一个空的、可增长的字符串(在堆上分配)。

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

    • io::stdin():获取标准输入流。

    • .read_line(&mut guess):读取用户输入的一行,并追加到 guess 字符串中。

      • &mut guess 是对 guess 的可变引用,允许 read_line 修改它。
    • .expect("..."):处理可能的错误。read_line 返回一个 Result 类型,expect 在出错时会 panic 并显示指定消息。

  • println!("您猜的数字是 {guess}");

    使用 {} 占位符打印 guess 变量的内容。Rust 会自动将其转换为字符串显示。

测试一下游戏的第一部分,先从控制台运行一下这段代码看看结果:

如果如图所示,说明第一部分已经完成。

生成随机数

Rust在标准库中没有包含随机数的方法,Rust团队提供了一个可以实现随机数功能的rand crate

rand crate 是 Rust 社区中最常用、最权威的随机数生成库(crate),它让你可以轻松地在程序中生成各种类型的随机值,比如随机整数、浮点数、布尔值、字符串、数组元素等。

  • crate 是一个独立的代码包(库或可执行程序)。
  • rand 是一个外部 crate,不在标准库中,所以你需要先在项目中添加它。
  1. 添加依赖

打开你的项目目录中的 Cargo.toml 文件,在[dependencies]中添加以下代码

复制代码
rand = "0.8.5"
  1. 构建项目

在控制台中输入以下命令构建项目:

复制代码
cargo build
  1. 代码生成随机数
Rust 复制代码
use std::io;
use rand::Rng;

fn main() {

    let secret_number = rand::thread_rng().gen_range(1..=100);
    println!("随机数字是{secret_number}");

    println!("请猜一个数字");

    let mut guess = String::new();

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

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

use rand::Rng:导入 rand crate 提供的 Rng trait。这是使用 .gen_range() 等随机数方法所必需的。

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

  • rand::thread_rng():获取当前线程的随机数生成器。
  • .gen_range(1..=100):生成一个 1 到 100 之间的随机整数(包含 1 和 100)
  • let secret_number = ...:把这个随机数存到不可变变量 secret_number 中(类型通常是 i32u32)。

println!("随机数字是{secret_number}");:输出提示,显示生成的随机数。

将猜测的数字和随机生成的数字进行比较

Rust 复制代码
use std::io;
use rand::Rng;
use std::cmp::Ordering;

fn main() {

    let secret_number = rand::thread_rng().gen_range(1..=100);
    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!("恭喜你,猜对了"),
    }
}

use std::cmp::Ordering;导入 Ordering` 枚举类型,它是 Rust 标准库中用于比较操作的结果类型。有三个变体:

  • Ordering::Less(小于)
  • Ordering::Greater(大于)
  • Ordering::Equal(等于)

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

  • guess.trim():去掉字符串前后的空白字符(特别是 \n 换行符)
  • .parse():尝试将字符串解析为数字
  • let guess: u32:指定目标类型为 u32(无符号32位整数)
  • .expect("..."):如果解析失败(比如用户输入了 abc),程序崩溃并提示"请输入一个数字"

这样 guess 就从 String 变成了 u32 类型,可以和 secret_number 比较了。

Rust 复制代码
match guess.cmp(&secret_number){
        Ordering::Less => println!("太小了"),
        Ordering::Greater => println!("太大了"),
        Ordering::Equal => println!("恭喜你,猜对了"),
    }

使用 cmp 方法比较用户猜测和神秘数字:

  • guess.cmp(&secret_number) 返回一个 Ordering 枚举值
  • 根据结果输出不同提示
  • 如果相等(Equal),打印恭喜信息,并执行 break退出 loop 循环

使用循环语句进行多次猜测以及完善优化

rust 复制代码
use std::io;
use rand::Rng;
use std::cmp::Ordering;

fn main() {

    let secret_number = rand::thread_rng().gen_range(1..=100);
    // 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(_) => {
                println!("请输入有效数字");
                continue;
            }
        };

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

        match guess.cmp(&secret_number){
            Ordering::Less => println!("太小了"),
            Ordering::Greater => println!("太大了"),
            Ordering::Equal => {
                println!("恭喜你,猜对了");
                break;
            }
        }
    }
}

loop{}loop 是 Rust 中的无限循环关键字。它会一直执行里面的代码,直到遇到 break

复制代码
let guess: u32 = match guess.trim().parse(){
            Ok(num) => num,
            Err(_) => {
                println!("请输入有效数字");
                continue;
            }
        };

这是错误处理的关键部分!

  • guess.trim():去掉字符串前后的空白字符(特别是换行符 \n
  • .parse():尝试将字符串解析为 u32 类型
  • 返回 Result<u32, ParseIntError>
  • 使用 match 处理结果:
    • Ok(num):解析成功,返回数字
    • Err(_):解析失败(比如输入了 abc),打印提示并执行 continue
    • continue:跳过本次循环的剩余部分,重新开始下一次循环,再次提示输入

总结

项目功能

功能 实现方式
生成随机数 rand::thread_rng().gen_range(1..=100)
读取用户输入 std::io::stdin().read_line(&mut guess)
字符串转数字 .trim().parse()String 转为 u32
错误处理 match 处理 parse() 失败,提示用户重新输入
多次猜测 使用 loop {} 实现无限循环
比较大小 使用 .cmp()std::cmp::Ordering 枚举
游戏结束 猜中时使用 break 跳出循环

核心 Rust 概念掌握

概念 在项目中的体现
变量与可变性 let mut guess = String::new();
数据类型 String(字符串)、u32(无符号整数)
函数调用 read_line()trim()parse()gen_range()
表达式与语句 match 是表达式,可以返回值
模式匹配(match) 处理 ResultOrdering 枚举
错误处理 使用 match 安全处理 parse() 失败
循环控制 loop + continue / break
外部依赖(crate) 使用 rand crate 生成随机数
模块系统 use std::io;use rand::Rng;use std::cmp::Ordering;

技术栈

  • 语言:Rust
  • 构建工具:Cargo(自动管理依赖和编译)
  • 依赖库
    • rand = "0.8":生成随机数
  • 标准库模块
    • std::io
      h安全处理parse()失败 | | **循环控制** |loop+continue/break| | **外部依赖(crate)** | 使用randcrate 生成随机数 | | **模块系统** |use std::io;use rand::Rng;use std::cmp::Ordering;` |

技术栈

  • 语言:Rust
  • 构建工具:Cargo(自动管理依赖和编译)
  • 依赖库
    • rand = "0.8":生成随机数
  • 标准库模块
    • std::io
    • std::cmp::Ordering
相关推荐
长存祈月心3 小时前
Rust HashSet 与 BTreeSet深度剖析
开发语言·后端·rust
长存祈月心3 小时前
Rust BTreeMap 红黑树
开发语言·后端·rust
颜颜yan_4 小时前
Rust impl块的组织方式:从基础到实践的深度探索
开发语言·后端·rust
代码改善世界4 小时前
Rust 入门基础:安全、并发与高性能的系统编程语言
开发语言·安全·rust
JMzz4 小时前
Rust 中的数据结构选择与性能影响:从算法复杂度到硬件特性 [特殊字符]
开发语言·数据结构·后端·算法·性能优化·rust
向上的车轮5 小时前
Actix Web 入门与实战
前端·rust·actix web
想不明白的过度思考者6 小时前
Rust——Trait 定义与实现:从抽象到实践的深度解析
开发语言·后端·rust
凤年徐6 小时前
Rust async/await 语法糖的展开原理:从表象到本质
开发语言·后端·rust
Kapaseker6 小时前
深入 Rust 迭代器(上)
rust