Rust 小游戏开发:猜数字项目实现
Hello,游戏开发爱好者们!今天,我特别兴奋地和大家唠唠用 Rust 打造一个小游戏 ——“猜数字” 的那些事儿。要是你对 Rust 还不太熟悉,别慌!这趟旅程咱们从零起步,一路摸索到游戏成品。相信我,等你把这个小游戏实现出来,不仅编程技能会 “更上一层楼”,还会被 Rust 的魅力给深深吸引。话不多说,快往这儿瞧,咱们这就开启这段超有意思的开发之旅!
一、项目初始化
(一)搭建开发环境
-
安装 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 连带依赖都搞定啦。
- 利用 Homebrew 来安 Rust,特省事儿。要是你还没装 Homebrew,先在终端输入这段代码装一个:
-
对于 Linux 用户:
- 基于 Debian/Ubuntu 的系统,先在终端执行
sudo apt update
更新软件包列表,接着sudo apt install rustc
就能安上 Rust 编译器。要是用的是基于 Red Hat/CentOS 的系统,就用sudo yum install rust
。
- 基于 Debian/Ubuntu 的系统,先在终端执行
-
-
验证安装 :安装完毕,得确认 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 里,靠 “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 总结
三、代码完善与优化
(一)循环多次猜测
现在程序只能让玩家猜一次,要是猜不对就得重新运行,这可不行。得让玩家能一直猜,直到猜对为止。这就得用上循环啦。把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 总结
四、游戏测试与调试
(一)正常流程测试
先来试试最顺利的流程 —— 玩家第一次就猜对。运行程序后,输入正确的数字,看程序是不是能准确识别并祝贺玩家。
(二)异常输入测试
故意输入字母、符号、空行这些非法内容,检验程序能不能正确识别并提示重新输入。
(三)边界值测试
输入可能的边界值,像 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 总结
- 点赞
- 收藏
- 关注作者
评论(0)