900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > c 语言推箱子vs C语言推箱子小游戏教程

c 语言推箱子vs C语言推箱子小游戏教程

时间:2021-05-19 11:14:25

相关推荐

c 语言推箱子vs C语言推箱子小游戏教程

作者GitHub-Pages个人主页

本教程GitHub-Pages链接

本教程百度云下载地址

本教程编写于/11/22

Dawson Lee edited this page on Beijing, /7/3

设计思路

将整个画面分成13*16的矩阵,每个元素对应者一个小矩形。然后用0代表黑格,1代表白墙,2代表蓝格……,这样就有了整幅图像的信息。然后移动就可以想象成,改变矩阵的坐标信息,形成一个新的矩阵,再重绘。这就是推箱子的基本原理。

#define BLACK 0 //黑格:用于填充图像

#define WHITEWALL 1 //白墙:用于阻挡主角移动

#define BLUEWALL 2 //蓝格:用于表示可移动空间

#define BALL 3 //点:用于指定箱子放置位置

#define BOX 4 //箱子:用于表示初始箱子位置

#define REDBOX 5 //变色的箱子:用于表示这个点位置已经放置箱子

#define MAN 6 //主角:用于表示主角位置

#define MANBALL 7 //主角站在点上

设计思路

步骤

Tip:

您也可以自行百度或者google Visual Studio Community 的其它下载途径

您也可以尝试使用Visual Studio其它版本,但有可能会出现未知问题

2.要给VS安装EGE图形库

3.要参考EGE图形库帮助文档

Tip:如果链接失效,请自行百度或者google"EGE图形库帮助文档"

4.刚才我们说到,图像的背后对应着一个矩阵,我们可以考虑将矩阵的信息存储在一个MAP.txt文件中,在程序运行时读取。下面我来介绍,在文件中读取一个矩阵。

首先我们得有一个TXT文件:MAP.txt(一定确保路径放置正确),它存储着这样一个13*16的矩阵

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 1 1 1 1 1 1 1 0 0 0

0 0 0 1 2 2 2 2 2 2 2 2 1 0 0 0

0 0 0 1 2 2 2 2 2 2 2 2 1 0 0 0

0 0 0 1 2 6 2 4 2 3 2 2 1 0 0 0

0 0 0 1 2 2 2 2 2 2 2 2 1 0 0 0

0 0 0 1 2 2 2 2 2 2 2 2 1 0 0 0

0 0 0 1 2 2 2 2 2 2 2 2 1 0 0 0

0 0 0 1 1 1 1 1 1 1 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

文本文件中的矩阵读取操作源代码:

#include

#include

int main()

{

FILE *fp = fopen("MAP.txt", "rb");//以只读形式打开文件MAP.txt

if (!fp) {

printf("打开文件失败,文件位置你可能放错了\n");

exit(1);

}

int map[13][16];//创建一个map数组用来存储矩阵信息

int i, j;

char str[10];//用于存储从文本文件读取的字符串信息

for (i = 0; i<13; i++)

for (j = 0; j < 16; j++) {

fscanf(fp, "%s", str); //从文件中读取一个字符串,遇到空格结束

map[i][j] = atoi(str);//将字符串转变为整型,并赋值给map[i][j]

}

for (i = 0; i < 13; i++) {

for (j = 0; j < 16; j++) {

printf("%d", map[i][j]);//遍历输出矩阵信息

}

printf("\n");

}

return 0;

}

接下我们要把TXT文件的读取矩阵的功能,写在一个readmap()函数中,实现功能的模块化。并加多一项功能,就是查找出,MAN的位置。

//map[13][16]是形参,其中&man_i表是的是man_i的引用,引用传递的意义在于:传入参数会因函数中的操作而改变

int readmap(int map[13][16], int &man_i, int &man_j)

{

FILE *fp = fopen("MAP.txt", "rb");//以只读形式打开文件MAP.txt

if (!fp) {

printf("打开文件失败,文件位置你可能放错了\n");

exit(1);//打开失败则结束程序

}

int i, j;

char str[10];//用于存储从文本文件读取的字符串信息

for (i = 0; i<13; i++)

for (j = 0; j < 16; j++)

{

fscanf(fp, "%s", str); //从文件中读取一个字符串,遇到空格结束

map[i][j] = atoi(str);//将字符串转变为整型,并赋值给map[i][j]

if (map[i][j] == MAN) //如果找到了MAN的位置,则返回坐标在 man_i和 man_j 中

{

man_i = i;

man_j = j;

}

}

return 0;

}

