rust语言写的贪吃蛇游戏
Posted 福大大架构师每日一题
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了rust语言写的贪吃蛇游戏相关的知识,希望对你有一定的参考价值。
首先新建工程,然后用vscode打开,命令如下:
cargo new snake --bin
文件结构如下:
Cargo.Toml文件内容如下:
[package]
name = "snake"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rand = "0.4.6"
piston_window="0.74.0"
[profile.release]
opt-level = 0
lto = true
codegen-units = 1
panic = "abort"
src/draw.rs文件内容如下:
use piston_window::types::Color;
use piston_window::rectangle, Context, G2d;
const BLOCK_SIZE: f64 = 25.0;
pub fn to_coord(game_coord: i32) -> f64
(game_coord as f64) * BLOCK_SIZE
pub fn to_coord_u32(game_coord: i32) -> u32
to_coord(game_coord) as u32
pub fn draw_block(color: Color, x: i32, y: i32, con: &Context, g: &mut G2d)
let gui_x = to_coord(x);
let gui_y = to_coord(y);
rectangle(
color,
[gui_x, gui_y, BLOCK_SIZE, BLOCK_SIZE],
con.transform,
g,
);
pub fn draw_rectangle(
color: Color,
x: i32,
y: i32,
width: i32,
height: i32,
con: &Context,
g: &mut G2d,
)
let x = to_coord(x);
let y = to_coord(y);
rectangle(
color,
[
x,
y,
BLOCK_SIZE * (width as f64),
BLOCK_SIZE * (height as f64),
],
con.transform,
g,
);
game.rs文件内容如下:
use crate::draw::draw_block, draw_rectangle;
use piston_window::types::Color;
use piston_window::*;
use rand::thread_rng, Rng;
use crate::snake::Direction, Snake;
const FOOD_COLOR: Color = [0.80, 0.00, 0.00, 1.0];
const BORDER_COLOR: Color = [0.80, 0.00, 0.00, 1.0];
const GAMEOVER_COLOR: Color = [0.90, 0.00, 0.00, 0.5];
const MOVING_PERIOD: f64 = 0.1;
const RESTART_TIME: f64 = 1.0;
pub struct Game
snake: Snake,
food_exists: bool,
food_x: i32,
food_y: i32,
width: i32,
height: i32,
game_over: bool,
waiting_time: f64,
impl Game
pub fn new(width: i32, height: i32) -> Game
Game
snake: Snake::new(2, 2),
food_exists: true,
food_x: 6,
food_y: 4,
width,
height,
game_over: false,
waiting_time: 0.0,
pub fn key_pressed(&mut self, key: Key)
if self.game_over
return;
let dir = match key
Key::Up => Some(Direction::Up),
Key::Down => Some(Direction::Down),
Key::Left => Some(Direction::Left),
Key::Right => Some(Direction::Right),
_ => None,
;
if dir.unwrap() == self.snake.head_direction().opposite()
return;
self.update_snake(dir);
pub fn draw(&self, con: &Context, g: &mut G2d)
self.snake.draw(con, g);
if self.food_exists
draw_block(FOOD_COLOR, self.food_x, self.food_y, con, g);
draw_rectangle(BORDER_COLOR, 0, 0, self.width, 1, con, g);
draw_rectangle(BORDER_COLOR, 0, self.height - 1, self.width, 1, con, g);
draw_rectangle(BORDER_COLOR, 0, 0, 1, self.height, con, g);
draw_rectangle(BORDER_COLOR, self.width - 1, 0, 1, self.height, con, g);
if self.game_over
draw_rectangle(GAMEOVER_COLOR, 0, 0, self.width, self.height, con, g);
pub fn update(&mut self, delta_time: f64)
self.waiting_time += delta_time;
if self.game_over
if self.waiting_time > RESTART_TIME
self.restart();
return;
if !self.food_exists
self.add_food();
if self.waiting_time > MOVING_PERIOD
self.update_snake(None);
fn check_eating(&mut self)
let (head_x, head_y): (i32, i32) = self.snake.head_position();
if self.food_exists && self.food_x == head_x && self.food_y == head_y
self.food_exists = false;
self.snake.restore_tail();
fn check_if_snake_alive(&self, dir: Option<Direction>) -> bool
let (next_x, next_y) = self.snake.next_head(dir);
if self.snake.overlap_tail(next_x, next_y)
return false;
next_x > 0 && next_y > 0 && next_x < self.width - 1 && next_y < self.height - 1
fn add_food(&mut self)
let mut rng = thread_rng();
let mut new_x = rng.gen_range(1, self.width - 1);
let mut new_y = rng.gen_range(1, self.width - 1);
while self.snake.overlap_tail(new_x, new_y)
new_x = rng.gen_range(1, self.width - 1);
new_y = rng.gen_range(1, self.width - 1);
self.food_x = new_x;
self.food_y = new_y;
self.food_exists = true;
fn update_snake(&mut self, dir: Option<Direction>)
if self.check_if_snake_alive(dir)
self.snake.move_forward(dir);
self.check_eating();
else
self.game_over = true;
self.waiting_time = 0.0;
fn restart(&mut self)
self.snake = Snake::new(2, 2);
self.waiting_time = 0.0;
self.food_exists = true;
self.food_x = 6;
self.food_y = 4;
self.game_over = false;
main.rs文件内容如下:
extern crate piston_window;
extern crate rand;
mod draw;
mod game;
mod snake;
use draw::to_coord_u32;
use game::Game;
use piston_window::types::Color;
use piston_window::*;
const BACK_COLOR: Color = [0.5, 0.5, 0.5, 1.0];
fn main()
//https://magiclen.org/rust-compile-optimize/
let (width, height) = (30, 30);
let mut window: PistonWindow =
WindowSettings::new("Snake", [to_coord_u32(width), to_coord_u32(height)])
.exit_on_esc(true)
.build()
.unwrap();
let mut game = Game::new(width, height);
while let Some(event) = window.next()
if let Some(Button::Keyboard(key)) = event.press_args()
game.key_pressed(key);
window.draw_2d(&event, |c, g|
clear(BACK_COLOR, g);
game.draw(&c, g);
);
event.update(|arg|
game.update(arg.dt);
);
snake.rs文件内容如下:
use piston_window::types::Color;
use piston_window::Context, G2d;
use std::collections::LinkedList;
use crate::draw::draw_block;
const SNAKE_COLOR: Color = [0.00, 0.80, 0.00, 1.0];
#[derive(Copy, Clone, PartialEq)]
pub enum Direction
Up,
Down,
Left,
Right,
impl Direction
pub fn opposite(&self) -> Direction
match *self
Direction::Up => Direction::Down,
Direction::Down => Direction::Up,
Direction::Left => Direction::Right,
Direction::Right => Direction::Left,
#[derive(Debug, Clone)]
struct Block
x: i32,
y: i32,
pub struct Snake
direction: Direction,
body: LinkedList<Block>,
tail: Option<Block>,
impl Snake
pub fn new(x: i32, y: i32) -> Snake
let mut body: LinkedList<Block> = LinkedList::new();
body.push_back(Block x: x + 2, y );
body.push_back(Block x: x + 1, y );
body.push_back(Block x, y );
Snake
direction: Direction::Right,
body,
tail: None,
pub fn draw(&self, con: &Context, g: &mut G2d)
for block in &self.body
draw_block(SNAKE_COLOR, block.x, block.y, con, g);
pub fn head_position(&self) -> (i32, i32)
let head_block = self.body.front().unwrap();
(head_block.x, head_block.y)
pub fn move_forward(&mut self, dir: Option<Direction>)
match dir
Some(d) => self.direction = d,
None => (),
let (last_x, last_y): (i32, i32) = self.head_position();
let new_block = match self以上是关于rust语言写的贪吃蛇游戏的主要内容,如果未能解决你的问题,请参考以下文章