MFC写的贪吃蛇代码.docx

上传人:b****6 文档编号:5883937 上传时间:2023-01-01 格式:DOCX 页数:19 大小:922.68KB
下载 相关 举报
MFC写的贪吃蛇代码.docx_第1页
第1页 / 共19页
MFC写的贪吃蛇代码.docx_第2页
第2页 / 共19页
MFC写的贪吃蛇代码.docx_第3页
第3页 / 共19页
MFC写的贪吃蛇代码.docx_第4页
第4页 / 共19页
MFC写的贪吃蛇代码.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

MFC写的贪吃蛇代码.docx

《MFC写的贪吃蛇代码.docx》由会员分享,可在线阅读,更多相关《MFC写的贪吃蛇代码.docx(19页珍藏版)》请在冰豆网上搜索。

MFC写的贪吃蛇代码.docx

MFC写的贪吃蛇代码

手把手教“MFC版贪吃蛇教程”

写在前面的话

本次贪吃蛇教程主要知识点包括以下几个方面

1CView类中的消息响应

2控件的消息响应

3基于CView类内的具体游戏实现

4数组

5游戏图形的实现用CDC类实现。

本版游戏的具体实现是在CViewl类中实现,所以其他类不用添加任何代码。

由于此次贪吃蛇需要MFC的开发环境,所以打开VisualC++新建一个MFCAppWizard单文档工程,随意取名一个工程名称。

 

本次贪吃蛇基本流程与大体思想

1定义蛇类和食物类,初始化贪吃蛇各项成员变量,包括图像的出现在屏幕的初始位置,长度,以及蛇的行走方向。

食物类的定义包括出现的初始位置,以及食物是否被吃掉的判断。

2用数组初始化长度为3的贪吃蛇,并且默认食物未出现

3在CView类上运用MFC提供的Windows消息中WM_TIMER消息,运用OnTimer()函数让系统提供一个时钟节拍,更新游戏

4具体游戏实现,包括蛇撞到自己和围墙都将使游戏结束,判断吃豆等,其中还包括根据蛇的长度来进行游戏难度的改变。

5具体键盘游戏操作运用到Windows消息响应中的WM_KEYDOWN,用OnKeyDown()来响应玩家的实际操作。

=10;

Snake[0].y=10;

Snake[1].x=11;

Snake[1].y=10;

Snake[2].x=12;

Snake[2].y=10;

Snake[0].direct=3;

Snake[0].len=3;

=1;

irect!

=2)Snake[0].direct=1;break;

caseVK_DOWN:

if(Snake[0].direct!

=1)Snake[0].direct=2;break;

caseVK_LEFT:

if(Snake[0].direct!

=4)Snake[0].direct=3;break;

caseVK_RIGHT:

if(Snake[0].direct!

=3)Snake[0].direct=4;break;}

CView:

:

OnKeyDown(nChar,nRepCnt,nFlags);

CView:

:

OnKeyDown(nChar,nRepCnt,nFlags);

}

OnKeyDown函数的第一个参数UINTnChar是接收用户键入的信息,然后我们用switch进行选择判断

代码说明:

Snake[0]代表的是蛇头,我们对蛇头的方向Snake[0].direct进行判断。

caseVK_UP:

if(Snake[0].direct!

=2)Snake[0].direct=1;break;

意思就是当Snake[0].direct的方向此时并不等于“下”的时候,才能做出“上”的操作动作,否则则忽略用户“向上”的操作按键效果

Step3对OnRButtonDown()具体添加代码

voidCSNAKEView:

:

OnRButtonDown(UINTnFlags,CPointpoint)

{

-1;i++)

pDC->Rectangle(snake[i].x*20,snake[i].y*20,(snake[i].x+1)*20,(snake[i].y+1)*20);

pDC->SelectObject(DrawBrush);

}

 

代码说明:

利用Windows给我们提供的CDC类来进行画图,我们首先用一个指向CDC类的指针去接受与该窗口相关联的DC句柄,然后用定义画刷一个DrawBrush对象,并且用RGB(100,100,100)来给画刷初始化颜色。

并且用SelectObject(&DrawBrush);函数把对象画刷选入到设备描述表中,用for循环依次把贪吃蛇的3个节点画出来。

voidfarrectangle(intleft,inttop,intright,intbottom);

这个函数的的功能根据

函数功能:

