rust游戏
·
use std::io::{self, Write};
use crossterm::{
event::{self, Event, KeyCode, KeyEventKind},
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use tui::{
backend::{Backend, CrosstermBackend},
layout::{Alignment, Constraint, Direction, Layout},
style::{Color, Modifier, Style},
text::{Span, Spans},
widgets::{Block, Borders, Paragraph, Wrap},
Terminal,
};
use std::time::{Duration, Instant};
// 游戏主类
struct ChoiceGame {
current_screen: ScreenType,
main_menu_selected: usize,
adventure_selected: usize,
quiz_selected: usize,
random_event_selected: usize,
game_state: GameState,
}
// 屏幕类型枚举
enum ScreenType {
MainMenu,
Adventure,
Quiz,
RandomEvent,
Result(String),
}
// 游戏状态
struct GameState {
score: i32,
health: i32,
steps: i32,
}
impl ChoiceGame {
// 初始化游戏
fn new() -> Self {
Self {
current_screen: ScreenType::MainMenu,
main_menu_selected: 0,
adventure_selected: 0,
quiz_selected: 0,
random_event_selected: 0,
game_state: GameState {
score: 0,
health: 100,
steps: 0,
},
}
}
// 运行游戏主循环
fn run(&mut self) -> io::Result<()> {
// 初始化终端
enable_raw_mode()?;
let mut stdout = io::stdout();
execute!(stdout, EnterAlternateScreen)?;
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
terminal.clear()?;
// 游戏主循环
let mut last_update = Instant::now();
loop {
// 绘制界面
terminal.draw(|f| self.draw(f))?;
// 处理输入
if event::poll(Duration::from_millis(50))? {
if let Event::Key(event) = event::read()? {
if event.kind == KeyEventKind::Press {
match event.code {
KeyCode::Up => self.handle_up(),
KeyCode::Down => self.handle_down(),
KeyCode::Enter => self.handle_enter(),
KeyCode::Esc => break,
_ => {}
}
}
}
}
// 随机事件定时触发
if let ScreenType::Adventure | ScreenType::RandomEvent = self.current_screen {
if last_update.elapsed() > Duration::from_secs(30) {
self.game_state.steps += 1;
if self.game_state.steps % 5 == 0 {
self.current_screen = ScreenType::Result(
format!("时间过去了很久,你的体力下降了!健康值: {}",
{self.game_state.health -= 10; self.game_state.health})
);
}
last_update = Instant::now();
}
}
}
// 恢复终端状态
disable_raw_mode()?;
execute!(
terminal.backend_mut(),
LeaveAlternateScreen
)?;
terminal.show_cursor()?;
Ok(())
}
// 处理上方向键
fn handle_up(&mut self) {
match self.current_screen {
ScreenType::MainMenu => {
self.main_menu_selected = if self.main_menu_selected == 0 {
self.get_main_menu_options().len() - 1
} else {
self.main_menu_selected - 1
};
}
ScreenType::Adventure => {
self.adventure_selected = if self.adventure_selected == 0 {
self.get_adventure_options().len() - 1
} else {
self.adventure_selected - 1
};
}
ScreenType::Quiz => {
self.quiz_selected = if self.quiz_selected == 0 {
self.get_quiz_options().len() - 1
} else {
self.quiz_selected - 1
};
}
ScreenType::RandomEvent => {
self.random_event_selected = if self.random_event_selected == 0 {
self.get_random_event_options().len() - 1
} else {
self.random_event_selected - 1
};
}
ScreenType::Result(_) => {
self.current_screen = ScreenType::MainMenu;
}
}
}
// 处理下方向键
fn handle_down(&mut self) {
match self.current_screen {
ScreenType::MainMenu => {
self.main_menu_selected = (self.main_menu_selected + 1) % self.get_main_menu_options().len();
}
ScreenType::Adventure => {
self.adventure_selected = (self.adventure_selected + 1) % self.get_adventure_options().len();
}
ScreenType::Quiz => {
self.quiz_selected = (self.quiz_selected + 1) % self.get_quiz_options().len();
}
ScreenType::RandomEvent => {
self.random_event_selected = (self.random_event_selected + 1) % self.get_random_event_options().len();
}
ScreenType::Result(_) => {
self.current_screen = ScreenType::MainMenu;
}
}
}
// 处理回车键
fn handle_enter(&mut self) {
match self.current_screen {
ScreenType::MainMenu => {
match self.main_menu_selected {
0 => self.current_screen = ScreenType::Adventure,
1 => self.current_screen = ScreenType::Quiz,
2 => self.current_screen = ScreenType::RandomEvent,
3 => {
// 退出游戏
std::process::exit(0);
}
_ => {}
}
}
ScreenType::Adventure => {
let result = match self.adventure_selected {
0 => {
self.game_state.score += 50;
"你选择了穿越森林,发现了宝藏!获得50分!".to_string()
}
1 => {
self.game_state.health -= 20;
format!("你选择了翻越高山,路途艰险,健康值减少20。当前健康值: {}", self.game_state.health)
}
2 => {
self.game_state.score += 30;
"你选择了沿着河流前进,找到了食物!获得30分!".to_string()
}
3 => {
self.current_screen = ScreenType::MainMenu;
return;
}
_ => "未知选择".to_string()
};
self.current_screen = ScreenType::Result(result);
}
ScreenType::Quiz => {
let result = match self.quiz_selected {
0 => {
self.game_state.score += 100;
"正确!Rust是由Mozilla开发的。获得100分!".to_string()
}
1 => {
self.game_state.score -= 20;
"错误!Rust不是由Google开发的。扣20分!".to_string()
}
2 => {
self.game_state.score -= 20;
"错误!Rust不是由Microsoft开发的。扣20分!".to_string()
}
3 => {
self.current_screen = ScreenType::MainMenu;
return;
}
_ => "未知选择".to_string()
};
self.current_screen = ScreenType::Result(result);
}
ScreenType::RandomEvent => {
let result = match self.random_event_selected {
0 => {
self.game_state.score += 70;
"你帮助了陌生人,获得了奖励!获得70分!".to_string()
}
1 => {
self.game_state.health -= 30;
format!("你选择无视,遭遇了不幸!健康值减少30。当前健康值: {}", self.game_state.health)
}
2 => {
self.game_state.score += 20;
"你谨慎观察后离开,发现了一些金币!获得20分!".to_string()
}
3 => {
self.current_screen = ScreenType::MainMenu;
return;
}
_ => "未知选择".to_string()
};
self.current_screen = ScreenType::Result(result);
}
ScreenType::Result(_) => {
self.current_screen = ScreenType::MainMenu;
}
}
}
// 获取主菜单选项
fn get_main_menu_options(&self) -> Vec<&str> {
vec!["冒险模式", "答题挑战", "随机事件", "退出游戏"]
}
// 获取冒险模式选项
fn get_adventure_options(&self) -> Vec<&str> {
vec!["穿越森林", "翻越高山", "沿着河流前进", "返回主菜单"]
}
// 获取答题挑战选项
fn get_quiz_options(&self) -> Vec<&str> {
vec!["Mozilla", "Google", "Microsoft", "返回主菜单"]
}
// 获取随机事件选项
fn get_random_event_options(&self) -> Vec<&str> {
vec!["提供帮助", "视而不见", "谨慎观察", "返回主菜单"]
}
// 绘制界面
fn draw<B: Backend>(&self, f: &mut tui::Frame<B>) {
let size = f.size();
// 创建主布局
let main_layout = Layout::default()
.direction(Direction::Vertical)
.margin(1)
.constraints(
[
Constraint::Length(3), // 标题区域
Constraint::Min(10), // 内容区域
Constraint::Length(3), // 状态区域
]
.as_ref(),
)
.split(size);
// 绘制标题
let title = match self.current_screen {
ScreenType::MainMenu => "选择对话框小游戏 - 主菜单",
ScreenType::Adventure => "冒险模式",
ScreenType::Quiz => "答题挑战 - Rust是由哪家公司开发的?",
ScreenType::RandomEvent => "随机事件 - 你遇到了一个陌生人需要帮助",
ScreenType::Result(_) => "结果反馈",
};
let title_block = Paragraph::new(title)
.style(Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD))
.alignment(Alignment::Center)
.block(Block::default().borders(Borders::ALL).title("标题"));
f.render_widget(title_block, main_layout[0]);
// 绘制内容区域
let content_block = Block::default().borders(Borders::ALL).title("内容");
f.render_widget(content_block, main_layout[1]);
// 内容区域内部布局
let content_layout = Layout::default()
.direction(Direction::Vertical)
.margin(1)
.constraints(
std::iter::repeat(Constraint::Length(1))
.take(match self.current_screen {
ScreenType::MainMenu => self.get_main_menu_options().len(),
ScreenType::Adventure => self.get_adventure_options().len(),
ScreenType::Quiz => self.get_quiz_options().len(),
ScreenType::RandomEvent => self.get_random_event_options().len(),
ScreenType::Result(_) => 1,
})
.chain(std::iter::once(Constraint::Min(0)))
.collect::<Vec<_>>()
)
.split(main_layout[1]);
// 根据当前屏幕类型绘制不同内容
match self.current_screen {
ScreenType::MainMenu => {
self.get_main_menu_options().iter().enumerate().for_each(|(i, option)| {
let style = if i == self.main_menu_selected {
Style::default().fg(Color::Black).bg(Color::White).add_modifier(Modifier::BOLD)
} else {
Style::default().fg(Color::White)
};
let text = Spans::from(Span::styled(format!(" {}", option), style));
let paragraph = Paragraph::new(text).alignment(Alignment::Center);
f.render_widget(paragraph, content_layout[i]);
});
}
ScreenType::Adventure => {
self.get_adventure_options().iter().enumerate().for_each(|(i, option)| {
let style = if i == self.adventure_selected {
Style::default().fg(Color::Black).bg(Color::White).add_modifier(Modifier::BOLD)
} else {
Style::default().fg(Color::White)
};
let text = Spans::from(Span::styled(format!(" {}", option), style));
let paragraph = Paragraph::new(text).alignment(Alignment::Center);
f.render_widget(paragraph, content_layout[i]);
});
}
ScreenType::Quiz => {
self.get_quiz_options().iter().enumerate().for_each(|(i, option)| {
let style = if i == self.quiz_selected {
Style::default().fg(Color::Black).bg(Color::White).add_modifier(Modifier::BOLD)
} else {
Style::default().fg(Color::White)
};
let text = Spans::from(Span::styled(format!(" {}", option), style));
let paragraph = Paragraph::new(text).alignment(Alignment::Center);
f.render_widget(paragraph, content_layout[i]);
});
}
ScreenType::RandomEvent => {
self.get_random_event_options().iter().enumerate().for_each(|(i, option)| {
let style = if i == self.random_event_selected {
Style::default().fg(Color::Black).bg(Color::White).add_modifier(Modifier::BOLD)
} else {
Style::default().fg(Color::White)
};
let text = Spans::from(Span::styled(format!(" {}", option), style));
let paragraph = Paragraph::new(text).alignment(Alignment::Center);
f.render_widget(paragraph, content_layout[i]);
});
}
ScreenType::Result(message) => {
let text = Spans::from(Span::styled(message, Style::default().fg(Color::Green)));
let paragraph = Paragraph::new(text)
.alignment(Alignment::Center)
.wrap(Wrap { trim: true });
f.render_widget(paragraph, content_layout[0]);
let hint = Spans::from(Span::styled("按上/下方向键返回主菜单", Style::default().fg(Color::Yellow)));
let hint_paragraph = Paragraph::new(hint)
.alignment(Alignment::Center);
f.render_widget(hint_paragraph, content_layout[1]);
}
}
// 绘制状态区域
let status_text = format!(
" 分数: {} | 健康值: {} | 操作提示: 上下方向键选择,Enter确认,Esc退出 ",
self.game_state.score, self.game_state.health
);
let status_block = Paragraph::new(status_text)
.style(Style::default().fg(Color::Black).bg(Color::Cyan))
.alignment(Alignment::Center)
.block(Block::default().borders(Borders::ALL).title("状态"));
f.render_widget(status_block, main_layout[2]);
}
}
// 程序入口
fn main() -> io::Result<()> {
let mut game = ChoiceGame::new();
game.run()
}
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)