c语言实现推箱子小游戏
下面是实现推箱子小游戏的全部代码
这个推箱子小游戏采用文件操作,通过easy_x图形库实现了图形界面,相对来说更具有玩游戏的感觉,给人以视觉盛宴。
说笑了,好了大家可以好好的看一下源代码
本游戏所需的关卡文件在最后面,大家可以看一下
另外运行此小游戏,大家可能还需要安装easy_x图形库文件,这里我分享以下easy_x的安装文件链接,由于时间关系,本游戏只设计了三关,在闯关成功后,可以弹出闯关成功的提示
链接:https://pan.baidu.com/s/1zvMlFfLkKtU0sIwSS2KU2g
提取码:q3n8
1.推箱子总体概述
1.1游戏总体设计
此游戏本着娱乐为目的,游戏界面简单,操作容易,游戏者可以在游戏中锻炼反应速度与灵敏速度,在游戏中设置有关卡,级别由低到高,一关更比一关难。
1.2功能模块规划
在该游戏中共设计了三个模块:
(1)初始化模块,
对游戏界面进行初始化,包含两个函数,分别为GameInitMap函数,进行图片的加载,GamePaint,进行贴图,从而完成对地图的绘制,在此游戏中,不同的数字代表贴不同的图。
(2)游戏操作模块,
由GamePlay构成玩家通过对小人的操作使小人能够操作木箱到各个位置
(3)游戏判断模块,
由GameJudgement构成,通过对地图的遍历,观察是否有箱子未推到目的地,进行游戏是否结束的判断。
2程序说明
2.1 按钮设计
游戏中通过键盘输入来操作小人移动箱子完成游戏任务,键盘输入按钮及其效果如下
(1)上:通过按w或W或 来移动小人往上移动。
(1)下:通过按s或S或 来移动小人往下移动。
(1)左:通过按a或A或 来移动小人往左移动。
(1)右:通过按d或D或 来移动小人往右移动。
2.2地图的绘制形成—初始化模块
(1)二维数组数字的意义
地图是以二维数组的形式进行存储的,不同的数字有着不同的含义。我将0~9解读为不同的图形。
0代表地图内的空位;
1代表墙壁;
3’代表目的地;
4代表箱子;
5代表小人;
7代表箱子在目的地;
8代表人在目的地。
(2)加载图片与贴图
本游戏地图的绘制采用Easyx library进行游戏界面的加载与绘制,先声明IMAGE变量, loadimage函数用来进行图片的加载,然后用文件操作,从Map.txt读取地图信息,通过双层循环进行遍历,根据对应位置的Map二维数组的值来选择不同的图片进行贴图。
2.3游戏操作模块
2.3.1关卡设计
本游戏采用文件操作进行关卡的设计,地图信息存储在Map.txt文档中,当一个关卡通过判断通过时,地图通过文件操作进行更新,直到所有关卡完成,弹出闯关成功窗口。
关卡设计
2.3.2小人与箱子移动
本游戏移动只有正移动,小人上下移动归结起来是一个判断的算法。判断都是通过小人前面是否是空位,箱子,或者是墙。如果没有,就移动;有的话,在判断箱子是否可以移动。最后讨论箱子推过的,小移动的图形变化,重新绘制地图。:
2.4游戏判断模块
游戏通过双层for循环进行地图遍历,观察地图上是否有没有推到目的地的箱子,并返回结果,从而对这一关游戏与游戏是否结束进行判断,全部代码如下:
#include <stdio.h>
#include <conio.h> //控制台输入输出的头文件
#include <graphics.h> //头文件图形库
#include "resource.h"
int Map[8][8] = {
0, 0, 0, 1, 1, 1, 0, 0,
0, 0, 0, 1, 3, 1, 0, 0,
1, 1, 1, 1, 0, 1, 0, 0,
1, 3, 4, 0, 4, 1, 1, 1,
1, 1, 1, 5, 4, 0, 3, 1,
0, 0, 1, 4, 1, 1, 1, 1,
0, 0, 1, 3, 1, 0, 0, 0,
0, 0, 1, 1, 1, 0, 0, 0
};
void GameInitMap();//加载图片
void GamePaint(); //贴图
void GamePlay(); //操作
int GameJudgement(); //判断游戏是否结束
IMAGE BackImage, Wall; //背景 墙
IMAGE Box, dBox; //箱子 箱子推到目的地
IMAGE Point; //目的地
IMAGE Person; //人
void GameInitMap(int live) //给出关卡数 用来判断是第几关
{
loadimage(&BackImage, L"jpg",MAKEINTRESOURCE(101), 550, 550);//背景
loadimage(&Wall, L"jpg", MAKEINTRESOURCE(107), 69, 69);//墙壁
loadimage(&Box, L"jpg", MAKEINTRESOURCE(103), 69, 69);//箱子
loadimage(&Point, L"jpg", MAKEINTRESOURCE(106), 69, 69);//目的地
loadimage(&dBox, L"jpg", MAKEINTRESOURCE(104), 69, 69);//箱子到达目的地
loadimage(&Person, L"jpg", MAKEINTRESOURCE(105), 69, 69);//人物
FILE *fp = fopen("Map.txt", "r");
if (NULL == fp) //如果打开失败 异常处理
{
MessageBox(NULL, L"地图加载失败", NULL, NULL);
exit(0);
}
int FileOffset; // 文件的偏移
FileOffset = 66 * (live - 1);
fseek(fp, FileOffset, SEEK_SET);
int i, j;
char c;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
c = fgetc(fp);
Map[i][j] = c - '0';
}
}
fclose(fp); //关闭文件
}
void GamePaint()
{
for (int i = 0; i < 8; ++i)
{
for (int j = 0; j < 8; ++j)
{
switch (Map[j][i])
{
case 0: //空地
break;
case 1: //墙壁
putimage(69 * i, 69 * j, &Wall);
break;
case 3://目的地
putimage(69 * i, 69 * j, &Point);
break;
case 4://箱子
putimage(69 * i, 69 * j, &Box);
break;
case 5://人物
putimage(69 * i, 69 * j, &Person);
break;
case 7://箱子在目的地上
putimage(69 * i, 69 * j, &dBox);
break;
case 8://人物在目的地上
putimage(69 * i, 69 * j, &Person);
break;
}
}
}
}
/*
0 空地
1 墙壁
3 目的地
4 箱子
5 人物
7 箱子在目的地
8 人在目的
*/
int GameJudgement()
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
if (Map[i][j] == 4) //判断 有没有落在空地上的箱子
{
return 1; //游戏还没有结束
}
}
}
return 0;
}
void GamePlay()
{
char ch; //用来获取键盘输入的信息
int x, y; //描述当前坐标
int live = 1; //描述关卡
GameInitMap(live); //贴图
while (true)
{
BeginBatchDraw();
cleardevice();
putimage(0, 0, &BackImage);
if (!GameJudgement()) //判断 每一关是否玩完了
{
live++; // 进入下一关
if (4 == live) //
{
GamePaint();// 绘图
FlushBatchDraw(); //批量绘图 防闪屏
MessageBox(GetHWnd(), L"闯关成功\r\n", L"闯关提示", MB_OK);
// 弹出对话框
FlushBatchDraw();
Sleep(5000);
closegraph(); //关闭窗口
exit(0); //结束程序
}
GameInitMap(live);
}
//批量绘图结束
GamePaint();
EndBatchDraw();
for (x = 0; x < 8; x++)
{
for (y = 0; y < 8; y++)
{ //如果人在目的地 或者 人在空地
if (Map[x][y] == 5 || Map[x][y] == 8)
{
break;
}
}
if (Map[x][y] == 5 || Map[x][y] == 8)
{
break;
}
}
ch = getch(); //获取键盘消息
//人在 Map[x][y]
switch (ch)
{
case 'w':
case 'W':
case 72://向上
if (Map[x - 1][y] == 0 || Map[x - 1][y] == 3)
{
Map[x][y] -= 5;
Map[x - 1][y] += 5;
}
else if (Map[x - 1][y] == 4 || Map[x - 1][y] == 7)
{
if (Map[x - 2][y] == 0 || Map[x - 2][y] == 3)
{
Map[x - 2][y] += 4;
Map[x - 1][y] += 1;
Map[x][y] -= 5;
}
}
break;
case 'a':
case 'A':
case 75://向左
if (Map[x][y - 1] == 0 || Map[x][y - 1] == 3)
{
Map[x][y] -= 5;
Map[x][y - 1] += 5;
}
else if (Map[x][y - 1] == 4 || Map[x][y - 1] == 7)
{
if (Map[x][y - 2] == 0 || Map[x][y - 2] == 3)
{
Map[x][y - 2] += 4;
Map[x][y - 1] += 1;
Map[x][y] -= 5;
}
}
break;
case 's':
case 'S':
case 80: // 往下
if (Map[x + 1][y] == 0 || Map[x + 1][y] == 3)
{
Map[x][y] -= 5;
Map[x + 1][y] += 5;
}
else if (Map[x + 1][y] == 4 || Map[x + 1][y] == 7)
{
if (Map[x + 2][y] == 0 || Map[x + 2][y] == 3)
{
Map[x + 2][y] += 4;
Map[x + 1][y] += 1;
Map[x][y] -= 5;
}
}
break;
case 'd':
case 'D':
case 77: //往右
if (Map[x][y + 1] == 0 || Map[x][y + 1] == 3)
{
Map[x][y] -= 5;
Map[x][y + 1] += 5;
}
else if (Map[x][y + 1] == 4 || Map[x][y + 1] == 7)
{
if (Map[x][y + 2] == 0 || Map[x][y + 2] == 3)
{
Map[x][y + 2] += 4;
Map[x][y + 1] += 1;
Map[x][y] -= 5;
}
}
break;
}
}
}
int main()
{
initgraph(550, 550);
GamePlay();
return 0;
}
关卡文件的配置
请在项目文件下建立 “地图Map.txt"文件,并将下面内容复制进去
0001110000013100111101001340411111154031001411110013100000111000
0111111101000001010343011104540110034301100000011111111100000000
0111100001001000010310001145100010401111100300011111000100011111