该函数画一个矩形,用当前的画笔画矩形轮廓,用当前画刷进行填充.

Step5控件添加代码

voidCSNAKEView:

:

OnStart()

{

.");

}

voidCSNAKEView:

:

OnExit()

{

.");

exit0;

}

voidCSNAKEView:

:

OnContinue()

{

图类的输出基本上都是在视图类的OnDraw函数中处理的,系统会准备好入参,然后调用OnDraw函数

本人也没有过多的去研究过次函数,仅知道一些皮毛。

不过这里有个知识点那便是OnPaint()与OnDraw()的区别,OnPaint()派生于CWnd类,响应WM_PAINT消息。

OnDraw是CView类的成员函数,并且没有消息响应功能,这就是为什么视图类没有只有OnDraw()而没有OnPaint()的原因。

OnDraw()维护视图客户区(例如通过试表在视图中画图),而OnPaint()维护窗口的客户区

voidCSNAKEView:

:

OnDraw(CDC*pDC)

{

CSNAKEDoc*pDoc=GetDocument();

ASSERT_VALID(pDoc);

en==2)SetTimer(1,370,NULL);

if(Snake[0].len==3)SetTimer(1,270,NULL);

if(Snake[0].len==6)SetTimer(1,200,NULL);

if(Snake[0].len==9)SetTimer(1,100,NULL);

("得分:

%d!

",(Snake[0].len-3)*10);

*20<=37||Snake[0].y*20<=37||Snake[0].x*20>=462||Snake[0].y*20>=462)

{

KillTimer

(1);

AfxMessageBox(soure);

en>3)

for(intsn=Snake[0].len-1;sn>0;sn--)

{

if(Snake[0].x*20==Snake[sn].x*20&&Snake[0].y*20==Snake[sn].y*20)

{

KillTimer

(1);

AfxMessageBox(soure);

en-1].x*20,Snake[Snake[0].len-1].y*20,(Snake[Snake[0].len-1].x+1)*20,(Snake[Snake[0].len-1].y+1)*20);

for(inti=Snake[0].len-1;i>0;i--)

{

Snake[i].x=Snake[i-1].x;

Snake[i].y=Snake[i-1].y;

}

irect==1)Snake[0].y--;

if(Snake[0].direct==2)Snake[0].y++;

if(Snake[0].direct==3)Snake[0].x--;

if(Snake[0].direct==4)Snake[0].x++;

pDC->SelectStockObject(BLACK_PEN);

CBrushDrawBrush=(RGB(100,100,100));

CBrush*Drawbrush=pDC->SelectObject(&DrawBrush);

pDC->Rectangle(Snake[0].x*20,Snake[0].y*20,(Snake[0].x+1)*20,(Snake[0].y+1)*20);

pDC->SelectObject(DrawBrush);

*20==*20&&Snake[0].y*20==*20)

{

Snake[0].len++;

=1;

Snake[Snake[0].len-1].x=Snake[Snake[0].len-2].x;

Snake[Snake[0].len-1].y=Snake[Snake[0].len-2].y;

}

en-1;isfo>=0;isfo--)

if(Snake[0].x*20==Snake[isfo].x*20&&Snake[0].y*20==Snake[isfo].y*20)

{

=rand()%;

=rand()%;

}

}

while*20<70||*20<70||*20>430||*20>430);

pDC->Rectangle*20,*20,+1)*20,+1)*20);

=0;

}

CView:

:

OnTimer(nIDEvent);

}

 

en==2)SetTimer(1,370,NULL);

if(Snake[0].len==3)SetTimer(1,270,NULL);

if(Snake[0].len==6)SetTimer(1,200,NULL);

if(Snake[0].len==9)SetTimer(1,100,NULL);

此段代码的作用是根据蛇的长度来进行SetTimer()函数的定义,可以根据长度来进行游戏难度的设定,如上代码分别370ms270ms200ms100ms进行一次新的移动。

*20<=37||Snake[0].y*20<=37||Snake[0].x*20>=462||Snake[0].y*20>=462)

{

KillTimer

(1);

AfxMessageBox(soure);

}

这里为什么要乘以20呢由于我们初始化的时候是

Snake[0].x=10;

Snake[0].y=10;

Snake[1].x=11;

Snake[1].y=10;

Snake[2].x=12;

Snake[2].y=10;