5.接下来我们实现在窗口中,把矩阵信息转变成图像。原理就是,将图片贴在窗口上。

图片资源pic.zip(把当中的pic文件夹解压,存放在正确路径中,如果路径不正确会导致窗口中没有图像)

实现的效果如图所示:

效果图-无背景

绘制操作的源代码:

#include

#include

#include

#define BLACK 0 //黑格:用于填充图像

#define WHITEWALL 1 //白墙:用于阻挡主角移动

#define BLUEWALL 2 //蓝格:用于表示可移动空间

#define BALL 3 //点:用于指定箱子放置位置

#define BOX 4 //箱子:用于表示初始箱子位置

#define REDBOX 5 //变色的箱子:用于表示这个点位置已经放置箱子

#define MAN 6 //主角:用于表示主角位置

#define MANBALL 7 //主角站在点上

int main()

{

int map[13][16];//创建一个map数组用来存储矩阵信息

int man_i, man_j;//用来存储人物的位置信息

int readmap(int map[13][16], int &man_x, int &man_y);//声明

void darm(int a, int ii, int jj);//声明

readmap(map, man_i, man_j);//调用readmap()函数。

initgraph(800, 650);//生成一个宽800,高650的窗口。假设矩阵元素对应的每个小矩形是50*50的,那个窗口就应该是这么大。

for (int i = 0; i<13; i++)

for (int j = 0; j < 16; j++)

{

darm(map[i][j], i, j);//遍历绘制每个小矩形

}

getch();//等待一个键盘输入,如果没有的话,窗口会看不到,因为程序运行结束就会关闭窗口。生成关闭就转瞬即逝

closegraph();//关闭窗口

return 0;

}

//map[13][16]是形参,其中&man_i表是的是man_i的引用,引用传递的意义在于:传入参数会因函数中的操作而改变

int readmap(int map[13][16], int &man_i, int &man_j)

{

FILE *fp = fopen("MAP.txt", "rb");//以只读形式打开文件MAP.txt

if (!fp) {

printf("打开文件失败,文件位置你可能放错了\n");

exit(1);//打开失败则结束程序

}

int i, j;

char str[10];//用于存储从文本文件读取的字符串信息

for (i = 0; i<13; i++)

for (j = 0; j < 16; j++)

{

fscanf(fp, "%s", str); //从文件中读取一个字符串,遇到空格结束

map[i][j] = atoi(str);//将字符串转变为整型,并赋值给map[i][j]

if (map[i][j] == MAN) //如果找到了MAN的位置,则返回坐标在 man_i和 man_j 中

{

man_i = i;

man_j = j;

}

}

return 0;

}

/*

下面是在图形库绘制小矩形中图像的功能模块

这部分涉及C++中的知识,C语言新手不必过多纠结不懂的东西。但要知道,创建的源文件要是cpp格式的

*/

void darm(int a, int ii, int jj)

{

PIMAGE img;//声明

img = newimage();//实例化

switch (a)

{

case BLACK:break;

case WHITEWALL:

{

getimage(img, "pic/墙.jpg");//getimage()和putimage请翻阅ege图形库帮助手册。

putimage(jj * 50, ii * 50, img);//在ii行jj列绘制一个50*50像素的矩形图像

break;

}

case BLUEWALL:

{

getimage(img, "pic/路.jpg");

putimage(jj * 50, ii * 50, img);

break;

}

case BALL:

{

getimage(img, "pic/目的地.png");

putimage(jj * 50, ii * 50, img);

break;

}

case BOX:

{

getimage(img, "pic/箱子.png");

putimage(jj * 50, ii * 50, img);

break;

}

case MAN:

{

getimage(img, "pic/人.jpg");

putimage(jj * 50, ii * 50, img);

break;

}

case MANBALL:

{

getimage(img, "pic/人.jpg");

putimage(jj * 50, ii * 50, img);

break;

}

case REDBOX:

{

getimage(img, "pic/红箱子.png");

putimage(jj * 50, ii * 50, img);

break;

}

}

ege::delimage(img);

}

6.实现图像的绘制以后那我们就应该实现图像的移动了。

