C语言实现推箱子小游戏
一、设计目的
-
用简单的C语言知识制作的推箱子游戏,通过上下左右键将所有箱子移动到目标位置。
2.让我们更好地了解和巩固C语言知识,并实际运用,同时运用一些不太常见的知识点。
二、功能描述
1.模块功能
本程序可分为初始界面、进行游戏、判定通关三个模块。
-
初始界面模块:欢迎来到推箱子游戏,按方向键上下左右,可以实现方向,按->键进行游戏。
-
进行游戏:通过上下左右键控制人的上下左右来移动箱子,箱子只能向前推,不能向后面拉,游戏分为两关,完成第一关,按->建可进入下一关。
-
判定输赢模块:当所有箱子都推到目的地时,则游戏过关。当两关都通过时,会提示”恭喜你过关了”。
-
流程图
三.总体设计
(一)使用到的头文件
#include#include #include #include
以上为本程序中所用到的头文件,#include
#include
(二)宏定义
//宏定义数据 #define SPACE 0 //空地 #define WALL 1 //墙 #define DEST 2 //目的地 #define BOX 3 //箱子 #define PLAYER 4 //玩家 #define ROW 10 //行数 #define COL 10 //列数
#define 是宏定义,在程序预处理阶段将define定义的内容进行了替换,可以增加代码可读性
(三)初始界面
void menu()
{
printf("*********欢迎来到推箱子小游戏**********\n");
printf("***按方向键上下左右,可以实现移动方向***\n");
system("pause");
}
Menu()函数里写好初始界面,并用system(“pause”)暂停程序,点任意键继续,进入游戏。
功能模块设计
创建并绘制地图:用 代表空地,■代表墙,☆代表目的地,★代表箱子,人字代表人,进代表到达目的地的箱子。在此基础上用数组储存数据,三维数组来创建两个不同的地图,并通过图标代替数字实现地图绘制。
(四)初始化地图
//数组储存数据
//定义地图
int map[2][ROW][COL];
int level = 0;//当前所在关
//初始化地图
void initMap()
{
//临时数组
int temp[2][ROW][COL] =
{
{
{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,3,0,2,1,0},
{0,1,2,3,4,0,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,0,1,1,0,0,1,1,0,0},
{0,1,0,0,1,1,0,0,1,0},
{1,0,2,0,0,0,0,2,0,1},
{1,0,0,3,4,0,3,0,0,1},
{0,1,0,3,0,0,3,0,1,0},
{0,0,1,0,2,2,0,1,0,0},
{0,0,0,1,0,0,1,0,0,0},
{0,0,0,0,1,1,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0}
}
};
//把临时的数组赋值给map
memcpy(map, temp, sizeof(temp));
}
1.map[2][ROW][COL](ROW==10,COL==10)三维数组可有效实现多关卡设置,游戏设置了两个关卡。
2.void initMap()
此函数用来初始化地图,并定义了一个临时数组来绘制地图结构,并调用memcpy()函数赋值给map数组。
3.memcpy函数实现赋值操作(在程序中要引用#include
(五)输出地图
void show()
{
system("cls");//清屏
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
//把数据转为图形输出
switch (map[level][i][j])
{
case SPACE:
printf(" ");
break;
case WALL:
printf("■");
break;
case DEST:
printf("☆");
break;
case BOX:
printf("★");
break;
case PLAYER:
printf("人");
break;
case BOX + DEST://箱子在目的地上
printf("进");
break;
}
}
printf("\n");
}
}
void show()此函数内运用for循环和switch分支结构来绘制地图,将数据用指定图标代替,使地图更具有可观性。
(六)移动操作:通过人或人和箱子的移动来进行,系统接受用户输入的一个字符(按键)来控制人的走向 ,在允许的条件下推动箱子。
void move()
{
int r = -1, c = -1;
//查找玩家的位置并复制给r c
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
if (map[level][i][j] == PLAYER || map[level][i][j] == PLAYER + DEST)
{
r = i;
c = j;
goto end;
}
}
}
end:;
//获取按键操作
int key = _getch();
switch (key)
{
case 'W':
case 'w':
case 72://上
//只有人前面是空地或者目的地的时候才可以移动
// r c 是玩家当前所在的下标
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)
{//箱子前面是空地或者是目的地
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 - 1][c] -= PLAYER;
}
}
break;
case 80://下
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] == 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 75://左
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)
{//箱子前面是空地或者是目的地
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 77:
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)
{//箱子前面是空地或者是目的地
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;
}
}
void move():先运用for循环遍历数组来定位人物的位置,定位好之后,我们可以将玩家的值赋值给r,c,找到玩家的位置。在人物移动时我们运用到了switch循环和if循环。先用switch循环判定得到key的值,此值可以确定按键操作方向,我们可以在此基础上对人物进行移动再运用if结构对人物移动或人物移动带动箱子的移动进行判定,将人(箱子)移动到指定位置,再进行删除人(箱子)原来的位置,运用goto语句到指定语句,以此,我们能实现箱子的连贯性移动。
(七)判定通关:当箱子全部达到目的地,最后提示恭喜你过关了,判定通关。
//判断什么情况下过关
int judge()
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
if (map[level][i][j] == BOX)
{
return 0;
}
}
}
return 1;
}
1.int judge():函数内通过for循环和if结构判断途中是否还有箱子,并通过return返回0或1,1表示过关。
2.system("cls"):清屏操作。
四、游戏测试
//(完整代码) #define _CRT_SECURE_NO_WARNINGS 1 #include#include #include #include #include //宏定义数据 #define SPACE 0 //空地 #define WALL 1 //墙 #define DEST 2 //目的地 #define BOX 3 //箱子 #define PLAYER 4 //玩家 #define ROW 10 //行数 #define COL 10 //列数 void menu() { printf("*********欢迎来到推箱子小游戏**********\n"); printf("***按方向键上下左右,可以实现移动方向***\n"); system("pause"); } //数组储存数据 //定义地图 int map[2][ROW][COL]; //初始化地图 int level = 0;//当前所在关 void initMap() { //临时数组 int temp[2][ROW][COL] = { { {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,3,0,2,1,0}, {0,1,2,3,4,0,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,0,1,1,0,0,1,1,0,0}, {0,1,0,0,1,1,0,0,1,0}, {1,0,2,0,0,0,0,2,0,1}, {1,0,0,3,4,0,3,0,0,1}, {0,1,0,3,0,0,3,0,1,0}, {0,0,1,0,2,2,0,1,0,0}, {0,0,0,1,0,0,1,0,0,0}, {0,0,0,0,1,1,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0} } }; //把临时的数组赋值给map memcpy(map, temp, sizeof(temp)); } //输出地图 void show() { system("cls");//清屏 for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { //printf("%d", map[level][i][j]); //把数据转为图形输出 墙,人 switch (map[level][i][j]) { case SPACE: printf(" "); break; case WALL: printf("■"); break; case DEST: printf("☆"); break; case BOX: printf("★"); break; case PLAYER: printf("人"); break; case PLAYER+DEST: printf("出"); break; case BOX + DEST://箱子在目的地上//玩家站在空地上 printf("进"); break; } } printf("\n"); } } void move() { int r = -1, c = -1; //查找玩家的位置并复制给r c for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { if (map[level][i][j] == PLAYER|| map[level][i][j] == PLAYER+DEST) { r = i; c = j; goto end; } } } end:; //获取按键操作 int key = _getch(); switch (key) { case 72://上 //只有人前面是空地或者目的地的时候我才可以移动 // r c 是玩家当前所在的下标 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) {//箱子前面是空地或者是目的地 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 - 1][c] -= PLAYER; } } break; case 80://下 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] == 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 75://左 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) {//箱子前面是空地或者是目的地 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 77: 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) {//箱子前面是空地或者是目的地 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; } } //什么情况下过关 int judge() { for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { if (map[level][i][j] == BOX) { return 0; } } } return 1; } int main() { menu(); initMap(); show(); move(); while (1) { show(); if (judge()) { level++;//每过一关加一 if (level == 2) { printf("恭喜你过关了!"); break; } } move(); } return 0; }
五、程序实现
第一关初始地图界面
按↑↓←→时,人物会向上下左右移动
第一关:
第一关通关:
第二关:
第二关完成:
总结:
上面是简易推箱子小游戏,由于我自身能力还有待提升,写出这些代码对我来说有一定难度,在此过程中我通过上网课,不断查找资料写了这篇文章,代码可能还存在许多需要改进的地方,各位小伙伴们如果有时间的话可以对其进行优化,如果上述有错误的地方麻烦大家能够指正,同时也可以给我一些建议,这样我可以向各位优秀的伙伴学习,文章较长,感谢大家愿意发时间观看。
本文来自网络,不代表协通编程立场,如若转载,请注明出处:https://net2asp.com/f869a62b9d.html
