软件工程作业二

推箱子游戏开发以及改进

推箱子游戏是目前比较流行的游戏之一,很多操作系统或者流行软件都会带有这种游戏。它既能锻炼思维的严密性,又有很多乐趣。我个人也比较喜欢玩这个游戏,因此,我就借这个机会将这个推箱子游戏用C语言实现了出来,当然,我也借鉴了前人的一些技巧经验。由于时间仓促和本人水平有限,此游戏的制作显得有些粗糙,希望老师能够谅解,我以后将会再接再厉。

设计思路:

程序包括5个模块,分别是初始化模块、画图模块、移动箱子模块、移动小人模块和功能控制模块。

1)初始化模块。

     该模块包括屏幕初始化和游戏第一关的初始化。屏幕初始化用于输出欢迎信息和操作提示,游戏每一关的初始化是构建每一关的关卡。

2)画图模块。

     该模块主要是被其它模块调用,用于画墙、在空地画箱子、在目的地画箱子、画小人和画目的地。

3)移动箱子模块。

     该模块用于移动箱子,包括目的地之间、空地之间和目的地与空地之间的箱子移动。

4)移动小人模块。

该模块用于控制小人移动,从而推动箱子到目的地。

5)功能控制模块。

该模块是几个功能函数的集合,包括屏幕输出功能、指定位置状态判断功能和关卡重置功能。

 

代码附上:

#include <dos.h> 

#include <stdio.h> 

#include <stdlib.h>

#include <ctype.h> 

#include <conio.h> 

#include <bios.h> 

#include <alloc.h> 

char ghouse[20][20]; 

char far *screen=(char far* )0xb8000000; 

void putchxy(int y,int x,char ch,char fc,char bc) 

screen[(x*160)+(y<<1)+0]=ch; 

screen[(x*160)+(y<<1)+1]=(bc*16)+fc; 

 

typedef struct winer { 

int x,y; 

struct winer *p; 

}winer; 

 

typedef struct boxs { 

int x,y; 

struct boxs *next; 

}boxs; 

 

void printwall(int x,int y) 

putchxy(y-1,x-1,219,MAGENTA,BLACK); 

ghouse[x][y]='w'; 

 

void printbox(int x,int y) 

putchxy(y-1,x-1,10,WHITE,BLACK); 

ghouse[x][y]='b'; 

 

void printwhither1(int x,int y,winer **win,winer **pw) 

winer *qw; 

putchxy(y-1,x-1,'*',YELLOW,BLACK); 

ghouse[x][y]='m'; 

if(*win==NULL) 

*win=*pw=qw=(winer* )malloc(sizeof(winer)); 

(*pw)->x=x;(*pw)->y=y;(*pw)->p=NULL; 

else 

qw=(winer* )malloc(sizeof(winer)); 

qw->x=x;qw->y=y;(*pw)->p=qw;(*pw)=qw;qw->p=NULL; 

 

 

void printwhither(int x,int y) 

putchxy(y-1,x-1,'*',YELLOW,BLACK); 

ghouse[x][y]='m'; 

 

void printman(int x,int y) 

gotoxy(y,x); 

_AL=02;_CX=01;_AH=0xa; 

geninterrupt(0x10); 

 

void printboxin(int x,int y) 

putchxy(y-1,x-1,10,YELLOW,BLACK); 

ghouse[x][y]='i'; 

 

void init() 

int i,j; 

system("cls"); 

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

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

ghouse[i][j]=0; 

_AL=3; 

_AH=0; 

geninterrupt(0x10); 

gotoxy(40,4); 

printf("Welcome to push box world!"); 

gotoxy(40,6); 

printf("Press up,down,left,right to play."); 

gotoxy(40,8); 

printf("Press Esc to quit it."); 

gotoxy(40,10); 

printf("Press space to reset the game."); 

gotoxy(40,12); 

printf("April 30th 2004."); 

 

winer *inithouse1() 