向右移动

首先将所有的情况列举出来并存入数组table[i][0]中,将改变后的第一个格子信息存在table[i][1]中,第二个格子信息存在table[i][2]中,第三个格子信息存在table[i][3]中。

数组table

然后就可以开始写move()函数,实现MAN的移动。move()函数源代码

/*

传入函数的参数 get表示用户输入的键盘按键,传入实时数组map的信息,传入实时MAN的位置信息man_i,man_j。

*/

void move(char get, int map[13][16], int &man_i, int &man_j)

{

//首先把情况的变化存在table[12][4]数组中

int table[12][4];

table[0][0] = MAN * BLUEWALL;

table[1][0] = MAN * BALL;

table[2][0] = MAN * BOX * BLUEWALL;

table[3][0] = MAN * BOX * BALL;

table[4][0] = MAN * REDBOX * BLUEWALL;

table[5][0] = MAN * REDBOX * BALL;

table[6][0] = MANBALL * BLUEWALL;

table[7][0] = MANBALL * BALL;

table[8][0] = MANBALL * BOX * BLUEWALL;

table[9][0] = MANBALL * BOX * BALL;

table[10][0] = MANBALL * REDBOX * BLUEWALL;

table[11][0] = MANBALL * REDBOX * BALL;

table[0][1] = BLUEWALL;

table[1][1] = BLUEWALL;

table[2][1] = BLUEWALL;

table[3][1] = BLUEWALL;

table[4][1] = BLUEWALL;

table[5][1] = BLUEWALL;

table[6][1] = BALL;

table[7][1] = BALL;

table[8][1] = BALL;

table[9][1] = BALL;

table[10][1] = BALL;

table[11][1] = BALL;

table[0][2] = MAN;

table[1][2] = MANBALL;

table[2][2] = MAN;

table[3][2] = MAN;

table[4][2] = MANBALL;

table[5][2] = MANBALL;

table[6][2] = MAN;

table[7][2] = MANBALL;

table[8][2] = MAN;

table[9][2] = MAN;

table[10][2] = MANBALL;

table[11][2] = MANBALL;

table[0][3] = -1;

table[1][3] = -1;

table[2][3] = BOX;

table[3][3] = REDBOX;

table[4][3] = BOX;

table[5][3] = REDBOX;

table[6][3] = -1;

table[7][3] = -1;

table[8][3] = BOX;

table[9][3] = REDBOX;

table[10][3] = BOX;

table[11][3] = REDBOX;

int i;

void darm(int a, int ii, int jj);//要用到绘制函数,所以先声明

switch (get)//switch判断用户输入的键盘信息

{

case 37: //左移,向左键的ASCII码

//for循环遍历判断MAN向左移动对应的是哪种情况

for (i = 0; i < 12; i++)

if (map[man_i][man_j] * map[man_i][man_j - 1] * map[man_i][man_j - 2] == table[i][0] ||

map[man_i][man_j] * map[man_i][man_j - 1] == table[i][0])

{

//找到对应的情况后执行以下语句

map[man_i][man_j] = table[i][1];

map[man_i][man_j - 1] = table[i][2];

if (table[i][3] != -1)map[man_i][man_j - 2] = table[i][3];//如果不需要改变第三个格子的图像,就不赋值。也就是如果table[i][3]==-1时。

//遍历绘制对应的三个格子信息

darm(map[man_i][man_j], man_i, man_j);

darm(map[man_i][man_j - 1], man_i, man_j - 1);

darm(map[man_i][man_j - 2], man_i, man_j - 2);

man_j--;//绘制结束后,要改变MAN的实时位置信息,并break跳出循环

break;

}

break;//再次break跳出switch语句

case 38://上移,向上键的ASCII码

//for循环遍历判断MAN向上移动对应的是哪种情况

for (i = 0; i < 12; i++)

if (map[man_i][man_j] * map[man_i - 1][man_j] * map[man_i - 2][man_j] == table[i][0] ||

map[man_i][man_j] * map[man_i - 1][man_j] == table[i][0])

{

map[man_i][man_j] = table[i][1];

map[man_i - 1][man_j] = table[i][2];

if (table[i][3] != -1)map[man_i - 2][man_j] = table[i][3];

darm(map[man_i][man_j], man_i, man_j);

darm(map[man_i - 1][man_j], man_i - 1, man_j);

darm(map[man_i - 2][man_j], man_i - 2, man_j);

man_i--;

break;

}

break;

case 39://右移,向右键的ASCII码

//for循环遍历判断MAN向右移动对应的是哪种情况

for (i = 0; i < 12; i++)

if (map[man_i][man_j] * map[man_i][man_j + 1] * map[man_i][man_j + 2] == table[i][0] ||

map[man_i][man_j] * map[man_i][man_j + 1] == table[i][0])

{

map[man_i][man_j] = table[i][1];

map[man_i][man_j + 1] = table[i][2];

if (table[i][3] != -1)map[man_i][man_j + 2] = table[i][3];

darm(map[man_i][man_j], man_i, man_j);

darm(map[man_i][man_j + 1], man_i, man_j + 1);

darm(map[man_i][man_j + 2], man_i, man_j + 2);

man_j++;

break;

}

break;

case 40://下移,向下键的ASCII码

//for循环遍历判断MAN向下移动对应的是哪种情况

for (i = 0; i < 12; i++)

if (map[man_i][man_j] * map[man_i + 1][man_j] * map[man_i + 2][man_j] == table[i][0] ||

map[man_i][man_j] * map[man_i + 1][man_j] == table[i][0])

{

map[man_i][man_j] = table[i][1];

map[man_i + 1][man_j] = table[i][2];

if (table[i][3] != -1)map[man_i + 2][man_j] = table[i][3];

darm(map[man_i][man_j], man_i, man_j);

darm(map[man_i + 1][man_j], man_i + 1, man_j);

darm(map[man_i + 2][man_j], man_i + 2, man_j);

man_i++;

break;

}

break;

default:

break;

}

}