所以只是把贪吃蛇的起始位置“搬移”到20倍的位置当然可以等价于

Snake[0].x=10*20;

Snake[0].y=10*20;

Snake[1].x=11*20;

Snake[1].y=10*20;

Snake[2].x=12*20;

Snake[2].y=10*20;

蛇的一节身体为一个矩形块,这样表示每个矩形块只需起点坐标x和y身体是不断增长的,所以用数组存放每一节的坐标

en>3)

for(intsn=Snake[0].len-1;sn>0;sn--)

{

if(Snake[0].x*20==Snake[sn].x*20&&Snake[0].y*20==Snake[sn].y*20)

{

KillTimer

(1);

AfxMessageBox(soure);

进行比较(之所以进行sn-1次那肯定是不包括蛇头而且蛇的长度也必须大于3才会发生自己咬自己的情况)

KillTimer

(1);是停止计时器;和之前的SetTime()对应而已

AfxMessageBox(soure);这里不深究,总之就是输出一个原样输出内容

pDC->SelectStockObject(WHITE_PEN);en-1].x*20,Snake[Snake[0].len-1].y*20,

(Snake[Snake[0].len-1].x+1)*20,(Snake[Snake[0].len-1].y+1)*20);en-1;i>0;i--)=Snake[i-1].x;

Snake[i].y=Snake[i-1].y;

}

这段的知识点要严重的说明一下

1为什么要专门用白笔画最后一个呢因为我们的游戏界面是用白色的,贪吃蛇移动的时候,肯定是蛇头向前走一单位,而尾部肯定要“擦除”掉一个单位,那怎么擦除呢我们只能用和背景色一样的画笔。

原来蛇的位置和新蛇的位置差一个单位,所以看起来蛇会多一节身体,所以将蛇的最后一节用背景色覆盖SelectStockObject(WHITE_PEN)让它起到“消失”最后一个节点的功能

让我们以为蛇是向前走了。

如假设现在贪吃蛇有4个单位0123

Snake[Snake[0].len-1].x*20<=>Snake[Snake[0].4-1].x*20=Snake[3].x*20

数组3恰好是最后一个节点的下标,别忘了数组是从0开始算的

请仔细领悟

2

for(inti=Snake[0].len-1;i>0;i--)

{

Snake[i].x=Snake[i-1].x;

Snake[i].y=Snake[i-1].y;

}

进行次数为"长度-1"次的循环

为什么要进行长度-1次呢我这里要说明一下,这里是不包括蛇头的进行的平移,用数组赋值的方法,把前一节点保存在后一个结点,然后头结点向前移动。

irect==1)Snake[0].y--;

if(Snake[0].direct==2)Snake[0].y++;

if(Snake[0].direct==3)Snake[0].x--;

if(Snake[0].direct==4)Snake[0].x++;

pDC->SelectStockObject(BLACK_PEN);

CBrushDrawBrush=(RGB(100,100,100));

CBrush*Drawbrush=pDC->SelectObject(&DrawBrush);

pDC->Rectangle(Snake[0].x*20,Snake[0].y*20,(Snake[0].x+1)*20,(Snake[0].y+1)*20);

pDC->SelectObject(DrawBrush);

“1234”本别代表“上下左右”x++,y++进行移动,然后用选定画刷画出一个新节点的矩形作为头结点

en-1;isfo>=0;isfo--)

if(Snake[0].x*20==Snake[isfo].x*20&&Snake[0].y*20==Snake[isfo].y*20)

{

=rand()%;

=rand()%;

}

}

while*20<70||*20<70||*20>430||*20>430);

pDC->Rectangle*20,*20,+1)*20,+1)*20);

=1;

}

这里关于

srand((unsigned)time(NULL));

rand()

的用法在本博客有研究帖这里不再赘述。

当食物被吃了指定食物的地方出现的地方在小于70和大于430的矩形区域内

并且把食物属性更改为“存在”

//////////////////////////////////////////////////////////////////

以上就是MFC版步骤已经详细之至了,通过此次贪吃蛇我发现MFC不难,不过花了我整整一个国庆的时间,茶饭不思夜不能寐

,CView类的强大我是第一次看到,以后我要多加关注CView类的知识点,写出这个文档的意义我觉得能让我的思路更加清晰,毕竟能和他人解释代码并且让别人能理解那是一件很愉快的事情。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 法律文书 > 辩护词

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1