问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Rust小白自练手项目——贪吃蛇

创作时间:
作者:
@小白创作中心

Rust小白自练手项目——贪吃蛇

引用
CSDN
1.
https://blog.csdn.net/djw_CSDN/article/details/140478178

Rust自练手小项目 - 贪吃蛇

1. 贪吃蛇游戏长什么样子


图片来源于网络

可以看出,基本的贪吃蛇游戏有几个部分:1. 背板;2. 蛇;3. 食物。知道了这些我们就可以进行贪吃蛇的设计了。

2. 贪吃蛇游戏的设计

2.1 方块

显然可以看出,无论是食物、蛇还是背景板,其基本构成都是方块。食物和背景板是一个方块,蛇是很多个方块。因此,先写一个方块:

const BLOCK_SIZE: f64 = 25.0;

#[derive(Debug, Clone)]
pub struct Block {
    pub x: i32,
    pub y: i32,
}

xy是方块位置坐标,方块大小使用常量BLOCK_SIZE,因为蛇身体每一节和食物的方块大小都一样。当然,我们需要把方块位置映射具体一点:

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_rangtangle(
    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,
    )
}

好了,我们已经完成方块的绘制了,很多事件就显然了,比如说食物就是随机在面板的一个位置绘制一个方块,这个问题暂且不表。下面来看看难一点的snake需要怎么处理。

2.2 蛇的处理

想明白一点,蛇的本质是什么?蛇其实就是一些方块组成的集合罢了。那选用什么数据结构来存储呢,常见数据结构有arraystackqueuesetmap。容易想到蛇移动一个位置,就是蛇头前面一个方块进入蛇,蛇尾一个方块离开蛇,这样很容易想到一种数据结构:queue。因此可以描述队列的结构都行,我们使用LinkList描述蛇的身体,当然也可以使用VecDeque

pub struct Snake {
    direction: Direction,
    body: LinkedList<Block>,
    tail: Option<Block>,
}

这里面还包含着蛇的一个重要特性:移动方向。这是一个枚举,显然只有上、下、左、右咯,

#[derive(Clone, Copy, PartialEq)]
pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}

我们知道,如果蛇头向上,那它下一步可以向左、右、上移动,但是不可以向反方向移动,我们在Direction上实现一个关联函数表示其反方向,

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,
        }
    }
}

接下来,我们来实现蛇的一些逻辑,

impl Snake {
    pub fn new(x: i32, y: i32) -> Snake {
        let mut body: LinkedList<Block> = LinkedList::new();
        body.push_back(
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号