写好move()函数后,我们就可以实现推箱子的功能了。整合后的源代码:

#include

#include

#include

#define BLACK 0 //黑格:用于填充图像

#define WHITEWALL 1 //白墙:用于阻挡主角移动

#define BLUEWALL 2 //蓝格:用于表示可移动空间

#define BALL 3 //点:用于指定箱子放置位置

#define BOX 4 //箱子:用于表示初始箱子位置

#define REDBOX 5 //变色的箱子:用于表示这个点位置已经放置箱子

#define MAN 6 //主角:用于表示主角位置

#define MANBALL 7 //主角站在点上

int main()

{

int map[13][16];//创建一个map数组用来存储矩阵信息

int man_i, man_j;//用来存储人物的位置信息

int readmap(int map[13][16], int &man_x, int &man_y);

void darm(int a, int ii, int jj);

readmap(map, man_i, man_j);//调用readmap()函数。

initgraph(800, 650);//生成一个宽800,高650的窗口。假设矩阵元素对应的每个小矩形是50*50的,那个窗口就应该是这么大。

for (int i = 0; i<13; i++)

for (int j = 0; j < 16; j++)

{

darm(map[i][j], i, j);//遍历绘制每个小矩形

}

void move(char get, int map[13][16], int &man_i, int &man_j);

char get;

for (; is_run(); delay_fps(60))//is_run()表示窗口一直显示,delay_fps(60)表示窗口以60帧的频率刷新

{

get = getch();//等待用户输入键盘按键

move(get, map, man_i, man_j);

}

closegraph();//关闭窗口

return 0;

}

//map[13][16]是形参,其中&man_i表是的是man_i的引用,引用传递的意义在于:传入参数会因函数中的操作而改变

int readmap(int map[13][16], int &man_i, int &man_j)

{

FILE *fp = fopen("MAP.txt", "rb");//以只读形式打开文件MAP.txt

if (!fp) {

printf("打开文件失败,文件位置你可能放错了\n");

exit(1);//打开失败则结束程序

}

int i, j;

char str[10];//用于存储从文本文件读取的字符串信息

for (i = 0; i<13; i++)

for (j = 0; j < 16; j++)

{

fscanf(fp, "%s", str); //从文件中读取一个字符串,遇到空格结束

map[i][j] = atoi(str);//将字符串转变为整型,并赋值给map[i][j]

if (map[i][j] == MAN) //如果找到了MAN的位置,则返回坐标在 man_i和 man_j 中

{

man_i = i;

man_j = j;

}

}

return 0;

}

