Rust 小游戏开发:猜数字项目实现

举报
数字扫地僧 发表于 2025/06/10 18:41:58 2025/06/10
【摘要】 Hello,游戏开发爱好者们!今天,我特别兴奋地和大家唠唠用 Rust 打造一个小游戏 ——“猜数字” 的那些事儿。要是你对 Rust 还不太熟悉,别慌!这趟旅程咱们从零起步,一路摸索到游戏成品。相信我,等你把这个小游戏实现出来,不仅编程技能会 “更上一层楼”,还会被 Rust 的魅力给深深吸引。话不多说,快往这儿瞧,咱们这就开启这段超有意思的开发之旅! 一、项目初始化 (一)搭建开发环境安...

Hello,游戏开发爱好者们!今天,我特别兴奋地和大家唠唠用 Rust 打造一个小游戏 ——“猜数字” 的那些事儿。要是你对 Rust 还不太熟悉,别慌!这趟旅程咱们从零起步,一路摸索到游戏成品。相信我,等你把这个小游戏实现出来,不仅编程技能会 “更上一层楼”,还会被 Rust 的魅力给深深吸引。话不多说,快往这儿瞧,咱们这就开启这段超有意思的开发之旅!

一、项目初始化

(一)搭建开发环境

  1. 安装 Rust :得先把 Rust 安装到电脑上才行。好在 Rust 官方给了咱一个超方便的安装工具 ——Rustup。这玩意儿不仅能安稳定版 Rust,还能在不同版本间轻松切换。打开终端(Windows 用户用命令提示符或者 PowerShell 也行),输入以下命令就行啦:

    • 对于 Windows 用户:

      • 先下载 Rust 安装程序,去 Rust 官方下载站找对应 Windows 的安装包,下载完毕,双击运行,跟着安装向导一步步来就行。装的时候,程序会自动把 Rust 添加到系统环境变量里,后续在命令提示符里调用 Rust 命令就特方便。
    • 对于 macOS 用户:

      • 利用 Homebrew 来安 Rust,特省事儿。要是你还没装 Homebrew,先在终端输入这段代码装一个:/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"。装好 Homebrew 后,输入brew install rust,Homebrew 就把 Rust 连带依赖都搞定啦。
    • 对于 Linux 用户:

      • 基于 Debian/Ubuntu 的系统,先在终端执行sudo apt update更新软件包列表,接着sudo apt install rustc就能安上 Rust 编译器。要是用的是基于 Red Hat/CentOS 的系统,就用sudo yum install rust
  2. 验证安装 :安装完毕,得确认 Rust 真的装好了没。在终端输入rustc --version,要是能弹出类似rustc 1.70.0 (03d473de7 2023-07-20)这样的版本信息,那说明 Rust 编译器妥妥地装好了,可以开始写代码啦。

(二)创建新项目

有了 Rust 环境,就差一个新项目来 “大展身手” 啦。用 Cargo(Rust 的包管理和构建工具)来创建项目,超简单。在终端输入cargo new guess_the_number,Cargo 就会在当前文件夹下生成一个叫guess_the_number的新项目文件夹。这个文件夹里头,Cargo.toml是项目的配置文件,而src文件夹里装着主要的源代码文件main.rs

(三)项目文件结构初探

新鲜出炉的项目文件结构是这样的:

  • guess_the_number/:项目根目录。
    • Cargo.toml:记录项目元数据(像项目名、版本号这些),也声明项目的依赖项。
    • src/:源代码的大本营。
      • main.rs:程序的主文件,Rust 程序从这儿的main函数开始执行。

用树状图来表示文件结构就是:

guess_the_number/
├── Cargo.toml
└── src
    └── main.rs

(四)mermaid 总结

搭建开发环境
安装 Rust
选择操作系统
Windows 安装
macOS 安装
Linux 安装
使用安装包
使用 Rustup
利用 Homebrew
使用 Rustup
基于 Debian/Ubuntu 的发行版
基于 Red Hat/CentOS 的发行版
使用 apt 安装
使用 Rustup 安装
使用 yum 安装
使用 Rustup 安装
验证安装
创建新项目
项目文件结构初探

二、游戏逻辑核心剖析

(一)生成随机数

猜数字游戏,核心就是让电脑整一个随机数,玩家去猜。在 Rust 里,靠 “rand” 这个 crate(Rust 的包)来生成随机数。先去 crates.io把 “rand” 加入项目依赖,在Cargo.toml[dependencies] 部分添上rand = "0.8.5"(具体版本号得看 crates.io上最新的稳定版)。接下来,在main.rs里引入随机数功能,代码如下:

