}
//2 放置完成的前面是放置位置
else if(Map[(movex)/40-1][(movey)/40]==2){ } else{ }
key_up+=40;
Map[(movex)/40-1][(movey)/40]=5;//把放置完成的前面换成“完成”, Map[(movex)/40][(movey)/40]=2;//当前的放置完成换成位置 if(peopleflag==1){//之前人在位置上 }
else{//之前人不在位置上 }
peopleflag=1;//即将在位置上 movexold=movex; moveyold=movey;
Map[(movexold)/40][(moveyold)/40]=0;//路
Map[(movexold)/40][(moveyold)/40]=2;//位置
else if(Map[(movex)/40][(movey)/40]==2){//前面是位置 }
else if(Map[(movex)/40][(movey)/40]==1) { } }
key_up+=40;
Map[(movex)/40][(movey)/40]=2;//当前的放置完成换成位置 if(peopleflag==1){//之前人在位置上 }
else{//之前人不在位置上 }
peopleflag=1;//即将在位置上 movexold=movex;//之前路过 moveyold=movey;
Map[(movexold)/40][(moveyold)/40]=0;//路
Map[(movexold)/40][(moveyold)/40]=2;//位置
……
6
说明:例如当按方向键上时
① 先判断是否在有效区域内(避免越界),然后把key_up的值减40,重绘,接着进入了绘图函数中。
② 把四个方向的记录的移到值解析成水平方向和竖直方向的位置坐标值movex,movey, ③ 接着在movex/40,movey/40是把实际的坐标转换成二维数组中的相应位置。 ④ 状态的判断:判断人前面(指的是各个方向的前方)的情况。
a.如果是路,就把前面的值换成人的值,当前人的位置就换成路,这个地方我用的是
movexold=movex;moveyold=movey;来实现的。
b.如果为箱子,就判断箱子前面的值,如果是路,就把路换成箱子,箱子处换成人,人换成路。
c.如果为位置就把位置换成完成状态,箱子换成人,人换成路。 d.如果人前面是完成状态,就判断完成状态前面的情况:
前面是路,把路换成箱子(推出了箱子),完成状态换位置状态,人在位置上,这个地方用了一个peopleflag来表示。
如果完成状态前面是位置,就把前面的位置状态换成完成状态,完成状态换成,人在位置上的状态,当前人所在的位置状态换成之前movexold,moveyold所代表的状态。(实现从一个位置上推到另外一个位置,即在地图设计中多个位置相邻的情况的解决)
⑤其他情况(前面是墙,前面是箱子而箱子的前面还是箱子,箱子的前面是墙,箱子的前面是完成状态,前面是完成状态而完成状态的前面是箱子,完成状态的前面是墙……)都是保持原地不动,实现的方法为: key_up+=40(其他方向类似),这是因为在键盘消息处理时key_up-=40,所以此处要还原,以实现保持原地不动。 4.绘图的操作
/*绘制此时二维数组中的数值所代表的含义*/
SelectObject(mDc,hPen);//选中灰色画笔进行描边 for(i=0;i<11;i++){
7
for(j=0;j<11;j++){
if(Map[i][j]==1){//墙 }
else if(Map[i][j]==0){//路 }
SelectObject(mDc,roadbr);
Rectangle(mDc,40+40*j,40+40*i,80+40*j,80+40*i); SelectObject(mDc,wallbr);
Rectangle(mDc,40+40*j,40+40*i,80+40*j,80+40*i);
else if(Map[i][j]==3){//箱子 }
else if(Map[i][j]==2){//放置位置
SelectObject(mDc,positionbr);
SelectObject(mDc,boxbr); SelectObject(mDc,yellowpen);
Rectangle(mDc,40+40*j,40+40*i,80+40*j,80+40*i);
MoveToEx ( mDc , 40+40*j, 40+40*i , NULL );//绘制黄色方块中的\LineTo( mDc , 80+40*j,80+40*i);
MoveToEx ( mDc , 40+40*j,80+40*i , NULL );// LineTo( mDc , 80+40*j,40+40*i); SelectObject(mDc,hPen);
Rectangle(mDc,40+40*j,40+40*i,80+40*j,80+40*i); SetTextColor(mDc,Gray);
TextOut(mDc,55+40*j,52+40*i,TEXT(\),1);
if(peopleflag==1&&movexold/40==i&&moveyold/40==j){ }
SelectObject(mDc,popplebr);
Ellipse(mDc,40+40*j,40+40*i,80+40*j,80+40*i);
8
}
else if(Map[i][j]==5){//放置完成
SelectObject(mDc,successbr);
Rectangle(mDc,40+40*j,40+40*i,80+40*j,80+40*i); SelectObject(mDc,greenpen);
Rectangle(mDc,40+40*j,40+40*i,80+40*j,80+40*i);
MoveToEx ( mDc , 40+40*j, 40+40*i , NULL );//绘制黄色方块中的\LineTo( mDc , 80+40*j,80+40*i);
MoveToEx ( mDc , 40+40*j,80+40*i , NULL );// LineTo( mDc , 80+40*j,40+40*i); SelectObject(mDc,hPen); SetTextColor(mDc,white);
TextOut(mDc,42+40*j,52+40*i,TEXT(\),4);
}
}
}
else if(Map[i][j]==4){//\人\的位置 }
SelectObject(mDc,roadbr);
Rectangle(mDc,40+40*j,40+40*i,80+40*j,80+40*i); SelectObject(mDc,popplebr);
Ellipse(mDc,40+40*j,40+40*i,80+40*j,80+40*i); SetTextColor(mDc,white);
TextOut(mDc,53+40*j,52+40*i,TEXT(\♀\),2);
说明:用各种填充矩形来把地图的二维数组中的各值含义绘制在界面上
9
5.游戏界面说明
:箱子:人:位置:完成:障碍物:路
:表示过关,同时播放欢呼声 :表示当前的关数
10
6.游戏中使用的资源说明
四、总结
本次实验收获很大,掌握了二维数组的操作,比较完美的做出了推箱子游戏,更加熟悉了栈的使用,在本次实验中用链栈实现了回退机制。在实验中也遇到各种问题:在初始化栈时,
headp->next=tailp;
headp->before=NULL; tailp->before=headp; tailp->next=NULL;
我把这部分代码放到了WM_CREAT窗口创建消息中了,结果在回退时只能回退两步,在反复检查了几遍也没有发现问题,最后调试才发现根本就没有执行这段代码。把这段代码放到WinMain函数中解决了问题。在推箱子
的逻辑处理中因为有一段少写了
movexold=movex; moveyold=movey;
出现了莫名其妙的问题,分析查找了近半个小时才找到问题所在。这次实验也锻炼了我的耐心和信心。在选择用Win32 SDK来设计推箱子时,我也不是很有把握的,先从在窗口上画个圆,画个矩形开始的。程序设计中的太多问题让我几次不想采用Win32 SDK了,但是我还是坚持了下来,仔细琢磨,分析问题,推断问题,到最后完美的解决了问题,还是很开心的。在实现了推箱子的基本功能后,就是对代码的优化,美化界面,提高绘图效率。这次的实验用DirectX来做可能会简单点。
11