/*

下面是在图形库绘制小矩形中图像的功能模块

这部分涉及C++中的知识,C语言新手不必过多纠结不懂的东西。但要知道,创建的源文件要是cpp格式的

*/

void darm(int a, int ii, int jj)

{

PIMAGE img;//声明

img = newimage();//实例化

switch (a)

{

case BLACK:break;

case WHITEWALL:

{

getimage(img, "pic/墙.jpg");//getimage()和putimage请翻阅ege图形库帮助手册。

putimage(jj * 50, ii * 50, img);//在ii行jj列绘制一个50*50像素的矩形图像

break;

}

case BLUEWALL:

{

getimage(img, "pic/路.jpg");

putimage(jj * 50, ii * 50, img);

break;

}

case BALL:

{

getimage(img, "pic/目的地.png");

putimage(jj * 50, ii * 50, img);

break;

}

case BOX:

{

getimage(img, "pic/箱子.png");

putimage(jj * 50, ii * 50, img);

break;

}

case MAN:

{

getimage(img, "pic/人.jpg");

putimage(jj * 50, ii * 50, img);

break;

}

case MANBALL:

{

getimage(img, "pic/人.jpg");

putimage(jj * 50, ii * 50, img);

break;

}

case REDBOX:

{

getimage(img, "pic/红箱子.png");

putimage(jj * 50, ii * 50, img);

break;

}

}

ege::delimage(img);

}

/*

传入函数的参数 get表示用户输入的键盘按键,传入实时数组map的信息,传入实时MAN的位置信息man_i,man_j。

*/

void move(char get, int map[13][16], int &man_i, int &man_j)

{

//首先把情况的变化存在table[12][4]数组中

int table[12][4];

table[0][0] = MAN * BLUEWALL;

table[1][0] = MAN * BALL;

table[2][0] = MAN * BOX * BLUEWALL;

table[3][0] = MAN * BOX * BALL;

table[4][0] = MAN * REDBOX * BLUEWALL;

table[5][0] = MAN * REDBOX * BALL;

table[6][0] = MANBALL * BLUEWALL;

table[7][0] = MANBALL * BALL;

table[8][0] = MANBALL * BOX * BLUEWALL;

table[9][0] = MANBALL * BOX * BALL;

table[10][0] = MANBALL * REDBOX * BLUEWALL;

table[11][0] = MANBALL * REDBOX * BALL;

table[0][1] = BLUEWALL;

table[1][1] = BLUEWALL;

table[2][1] = BLUEWALL;

table[3][1] = BLUEWALL;

table[4][1] = BLUEWALL;

table[5][1] = BLUEWALL;

table[6][1] = BALL;

table[7][1] = BALL;

table[8][1] = BALL;

table[9][1] = BALL;

table[10][1] = BALL;

table[11][1] = BALL;

table[0][2] = MAN;

table[1][2] = MANBALL;

table[2][2] = MAN;

table[3][2] = MAN;

table[4][2] = MANBALL;

table[5][2] = MANBALL;

table[6][2] = MAN;

table[7][2] = MANBALL;

table[8][2] = MAN;

table[9][2] = MAN;

table[10][2] = MANBALL;

table[11][2] = MANBALL;

table[0][3] = -1;

table[1][3] = -1;

table[2][3] = BOX;

table[3][3] = REDBOX;

table[4][3] = BOX;

table[5][3] = REDBOX;

table[6][3] = -1;

table[7][3] = -1;

table[8][3] = BOX;

table[9][3] = REDBOX;

table[10][3] = BOX;

table[11][3] = REDBOX;

int i;

void darm(int a, int ii, int jj);//要用到绘制函数,所以先声明

switch (get)//switch判断用户输入的键盘信息

{

case 37: //左移,向左键的ASCII码

//for循环遍历判断MAN向左移动对应的是哪种情况

for (i = 0; i < 12; i++)

if (map[man_i][man_j] * map[man_i][man_j - 1] * map[man_i][man_j - 2] == table[i][0] ||

map[man_i][man_j] * map[man_i][man_j - 1] == table[i][0])

{

//找到对应的情况后执行以下语句

map[man_i][man_j] = table[i][1];

map[man_i][man_j - 1] = table[i][2];

if (table[i][3] != -1)map[man_i][man_j - 2] = table[i][3];//如果不需要改变第三个格子的图像,就不赋值。也就是如果table[i][3]==-1时。

//遍历绘制对应的三个格子信息

darm(map[man_i][man_j], man_i, man_j);

darm(map[man_i][man_j - 1], man_i, man_j - 1);

darm(map[man_i][man_j - 2], man_i, man_j - 2);

man_j--;//绘制结束后,要改变MAN的实时位置信息,并break跳出循环

break;

}

break;//再次break跳出switch语句

case 38://上移,向上键的ASCII码

//for循环遍历判断MAN向上移动对应的是哪种情况

for (i = 0; i < 12; i++)

if (map[man_i][man_j] * map[man_i - 1][man_j] * map[man_i - 2][man_j] == table[i][0] ||

map[man_i][man_j] * map[man_i - 1][man_j] == table[i][0])

{

map[man_i][man_j] = table[i][1];

map[man_i - 1][man_j] = table[i][2];

if (table[i][3] != -1)map[man_i - 2][man_j] = table[i][3];

darm(map[man_i][man_j], man_i, man_j);

darm(map[man_i - 1][man_j], man_i - 1, man_j);

darm(map[man_i - 2][man_j], man_i - 2, man_j);

man_i--;

break;

}

break;

case 39://右移,向右键的ASCII码

//for循环遍历判断MAN向右移动对应的是哪种情况

for (i = 0; i < 12; i++)

if (map[man_i][man_j] * map[man_i][man_j + 1] * map[man_i][man_j + 2] == table[i][0] ||

map[man_i][man_j] * map[man_i][man_j + 1] == table[i][0])

{

map[man_i][man_j] = table[i][1];

map[man_i][man_j + 1] = table[i][2];

if (table[i][3] != -1)map[man_i][man_j + 2] = table[i][3];

darm(map[man_i][man_j], man_i, man_j);

darm(map[man_i][man_j + 1], man_i, man_j + 1);

darm(map[man_i][man_j + 2], man_i, man_j + 2);

man_j++;

break;

}

break;

case 40://下移,向下键的ASCII码

//for循环遍历判断MAN向下移动对应的是哪种情况

for (i = 0; i < 12; i++)

if (map[man_i][man_j] * map[man_i + 1][man_j] * map[man_i + 2][man_j] == table[i][0] ||

map[man_i][man_j] * map[man_i + 1][man_j] == table[i][0])

{

map[man_i][man_j] = table[i][1];

map[man_i + 1][man_j] = table[i][2];

if (table[i][3] != -1)map[man_i + 2][man_j] = table[i][3];

darm(map[man_i][man_j], man_i, man_j);

darm(map[man_i + 1][man_j], man_i + 1, man_j);

darm(map[man_i + 2][man_j], man_i + 2, man_j);

man_i++;

break;

}

break;

default:

break;

}

}

