作者GitHub-Pages個(gè)人主頁(yè)
本教程GitHub-Pages鏈接
本教程百度云下載地址
本教程編寫于2016/11/22
Dawson Lee edited this page on Beijing, 2018/7/3
設(shè)計(jì)思路
將整個(gè)畫面分成13*16的矩陣,每個(gè)元素對(duì)應(yīng)者一個(gè)小矩形。然后用0代表黑格桑李,1代表白墻,2代表藍(lán)格……娜氏,這樣就有了整幅圖像的信息。然后移動(dòng)就可以想象成墩新,改變矩陣的坐標(biāo)信息贸弥,形成一個(gè)新的矩陣,再重繪海渊。這就是推箱子的基本原理绵疲。
#define BLACK 0 //黑格:用于填充圖像
#define WHITEWALL 1 //白墻:用于阻擋主角移動(dòng)
#define BLUEWALL 2 //藍(lán)格:用于表示可移動(dòng)空間
#define BALL 3 //點(diǎn):用于指定箱子放置位置
#define BOX 4 //箱子:用于表示初始箱子位置
#define REDBOX 5 //變色的箱子:用于表示這個(gè)點(diǎn)位置已經(jīng)放置箱子
#define MAN 6 //主角:用于表示主角位置
#define MANBALL 7 //主角站在點(diǎn)上
步驟
1.編譯環(huán)境:Visual Studio Community 2015
Tip:
- 您也可以自行百度或者google Visual Studio Community 2015的其它下載途徑
- 您也可以嘗試使用Visual Studio其它版本,但有可能會(huì)出現(xiàn)未知問題
2.要給VS2015安裝EGE圖形庫(kù)
3.要參考EGE圖形庫(kù)幫助文檔
Tip:如果鏈接失效切省,請(qǐng)自行百度或者google"EGE圖形庫(kù)幫助文檔"
4.剛才我們說到最岗,圖像的背后對(duì)應(yīng)著一個(gè)矩陣,我們可以考慮將矩陣的信息存儲(chǔ)在一個(gè)MAP.txt文件中朝捆,在程序運(yùn)行時(shí)讀取般渡。下面我來介紹,在文件中讀取一個(gè)矩陣芙盘。
首先我們得有一個(gè)TXT文件:MAP.txt
(一定確保路徑放置正確),它存儲(chǔ)著這樣一個(gè)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<stdio.h>
#include<stdlib.h>
int main()
{
FILE *fp = fopen("MAP.txt", "rb");//以只讀形式打開文件MAP.txt
if (!fp) {
printf("打開文件失敗驯用,文件位置你可能放錯(cuò)了\n");
exit(1);
}
int map[13][16];//創(chuàng)建一個(gè)map數(shù)組用來存儲(chǔ)矩陣信息
int i, j;
char str[10];//用于存儲(chǔ)從文本文件讀取的字符串信息
for (i = 0; i<13; i++)
for (j = 0; j < 16; j++) {
fscanf(fp, "%s", str); //從文件中讀取一個(gè)字符串,遇到空格結(jié)束
map[i][j] = atoi(str);//將字符串轉(zhuǎn)變?yōu)檎腿謇希①x值給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文件的讀取矩陣的功能蝴乔,寫在一個(gè)readmap()函數(shù)中,實(shí)現(xiàn)功能的模塊化驮樊。并加多一項(xiàng)功能薇正,就是查找出片酝,MAN的位置。
//map[13][16]是形參挖腰,其中&man_i表是的是man_i的引用雕沿,引用傳遞的意義在于:傳入?yún)?shù)會(huì)因函數(shù)中的操作而改變
int readmap(int map[13][16], int &man_i, int &man_j)
{
FILE *fp = fopen("MAP.txt", "rb");//以只讀形式打開文件MAP.txt
if (!fp) {
printf("打開文件失敗,文件位置你可能放錯(cuò)了\n");
exit(1);//打開失敗則結(jié)束程序
}
int i, j;
char str[10];//用于存儲(chǔ)從文本文件讀取的字符串信息
for (i = 0; i<13; i++)
for (j = 0; j < 16; j++)
{
fscanf(fp, "%s", str); //從文件中讀取一個(gè)字符串猴仑,遇到空格結(jié)束
map[i][j] = atoi(str);//將字符串轉(zhuǎn)變?yōu)檎蜕舐郑①x值給map[i][j]
if (map[i][j] == MAN) //如果找到了MAN的位置,則返回坐標(biāo)在 man_i和 man_j 中
{
man_i = i;
man_j = j;
}
}
return 0;
}
5.接下來我們實(shí)現(xiàn)在窗口中辽俗,把矩陣信息轉(zhuǎn)變成圖像疾渣。原理就是,將圖片貼在窗口上崖飘。
- 圖片資源pic.zip(把當(dāng)中的pic文件夾解壓榴捡,存放在正確路徑中,如果路徑不正確會(huì)導(dǎo)致窗口中沒有圖像)
實(shí)現(xiàn)的效果如圖所示:
繪制操作的源代碼:
#include<stdio.h>
#include<stdlib.h>
#include<graphics.h>
#define BLACK 0 //黑格:用于填充圖像
#define WHITEWALL 1 //白墻:用于阻擋主角移動(dòng)
#define BLUEWALL 2 //藍(lán)格:用于表示可移動(dòng)空間
#define BALL 3 //點(diǎn):用于指定箱子放置位置
#define BOX 4 //箱子:用于表示初始箱子位置
#define REDBOX 5 //變色的箱子:用于表示這個(gè)點(diǎn)位置已經(jīng)放置箱子
#define MAN 6 //主角:用于表示主角位置
#define MANBALL 7 //主角站在點(diǎn)上
int main()
{
int map[13][16];//創(chuàng)建一個(gè)map數(shù)組用來存儲(chǔ)矩陣信息
int man_i, man_j;//用來存儲(chǔ)人物的位置信息
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);//調(diào)用readmap()函數(shù)坐漏。
initgraph(800, 650);//生成一個(gè)寬800薄疚,高650的窗口碧信。假設(shè)矩陣元素對(duì)應(yīng)的每個(gè)小矩形是50*50的赊琳,那個(gè)窗口就應(yīng)該是這么大。
for (int i = 0; i<13; i++)
for (int j = 0; j < 16; j++)
{
darm(map[i][j], i, j);//遍歷繪制每個(gè)小矩形
}
getch();//等待一個(gè)鍵盤輸入砰碴,如果沒有的話躏筏,窗口會(huì)看不到,因?yàn)槌绦蜻\(yùn)行結(jié)束就會(huì)關(guān)閉窗口呈枉。生成關(guān)閉就轉(zhuǎn)瞬即逝
closegraph();//關(guān)閉窗口
return 0;
}
//map[13][16]是形參趁尼,其中&man_i表是的是man_i的引用,引用傳遞的意義在于:傳入?yún)?shù)會(huì)因函數(shù)中的操作而改變
int readmap(int map[13][16], int &man_i, int &man_j)
{
FILE *fp = fopen("MAP.txt", "rb");//以只讀形式打開文件MAP.txt
if (!fp) {
printf("打開文件失敗猖辫,文件位置你可能放錯(cuò)了\n");
exit(1);//打開失敗則結(jié)束程序
}
int i, j;
char str[10];//用于存儲(chǔ)從文本文件讀取的字符串信息
for (i = 0; i<13; i++)
for (j = 0; j < 16; j++)
{
fscanf(fp, "%s", str); //從文件中讀取一個(gè)字符串酥泞,遇到空格結(jié)束
map[i][j] = atoi(str);//將字符串轉(zhuǎn)變?yōu)檎停①x值給map[i][j]
if (map[i][j] == MAN) //如果找到了MAN的位置啃憎,則返回坐標(biāo)在 man_i和 man_j 中
{
man_i = i;
man_j = j;
}
}
return 0;
}
/*
下面是在圖形庫(kù)繪制小矩形中圖像的功能模塊
這部分涉及C++中的知識(shí)芝囤,C語(yǔ)言新手不必過多糾結(jié)不懂的東西。但要知道辛萍,創(chuàng)建的源文件要是cpp格式的
*/
void darm(int a, int ii, int jj)
{
PIMAGE img;//聲明
img = newimage();//實(shí)例化
switch (a)
{
case BLACK:break;
case WHITEWALL:
{
getimage(img, "pic/墻.jpg");//getimage()和putimage請(qǐng)翻閱ege圖形庫(kù)幫助手冊(cè)悯姊。
putimage(jj * 50, ii * 50, img);//在ii行jj列繪制一個(gè)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.實(shí)現(xiàn)圖像的繪制以后那我們就應(yīng)該實(shí)現(xiàn)圖像的移動(dòng)了。
首先將所有的情況列舉出來并存入數(shù)組table[i][0]
中,將改變后的第一個(gè)格子信息存在table[i][1]
中贩毕,第二個(gè)格子信息存在table[i][2]
中悯许,第三個(gè)格子信息存在table[i][3]
中。
然后就可以開始寫move()
函數(shù)辉阶,實(shí)現(xiàn)MAN
的移動(dòng)先壕。move()
函數(shù)源代碼
/*
傳入函數(shù)的參數(shù) get表示用戶輸入的鍵盤按鍵瘩扼,傳入實(shí)時(shí)數(shù)組map的信息,傳入實(shí)時(shí)MAN的位置信息man_i垃僚,man_j邢隧。
*/
void move(char get, int map[13][16], int &man_i, int &man_j)
{
//首先把情況的變化存在table[12][4]數(shù)組中
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);//要用到繪制函數(shù),所以先聲明
switch (get)//switch判斷用戶輸入的鍵盤信息
{
case 37: //左移冈在,向左鍵的ASCII碼
//for循環(huán)遍歷判斷MAN向左移動(dòng)對(duì)應(yīng)的是哪種情況
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])
{
//找到對(duì)應(yīng)的情況后執(zhí)行以下語(yǔ)句
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];//如果不需要改變第三個(gè)格子的圖像倒慧,就不賦值。也就是如果table[i][3]==-1時(shí)包券。
//遍歷繪制對(duì)應(yīng)的三個(gè)格子信息
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--;//繪制結(jié)束后纫谅,要改變MAN的實(shí)時(shí)位置信息,并break跳出循環(huán)
break;
}
break;//再次break跳出switch語(yǔ)句
case 38://上移溅固,向上鍵的ASCII碼
//for循環(huán)遍歷判斷MAN向上移動(dòng)對(duì)應(yīng)的是哪種情況
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循環(huán)遍歷判斷MAN向右移動(dòng)對(duì)應(yīng)的是哪種情況
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循環(huán)遍歷判斷MAN向下移動(dòng)對(duì)應(yīng)的是哪種情況
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()
函數(shù)后侍郭,我們就可以實(shí)現(xiàn)推箱子的功能了询吴。整合后的源代碼:
#include<stdio.h>
#include<stdlib.h>
#include<graphics.h>
#define BLACK 0 //黑格:用于填充圖像
#define WHITEWALL 1 //白墻:用于阻擋主角移動(dòng)
#define BLUEWALL 2 //藍(lán)格:用于表示可移動(dòng)空間
#define BALL 3 //點(diǎn):用于指定箱子放置位置
#define BOX 4 //箱子:用于表示初始箱子位置
#define REDBOX 5 //變色的箱子:用于表示這個(gè)點(diǎn)位置已經(jīng)放置箱子
#define MAN 6 //主角:用于表示主角位置
#define MANBALL 7 //主角站在點(diǎn)上
int main()
{
int map[13][16];//創(chuàng)建一個(gè)map數(shù)組用來存儲(chǔ)矩陣信息
int man_i, man_j;//用來存儲(chǔ)人物的位置信息
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);//調(diào)用readmap()函數(shù)。
initgraph(800, 650);//生成一個(gè)寬800亮元,高650的窗口猛计。假設(shè)矩陣元素對(duì)應(yīng)的每個(gè)小矩形是50*50的,那個(gè)窗口就應(yīng)該是這么大爆捞。
for (int i = 0; i<13; i++)
for (int j = 0; j < 16; j++)
{
darm(map[i][j], i, j);//遍歷繪制每個(gè)小矩形
}
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();//關(guān)閉窗口
return 0;
}
//map[13][16]是形參,其中&man_i表是的是man_i的引用煮甥,引用傳遞的意義在于:傳入?yún)?shù)會(huì)因函數(shù)中的操作而改變
int readmap(int map[13][16], int &man_i, int &man_j)
{
FILE *fp = fopen("MAP.txt", "rb");//以只讀形式打開文件MAP.txt
if (!fp) {
printf("打開文件失敗盗温,文件位置你可能放錯(cuò)了\n");
exit(1);//打開失敗則結(jié)束程序
}
int i, j;
char str[10];//用于存儲(chǔ)從文本文件讀取的字符串信息
for (i = 0; i<13; i++)
for (j = 0; j < 16; j++)
{
fscanf(fp, "%s", str); //從文件中讀取一個(gè)字符串,遇到空格結(jié)束
map[i][j] = atoi(str);//將字符串轉(zhuǎn)變?yōu)檎统芍猓①x值給map[i][j]
if (map[i][j] == MAN) //如果找到了MAN的位置卖局,則返回坐標(biāo)在 man_i和 man_j 中
{
man_i = i;
man_j = j;
}
}
return 0;
}
/*
下面是在圖形庫(kù)繪制小矩形中圖像的功能模塊
這部分涉及C++中的知識(shí),C語(yǔ)言新手不必過多糾結(jié)不懂的東西双霍。但要知道砚偶,創(chuàng)建的源文件要是cpp格式的
*/
void darm(int a, int ii, int jj)
{
PIMAGE img;//聲明
img = newimage();//實(shí)例化
switch (a)
{
case BLACK:break;
case WHITEWALL:
{
getimage(img, "pic/墻.jpg");//getimage()和putimage請(qǐng)翻閱ege圖形庫(kù)幫助手冊(cè)。
putimage(jj * 50, ii * 50, img);//在ii行jj列繪制一個(gè)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);
}
/*
傳入函數(shù)的參數(shù) get表示用戶輸入的鍵盤按鍵店煞,傳入實(shí)時(shí)數(shù)組map的信息蟹演,傳入實(shí)時(shí)MAN的位置信息man_i,man_j顷蟀。
*/
void move(char get, int map[13][16], int &man_i, int &man_j)
{
//首先把情況的變化存在table[12][4]數(shù)組中
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);//要用到繪制函數(shù)酒请,所以先聲明
switch (get)//switch判斷用戶輸入的鍵盤信息
{
case 37: //左移,向左鍵的ASCII碼
//for循環(huán)遍歷判斷MAN向左移動(dòng)對(duì)應(yīng)的是哪種情況
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])
{
//找到對(duì)應(yīng)的情況后執(zhí)行以下語(yǔ)句
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];//如果不需要改變第三個(gè)格子的圖像鸣个,就不賦值羞反。也就是如果table[i][3]==-1時(shí)布朦。
//遍歷繪制對(duì)應(yīng)的三個(gè)格子信息
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--;//繪制結(jié)束后,要改變MAN的實(shí)時(shí)位置信息昼窗,并break跳出循環(huán)
break;
}
break;//再次break跳出switch語(yǔ)句
case 38://上移是趴,向上鍵的ASCII碼
//for循環(huán)遍歷判斷MAN向上移動(dòng)對(duì)應(yīng)的是哪種情況
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循環(huán)遍歷判斷MAN向右移動(dòng)對(duì)應(yīng)的是哪種情況
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循環(huán)遍歷判斷MAN向下移動(dòng)對(duì)應(yīng)的是哪種情況
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.最后唆途,我們給窗口載入一張完美的背景圖片,至此就可以實(shí)現(xiàn)完整推箱子小游戲了掸驱。
實(shí)際效果圖:
最后整合的代碼就是:
/*
作者:DawsonLee
Email:dawsonlee1790@foxmail.com
*/
#include<stdio.h>
#include<stdlib.h>
#include<graphics.h>
#define BLACK 0 //黑格:用于填充圖像
#define WHITEWALL 1 //白墻:用于阻擋主角移動(dòng)
#define BLUEWALL 2 //藍(lán)格:用于表示可移動(dòng)空間
#define BALL 3 //點(diǎn):用于指定箱子放置位置
#define BOX 4 //箱子:用于表示初始箱子位置
#define REDBOX 5 //變色的箱子:用于表示這個(gè)點(diǎn)位置已經(jīng)放置箱子
#define MAN 6 //主角:用于表示主角位置
#define MANBALL 7 //主角站在點(diǎn)上
int main()
{
int map[13][16];//創(chuàng)建一個(gè)map數(shù)組用來存儲(chǔ)矩陣信息
int man_i, man_j;//用來存儲(chǔ)人物的位置信息
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);//調(diào)用readmap()函數(shù)肛搬。
initgraph(800, 650);//生成一個(gè)寬800,高650的窗口毕贼。假設(shè)矩陣元素對(duì)應(yīng)的每個(gè)小矩形是50*50的温赔,那個(gè)窗口就應(yīng)該是這么大。
//載入一張漂亮的背景圖片
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);//遍歷繪制每個(gè)小矩形
}
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();//關(guān)閉窗口
return 0;
}
int readmap(int map[13][16], int &man_i, int &man_j)//map[13][16]是形參陶贼,其中&man_i表是的是man_i的引用,引用傳遞的意義在于:傳入?yún)?shù)會(huì)因函數(shù)中的操作而改變
{
FILE *fp = fopen("MAP.txt", "rb");//以只讀形式打開文件MAP.txt
if (!fp) {
printf("打開文件失敗待秃,文件位置你可能放錯(cuò)了\n");
exit(1);//打開失敗則結(jié)束程序
}
int i, j;
char str[10];//用于存儲(chǔ)從文本文件讀取的字符串信息
for (i = 0; i<13; i++)
for (j = 0; j < 16; j++)
{
fscanf(fp, "%s", str); //從文件中讀取一個(gè)字符串拜秧,遇到空格結(jié)束
map[i][j] = atoi(str);//將字符串轉(zhuǎn)變?yōu)檎停①x值給map[i][j]
if (map[i][j] == MAN) //如果找到了MAN的位置锥余,則返回坐標(biāo)在 man_i和 man_j 中
{
man_i = i;
man_j = j;
}
}
return 0;
}
/*
下面是在圖形庫(kù)繪制小矩形中圖像的功能模塊
這部分涉及C++中的知識(shí)腹纳,C語(yǔ)言新手不必過多糾結(jié)不懂的東西痢掠。但要知道驱犹,創(chuàng)建的源文件要是cpp格式的
*/
void darm(int a, int ii, int jj)
{
PIMAGE img;//聲明
img = newimage();//實(shí)例化
switch (a)
{
case BLACK:break;
case WHITEWALL:
{
getimage(img, "pic/墻.jpg");//getimage()和putimage請(qǐng)翻閱ege圖形庫(kù)幫助手冊(cè)。
putimage(jj * 50, ii * 50, img);//在ii行jj列繪制一個(gè)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);
}
/*
傳入函數(shù)的參數(shù) get表示用戶輸入的鍵盤按鍵足画,傳入實(shí)時(shí)數(shù)組map的信息雄驹,傳入實(shí)時(shí)MAN的位置信息man_i,man_j淹辞。
*/
void move(char get, int map[13][16], int &man_i, int &man_j)
{
//首先把情況的變化存在table[12][4]數(shù)組中
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);//要用到繪制函數(shù)医舆,所以先聲明
switch (get)//switch判斷用戶輸入的鍵盤信息
{
case 37: //左移,向左鍵的ASCII碼
//for循環(huán)遍歷判斷MAN向左移動(dòng)對(duì)應(yīng)的是哪種情況
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])
{
//找到對(duì)應(yīng)的情況后執(zhí)行以下語(yǔ)句
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];//如果不需要改變第三個(gè)格子的圖像象缀,就不賦值蔬将。也就是如果table[i][3]==-1時(shí)。
//遍歷繪制對(duì)應(yīng)的三個(gè)格子信息
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--;//繪制結(jié)束后央星,要改變MAN的實(shí)時(shí)位置信息霞怀,并break跳出循環(huán)
break;
}
break;//再次break跳出switch語(yǔ)句
case 38://上移,向上鍵的ASCII碼
//for循環(huán)遍歷判斷MAN向上移動(dòng)對(duì)應(yīng)的是哪種情況
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循環(huán)遍歷判斷MAN向右移動(dòng)對(duì)應(yīng)的是哪種情況
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循環(huán)遍歷判斷MAN向下移動(dòng)對(duì)應(yīng)的是哪種情況
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;
}
}