使用STM32F103VCT6最小系统板,通过max7219实现四个8*8led共阴点阵屏的级联,四个按键上下左右移动实现推箱子游戏设计
其中点阵屏的CLK接PA8,CS接PA10,DIN接PA12,控制左上右下移动的按键分别接引脚PD1,3,6,7,以下是部分代码
#include "stm32f10x.h" // 包含STM32F10x系列微控制器的头文件
#include "bsp_SysTick.h" // 包含系统滴答定时器的实现,用于延时
#include "Dot_Matrix.h" // 包含点阵屏的相关配置
#define MAP_WIDTH 16 // 定义地图宽度为16个格子
#define MAP_HEIGHT 16 //地图高度为16个格子
#define DEBOUNCE_DELAY 1000 // 设置消抖时间为1000ms
// 定义地图、玩家、箱子和目标位置的全局变量
char map[MAP_HEIGHT][MAP_WIDTH] = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 4, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 1, 1},
{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1},
{0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1},
{0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1},
{0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
};
int player_x = 2; // 玩家初始x坐标
int player_y = 3; // 玩家初始y坐标
int box_x = 2; // 箱子初始x坐标
int box_y = 6; // 箱子初始y坐标
int target_x = 7; // 目标x坐标
int target_y = 8; // 目标y坐标
// 函数声明
void Display_Update(void);
void Display_Win(void);
void Clear_Display(void);
void Display_Box(int x, int y);
void Display_Target(int x, int y);
void Display_Player(int x, int y);
// 按键初始化函数
void Key_Init(void) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); // 使能GPIOD端口时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_3 | GPIO_Pin_6 | GPIO_Pin_7; // 配置PD1, PD3, PD6, PD7引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // 设置为下拉输入模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 设置引脚速度
GPIO_Init(GPIOD, &GPIO_InitStructure); // 初始化GPIOD
}
// 按键扫描函数,带有消抖处理
int Key_Scan(void) {
static int key_state = 0;
static int key_pressed = 0;
static uint32_t key_time = 0;
int current_state;
// 检测按键状态
current_state = GPIO_ReadInputData(GPIOD) & (GPIO_Pin_1 | GPIO_Pin_3 | GPIO_Pin_6 | GPIO_Pin_7); // 只检测PD1, PD3, PD6, PD7
if (current_state != key_state) {
key_time = 0;
key_state = current_state;
}
if (key_time < DEBOUNCE_DELAY) {
key_time++;
} else {
if (current_state != key_pressed) {
key_pressed = current_state;
if (key_pressed == GPIO_Pin_1) return 1; // PD1按下
if (key_pressed == GPIO_Pin_3) return 2; // PD3按下
if (key_pressed == GPIO_Pin_6) return 3; // PD6按下
if (key_pressed == GPIO_Pin_7) return 4; // PD7按下
}
}
return 0;
}
// 主函数
int main(void) {
Key_Init(); // 初始化按键
SysTick_Init(); // 初始化系统滴答定时器
while (1) {
int key = Key_Scan(); // 扫描按键
if (key) {
SysTick_Delay_Ms(10); // 延时消抖
switch (key) {
case 1: // 向左移动
if (player_x > 0 && map[player_y][player_x - 1] != 1) { // 确保不是墙壁且不超出左边界
if (map[player_y][player_x - 1] == 2) { // 如果左边是箱子
if (player_y > 0 && map[player_y - 1][player_x - 1] == 0) { // 确保箱子可以被推动
map[player_y][player_x] = 0; // 清除玩家当前位置
map[player_y - 1][player_x - 1] = 2; // 移动箱子
map[player_y][player_x - 1] = 4; // 更新玩家位置
player_x--; // 更新玩家的x坐标
box_x--; // 更新箱子的x坐标
}
} else {
map[player_y][player_x] = 0; // 清除玩家当前位置
map[player_y][player_x - 1] = 4; // 更新玩家位置
player_x--; // 更新玩家的x坐标
}
}
break;
case 2: // 向上移动
if (player_y > 0 && map[player_y - 1][player_x] != 1) { // 确保不是墙壁且不超出上边界
if (map[player_y - 1][player_x] == 2) { // 如果上面是箱子
if (player_x > 0 && map[player_y - 1][player_x - 1] == 0) { // 确保箱子可以被推动
map[player_y][player_x] = 0; // 清除玩家当前位置
map[player_y - 1][player_x - 1] = 2; // 移动箱子
map[player_y - 1][player_x] = 4; // 更新玩家位置
player_y--; // 更新玩家的y坐标
box_y--; // 更新箱子的y坐标
}
} else {
map[player_y][player_x] = 0; // 清除玩家当前位置
map[player_y - 1][player_x] = 4; // 更新玩家位置
player_y--; // 更新玩家的y坐标
}
}
break;
case 3: // 向右移动
if (player_x < MAP_WIDTH - 1 && map[player_y][player_x + 1] != 1) { // 确保不是墙壁且不超出右边界
if (map[player_y][player_x + 1] == 2) { // 如果右边是箱子
if (player_y > 0 && map[player_y - 1][player_x + 1] == 0) { // 确保箱子可以被推动
map[player_y][player_x] = 0; // 清除玩家当前位置
map[player_y - 1][player_x + 1] = 2; // 移动箱子
map[player_y][player_x + 1] = 4; // 更新玩家位置
player_x++; // 更新玩家的x坐标
box_x++; // 更新箱子的x坐标
}
} else {
map[player_y][player_x] = 0; // 清除玩家当前位置
map[player_y][player_x + 1] = 4; // 更新玩家位置
player_x++; // 更新玩家的x坐标
}
}
break;
case 4: // 向下移动
if (player_y < MAP_HEIGHT - 1 && map[player_y + 1][player_x] != 1) { // 确保不是墙壁且不超出下边界
if (map[player_y + 1][player_x] == 2) { // 如果下边是箱子
if (player_x > 0 && map[player_y + 1][player_x - 1] == 0) { // 确保箱子可以被推动
map[player_y][player_x] = 0; // 清除玩家当前位置
map[player_y + 1][player_x - 1] = 2; // 移动箱子
map[player_y + 1][player_x] = 4; // 更新玩家位置
player_y++; // 更新玩家的y坐标
box_y++; // 更新箱子的y坐标
}
} else {
map[player_y][player_x] = 0; // 清除玩家当前位置
map[player_y + 1][player_x] = 4; // 更新玩家位置
player_y++; // 更新玩家的y坐标
}
}
break;
}
// 检查胜利条件
if (box_x == target_x && box_y == target_y) {
Display_Win(); // 显示胜利信息
}
// 更新显示
Display_Update(); // 更新游戏显示
}
}
}
// 显示更新函数
void Display_Update(void) {
Clear_Display(); // 清屏函数,根据你的显示设备实现
// 显示地图
for (int y = 0; y < MAP_HEIGHT; y++) {
for (int x = 0; x < MAP_WIDTH; x++) {
switch (map[y][x]) {
case 0: break; // 空白,不显示
case 1: Display_Box(x, y); break; // 箱子
case 2: Display_Target(x, y); break; // 目标位置
case 3: break; // 墙壁,不显示
case 4: Display_Player(x, y); break; // 玩家
}
}
}
}
// 清屏函数
void Clear_Display(void) {
// 清屏函数,根据你的显示设备实现
}
// 显示箱子函数
void Display_Box(int x, int y) {
// 绘制3x3全亮的LED表示箱子
for (int dy = -1; dy <= 1; dy++) {
for (int dx = -1; dx <= 1; dx++) {
Display_Char(x + dx, y + dy, 'O'); // 假设Display_Char函数可以显示单个字符
}
}
}
// 显示目标位置函数
void Display_Target(int x, int y) {
// 绘制3x3的"X"表示目标位置
for (int dy = -1; dy <= 1; dy++) {
for (int dx = -1; dx <= 1; dx++) {
if (abs(dx) + abs(dy) == 1) { // 绘制"X"形状
Display_Char(x + dx, y + dy, 'X');
}
}
}
}
// 显示玩家位置函数
void Display_Player(int x, int y) {
// 绘制3x3的空心框表示玩家位置
for (int dy = -1; dy <= 1; dy++) {
for (int dx = -1; dx <= 1; dx++) {
if (dx == -1 || dx == 1 || dy == -1 || dy == 1) { // 绘制边框
Display_Char(x + dx, y + dy, 'P');
}
}
}
}
// 显示字符函数
void Display_Char(int x, int y, char ch) {
// 显示字符函数,根据你的显示设备实现
}
// 显示胜利信息函数
void Display_Win(void) {
Clear_Display();
// 显示"WIN"字样
Display_Char(1, 1, 'W');
Display_Char(2, 1, 'I');
Display_Char(3, 1, 'N');
}
有几个问题是#include "Dot_Matrix.h" // 包含点阵屏的相关配置,这个头文件是在网上找的显示数字的代码,并不能实现其他功能
if (current_state != key_pressed) {
key_pressed = current_state;
if (key_pressed == GPIO_Pin_1) return 1; // PD1按下
if (key_pressed == GPIO_Pin_3) return 2; // PD3按下
if (key_pressed == GPIO_Pin_6) return 3; // PD6按下
if (key_pressed == GPIO_Pin_7) return 4; // PD7按下
}
这段代码不太懂return数字实现的什么
以下代码是待实现功能还未编写的函数
// 检查胜利条件
if (box_x == target_x && box_y == target_y) {
Display_Win(); // 显示胜利信息
}
// 更新显示
Display_Update(); // 更新游戏显示
}
// 显示更新函数
void Display_Update(void) {
Clear_Display(); // 清屏函数,根据你的显示设备实现
// 清屏函数
void Clear_Display(void) {
// 清屏函数,根据你的显示设备实现
Display_Char(x + dx, y + dy, 'O'); // 假设Display_Char函数可以显示单个字符,然而假设不成立
// 显示字符函数
void Display_Char(int x, int y, char ch) {
// 显示字符函数,根据你的显示设备实现
}
// 显示胜利信息函数
void Display_Win(void) {
Clear_Display();
// 显示"WIN"字样
Display_Char(1, 1, 'W');
Display_Char(2, 1, 'I');
Display_Char(3, 1, 'N');
}