7.最后,我们给窗口载入一张完美的背景图片,至此就可以实现完整推箱子小游戏了。

实际效果图:

效果图-背景

最后整合的代码就是:

/*

作者:DawsonLee

Email:dawsonlee1790@

*/

#include

#include

#include

#define BLACK 0 //黑格:用于填充图像

#define WHITEWALL 1 //白墙:用于阻挡主角移动

#define BLUEWALL 2 //蓝格:用于表示可移动空间

#define BALL 3 //点:用于指定箱子放置位置

#define BOX 4 //箱子:用于表示初始箱子位置

#define REDBOX 5 //变色的箱子:用于表示这个点位置已经放置箱子

#define MAN 6 //主角:用于表示主角位置

#define MANBALL 7 //主角站在点上

int main()

{

int map[13][16];//创建一个map数组用来存储矩阵信息

int man_i, man_j;//用来存储人物的位置信息

int readmap(int map[13][16], int &man_x, int &man_y);

void darm(int a, int ii, int jj);

readmap(map, man_i, man_j);//调用readmap()函数。

initgraph(800, 650);//生成一个宽800,高650的窗口。假设矩阵元素对应的每个小矩形是50*50的,那个窗口就应该是这么大。

//载入一张漂亮的背景图片

PIMAGE imgui;

imgui = newimage();

getimage(imgui, "pic/背景.jpg");

putimage(0, 0, imgui);

for (int i = 0; i<13; i++)

for (int j = 0; j < 16; j++)

{

darm(map[i][j], i, j);//遍历绘制每个小矩形

}

void move(char get, int map[13][16], int &man_i, int &man_j);

char get;

for (; is_run(); delay_fps(60))//is_run()表示窗口一直显示,delay_fps(60)表示窗口以60帧的频率刷新

{

get = getch();//等待用户输入键盘按键

move(get, map, man_i, man_j);

}

closegraph();//关闭窗口

return 0;

}