use rand::Rng; // 引入 Rng 特性,这是生成随机数的关键

fn main() {
    let secret_number = rand::thread_rng().gen_range(1..=100); // 生成 1 到 100 的随机数
    println!("秘密数字已生成!");
}

rand::thread_rng()拿到当前线程的随机数生成器,gen_range(1..=100)让它生成 1 到 100 范围内的随机数。

(二)获取用户输入

电脑整好随机数了,得让玩家能输入自己的猜测。Rust 里,std::io模块专门干这事儿。还是在main.rs里,加上这段代码:

use std::io;

fn main() {
    let secret_number = rand::thread_rng().gen_range(1..=100);
    println!("秘密数字已生成,请开始猜数字!");

    println!("请输入你的猜测:");
    let mut guess = String::new(); // 创建一个可变字符串,存玩家输入
    io::stdin()
        .read_line(&mut guess) // 读取玩家输入
        .expect("读取输入失败!"); // 输入出错时的处理提示

    println!("你猜的数字是:{}", guess);
}

io::stdin().read_line(&mut guess)这行代码,从标准输入(键盘)读取一行文本,存到guess字符串里。要是读取过程中出岔子,expect会把错误信息打印出来。

(三)对比猜测与答案

玩家输入完数字,就得比对和电脑生成的随机数是不是一样。这得先把玩家输入的字符串转成数字。代码接着改:

use std::io;
use rand::Rng;

fn main() {
    let secret_number = rand::thread_rng().gen_range(1..=100);
    println!("秘密数字已生成,请开始猜数字!");

    println!("请输入你的猜测:");
    let mut guess = String::new();
    io::stdin()
        .read_line(&mut guess)
        .expect("读取输入失败!");

    let guess: u32 = match guess.trim().parse() { // 把字符串转成 u32 类型的数字
        Ok(num) => num,
        Err(_) => {
            println!("请输入有效的数字!");
            return; // 输入不是数字,直接结束程序
        }
    };

    println!("你猜的数字是:{}", guess);

    if guess == secret_number {
        println!("恭喜你猜对了!");
    } else if guess < secret_number {
        println!("太小了!");
    } else {
        println!("太大了!");
    }
}

guess.trim().parse()这一步,trim是把输入字符串两端的空白去掉(像空格、换行符这些),parse尝试把字符串转成数字。要是转成功了,Ok(num)把数字取出来;要是转失败(比如玩家输了个字母),Err就提醒玩家重新运行程序。

最后,用if-else if-else判断玩家猜的数字和秘密数字的关系,给玩家相应的提示。

(四)mermaid 总结

游戏逻辑核心
生成随机数
引入 rand crate
在 Cargo.toml 添加依赖
编写生成随机数代码
获取用户输入
引入 std::io 模块
创建可变字符串存储输入
读取用户输入
错误处理
对比猜测与答案
字符串转数字
判断大小关系并给出提示

三、代码完善与优化

(一)循环多次猜测

现在程序只能让玩家猜一次,要是猜不对就得重新运行,这可不行。得让玩家能一直猜,直到猜对为止。这就得用上循环啦。把main.rs改成这样:

use std::io;
use rand::Rng;

fn main() {
    let secret_number = rand::thread_rng().gen_range(1..=100);
    println!("秘密数字已生成,请开始猜数字!");

    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);

        if guess == secret_number {
            println!("恭喜你猜对了!");
            break; // 猜对了,跳出循环
        } else if guess < secret_number {
            println!("太小了!");
        } else {
            println!("太大了!");
        }
    }
}

外层套了个loop循环,玩家每次猜完,程序就回到循环开头,重新让玩家输入。要是玩家输入的不是数字,continue跳过这次循环剩下的代码,让玩家重新输入;要是猜对了,用break跳出循环,游戏结束。

(二)限制猜测次数

一直让玩家猜下去也不太好,给个限制,比如最多猜 5 次。改进代码如下:

use std::io;
use rand::Rng;

fn main() {
    let secret_number = rand::thread_rng().gen_range(1..=100);
    println!("秘密数字已生成,请开始猜数字!");
    println!("你有 5 次猜测机会哦!");

    let mut attempts = 0; // 记录玩家已用猜测次数

    loop {
        attempts += 1; // 每次循环,次数加 1

        println!("第 {} 次猜测,请输入你的猜测:", attempts);
        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);

        if guess == secret_number {
            println!("恭喜你猜对了!");
            break;
        } else if guess < secret_number {
            println!("太小了!");
        } else {
            println!("太大了!");
        }

        if attempts >= 5 { // 超过 5 次还没猜对,游戏结束
            println!("很遗憾,你没猜对,游戏结束!");
            println!("正确的数字是:{}", secret_number);
            break;
        }
    }
}

