以下是初版代码,进行了初步的简单优化,具体思路以及优化步骤已经在备注中标明。
后期根据情况会出详细版的讲解。
#include <graphics.h>
#include <iostream>
#include <stdlib.h>
#include <string>
#include <conio.h> //与获取热键相关的头文件
using namespace std;
//使用宏定义,方便代码的后期维护
#define RATIO 61
#define SCREEN_WIDTH 960
#define SCREEN_HEIGHT 768
#define LINE 9
#define COLUMN 12
#define START_X 100
#define START_Y 150
#define isValid(pos) pos.x>0 && pos.x<LINE && pos.y>0 && pos.y<COLUMN
//控制键上下左右控制方向,q退出,增强代码可读性
#defin KEY_UP 'w'
#defin KEY_DOWN 's'
#defin KEY_LEFT 'a'
#defin KEY_RIGHT 'd'
#defin KEY_QUIT 'q'
//IMAGE images[6];//全局变量设置图标种类数目
enum _PROPS{
WALL, //墙
FLOOR, //地板
BOX_DES, //箱子目的地
MAN, //小人
BOX, //箱子
HIT, //箱子命中目标
ALL
};
struct _POS{
int x;//小人所在的二维数组的行
int y;//小人所在的二维数组的列
}
IMAGE images[ALL];
enum _DIRECTION{
UP,
DOWN,
LEFT,
RIGHT
};
/*游戏地图*/
int map[LINE][COLUMN] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
{ 0, 1, 4, 1, 0, 2, 1, 0, 2, 1, 0, 0 },
{ 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0 },
{ 0, 1, 0, 2, 0, 1, 1, 4, 1, 1, 1, 0 },
{ 0, 1, 1, 1, 0, 3, 1, 1, 1, 4, 1, 0 },
{ 0, 1, 2, 1, 1, 4, 1, 1, 1, 1, 1, 0 },
{ 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
};
/*******************************************************
*判断游戏是否结束,如果不存在游戏目的地,就代表游戏结束
*输入:
*返回值:
* true-游戏结束
* false-游戏继续
******************************************************/
bool isGameOver(){
for(int i=0;i<LINE;i++){
for(int j=0;j<COLUMN;j++){
if(map[i][j]==BOX_DES) return false;
}
}
return true;
}
/*******************************************************
*游戏结束场景,在玩家通关后显示
*输入:
* bg-背景图片变量的指针
*返回值:无
******************************************************/
void gameOverScene(IMAGE *bg){
putimage(0,0,bg);
settextcolor(WHITE);
RECT rec={0,0,SCREEN_WIDTH,SCREEN_HEIGHT};
settextstyle(20,0,_T("宋体"));
drawtext(_T("恭喜您!\n通过关卡!"),&rec,DT_CENTER|DT_VCENTER|DT_SINGLELINE);//水平居中|垂直居中|文字显示单行
}
/*******************************************************
*改变游戏地图视图中一格对应道具并重新显示
*输入:
* line-道具在地图数组的行下标
* column-道具在地图数组的列下标
* prop-道具的类型
*返回值:无
******************************************************/
void changeMap(struct _POS pos, enum _PROPS prop){//int line,int column
//map[line][column]=prop;
map[pos->x][pos->y]=prop;
//putimage(START_X+column*RATIO, START_Y+line*RATIO,&images[prop]);
putimage(START_X+pos->y*RATIO, START_Y+pos->x*RATIO,&images[prop]);
}
/*******************************************************
*实现游戏四个方向(上下左右)的控制
*输入:
* direct-人前进方向
*输出:无
******************************************************/
void getControl(enum _DIRECTION direct){
//int x=man.x;
//int y=man.y;
struct _POS next_pos=man;
struct _POS next_next_pos=man;
switch(direct){//找到人的下一个位置和下下个位置的坐标
case UP:
next_pos.x--;
next_next_pos.x-=2;
break;
case DOWN:
next_pos.x++;
next_next_pos.x+=2;
break;
case LEFT:
next_pos.y--;
next_next_pos.y-=2;
break;
case RIGHT:
next_pos.y++;
next_next_pos.y+=2;
break;
}
//优化后
//宏展开next_pos.x>0 && next_pos.x<LINE && next_pos.y>0 && next_pos.y<COLUMN
if(isVaild(next_pos) && map[next_pos.x][next_pos.y]==FLOOR){//人的前方是地板
//changeMap(next_pos.x,next_pos.y);
changeMap(&next_pos,MAN);
//changeMap(man.x,man.y,FLOOR);
changeMap(&man,FLOOR);
man=next_pos;
}else if(isVaild(next_next_pos) && map[next_pos.x][next_pos.y]==BOX){//人的前方是箱子
//两种情况,箱子前面是地板或者是箱子目的地
if(map[next_next_pos.x][next_next_pos.y]==FLOOR){//箱子前面是地板
changeMap(&next_next_pos,BOX);
changeMap(&next_pos,MAN);
changeMap(&man,FLOOR);
man=next_pos;
}else if(map[next_next_pos.x][next_next_pos.y]==BOX_DES){//箱子前面是目的地
changeMap(&next_next_pos,HIT);
changeMap(&next_pos,MAN);
changeMap(&man,FLOOR);
man=next_pos;
}
}
//优化前
// if(direct==UP){//先处理前进方向是地板的情况
// if((man.x-1)>=0 && map[next_pos.x][next_pos.y]==FLOOR){//map[x-1][y]==FLOOR
// //changeMap(x-1,y,MAN);//小人前进一格
// changeMap(next_pos.x,next_pos.y);
// //man.x=x-1;
// changeMap(man.x,man.y,FLOOR);
// man=next_pos;
// //changeMap(x,y,FLOOR);
// }
// }else if(direct==DOWN){
// if((man.x+1)<LINE && map[next_pos.x][next_pos.y]==FLOOR){//map[x+1][y]==FLOOR
// // changeMap(x+1,y,MAN);
// // man.x=x+1;
// // changeMap(x,y,FLOOR);
// changeMap(next_pos.x,next_pos.y);
// changeMap(man.x,man.y,FLOOR);
// man=next_pos;
// }
// }else if(direct==LEFT){
// if((man.y-1)>=0 && map[next_pos.x][next_pos.y]==FLOOR){//map[x][y-1]==FLOOR
// // changeMap(x,y-1,MAN);
// // man.y=y-1;
// // changeMap(x,y,FLOOR);
// changeMap(next_pos.x,next_pos.y);
// changeMap(man.x,man.y,FLOOR);
// man=next_pos;
// }
// }else if(direct==RIGHT){
// if((man.y+1)<COLUMN && map[next_pos.x][next_pos.y]==FLOOR){//map[x][y+1]==FLOOR
// // changeMap(x,y+1,MAN);
// // man.y=y+1;
// // changeMap(x,y,FLOOR);
// changeMap(next_pos.x,next_pos.y);
// changeMap(man.x,man.y,FLOOR);
// man=next_pos;
// }
// }
}
int main(void){
IMAGE bg_img;
//搭台
initgraph(SCREEN_WIDTH, SCREEN_HEIGHT);//创建画面,并设置其大小
loadimage(&bg_img, _T("blackground.bmp"), SCREEN_WIDTH,
SCREEN_HEIGHT, true);//加载画面背景图片
putimage(0, 0, &bg_img);//放置画面背景图片,并设置其位置
//加载道具图标
loadimage(&images[WALL], _T("wall.bmp"), RATIO, RATIO, true);
loadimage(&images[FLOOR], _T("floor.bmp"), RATIO, RATIO, true);
loadimage(&images[BOX_DES], _T("des.bmp"), RATIO, RATIO, true);
loadimage(&images[MAN], _T("man.bmp"), RATIO, RATIO, true);
loadimage(&images[BOX], _T("box.bmp"), RATIO, RATIO, true);
loadimage(&images[HIT], _T("box.bmp"), RATIO, RATIO, true);
for(int i = 0; i< LINE; i++){
for(int j = 0; j < COLUMN; j++){
if(map[i][j]==MAN){//找到小人的位置
man.x=i;
man.y=j;
}
putimage(START_X+j*RATIO, START_Y+i*RATIO,&images[map[i][j]]);//在对应位置放置道具图标
}
}
//游戏环节
bool quit=false;
do{
if(_kbhit()){//如果键盘被敲击,_kbhit()函数会返回true
char ch=_getch();//获取玩家敲击的键
//对不同的热键进行处理
if(ch==KEY_UP){
gameControl(UP);
}else if(ch==KEY_DOWN){
gameControl(DOWN);
}else if(ch==KEY_LEFT){
gameControl(LEFT);
}else if(ch==KEY_RIGHT){
gameControl(RIGHT);
}else if(ch==KEY_QUIT){
quit=true;
}
if(isGameOver()){
gameOverScene(&bg_img);
quit=true;
}
}
Sleep(100);//休眠0.1秒
}while(quit==false)
system("pause");
//游戏结束,释放资源
closegraph();
return 0;
}