int readmap(int map[13][16], int &man_i, int &man_j)//map[13][16]是形参,其中&man_i表是的是man_i的引用,引用传递的意义在于:传入参数会因函数中的操作而改变

{

FILE *fp = fopen("MAP.txt", "rb");//以只读形式打开文件MAP.txt

if (!fp) {

printf("打开文件失败,文件位置你可能放错了\n");

exit(1);//打开失败则结束程序

}

int i, j;

char str[10];//用于存储从文本文件读取的字符串信息

for (i = 0; i<13; i++)

for (j = 0; j < 16; j++)

{

fscanf(fp, "%s", str); //从文件中读取一个字符串,遇到空格结束

map[i][j] = atoi(str);//将字符串转变为整型,并赋值给map[i][j]

if (map[i][j] == MAN) //如果找到了MAN的位置,则返回坐标在 man_i和 man_j 中

{

man_i = i;

man_j = j;

}

}

return 0;

}

/*

下面是在图形库绘制小矩形中图像的功能模块

这部分涉及C++中的知识,C语言新手不必过多纠结不懂的东西。但要知道,创建的源文件要是cpp格式的

*/

void darm(int a, int ii, int jj)

{

PIMAGE img;//声明

img = newimage();//实例化

switch (a)

{

case BLACK:break;

case WHITEWALL:

{

getimage(img, "pic/墙.jpg");//getimage()和putimage请翻阅ege图形库帮助手册。

putimage(jj * 50, ii * 50, img);//在ii行jj列绘制一个50*50像素的矩形图像

break;

}

case BLUEWALL:

{

getimage(img, "pic/路.jpg");

putimage(jj * 50, ii * 50, img);

break;

}

case BALL:

{

getimage(img, "pic/目的地.png");

putimage(jj * 50, ii * 50, img);

break;

}

case BOX:

{

getimage(img, "pic/箱子.png");

putimage(jj * 50, ii * 50, img);

break;

}

case MAN:

{

getimage(img, "pic/人.jpg");

putimage(jj * 50, ii * 50, img);

break;

}

case MANBALL:

{

getimage(img, "pic/人.jpg");

putimage(jj * 50, ii * 50, img);

break;

}

case REDBOX:

{

getimage(img, "pic/红箱子.png");

putimage(jj * 50, ii * 50, img);

break;

}

}

ege::delimage(img);

}

/*

传入函数的参数 get表示用户输入的键盘按键,传入实时数组map的信息,传入实时MAN的位置信息man_i,man_j。

*/

void move(char get, int map[13][16], int &man_i, int &man_j)