加了个attempts变量来计数,每次循环开始前加 1。要是玩家 5 次都没猜对,就打印正确答案,结束游戏。

(三)mermaid 总结

代码完善与优化
循环多次猜测
使用 loop 循环
使用 continue 和 break 控制流程
限制猜测次数
添加次数计数变量
判断次数并给出结果

四、游戏测试与调试

(一)正常流程测试

先来试试最顺利的流程 —— 玩家第一次就猜对。运行程序后,输入正确的数字,看程序是不是能准确识别并祝贺玩家。

(二)异常输入测试

故意输入字母、符号、空行这些非法内容,检验程序能不能正确识别并提示重新输入。

(三)边界值测试

输入可能的边界值,像 1、100,测试程序的反应是否符合预期。

(四)猜测次数限制测试

连续猜 5 次都不对,看程序是不是能正确结束并给出正确答案。

(五)mermaid 总结

游戏测试与调试
正常流程测试
异常输入测试
边界值测试
猜测次数限制测试

五、游戏扩展与进阶

(一)增加难度等级

给游戏加个难度选择,不同难度对应不同范围的随机数。比如简单模式 1 - 50,困难模式 1 - 200。修改代码如下:

use std::io;
use rand::Rng;

fn main() {
    println!("请选择游戏难度:");
    println!("1. 简单模式(1-50)");
    println!("2. 困难模式(1-200)");

    let mut choice = String::new();
    io::stdin()
        .read_line(&mut choice)
        .expect("读取难度选择失败!");
    let choice: u32 = match choice.trim().parse() {
        Ok(num) => num,
        Err(_) => {
            println!("请输入有效的数字选择!");
            return;
        }
    };

    let secret_number_range = if choice == 1 { 1..=50 } else { 1..=200 }; // 根据选择定范围
    let secret_number = rand::thread_rng().gen_range(secret_number_range);
    println!("\n秘密数字已生成,请开始猜数字!");
    println!("你有 5 次猜测机会哦!");

    let mut attempts = 0;

    loop {
        attempts += 1;

        println!("第 {} 次猜测,请输入你的猜测:", attempts);
        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);

        if guess == secret_number {
            println!("恭喜你猜对了!");
            break;
        } else if guess < secret_number {
            println!("太小了!");
        } else {
            println!("太大了!");
        }

        if attempts >= 5 {
            println!("很遗憾,你没猜对,游戏结束!");
            println!("正确的数字是:{}", secret_number);
            break;
        }
    }
}

(二)记录历史最高分

弄个文本文件,把每次游戏的最好成绩(猜中所用的最少次数)存起来,下一次玩的时候读出来对比。这就需要文件操作啦,代码示例如下:

use std::io::{self, Write};
use rand::Rng;
use std::fs;

fn main() {
    let secret_number = rand::thread_rng().gen_range(1..=100);
    println!("秘密数字已生成,请开始猜数字!");
    println!("你有 5 次猜测机会哦!");

    let mut attempts = 0;

    // 尝试读取历史最高分
    let mut best_score: Option<u32> = None;
    if let Ok(contents) = fs::read_to_string("best_score.txt") {
        if let Ok(score) = contents.trim().parse() {
            best_score = Some(score);
            println!("当前历史最佳成绩:{} 次猜中", score);
        }
    }

    loop {
        attempts += 1;

        println!("第 {} 次猜测,请输入你的猜测:", attempts);
        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);

        if guess == secret_number {
            println!("恭喜你猜对了!");
            println!("你用了 {} 次猜中", attempts);

            // 更新历史最高分
            let new_best_score = if let Some(score) = best_score {
                if attempts < score { attempts } else { score }
            } else {
                attempts
            };

            fs::write("best_score.txt", new_best_score.to_string()).expect("写入文件失败!");
            println!("新的历史最佳成绩:{} 次猜中", new_best_score);
            break;
        } else if guess < secret_number {
            println!("太小了!");
        } else {
            println!("太大了!");
        }

        if attempts >= 5 {
            println!("很遗憾,你没猜对,游戏结束!");
            println!("正确的数字是:{}", secret_number);
            break;
        }
    }
}

这回,程序会读取best_score.txt文件里的历史最佳成绩,要是这次玩家用更少次数猜中,就更新文件内容。

(三)mermaid 总结

游戏扩展与进阶
增加难度等级
根据选择设置随机数范围
记录历史最高分
读取历史最高分文件
更新并写入新的历史最高分
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。