Rust 挖矿小游戏:打造复古 CMD 风格的挖矿冒险
在复古游戏热潮回归的今天,命令行界面(CMD)游戏凭借其简洁的交互和独特的怀旧感,依然拥有不少爱好者。本文将带大家用 Rust 语言开发一款 CMD 对话框风格的挖矿小游戏,通过模块化设计将所有功能封装在一个类中,同时深入探讨 Rust 的所有权机制、终端控制、随机数生成等核心特性。游戏中玩家将扮演一名矿工,在地下挖掘矿石、升级工具、躲避危险,体验纯粹的文字冒险乐趣。
一、游戏核心设计思路
这款挖矿小游戏的核心玩法围绕「挖掘 - 收集 - 升级 - 冒险」展开,具体设计如下:
- 游戏场景:采用文本网格模拟地下矿层,不同字符代表不同地形(泥土、矿石、岩石、危险区域)。
- 玩家属性:包含生命值、体力值、当前工具等级、背包(矿石数量、道具)等状态。
- 核心机制:
- 挖掘:消耗体力,随机获得矿石或触发事件(如遇到塌方、发现稀有矿石)。
- 升级:用矿石兑换更高级的工具,提升挖掘效率和成功率。
- 危险事件:挖掘过程中有概率触发塌方(减少生命值)、遇到怪物(强制战斗)等随机事件。
- 胜利条件:收集指定数量的稀有矿石,或挖到地下最深处的宝藏。
- 交互方式:CMD 对话框中通过输入命令(挖、背包、升级、退出)进行操作,全程文本反馈。
二、Rust 代码实现(单类封装)
下面是完整的 Rust 代码,所有功能封装在 MiningGame 结构体中,通过 impl 块实现方法,确保代码模块化和可维护性。
use rand::Rng;
use std::io;
use std::fmt;
// 矿石类型枚举
#[derive(Debug, Clone, Copy, PartialEq)]
enum OreType {
Coal, // 煤炭(普通)
Iron, // 铁(中级)
Gold, // 金(高级)
Diamond, // 钻石(稀有)
}
impl fmt::Display for OreType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
OreType::Coal => write!(f, "煤炭"),
OreType::Iron => write!(f, "铁"),
OreType::Gold => write!(f, "金"),
OreType::Diamond => write!(f, "钻石"),
}
}
}
// 工具等级枚举
#[derive(Debug, Clone, Copy, PartialEq)]
enum ToolLevel {
Wooden, // 木镐(初始)
Stone, // 石镐
Iron, // 铁镐
Diamond, // 钻石镐(最高级)
}
impl fmt::Display for ToolLevel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ToolLevel::Wooden => write!(f, "木镐"),
ToolLevel::Stone => write!(f, "石镐"),
ToolLevel::Iron => write!(f, "铁镐"),
ToolLevel::Diamond => write!(f, "钻石镐"),
}
}
}
// 游戏事件枚举
enum GameEvent {
NormalMine(OreType), // 正常挖矿获得矿石
NoOre, // 未挖到矿石
CaveIn, // 塌方(掉血)
MonsterAttack, // 怪物袭击
RareFind(OreType), // 稀有发现
}
// 挖矿游戏主类
struct MiningGame {
health: u32, // 生命值
stamina: u32, // 体力值
max_health: u32, // 最大生命值
max_stamina: u32, // 最大体力值
tool_level: ToolLevel,// 当前工具等级
ore_counts: [u32; 4], // 矿石数量(煤炭、铁、金、钻石)
depth: u32, // 当前挖掘深度
game_over: bool, // 游戏结束标志
}
impl MiningGame {
// 初始化游戏
fn new() -> Self {
MiningGame {
health: 100,
stamina: 80,
max_health: 100,
max_stamina: 80,
tool_level: ToolLevel::Wooden,
ore_counts: [0, 0, 0, 0],
depth: 0,
game_over: false,
}
}
// 游戏主循环
fn run(&mut self) {
self.print_welcome();
while !self.game_over {
self.print_status();
self.print_commands();
let command = self.get_user_input();
self.process_command(command);
self.check_victory();
}
self.print_game_over();
}
// 打印欢迎信息
fn print_welcome(&self) {
println!("=====================================");
println!(" Rust 挖矿冒险 ");
println!("=====================================");
println!("你是一名矿工,深入地下挖掘珍贵矿石!");
println!("注意体力消耗和地下危险,升级工具解锁更多可能~");
println!("收集 5 颗钻石即可获得终极胜利!");
println!("=====================================\n");
}
// 打印当前状态(生命值、体力、工具、矿石等)
fn print_status(&self) {
println!("\n【当前状态】");
println!("生命值:{} / {}", self.health, self.max_health);
println!("体力值:{} / {}", self.stamina, self.max_stamina);
println!("当前工具:{}", self.tool_level);
println!("挖掘深度:{} 米", self.depth);
println!("矿石背包:");
println!(" 煤炭:{} 块 | 铁:{} 块 | 金:{} 块 | 钻石:{} 块",
self.ore_counts[0], self.ore_counts[1], self.ore_counts[2], self.ore_counts[3]);
println!("-------------------------------------\n");
}
// 打印命令列表
fn print_commands(&self) {
println!("【可用命令】");
println!("1. 挖 / mine - 进行挖掘(消耗体力)");
println!("2. 背包 / bag - 查看详细背包信息");
println!("3. 升级 / upgrade - 用矿石升级工具");
println!("4. 休息 / rest - 恢复体力(不挖掘)");
println!("5. 退出 / exit - 结束游戏");
print!("\n请输入命令(直接输入关键词):");
}
// 获取用户输入
fn get_user_input(&self) -> String {
let mut input = String::new();
io::stdin().read_line(&mut input).expect("读取输入失败");
input.trim().to_lowercase()
}
// 处理用户命令
fn process_command(&mut self, command: String) {
match command.as_str() {
"挖" | "mine" => self.mine(),
"背包" | "bag" => self.show_bag(),
"升级" | "upgrade" => self.upgrade_tool(),
"休息" | "rest" => self.rest(),
"退出" | "exit" => self.game_over = true,
_ => println!("❌ 无效命令!请输入上述可用命令之一。"),
}
}
// 挖掘核心逻辑
fn mine(&mut self) {
// 检查体力是否充足
if self.stamina < 10 {
println!("⚠️ 体力不足!无法挖掘,请先休息恢复体力。");
return;
}
// 消耗体力(工具等级越高,体力消耗越少)
let stamina_cost = match self.tool_level {
ToolLevel::Wooden => 20,
ToolLevel::Stone => 15,
ToolLevel::Iron => 10,
ToolLevel::Diamond => 5,
};
self.stamina = self.stamina.saturating_sub(stamina_cost);
self.depth += 1;
// 随机生成挖矿事件
let event = self.generate_mine_event();
self.handle_event(event);
// 检查生命值是否为0(游戏结束)
if self.health == 0 {
self.game_over = true;
}
}
// 生成挖矿随机事件
fn generate_mine_event(&self) -> GameEvent {
let mut rng = rand::thread_rng();
let rand_num: u32 = rng.gen_range(0..100);
// 事件概率受工具等级影响(高级工具挖到好矿石概率更高,危险概率更低)
match self.tool_level {
ToolLevel::Wooden => {
match rand_num {
0..=30 => GameEvent::NoOre,
31..=60 => GameEvent::NormalMine(OreType::Coal),
61..=75 => GameEvent::NormalMine(OreType::Iron),
76..=85 => GameEvent::CaveIn,
86..=95 => GameEvent::MonsterAttack,
96..=99 => GameEvent::RareFind(OreType::Gold),
_ => unreachable!(),
}
}
ToolLevel::Stone => {
match rand_num {
0..=20 => GameEvent::NoOre,
21..=50 => GameEvent::NormalMine(OreType::Coal),
51..=75 => GameEvent::NormalMine(OreType::Iron),
76..=88 => GameEvent::RareFind(OreType::Gold),
89..=95 => GameEvent::CaveIn,
96..=99 => GameEvent::RareFind(OreType::Diamond),
_ => unreachable!(),
}
}
ToolLevel::Iron => {
match rand_num {
0..=10 => GameEvent::NoOre,
11..=40 => GameEvent::NormalMine(OreType::Iron),
41..=65 => GameEvent::RareFind(OreType::Gold),
66..=85 => GameEvent::NormalMine(OreType::Coal),
86..=90 => GameEvent::CaveIn,
91..=99 => GameEvent::RareFind(OreType::Diamond),
_ => unreachable!(),
}
}
ToolLevel::Diamond => {
match rand_num {
0..=5 => GameEvent::NoOre,
6..=30 => GameEvent::NormalMine(OreType::Gold),
31..=60 => GameEvent::RareFind(OreType::Diamond),
61..=85 => GameEvent::NormalMine(OreType::Iron),
86..=95 => GameEvent::RareFind(OreType::Gold),
96..=99 => GameEvent::RareFind(OreType::Diamond),
_ => unreachable!(),
}
}
}
}
// 处理挖矿事件
fn handle_event(&mut self, event: GameEvent) {
match event {
GameEvent::NormalMine(ore) => {
let ore_index = ore as usize;
self.ore_counts[ore_index] += 1;
println!("✅ 挖到了 {}!", ore);
}
GameEvent::NoOre => {
println!("❌ 什么都没挖到,白费力气...");
}
GameEvent::CaveIn => {
let damage = rand::thread_rng().gen_range(10..30);
self.health = self.health.saturating_sub(damage);
println!("⚠️ 发生塌方!受到 {} 点伤害,生命值剩余 {}。", damage, self.health);
}
GameEvent::MonsterAttack => {
let damage = rand::thread_rng().gen_range(15..40);
self.health = self.health.saturating_sub(damage);
println!("👹 遇到地下怪物!受到 {} 点伤害,生命值剩余 {}。", damage, self.health);
}
GameEvent::RareFind(ore) => {
let ore_index = ore as usize;
self.ore_counts[ore_index] += 1;
println!("🎉 稀有发现!挖到了珍贵的 {}!", ore);
}
}
}
// 查看背包详细信息
fn show_bag(&self) {
println!("\n【详细背包】");
println!("矿石总价值估算:");
println!(" 煤炭(10金币/块):{} 块 → {} 金币", self.ore_counts[0], self.ore_counts[0] * 10);
println!(" 铁(50金币/块):{} 块 → {} 金币", self.ore_counts[1], self.ore_counts[1] * 50);
println!(" 金(200金币/块):{} 块 → {} 金币", self.ore_counts[2], self.ore_counts[2] * 200);
println!(" 钻石(1000金币/块):{} 块 → {} 金币", self.ore_counts[3], self.ore_counts[3] * 1000);
println!("总金币:{}", self.calculate_total_gold());
println!("-------------------------------------");
}
// 计算总金币(用于升级判断)
fn calculate_total_gold(&self) -> u32 {
self.ore_counts[0] * 10 + self.ore_counts[1] * 50 + self.ore_counts[2] * 200 + self.ore_counts[3] * 1000
}
// 升级工具
fn upgrade_tool(&mut self) {
let total_gold = self.calculate_total_gold();
let next_level = match self.tool_level {
ToolLevel::Wooden => Some((ToolLevel::Stone, 100)), // 木镐→石镐:100金币
ToolLevel::Stone => Some((ToolLevel::Iron, 500)), // 石镐→铁镐:500金币
ToolLevel::Iron => Some((ToolLevel::Diamond, 2000)),// 铁镐→钻石镐:2000金币
ToolLevel::Diamond => None, // 已最高级
};
match next_level {
None => {
println!("✨ 你已经拥有最高级的钻石镐了,无需升级!");
}
Some((level, cost)) => {
if total_gold >= cost {
// 扣除升级所需金币(通过消耗矿石实现,这里简化为直接扣除价值)
println!("💰 花费 {} 金币升级工具到 {}!", cost, level);
self.tool_level = level;
// 升级后提升最大体力和生命值
self.max_stamina += 20;
self.max_health += 50;
self.stamina = self.max_stamina;
self.health = self.max_health;
println!("✨ 升级成功!最大生命值提升至 {},最大体力提升至 {}!", self.max_health, self.max_stamina);
} else {
println!("❌ 金币不足!升级到 {} 需要 {} 金币,当前只有 {} 金币。", level, cost, total_gold);
}
}
}
}
// 休息恢复体力
fn rest(&mut self) {
let recover = rand::thread_rng().gen_range(30..50);
self.stamina = (self.stamina + recover).min(self.max_stamina);
println!("😴 休息中...恢复了 {} 点体力,当前体力:{} / {}", recover, self.stamina, self.max_stamina);
// 休息时有小概率遇到危险(地下渗水)
if rand::thread_rng().gen_range(0..10) < 2 {
let damage = rand::thread_rng().gen_range(5..15);
self.health = self.health.saturating_sub(damage);
println!("⚠️ 休息时遇到地下渗水!受到 {} 点伤害,生命值剩余 {}。", damage, self.health);
if self.health == 0 {
self.game_over = true;
}
}
}
// 检查胜利条件(收集5颗钻石)
fn check_victory(&mut self) {
if self.ore_counts[3] >= 5 {
println!("\n=====================================");
println!("🎉 恭喜你!收集到 5 颗钻石,获得终极胜利!");
println!("你成为了传奇矿工,财富和荣誉加身!");
println!("=====================================");
self.game_over = true;
}
}
// 打印游戏结束信息
fn print_game_over(&self) {
if self.ore_counts[3] >= 5 {
return; // 胜利信息已打印
}
println!("\n=====================================");
println!("💀 游戏结束!");
if self.health == 0 {
println!("你在挖矿过程中遭遇不幸,未能完成冒险...");
} else {
println!("你选择结束冒险,下次再见!");
}
println!("最终成绩:");
println!("挖掘深度:{} 米", self.depth);
println!("收集钻石:{} 颗", self.ore_counts[3]);
println!("=====================================");
}
}
// 主函数
fn main() {
let mut game = MiningGame::new();
game.run();
}
三、代码核心特性解析
-
单类封装设计:所有游戏逻辑封装在
MiningGame结构体中,通过impl块实现初始化、运行、挖矿、升级等方法,符合面向对象的封装思想,同时保持 Rust 的简洁性。结构体中存储玩家状态(生命值、体力、矿石数量等),确保数据集中管理,便于维护。 -
枚举的灵活运用:定义
OreType(矿石类型)、ToolLevel(工具等级)、GameEvent(游戏事件)三个枚举,清晰区分不同游戏元素,同时通过fmt::Display实现枚举的字符串格式化,方便输出到终端。 -
随机事件系统:利用
rand库生成随机数,结合工具等级动态调整事件概率(高级工具挖到稀有矿石概率更高,危险事件概率更低),提升游戏的策略性和趣味性。例如木镐挖掘时塌方概率高达 10%,而钻石镐仅 4%。 -
终端交互优化:通过
std::io读取用户输入,支持中文命令(如「挖」和「mine」等价),降低操作门槛。同时定期打印玩家状态和命令列表,让用户清晰了解当前游戏进度和可执行操作。 -
状态管理与边界处理:使用
saturating_sub方法处理生命值、体力值的扣除(避免出现负数),通过game_over标志控制游戏循环,确保游戏逻辑的稳定性。升级工具时会同步提升最大生命值和体力,形成「升级 - 变强 - 挖掘更深处」的正反馈循环。
四、游戏玩法与体验优化
通过这款游戏的开发,不仅能深入理解 Rust 的核心语法和特性,还能体会到复古游戏的设计思路 —— 用简单的交互承载丰富的逻辑,让玩家在文字世界中获得沉浸式体验。无论是作为 Rust 初学者的实践项目,还是复古游戏爱好者的娱乐选择,这款挖矿小游戏都具有一定的价值。
未来可以通过扩展道具、地图、联机等功能,进一步丰富游戏内容,让这款 CMD 挖矿冒险变得更加完善。如果你也喜欢 Rust 或复古游戏,不妨尝试运行代码体验一番,或基于此进行二次开发,打造属于自己的独特游戏!
七、总结
本文通过 Rust 语言开发了一款 CMD 风格的挖矿小游戏,实现了「挖掘 - 收集 - 升级 - 冒险」的核心玩法,所有功能封装在单类中,兼顾了代码的模块化和可维护性。游戏利用 Rust 的枚举、随机数生成、终端交互等特性,打造了一款兼具策略性和趣味性的复古冒险游戏。
-
策略性升级路径:游戏设计了清晰的工具升级阶梯(木镐→石镐→铁镐→钻石镐),升级需要消耗矿石兑换的「金币」,玩家需要权衡「立即挖掘」和「积累矿石升级」的优先级。例如初期木镐效率低,尽早升级石镐能显著提升挖矿收益。
-
随机事件的趣味性:除了常规挖矿,还加入了塌方、怪物袭击、稀有发现等随机事件,让每一次挖掘都充满不确定性。休息时也有小概率遇到危险,避免玩家无脑休息恢复体力,增加游戏的紧张感。
-
胜利条件明确:以「收集 5 颗钻石」为终极目标,同时设置生命值为 0 即失败的机制,让游戏既有明确的奋斗方向,又有一定的挑战性。玩家可以根据自身情况选择「激进挖掘」或「稳健积累」的玩法。
五、编译与运行指南
-
环境准备:确保已安装 Rust 编译环境(
rustc和cargo),可通过 Rust 官网 下载安装。 -
添加依赖:在项目的
Cargo.toml中添加rand库依赖(用于随机数生成):[dependencies] rand = "0.8.5"编译运行:在项目目录执行以下命令,即可启动游戏:
cargo run -
操作说明:启动后按照终端提示输入命令(支持中文或英文关键词),例如输入「挖」开始挖掘,输入「升级」查看工具升级条件,输入「背包」查看矿石详情。
-
六、开发心得与扩展方向
-
Rust 语言的优势:在开发过程中,Rust 的所有权机制和类型安全特性有效避免了空指针、数据竞争等问题。例如矿石数量存储在固定大小的数组中,通过枚举索引访问,确保不会出现越界错误;
saturating_sub等方法的使用,让数值处理更安全。 -
游戏扩展方向:
- 增加道具系统:例如「体力药水」「急救包」「防爆符」等,提升游戏的策略性。
- 加入地图探索:设计不同矿层(如煤炭层、铁矿层、钻石层),不同矿层的矿石分布和危险程度不同。
- 多人联机:通过网络实现多人协作挖矿或竞争,共享资源或抢夺矿石。
- 图形化界面:基于
tui-rs等库开发终端图形界面,用色彩和简单图形替代纯文本,提升视觉体验。
-
复古游戏的魅力:CMD 风格的游戏虽然没有华丽的画面,但通过简洁的文本交互和丰富的逻辑设计,能让玩家更专注于游戏本身的乐趣。这款挖矿游戏的核心在于「随机性」和「成长性」,每一次挖掘都可能带来惊喜或危险,升级工具的过程能给玩家带来明确的成就感。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)