{

//首先把情况的变化存在table[12][4]数组中

int table[12][4];

table[0][0] = MAN * BLUEWALL;

table[1][0] = MAN * BALL;

table[2][0] = MAN * BOX * BLUEWALL;

table[3][0] = MAN * BOX * BALL;

table[4][0] = MAN * REDBOX * BLUEWALL;

table[5][0] = MAN * REDBOX * BALL;

table[6][0] = MANBALL * BLUEWALL;

table[7][0] = MANBALL * BALL;

table[8][0] = MANBALL * BOX * BLUEWALL;

table[9][0] = MANBALL * BOX * BALL;

table[10][0] = MANBALL * REDBOX * BLUEWALL;

table[11][0] = MANBALL * REDBOX * BALL;

table[0][1] = BLUEWALL;

table[1][1] = BLUEWALL;

table[2][1] = BLUEWALL;

table[3][1] = BLUEWALL;

table[4][1] = BLUEWALL;

table[5][1] = BLUEWALL;

table[6][1] = BALL;

table[7][1] = BALL;

table[8][1] = BALL;

table[9][1] = BALL;

table[10][1] = BALL;

table[11][1] = BALL;

table[0][2] = MAN;

table[1][2] = MANBALL;

table[2][2] = MAN;

table[3][2] = MAN;

table[4][2] = MANBALL;

table[5][2] = MANBALL;

table[6][2] = MAN;

table[7][2] = MANBALL;

table[8][2] = MAN;

table[9][2] = MAN;

table[10][2] = MANBALL;

table[11][2] = MANBALL;

table[0][3] = -1;

table[1][3] = -1;

table[2][3] = BOX;

table[3][3] = REDBOX;

table[4][3] = BOX;

table[5][3] = REDBOX;

table[6][3] = -1;

table[7][3] = -1;

table[8][3] = BOX;

table[9][3] = REDBOX;

table[10][3] = BOX;

table[11][3] = REDBOX;

int i;

void darm(int a, int ii, int jj);//要用到绘制函数,所以先声明

switch (get)//switch判断用户输入的键盘信息

{

case 37: //左移,向左键的ASCII码

//for循环遍历判断MAN向左移动对应的是哪种情况

for (i = 0; i < 12; i++)

if (map[man_i][man_j] * map[man_i][man_j - 1] * map[man_i][man_j - 2] == table[i][0] ||

map[man_i][man_j] * map[man_i][man_j - 1] == table[i][0])

{

//找到对应的情况后执行以下语句

map[man_i][man_j] = table[i][1];

map[man_i][man_j - 1] = table[i][2];

if (table[i][3] != -1)map[man_i][man_j - 2] = table[i][3];//如果不需要改变第三个格子的图像,就不赋值。也就是如果table[i][3]==-1时。

//遍历绘制对应的三个格子信息

darm(map[man_i][man_j], man_i, man_j);

darm(map[man_i][man_j - 1], man_i, man_j - 1);

darm(map[man_i][man_j - 2], man_i, man_j - 2);

man_j--;//绘制结束后,要改变MAN的实时位置信息,并break跳出循环

break;

}

break;//再次break跳出switch语句

case 38://上移,向上键的ASCII码

//for循环遍历判断MAN向上移动对应的是哪种情况

for (i = 0; i < 12; i++)

if (map[man_i][man_j] * map[man_i - 1][man_j] * map[man_i - 2][man_j] == table[i][0] ||

map[man_i][man_j] * map[man_i - 1][man_j] == table[i][0])

{

map[man_i][man_j] = table[i][1];

map[man_i - 1][man_j] = table[i][2];

if (table[i][3] != -1)map[man_i - 2][man_j] = table[i][3];

darm(map[man_i][man_j], man_i, man_j);

darm(map[man_i - 1][man_j], man_i - 1, man_j);

darm(map[man_i - 2][man_j], man_i - 2, man_j);

man_i--;

break;

}

break;

case 39://右移,向右键的ASCII码

//for循环遍历判断MAN向右移动对应的是哪种情况

for (i = 0; i < 12; i++)

if (map[man_i][man_j] * map[man_i][man_j + 1] * map[man_i][man_j + 2] == table[i][0] ||

map[man_i][man_j] * map[man_i][man_j + 1] == table[i][0])

{

map[man_i][man_j] = table[i][1];

map[man_i][man_j + 1] = table[i][2];

if (table[i][3] != -1)map[man_i][man_j + 2] = table[i][3];

darm(map[man_i][man_j], man_i, man_j);

darm(map[man_i][man_j + 1], man_i, man_j + 1);

darm(map[man_i][man_j + 2], man_i, man_j + 2);

man_j++;

break;

}

break;

case 40://下移,向下键的ASCII码

//for循环遍历判断MAN向下移动对应的是哪种情况

for (i = 0; i < 12; i++)

if (map[man_i][man_j] * map[man_i + 1][man_j] * map[man_i + 2][man_j] == table[i][0] ||

map[man_i][man_j] * map[man_i + 1][man_j] == table[i][0])

{

map[man_i][man_j] = table[i][1];

map[man_i + 1][man_j] = table[i][2];

if (table[i][3] != -1)map[man_i + 2][man_j] = table[i][3];

darm(map[man_i][man_j], man_i, man_j);

darm(map[man_i + 1][man_j], man_i + 1, man_j);

darm(map[man_i + 2][man_j], man_i + 2, man_j);

man_i++;

break;

}

break;

default:

break;

}

}

8.附上整个工程项目的文件

9.通过学习,您还可以加上诸多功能,比如音乐的播放,用户登陆和地图的绘制等。下面给一个有上述功能的推箱子游戏

源码版本

Release版本(可执行文件 .exe)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。