推箱子游戏利用数组就可以实现,在vs里使用特殊符号来代表墙、箱子、小人等物体,但是在stm32上面好像无法输出这些特殊符号(也有可能是我不会),所以就使用不同颜色来代替。包含头文件和一些宏定义如下:
#include "stdio.h" #include "stdbool.h" #include "stdlib.h" #include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "lcd.h" #include "beep.h" #include "key.h" #define SPACE 0 //空地 #define WALL 1 //墙 #define DEST 2 //目的地 #define BOX 3 //箱子 #define PLAYER 4 //玩家
完整代码如下:
//当前所在关卡
int level = 0;
//定义推箱子地图
int initMap[3][10][10] =
{
{
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,1,1,1,0,0,0,0},
{0,0,0,1,2,1,0,0,0,0},
{0,0,0,1,0,1,1,1,1,0},
{0,1,1,1,3,0,3,2,1,0},
{0,1,2,0,3,4,1,1,1,0},
{0,1,1,1,1,3,1,0,0,0},
{0,0,0,0,1,2,1,0,0,0},
{0,0,0,0,1,1,1,0,0,0},
{0,0,0,0,0,0,0,0,0,0}
},
{
{0,0,0,0,0,0,0,0,0,0},
{0,1,1,1,1,1,0,0,0,0},
{0,1,4,0,0,1,0,0,0,0},
{0,1,0,3,3,1,0,1,1,1},
{0,1,0,3,0,1,0,1,2,1},
{0,1,1,1,0,1,1,1,2,1},
{0,0,1,1,0,0,0,0,2,1},
{0,0,1,0,0,0,1,0,0,1},
{0,0,1,0,0,0,1,1,1,1},
{0,0,1,1,1,1,1,0,0,0}
},
{
{0,0,0,0,0,0,0,0,0,0},
{0,1,1,1,1,1,1,1,1,0},
{0,1,2,0,0,0,0,2,1,0},
{0,1,0,3,0,0,3,0,1,0},
{0,1,0,0,0,0,0,0,1,0},
{0,1,0,0,4,0,0,0,1,0},
{0,1,0,3,0,0,3,0,1,0},
{0,1,2,0,0,0,0,2,1,0},
{0,1,1,1,1,1,1,1,1,0},
{0,0,0,0,0,0,0,0,0,0}
}
};
int map[3][10][10];
//刷新地图
void init()
{
for (u8 l = 0; l < 3; l++)
{
for (u8 i = 0; i < 10; i++)
{
for (u8 k = 0; k < 10; k++)
{
map[l][i][k] = initMap[l][i][k];
}
}
}
}
//绘制地图
void drawMap()
{
LCD_Fill(350,50,380,80,BLACK);
LCD_ShowString(390,50,200,24,24,"BOX");
LCD_Fill(350,100,380,130,YELLOW);
LCD_ShowString(390,100,200,24,24,"PLAYER");
LCD_Fill(350,150,380,180,GREEN);
LCD_ShowString(390,150,200,24,24,"DEST");
for (int i = 0; i < 10; i++)
{
for (int k = 0; k < 10; k++)
{
switch (map[level][i][k])
{
case SPACE:
LCD_Fill(k*30,i*30,(k+1)*30,(i+1)*30,WHITE);
break;
case WALL:
LCD_Fill(k*30,i*30,(k+1)*30,(i+1)*30,RED);
break;
case DEST:
LCD_Fill(k*30,i*30,(k+1)*30,(i+1)*30,GREEN);
break;
case BOX:
LCD_Fill(k*30,i*30,(k+1)*30,(i+1)*30,BLACK);
break;
case PLAYER:
LCD_Fill(k*30,i*30,(k+1)*30,(i+1)*30,YELLOW);
break;
case DEST + BOX://箱子在目的地上
LCD_Fill(k*30,i*30,(k+1)*30,(i+1)*30,BROWN);
break;
case DEST + PLAYER://玩家在目的地上
LCD_Fill(k*30,i*30,(k+1)*30,(i+1)*30,BLUE);
break;
}
}
}
}
//判断是否通关
bool jude()
{
for (u8 i = 0; i < 10; i++)
{
for (u8 k = 0; k < 10; k++)
{
if (map[level][i][k] == BOX)
{
return false;
}
}
}
}
void donghua()
{
LCD_ShowString(120,120,210,24,24,"Welcome to my game");
delay_ms(3000);
LCD_Clear(WHITE);
LCD_ShowString(120,120,210,24,24,"Now let's start");
delay_ms(3000);
}
int main()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168); //初始化延时函数
uart_init(115200); //初始化串口波特率为115200
POINT_COLOR=RED;
LED_Init(); //初始化LED
LCD_Init(); //初始化LCD FSMC接口
BEEP_Init(); //初始化蜂鸣器端口
KEY_Init(); //初始化与按键连接的硬件接口
u8 key; //保存键值
//初始化地图
init();
LCD_Clear(WHITE);
//过场动画
donghua();
//输出地图
drawMap();
//推箱子
while (1)
{
int r = 0, c = 0;//玩家所在坐标
for (int i = 0; i < 10; i++)
{
for (int k = 0; k < 10; k++)
{
if (map[level][i][k]==PLAYER || map[level][i][k]==DEST + PLAYER)
{
r = i;
c = k;
}
}
}
//输出第几关
switch(level)
{
case 0:
LCD_ShowString(30,350,210,24,24,"First Pass");
break;
case 1:
LCD_ShowString(30,350,210,24,24,"Second Pass");
break;
case 2:
LCD_ShowString(30,350,210,24,24,"Third Pass");
break;
}
//按键操作
key=KEY_Scan(0);
if(key)
{
switch (key)
{
case WKUP_PRES:
//玩家上面是空地
if (map[level][r-1][c]==SPACE || map[level][r-1][c]==DEST)
{
map[level][r - 1][c] += PLAYER;
map[level][r][c] -= PLAYER;
}
//玩家上面是箱子
else if (map[level][r-1][c]==BOX||map[level][r-1][c]==BOX+DEST)
{
//箱子上面是空地或目的地
if (map[level][r - 2][c] == SPACE || map[level][r - 2][c] == DEST)
{
//移动箱子
map[level][r - 2][c] += BOX;
map[level][r - 1][c] -= BOX;
//移动玩家
map[level][r - 1][c] += PLAYER;
map[level][r][c] -= PLAYER;
}
}
break;
case KEY1_PRES:
//玩家下面是空地
if (map[level][r + 1][c] == SPACE || map[level][r + 1][c] == DEST)
{
map[level][r + 1][c] += PLAYER;
map[level][r][c] -= PLAYER;
}
//玩家下面是箱子
else if (map[level][r + 1][c] == BOX || map[level][r + 1][c] == BOX + DEST)
{
//箱子下面是空地或目的地
if (map[level][r + 2][c] == SPACE || map[level][r + 2][c] == DEST)
{
//移动箱子
map[level][r + 2][c] += BOX;
map[level][r + 1][c] -= BOX;
//移动玩家
map[level][r + 1][c] += PLAYER;
map[level][r][c] -= PLAYER;
}
}
break;
case KEY2_PRES:
//玩家左面是空地
if (map[level][r][c - 1] == SPACE || map[level][r][c - 1] == DEST)
{
map[level][r][c - 1] += PLAYER;
map[level][r][c] -= PLAYER;
}
//玩家左面是箱子
else if (map[level][r][c - 1] == BOX || map[level][r][c - 1] == BOX + DEST)
{
//箱子左面是空地或目的地
if (map[level][r][c - 2] == SPACE || map[level][r][c - 2] == DEST)
{
//移动箱子
map[level][r][c - 2] += BOX;
map[level][r][c - 1] -= BOX;
//移动玩家
map[level][r][c - 1] += PLAYER;
map[level][r][c] -= PLAYER;
}
}
break;
case KEY0_PRES:
//玩家右面是空地
if (map[level][r][c + 1] == SPACE || map[level][r][c + 1] == DEST)
{
map[level][r][c + 1] += PLAYER;
map[level][r][c] -= PLAYER;
}
//玩家右面是箱子
else if (map[level][r][c + 1] == BOX || map[level][r][c + 1] == BOX + DEST)
{
//箱子右面是空地或目的地
if (map[level][r][c + 2] == SPACE || map[level][r][c + 2] == DEST)
{
//移动箱子
map[level][r][c + 2] += BOX;
map[level][r][c + 1] -= BOX;
//移动玩家
map[level][r][c + 1] += PLAYER;
map[level][r][c] -= PLAYER;
}
}
break;
}
drawMap();
}
if (jude())
{
if (level > 2)
{
LCD_Clear(WHITE);
LCD_ShowString(120,100,210,24,24,"The game is over");
delay_ms(3000);
LCD_Clear(WHITE);
LCD_ShowString(120,100,210,24,24,"Thanks for playing");
delay_ms(3000);
LCD_Clear(WHITE);
LCD_ShowString(120,100,210,24,24,"Made by Xiang Yang");
delay_ms(10000);
}
else
level++;
}
}
}
效果如下:



