使用C语言实现超简单的推箱子游戏!
感谢您打开了这篇文章,下面我将讲述一下推箱子是如何实现的。
如果您喜欢我的文章可以点赞支持一下。
如果您对我的程序有什么意见和建议欢迎在评论区发表评论。
另外附赠适配该程序简单好用 专属推箱子地图编辑器 让您在16 * 16大地图的条件下也能轻松编辑地图。
链接:地图编辑器
本程序在没有检测到地图文件的情况下也能独自运行!代码中储存了推箱子游戏第一关的标准地图,让您在没有地图文件的情况下也能熟悉整个程序的流程!
当然,拥有地图文件会也会获得更好的游戏体验,请自行编辑。
废话不多说!
下面进入技术环节:
C语言版 多功能推箱子
编译环境: Windows VS2019
其他编译器,可通过查看下文的“注意事项”将代码更正为其他平台可正常版本
需求:
控制人物将箱子推至目标中,目标全部完成进入下一关。
思路:
使用二维数组储存不同数字,数字包括了地图中所有的元素,通过按键控制人物完成推箱子的操作,达成关卡内的所有目标后,自动进入下一关。
做法:
主要逻辑移动推箱子部分:按下方向键后,双重循环找到人物,根据移动方向储存 人物、人物前面、箱子、箱子前面四大基础信息,并通过判断前方数组值是否是墙壁、目标等,进行人物移动和箱子移动操作。
具体详细做法我已经整理到了代码注释当中,以便一一对应查看。
使用到知识点:
循环、二维数组、读取文件
难点:
在人物和箱子移动的同时,有需要注意当人物移动到了未完成目标或已完成目标、箱子移动到了已完成目标的情况,这种情况需要判断在人物/箱子离开之后,原地又再次变为原元素。
说明:
程序前部分有较多代码用于写出未检测到文件的情况逻辑和关卡选择逻辑,如果要直接查看核心代码请移动到operation();操作人物函数和gbszszhs(char ch);修改二维数组函数。
注意:
由于编译器原因,程序中_kbhit()和_getch()函数可能在其他编译器上编译会出现错误,解决办法是去掉函数前面的“_”。
同时,要将 文件打开函数fopen_s(&fp, FLPA, “r”);更改为fp = fopen(FLPA, “r”);
fcanf_s更改为fcanf scanf_s()更改为scanf
运行效果:
菜单选择:
游戏进行:
代码实现:
#include <stdio.h>
#include <windows.h>
#include <conio.h>
//0代表空地,1代表墙,2代表未达成的目标,3代表箱子,4代表玩家,5代表已放箱子的目标,
//6代表人暂时所在的未达成的目标,7代表人暂时所在的已达成的目标,8代表箱子暂时所在的已达成的目标
#define WH 16 //地图的宽高
#define BYT 529 //一关需要跳过的字数 因为文件指针定位函数的原因,有时定位可能会不准确,可以通过修改BYT进行适配
#define FLPA "C:\\Users\\ASUS\\Desktop\\推箱子地图.txt" //需要读取地图文件的路径 游戏之前需进行设置!!
//找不到路径将只能进行第一关游戏
//注意:游戏地图边界 不可以 当做墙壁使用!
#define INITMAP \
int mapch_init[WH][WH] = { \
{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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
{0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, \
{0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0}, \
{0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0}, \
{0, 0, 0, 0, 1, 1, 1, 3, 0, 3, 2, 1, 0, 0, 0, 0}, \
{0, 0, 0, 0, 1, 2, 0, 3, 4, 1, 1, 1, 0, 0, 0, 0}, \
{0, 0, 0, 0, 1, 1, 1, 1, 3, 1, 0, 0, 0, 0, 0, 0}, \
{0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0}, \
{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, 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, 0, 0, 0, 0}, \
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
};
int mapch[WH][WH];
//所有函数之间不是独立和顺序的,会互相调用
void HideCursor(); //隐藏光标
void gotoxy(int x, int y);//光标定位
void scmbxyhs(); //输出地图下方文字信息函数
void wjzdwjzjjrqk(); //未找到文件直接进入第一关情况
int gkxzhs(); //关卡选择函数
void cwjzjrwkdhs(); //从文件中进入关卡的函数
void gnxzjm(); //主菜单选择
void cshhs(); //初始化函数
void tranmap(); //翻译并画出地图
void detection(); //寻找所有该地图中未完成的目标
void gktgszxhs(); //判断关卡是否通过,是进行下一关卡
void operation(); //操作人物主要函数***
void gbszszhs(char ch); //改变数组数值函数
int updatetime(); //获取一次电脑现在的时间
void process(); //主要流程
int main()
{
cshhs(); //初始化函数
process(); //主要流程
return 0;
}
//游戏开始初始化部分
void scmbxyhs() //输出地图提示信息函数
{
gotoxy(34, 17);
printf("本关剩余目标数:");
gotoxy(34, 19);
printf("本关已走步数:");
gotoxy(32, 21);
printf("您使用 秒完成了本关!");
gotoxy(49, 19);
printf("0"); //输出初始的步数0
}
void wjzdwjzjjrqk() //未找到文件直接进入第一关情况
{
system("cls");
printf("地图文件不存在,\n直接进入第一关");
INITMAP //初始地图数组
for (int i = 0; i < WH; i ) //如果地图文件不存在则将初始地图数组的值赋给需要使用的地图
for (int j = 0; j < WH; j ) //将初始地图数组的值复制给当前地图数组
mapch[i][j] = mapch_init[i][j];
Sleep(2000); //等待两秒进入第一关
system("cls"); //清屏
tranmap(); //画出初始地图
detection(); //目标信息
scmbxyhs(); //输出地图下方文字信息
}
int n = 1; //输入关卡变量**
int maxn = 0; //最大关数
int dczdgshs() //最大关数
{
FILE* fp = NULL; //因为用于提示和限制输入情况,所以需要得到最大关卡数maxn
fopen_s(&fp, FLPA, "r");
if (fp == NULL)
{
wjzdwjzjjrqk();