本章做一个游戏-贪吃蛇大作战。
蛇身数据可以用链表,也可以用数组。
用链表的话,每次移动时在链表头部插入位置数据并删除队尾数据即可。理解上比较简单,但实现时容易出错。调试成本略高。数组就比较暴力,提前分配好空间,不太容易出错。代码量会少很多。空间换时间。
这里我就用数组了。
1、先定义基础数据。
蛇身位置数据存在数组data中。
typedef struct {
uint8_t direction;
uint8_t length;
uint16_t data[SnakeMaxLength] = { 65535 };
int speed = 80;
uint16_t color;
} SnakePlayer_t;
定义宏,将蛇身XY值转为data的值
#define Snake_XY(x,y) (((x)<<8)+(y))
定义整个空间
uint16_t board[Snake_Board_Width * Snake_Board_Height] = { 0 };
定义宏,将空间XY值转为board的值。
#define Snake_Board_XY(x,y) (((y)*Snake_Board_Width)+(x))
2、核心算法的实现
移动。根据direction移动蛇头XY位置。整个玩家data数组往后平移一格。
移动中如果吃到豆豆的话,蛇身长度+1.
void Snake::Move(SnakePlayer_t *player) {
uint8_t x = player->data[0] >> 8;
uint8_t y = player->data[0] & 0xff;
switch (player->direction) {
case 1:
x--;
break;
case 2:
y--;
break;
case 3:
x++;
break;
case 4:
y++;
break;
}
if (board[Snake_Board_XY(x, y)] && player->length < SnakeMaxLength) {
board[Snake_Board_XY(x, y)] = 0;
player->length++;
}
for (uint16_t i = player->length - 1; i > 0; i--) {
player->data[i] = player->data[i - 1];
}
player->data[0] = Snake_XY(x, y);
player->speed = Snake_Default_Speed;
player->color = (player->color + 10) % 720;
}
死亡检测。双人对战模式中,玩家是可以咬自己尾巴的。撞到对方或者边缘才会死亡。
uint8_t Snake::Kill(SnakePlayer_t *playerA, SnakePlayer_t *playerB) {
uint8_t x = playerA->data[0] >> 8;
uint8_t y = playerA->data[0] & 0xff;
if (x == 0 || y == 0) {
return 1;
}
if (x == Snake_Board_Width - 1 || y == Snake_Board_Height - 1) {
return 1;
}
for (uint16_t i = 0; i < playerB->length; i++)