{

int x,y; 

winer *win=NULL,*pw; 

gotoxy(8,2); 

printf("Level No.1"); 

for(x=1,y=5;y<=9;y++) 

printwall(x+4,y+10); 

for(y=5,x=2;x<=5;x++) 

printwall(x+4,y+10); 

for(y=9,x=2;x<=5;x++) 

printwall(x+4,y+10); 

for(y=1,x=3;x<=8;x++) 

printwall(x+4,y+10); 

for(x=3,y=3;x<=5;x++) 

printwall(x+4,y+10); 

for(x=5,y=8;x<=9;x++) 

printwall(x+4,y+10); 

for(x=7,y=4;x<=9;x++) 

printwall(x+4,y+10); 

for(x=9,y=5;y<=7;y++) 

printwall(x+4,y+10); 

for(x=8,y=2;y<=3;y++) 

printwall(x+4,y+10); 

printwall(5+4,4+10); 

printwall(5+4,7+10); 

printwall(3+4,2+10); 

printbox(3+4,6+10); 

printbox(3+4,7+10); 

printbox(4+4,7+10); 

printwhither1(4+4,2+10,&win,&pw); 

printwhither1(5+4,2+10,&win,&pw); 

printwhither1(6+4,2+10,&win,&pw); 

printman(2+4,8+10); 

return win; 

 

winer *inithouse3() 

{int x,y; 

winer *win=NULL,*pw; 

gotoxy(8,3); 

printf("Level No.3"); 

for(x=1,y=2;y<=8;y++) 

printwall(x+4,y+10); 

for(x=2,y=2;x<=4;x++) 

printwall(x+4,y+10); 

for(x=4,y=1;y<=3;y++) 

printwall(x+4,y+10); 

for(x=5,y=1;x<=8;x++) 

printwall(x+4,y+10); 

for(x=8,y=2;y<=5;y++) 

printwall(x+4,y+10); 

for(x=5,y=5;x<=7;x++) 

printwall(x+4,y+10); 

for(x=7,y=6;y<=9;y++) 

printwall(x+4,y+10); 

for(x=3,y=9;x<=6;x++) 

printwall(x+4,y+10); 

for(x=3,y=6;y<=8;y++) 

printwall(x+4,y+10); 

printwall(2+4,8+10); 

printwall(5+4,7+10); 

printbox(6+4,3+10); 

printbox(4+4,4+10); 

printbox(5+4,6+10); 

printwhither1(2+4,5+10,&win,&pw); 

printwhither1(2+4,6+10,&win,&pw); 

printwhither1(2+4,7+10,&win,&pw); 

printman(2+4,4+10); 

return win; 

 

winer *inithouse2() 

{int x,y; 

winer *win=NULL,*pw; 

gotoxy(8,2); 

printf("Level No.2"); 

for(x=1,y=4;y<=7;y++) 

printwall(x+4,y+10); 

for(x=2,y=2;y<=4;y++) 

printwall(x+4,y+10); 

for(x=2,y=7;x<=4;x++) 

printwall(x+4,y+10); 

for(x=4,y=1;x<=8;x++) 

printwall(x+4,y+10); 

for(x=8,y=2;y<=8;y++) 

printwall(x+4,y+10); 

for(x=4,y=8;x<=8;x++) 

printwall(x+4,y+10); 

for(x=4,y=6;x<=5;x++) 

printwall(x+4,y+10); 

for(x=3,y=2;x<=4;x++) 

printwall(x+4,y+10); 

for(x=4,y=4;x<=5;x++) 

printwall(x+4,y+10); 

printwall(6+4,3+10); 

printbox(3+4,5+10); 

printbox(6+4,6+10); 

printbox(7+4,3+10); 

printwhither1(5+4,7+10,&win,&pw); 

printwhither1(6+4,7+10,&win,&pw); 

printwhither1(7+4,7+10,&win,&pw); 

printman(2+4,6+10); 

return win; 

 

winer *inithouse4() 

{int x,y; 

winer *win=NULL,*pw; 

gotoxy(8,2); 

printf("Level No.4"); 

for(x=1,y=1;y<=6;y++) 

printwall(x+4,y+10); 

for(x=2,y=7;y<=8;y++) 

printwall(x+4,y+10); 

for(x=2,y=1;x<=7;x++) 

printwall(x+4,y+10); 

for(x=7,y=2;y<=4;y++) 

printwall(x+4,y+10); 

for(x=6,y=4;y<=9;y++) 

printwall(x+4,y+10); 

for(x=3,y=9;x<=5;x++) 

printwall(x+4,y+10); 

for(x=3,y=3;y<=4;y++) 

printwall(x+4,y+10); 

printwall(3+4,8+10); 

printbox(3+4,5+10); 

printbox(4+4,4+10); 

printbox(4+4,6+10); 

printbox(5+4,5+10); 

printbox(5+4,3+10); 

printwhither1(3+4,7+10,&win,&pw); 

printwhither1(4+4,7+10,&win,&pw); 

printwhither1(5+4,7+10,&win,&pw); 

printwhither1(4+4,8+10,&win,&pw); 

printwhither1(5+4,8+10,&win,&pw); 

printman(2+4,2+10); 

return win; 

 

movebox(int x,int y,char a) 

{switch(a) 

case 'u':ghouse[x-1][y]=0;printf(" "); 

printbox(x-2,y);printman(x-1,y); 

ghouse[x-2][y]='b';break; 

case 'd':ghouse[x+1][y]=0;printf(" "); 

printbox(x+2,y);printman(x+1,y); 

ghouse[x+2][y]='b';break; 

case 'l':ghouse[x][y-1]=0;printf(" "); 

printbox(x,y-2);printman(x,y-1); 

ghouse[x][y-2]='b';break; 

case 'r':ghouse[x][y+1]=0;printf(" "); 

printbox(x,y+2);printman(x,y+1); 

ghouse[x][y+2]='b';break; 

default: break; 

 

moveinbox(int x,int y,char a) 

{switch(a) 

case 'u':ghouse[x-1][y]='m';printf(" "); 

printbox(x-2,y);printman(x-1,y); 

ghouse[x-2][y]='b';break; 

case 'd':ghouse[x+1][y]='m';printf(" "); 

printbox(x+2,y);printman(x+1,y); 

ghouse[x+2][y]='b';break; 

case 'l':ghouse[x][y-1]='m';printf(" "); 

printbox(x,y-2);printman(x,y-1); 

ghouse[x][y-2]='b';break; 

case 'r':ghouse[x][y+1]='m';printf(" "); 

printbox(x,y+2);printman(x,y+1); 

ghouse[x][y+2]='b';break; 

default: break; 

 

moveboxin(int x,int y,char a) 

{switch(a) 

case 'u':ghouse[x-1][y]=0;printf(" "); 

printboxin(x-2,y);printman(x-1,y); 

ghouse[x-2][y]='i';break; 

case 'd':ghouse[x+1][y]=0;printf(" "); 

printboxin(x+2,y);printman(x+1,y); 

ghouse[x+2][y]='i';break; 

case 'l':ghouse[x][y-1]=0;printf(" "); 

printboxin(x,y-2);printman(x,y-1); 

ghouse[x][y-2]='i';break; 

case 'r':ghouse[x][y+1]=0;printf(" "); 

printboxin(x,y+2);printman(x,y+1); 

ghouse[x][y+2]='i';break; 

default: break; 

 

moveinboxin(int x,int y,char a) 

{switch(a) 

case 'u':ghouse[x-1][y]='m';printf(" "); 

printboxin(x-2,y);printman(x-1,y); 

ghouse[x-2][y]='i';break; 

case 'd':ghouse[x+1][y]='m';printf(" "); 

printboxin(x+2,y);printman(x+1,y); 

ghouse[x+2][y]='i';break; 

case 'l':ghouse[x][y-1]='m';printf(" "); 

printboxin(x,y-2);printman(x,y-1); 

ghouse[x][y-2]='i';break; 

case 'r':ghouse[x][y+1]='m';printf(" "); 

printboxin(x,y+2);printman(x,y+1); 

ghouse[x][y+2]='i';break; 

default: break; 

 

int judge(int x,int y) 

{int i; 

switch(ghouse[x][y]) 

case 0: i=1;break; 

case 'w': i=0;break; 

case 'b': i=2;break; 

case 'i': i=4;break; 

case 'm': i=3;break; 

default: break; 

return i; 

 

move(int x,int y,char a) 

{switch(a) 

case 'u':if(!judge(x-1,y)) {gotoxy(y,x);break;} 

else if(judge(x-1,y)==1||judge(x-1,y)==3) 

{if(judge(x,y)==3) 

{ printwhither(x,y);printman(x-1,y);break;} 

else 

{printf(" ");printman(x-1,y);break;} 

else if(judge(x-1,y)==2) 

{ if(judge(x-2,y)==1) 

{movebox(x,y,'u'); 

if(judge(x,y)==3) printwhither(x,y); gotoxy(y,x-1); 

else if(judge(x-2,y)==3) 

{ moveboxin(x,y,'u'); 

if(judge(x,y)==3) printwhither(x,y); gotoxy(y,x-1); 

else gotoxy(y,x); 

break; 

else if(judge(x-1,y)==4) 

{ if(judge(x-2,y)==1) 

{moveinbox(x,y,'u'); 

if(judge(x,y)==3) printwhither(x,y);gotoxy(y,x-1); 

else if(judge(x-2,y)==3) 

{ moveinboxin(x,y,'u'); 

if(judge(x,y)==3) printwhither(x,y);gotoxy(y,x-1); 

else gotoxy(y,x); 

break; 

case 'd':if(!judge(x+1,y)) {gotoxy(y,x);break;} 

else if(judge(x+1,y)==1||judge(x+1,y)==3) 

{if(judge(x,y)==3) 

{ printwhither(x,y);printman(x+1,y);break;} 

else 

{printf(" ");printman(x+1,y);break;} 

else if(judge(x+1,y)==2) 

{ if(judge(x+2,y)==1) 

{movebox(x,y,'d'); 

if(judge(x,y)==3) printwhither(x,y);gotoxy(y,x+1); 

else if(judge(x+2,y)==3) 

{moveboxin(x,y,'d'); 

if(judge(x,y)==3) printwhither(x,y);gotoxy(y,x+1); 

else gotoxy(y,x); 

break; 

else if(judge(x+1,y)==4) 

{ if(judge(x+2,y)==1) 

{moveinbox(x,y,'d'); 

if(judge(x,y)==3) printwhither(x,y);gotoxy(y,x+1); 

else if(judge(x+2,y)==3) 

{moveinboxin(x,y,'d'); 

if(judge(x,y)==3) printwhither(x,y);gotoxy(y,x+1); 

else gotoxy(y,x); 

break; 

 

case 'l':if(!judge(x,y-1)) {gotoxy(y,x);break;} 

else if(judge(x,y-1)==1||judge(x,y-1)==3) 

{if(judge(x,y)==3) 

{ printwhither(x,y);printman(x,y-1);break;} 

else 

{printf(" ");printman(x,y-1);break;} 

else if(judge(x,y-1)==2) 

{ if(judge(x,y-2)==1) 

{movebox(x,y,'l'); 

if(judge(x,y)==3) printwhither(x,y); gotoxy(y-1,x); 

else if(judge(x,y-2)==3) 

{moveboxin(x,y,'l'); 

if(judge(x,y)==3) printwhither(x,y); gotoxy(y-1,x); 

else gotoxy(y,x); 

break; 

else if(judge(x,y-1)==4) 

{ if(judge(x,y-2)==1) 

{moveinbox(x,y,'l'); 

if(judge(x,y)==3) printwhither(x,y); gotoxy(y-1,x); 

else if(judge(x,y-2)==3) 

{moveinboxin(x,y,'l'); 

if(judge(x,y)==3) printwhither(x,y); gotoxy(y-1,x); 

else gotoxy(y,x); 

break; 

case 'r':if(!judge(x,y+1)) {gotoxy(y,x);break;} 

else if(judge(x,y+1)==1||judge(x,y+1)==3) 

{if(judge(x,y)==3) 

{printwhither(x,y);printman(x,y+1);break;} 

else 

{printf(" ");printman(x,y+1);break;} 

else if(judge(x,y+1)==2) 

{ if(judge(x,y+2)==1) 

{movebox(x,y,'r'); 

if(judge(x,y)==3) printwhither(x,y); gotoxy(y+1,x); 

else if(judge(x,y+2)==3) 

{moveboxin(x,y,'r'); 

if(judge(x,y)==3) printwhither(x,y); gotoxy(y+1,x); 

else gotoxy(y,x); 

break; 

else if(judge(x,y+1)==4) 

{ if(judge(x,y+2)==1) 

{moveinbox(x,y,'r'); 

if(judge(x,y)==3) printwhither(x,y); gotoxy(y+1,x); 

else if(judge(x,y+2)==3) 

{moveinboxin(x,y,'r'); 

if(judge(x,y)==3) printwhither(x,y); gotoxy(y+1,x); 

else gotoxy(y,x); 

break; 

default: break; 

 

void reset(int i) 

{switch(i) 

case 0: init(); 

inithouse1();break; 

case 1: init(); 

inithouse2();break; 

case 2: init(); 

inithouse3();break; 

case 3: init(); 

inithouse4();break; 

default:break; 

 

main() 

{int key,x,y,s,i=0; 

winer *win,*pw; 

_AL=3;_AH=0; 

geninterrupt(0x10); 

init(); 

win=inithouse1();

do{ 

_AH=3; 

geninterrupt(0x10); 

x=_DH+1;y=_DL+1; 

while(bioskey(1)==0); 

key=bioskey(0); 

switch(key) 

case 0x4800:move(x,y,'u');break; 

case 0x5000:move(x,y,'d');break;  

case 0x4b00:move(x,y,'l');break; 

case 0x4d00:move(x,y,'r');break; 

case 0x3920:reset(i);break; 

default:break; 

s=0; 

pw=win; 

while(pw) 

if(ghouse[pw->x][pw->y]=='m') s++; 

pw=pw->p; 

if(s==0) 

free(win); 

gotoxy(25,2); 

printf("Congratulate! You have passed Level %d!",i+1); 

getch(); 

i++; 

switch(i) 

case 1: init(); 

win=inithouse2();break; 

case 2: init(); 

win=inithouse3();break; 

case 3: init(); 

win=inithouse4();break; 

case 4: gotoxy(8,14); 

printf("Great! You have passed all the levels! Press any key to quit!"); 

key=0x011b;getch();break; 

default: break; 

}

}while(key!=0x011b); 

_AL=3; 

_AH=0; 

geninterrupt(0x10); 

 

改进:

重新分析程序后发现,可以更加清晰地呈现五个模块,所以重新对程序重新进行了优化。

1、设置全局变量

定义二维数组char status[20][20],用于记录屏幕一各点的状态。其中,“0”表示什么都没有,“b”表示箱子,“w”表示目的地,“i”表示箱子在目的地。首先将屏幕20*20范围内的状态初始化为0,然后根据具体情况,在画箱子时,将箱子所在点的状态改为“b”;在画墙壁时,将墙壁所在点的状态改为“w”;在画目的地时,将目的地所在点的状态改为“m”;当箱子被推到目的地时,箱子所在点的状态改为“i”,如果每一关中所有目的地的状态都为“i”,则说明该关已完成。

定义全局变量,char far *printScreen=(char far*)0xB8000000,用于在屏幕上输出字符。彩色显示器的字符缓冲区首地址为0xB8000000,每一个字符占2个字节(第一个字节为ASCII值,第二个字节为颜色值),字符模式下屏幕宽80像素,高25像素,一屏可以写80*25个字符。

2、定义结构体

typedef struct winer

{

int x;

int y;

struct winer *p;

}winer;

 

定义结构体struct winer用于判断每一关是否已完成。其中x用于存放目的地的横坐标,y用于存放目的地的纵坐标。如果所有表示目的地坐标对应的状态都为“i”,即箱子在目的地,则表示已经过关,可以进入下一关。该结构体的初始化在每一关的初始化时进行。

三、函数功能描述

1、 putoutChar()

函数原型:void putoutChar(int y,int x,char ch,char fc,char bc)

putoutChar()函数在屏幕上的指定位置输出指定的字符。其中,xy指明输出的位置,ch表示输出的字符,fc表示输出的字符颜色,bc 表示背景色。

 

2、 printWall()

函数原型:void printWall(int x,int y)

printWall()函数用于画墙壁,传入参数xy指明位置。该函数调用putoutChar()进行输出,以黑色为背景画绿色墙,用小方块表示墙(ASCII值为219)。

 

3、 printBox()

函数原型:void printBox(int x,int y)

printBox()函数用于在非目的地画箱子,传入参数xy指明位置。该函数调用putoutChar()进行输出,以黑色为背景白色箱子,用ASCII值为10的字符表示箱子。

 

4、 printBoxDes()

函数原型:void printBoxDes(int x,int y)

printBoxDes()函数用于在目的地画箱子,传入参数xy指明位置。该函数调用putoutChar()进行输出,以黑色为背景画黄色箱子,仍用ASCII值为10的字符表示箱子。

 

5、 printDestination()

函数原型:void printDestination(int x,int y)

printDestination()函数用于画目的地,传入参数xy指明位置。该函数调用putoutChar()进行输出,以黑色为背景画黄色目的地,用心型表示(ASCII值为003)。

 

6、 printDestination1()

函数原型: void printDestination1(int x,int y,winer **win,winer **pw)

printDestination1()函数与printDestination()函数功能基本相同,都是画目的地函数,但是printDestination1()增加了记录每一个目的地位置的功能。其中xy指明目的地的位置,每一关的所有目的地位置存放在结构体struct winer中,形成一条链表,**winer返回链表的头,**pw则指向链表的尾部。

 

7、 printMan()

函数原型: void printMan(int x,int y)

printMan()函数用于画小人。X、y指明画的位置。该函数通过软中断来实现,首先设置寄存器AX的高位和低位,设置高位0xa表示在光标位置显示字符;设置低位02(ASCII),表示输出的字符;然后设置寄存器CX01,表示重复输出的次数,这里只输出一次;最后产生类型为0x10的中断,表示显示器输出。

 

8、 init()

函数原型: void init()

init()函数用于初始化屏幕。该函数首先用两个for循环初始化屏幕20*20范围内的状态,初始化为0,以后根据实际情况重新赋值;然后设置屏幕输出状态,设置寄存器AX的高位为0,低位为3,表示以80*25的彩色方式显示;最后移动光标到指定的位置输出操作提示信息以及版权信息。

 

9、 初始化游戏

函数原型:winer *initStep1()winer *initStep2()winer *initStep3()winer *initStep4()

这几个函数分别初始化游戏的第一关到第四关。这些函数的功能和实现步骤相似。首先根据需要在指定的位置画墙壁和画箱子,在这里可以设置游戏的难度,初始化的墙壁越复杂,箱子越多,则游戏就越难。游戏的第一关至第四关难度依次增加。然后分别调用printDestination1()printMan()函数画目的地和小人。函数返回包含各个目的地位置的链表。

 

10、 移动箱子

函数原型: void moveBoxSpacetoSpace(int x,int y,char a)void moveBoxDestoSpace(int x,int y, char a)void moveBoxSpacetoDes(int x,int y,char a)void moveBoxDestoDes(int x,int y,char a)

这几个函数实现的功能分别是人空地移动箱子到空地、从目的地移动箱子到空地、从空地移动箱子到目的地和中从目的地移动箱子到目的地。X、y指明小人当前所处的位置,字符a表示移动的方向,有“u”、“d”、“l”和“r4个值,分别表示向上、下、左、右移动。这几个函数的实现原理大致相似。对于前面两个函数,首先判断移动的方向,人小人所在的位置沿着移动的方向移动一步画小人,移动两步画箱子(调用printBox()函数),并设置状态为“b”;对于后面两个参数,首先判断移动的方向,从小人所在的位置沿着移动方向移动一步画小人,移动两上在目的地画箱子(调用printBoxDes()函数),并设置状态为“i”,表明箱子在目的地上。

 

11、 judge()

函数原型: int judge(int x,int y)

judge()根据结构体struct[x][y]中存的值来判断该点的状态。

 

12、 move()

函数原型: void moid(int x,int y,char a)

Move()函数根据按下的键来处理小人的移动。小人移动的方向有上(“u)、下(“d”)、左(“l”)、右(“r”)4个,4个方向的处理方式一样。首先判断移动的方向,然后根据小人的当前位置、下一步位置以及下下一步位置所在的状态进行处理。

(1) 若下一步所在位置的状态为墙壁(“w”),则直接退出,不作任何处理。

(2) 若下一步所在位置的状态为目的地(“i”)或者什么都没有(“0”),则:

① 若当前位置的状态为目的地,则在当前位置画目的地(调用printDestination()函数)、在下一步位置画小人(调用printMan()函数)。

② 若当前位置的状态为非目的地,则输出空格清空当前位置的小人,并在下一步位置画小人(调用printMan()函数)。

(3) 若下一步所在位置的状态为箱子(“b”),则:

① 如果下下一步位置的状态为“0”,则把箱子从空地移动到空地(调用moveBoxSpacetoSpace()函数),然后把光标移动到下一步位置(如果当前位置的状态为目的地,则应先画目的地(调用printDestinanion()函数))。

② 如果下下一步位置的状态为目的地,则把箱子从空地移动到目的地(调用moveBoxSpacetoDes()函数),然后把光标移动到下一步位置(如果当前位置的状态   为目的地,则应先画目的地(调用printDestination()函数))。

③ 其它情况则直接返回,不作任何处理。

(4) 若下一步所在位置的状态为箱子在目的地(“i”),则:

① 如果下下一步位置的状态为“0”,则把箱子从目的地移动到空地(调用moveBoxDestoSpace()函数),然后把光标移动到下一步位置(如果当前位置的状态为目的地,则应先画目的地(调用printDestination()函数))。

② 如果下下一步位置的状态为目的地,则把箱子从目的地移动到目的地(调用moveBoxDestoDes()函数),然后把光标移动到下一步位置(如果当前位置的状态为目的地,则应先画目的地(调用printDestination()函数))。

③ 其它情况则直接返回,不作任何处理。

 

13、 reset()

函数原型:void reset(int i)

reset()函数的功能是重置当前关。该函数首先判断当前关是第几关,然后调用init()函数和初始化当前关的函数进行重置。

 

14、 主函数

主函数首先设置寄存器AX的高位和低位,显示器软中断,进行显示状态的设置,初始化

屏幕,初始化第一关,并显示操作提示信息和版权信息。然后根据按下的键(bioskey(0)函数返回按下的键值)进行处理,处理过程由move()函数进行(如果按下Esc键,则退出程序)。对于每一关,如果所有的表示目的地的状态都由“m”变成了“i”,则表示通过该关,可以进入下一关。

 

附上优化代码:

#include <dos.h> 

#include <stdio.h> 

#include <ctype.h> 

#include <conio.h> 

#include <bios.h> 

#include <alloc.h>

1、 初始化模块

void init(),初始化屏幕的大小、显示方式、显示操作提示信息和版权信息。

winer *initStep1(),初始化游戏的第一关。

winer *initStep2(),初始化游戏的第二关。

winer *initStep3(),初始化游戏的第三关。

winer *initStep4(),初始化游戏的第四关。

其中初始化屏幕函数的详细代码如下:

void init() 

    int i,j; 

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

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

     /*屏幕20*20范围内状态初始化为0,表示什么都没有*/

        status[i][j]=0; 

      /*设置寄存器AX低位,80*25彩色方式显示*/

_AL=3;

/*设置寄存器AX高位*/ 

    _AH=0; 

geninterrupt(0x10);

/*移动光标到指定位置输出屏幕信息*/ 

    gotoxy(41,4); 

    printf(" --------- up"); 

    gotoxy(41,6); 

    printf(" --------- down"); 

    gotoxy(41,8); 

    printf(" --------- left");

    gotoxy(41,10); 

    printf(" --------- right"); 

    gotoxy(40,12); 

    printf("Space ----- reset"); 

    gotoxy(40,14); 

    printf("Esc ------- quit"); 

    gotoxy(18,24);

    printf("CopyRight: 2008 LuoFuxing");

    gotoxy(40,4);

    _CX=01;

    _AH=0xa;

    _AL=24;

    geninterrupt(0x10);

    gotoxy(40,6);

    _CX=01;

    _AH=0xa;

    _AL=25;

    geninterrupt(0x10);

    gotoxy(40,8);

    _CX=01;

    _AH=0xa;

    _AL=27;

    geninterrupt(0x10);

    gotoxy(40,10);

    _CX=01;

    _AH=0xa;

    _AL=26;

    geninterrupt(0x10);

}

 

2、 画图模块

void printWall(int x,int y),用于画墙。

void printBox(int x,int y),在空白地(非目的地)画箱子。

void printBoxDes(int x,int y),在目的地画箱子。

void printDestination(int x,int y),画目的地函数。

void printDestination1(int x,int y,winer **win,winer **pw),画目的地函数,并记录每个目的地的位置。

void printMan(int x,int y),画小人函数。

其中画墙函数的代码如下:

void printWall(int x,int y) 

/*以黑色为背景画绿色墙,用小方块表示*/

putoutChar(y-1,x-1,219,GREEN,BLACK);

/*记录状态为墙*/ 

    status[x][y]='w'; 

}

 

3、 移动箱子模块

void moveBoxSpacetoSpace(int x,int y,char a),把箱子从空地移动到空地。

void moveBoxDestoSpace(int x,int y,char a),把箱子从目的地移动到空地。

void moveBoxSpacetoDes(int x,int y,char a),把箱子从空地移动到目的地。

void moveBoxDestoDes(int x,int y,char a),把箱子从目的地移动到目的地。

其中从空地移动箱子到空地函数的详细代码如下:

void moveBoxSpacetoSpace(int x,int y,char a) 

    switch(a)

{

/*如果按向上键*/

case 'u':

/*重设((x-1),y)位置的状态为0*/

status[x-1][y]=0;

/*清空(x,y)处原有的小人*/

printf(" "); 

/*在((x-2),y)处重新画箱子*/

printBox(x-2,y);

/*在((x-1),y)处重新画小人*/

printMan(x-1,y); 

/*重设((x-2),y)位置的状态为箱子*/

    status[x-2][y]='b';

break; 

/*如果按向下键*/

    case 'd':

    status[x+1][y]=0;

    printf(" "); 

    printBox(x+2,y);

    printMan(x+1,y); 

    status[x+2][y]='b';

break;

/*如果按向左键*/

    case 'l':

    status[x][y-1]=0;

    printf(" "); 

    printBox(x,y-2);

    printMan(x,y-1); 

    status[x][y-2]='b';

break;

/*如果按向右键*/

    case 'r':

    status[x][y+1]=0;

    printf(" "); 

    printBox(x,y+2);

    printMan(x,y+1); 

    status[x][y+2]='b';

    break;

    default:

    break;

    }

}     

 

 

4、 移动小人模块

void move(int x,int y,char a) 

    switch(a) 

{

/*如果按向上键*/

case 'u':

/*如果(x-1,y)即小人的下一步状态为墙*/

    if(!judge(x-1,y))

{

    /*则跳转到(y,x),并跳出循环*/

        gotoxy(y,x); 

        break; 

}

/*如果小人的下一步状态为目的地或者什么都没有*/

    else if(judge(x-1,y)==1||judge(x-1,y)==3) 

{

    /*如果当前状态为目的地*/

        if(judge(x,y)==3) 

        {

        /*画目的地*/

        printDestination(x,y);

        /*在新位置重新画小人*/

        printMan(x-1,y); 

        break; 

        }

        /*如果下一步状态为0*/

        else 

        {

        /*输出空字符,覆盖当前状态的小人*/

        printf(" "); 

        /*在下一步重新画小人*/

        printMan(x-1,y); 

        break; 

        }

}

/*如果下一步状态是箱子*/

    else if(judge(x-1,y)==2) 

{

/*如果下下一步为空*/

        if(judge(x-2,y)==1) 

        {

        /*则将箱子从空地向上移动到空地*/

        moveBoxSpacetoSpace(x,y,'u'); 

        /*如果当前状态为目的地*/

        if(judge(x,y)==3)  

            /*画目的地*/

            printDestination(x,y);  

        gotoxy(y,x-1); 

        }

        /*如果下下一步为目的地*/

        else if(judge(x-2,y)==3) 

        {

        /*则将箱子从空地向上移动到目的地*/

        moveBoxSpacetoDes(x,y,'u'); 

        if(judge(x,y)==3) 

            printDestination(x,y); 

        gotoxy(y,x-1); 

        }

        else 

                gotoxy(y,x); 

        break;

}

……

……

 

5、   功能控制模块

void putoutChar(int y,int x,char fc,char bc),在屏幕上指定的位置输出指定的字符。

int judge(int x,int y),判断位置(x,y)处的状态,状态值可参见“数据结构设计”部分。

void reset (int i),重置关卡。

其中在屏幕上的指定位置输出指定的字符函数的代码如下:

void putoutChar(int y,int x,char ch,char fc,char bc) 

{

    /*屏幕输出字符*/

printScreen[(x*160)+(y<<1)+0]=ch;

/*指定字符颜色fc,背景色bc*/ 

printScreen[(x*160)+(y<<1)+1]=(bc*16)+fc; 

}

 

 

6、 主函数

void main() 

    /*记录按下的键*/

    int key;

    int x;

int y;

/*记录未被推到目的地的箱子个数*/

int s;

/*记录已经过了几关*/

    int i=0; 

    winer *win;

winer *pw; 

/*设置寄存器AX低位*/

_AL=3;

/*设置寄存器AX高位*/

    _AH=0; 

    geninterrupt(0x10); 

    init(); 

    win=initStep1(); 

do{

/*设置AH,读取光标位置*/

    _AH=3; 

geninterrupt(0x10); 

/*读取光标所在的行,加1*/

x=_DH+1;

/*读取光标所在的列,加1*/

y=_DL+1; 

/*bioskey(1)返回0,直到有键按下*/

while(bioskey(1)==0);

/*返回按下的键*/

    key=bioskey(0); 

    switch(key) 

{

/*如果按下向上键*/

    case 0x4800:

        move(x,y,'u');

        break;

    /*如果按下向下键*/

    case 0x5000:

        move(x,y,'d');

        break;

    /*如果按下向左键*/

    case 0x4b00:

        move(x,y,'l');

        break;

    /*如果按下向右键*/

    case 0x4d00:

        move(x,y,'r');

        break;  

    /*如果按下空格键*/

    case 0x3920:

        reset(i);

        break;

    default:

        break; 

    }    

    s=0; 

pw=win; 

/*如果指针非空*/

    while(pw) 

/*如果目的地的状态为m,不是i,表示还有箱子

未被推到目的地,该关还未完成*/

        if(status[pw->x][pw->y]=='m')

        /*未被推到目的地的箱子数*/

        s++; 

        /*判断下一个目的地的状态*/

        pw=pw->p; 

}

/*该关完成*/

    if(s==0) 

    /*释放分配的空间*/

        free(win);

        gotoxy(15,20);

        printf("congratulate! You have done this step!"); 

        getch();

        i++; 

        switch(i) 

        {

        /*进入第二关*/

        case 1:

        init();

        win=initStep2();

        break;

        /*进入第三关*/

        case 2:

        init();

        win=initStep3();

        break;

        /*进入第四关*/

        case 3:

        init();

        win=initStep4();

        break;

        /*完成所有关*/

        case 4:

        gotoxy(15,21); 

        printf("Congratulation! \n");

        gotoxy(15,22);

        printf("You have done all the steps, You are very clever!");

                /*设置键为Esc以便退出程序*/ 

        key=0x011b;

        /*按任意键结束*/

        getch();

        break;

        default:

        break; 

        } 

    } 

 

    }while(key!=0x011b); 

    _AL=3; 

    _AH=0; 

    geninterrupt(0x10); 

}

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值