当前位置:文档之家› VC实现贪吃蛇的实验报告

VC实现贪吃蛇的实验报告

题目:利用VC++实现贪吃蛇小游戏一、题目:利用VC++实现贪吃蛇小游戏利用VC++实现的贪吃蛇小游戏更加注重可视化。

一条蛇在封闭的围墙内,在围墙内会随机出现一个食物,通过键盘上的W S A D四个键控制它向上,下,左,右四个方向移动。

当蛇头撞到食物时表示将食物吃掉,这时蛇身增长一节,得分加一。

接着随机生成食物,等待被蛇吃掉。

如果在移动过程中撞到墙壁或者自己的身体,则游戏结束。

游戏过程中,可以在菜单中选择暂停或者结束游戏,对游戏进行暂停或者退出。

二、编程要点(或基本思路、算法分析与说明):本次游戏设计包含两大模块,一个模块是贪吃蛇游戏本身算法的设计,完成了贪吃蛇的食物产生,获取食物,蛇的移动等功能。

另一个模块是利用MFC完成贪吃蛇的可视化显示,产生了一个对话框,在对话框可以控制游戏及游戏的显示。

1.贪吃蛇游戏算法设计包括:<1>果实出现的设计思路:(1)采用随机数生成果实出现坐标(2)判断当前生成的果实是否在贪吃蛇身体范围内。

(3)如果在,重新生成直到不在为止。

如果不在,则把坐标位置返回给调用对象。

<2>贪吃蛇更新的算法设计(1)接收玩家按下的方向键消息,并保存到方向变量中。

(2)定义一个时间定时器,用来控制蛇运动的速度。

(3)当每次时间间隔到达时,则根据方向变量来更新贪吃蛇curr(即贪吃蛇身体)向量。

(4)判断curr向量的第一个元素中的坐标数据是否碰到边界或者蛇身,如果有,则游戏结束。

否则,进行下一步。

(5)判断curr向量的第一个元素中的坐标数据是否与当前果实重合,如果有,表示贪吃蛇已经吃到果实。

这时就向贪吃蛇curr向量添加一个元素,并重新生成一个果实。

(6)吃到食物后,得分会同步增加。

2.利用MFC完成贪吃蛇的可视化显示:首先初始对话框,完成游戏的整体框架的显示。

然后游戏玩家在菜单栏里选择开始,暂停,结束等,控制游戏状态。

游戏开始后,玩家通过键盘上的消息控制蛇的运动。

在函数DrawSnake(CDC *pDC,Snake snake),和DrawFood(CDC *pDC,SnakeFood f)完成对蛇和食物的重绘,从而显示出蛇的运动和对食物的获取。

在OnPaint()函数中完成得分和游戏操作提示的显示。

本次游戏设计的主要功能函数如下:OnGameStart()(游戏开始函数), OnGamePauseStart()(游戏暂停函数)OnGameExit()(游戏退出函数),OnPaint()(游戏界面的显示函数),AddSnake(Snake *snake)(增加蛇身长度函数),DrawFood(CDC *pDC, SnakeFood f)(画食物函数),DrawSnake(CDC *pDC,Snake snake)(画蛇函数),MoveSnake(Snake *snake)(蛇的移动函数),InitSnake(Snake *snake)(初始化蛇函数),UnDrawSnake(Snake snake)(更新蛇函数),GameOver()(游戏结束函数)三、实现过程:(1) 流程图否是定时器启动否是否是(2) 主要功能程序代码:typedef struct SnakeNode //定义蛇结点{int x; //蛇每个节点的横纵坐标int y;}SnakeNode;typedef struct Snake //定义蛇的身体{SnakeNode data[100]; //用数组来表示蛇身体的每一节int curr; //移动指向蛇的每一节并统计蛇的长度}Snake;typedef struct food //定义食物结构体{int x; //食物的横坐标int y; //食物的纵坐标}SnakeFood;Snake snake;SnakeFood food;int x, y; //定义横纵坐标int direct; //定义方向变量int nGameState; //定义游戏的状态int score; //定义分数变量int speed; //定义速度变量int d; //该变量用于控制蛇身不能后退void InitSnake(Snake *snake); //初始化蛇void MoveSnake(Snake *snake); //蛇的移动void AddSnake(Snake *snake); //增加蛇的身体长度void DrawSnake(CDC *pDC , Snake snake); //绘制蛇void UnDrawSnake(Snake snake); //绘制蛇的显示框void DrawFood(CDC *pDC, SnakeFood f); //绘制食物int GameOver(); //游戏结束//完成与对话框的数据交互void CSnakeDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CSnakeDlg)// NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CSnakeDlg, CDialog)//{{AFX_MSG_MAP(CSnakeDlg)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_COMMAND(IDM_HELP_ABOUT, OnHelpAbout)ON_WM_TIMER()ON_COMMAND(IDM_GAME_START, OnGameStart)ON_WM_KEYDOWN()ON_COMMAND(IDM_GAME_PAUSE_START, OnGamePauseStart)ON_COMMAND(IDM_GAME_EXIT, OnGameExit)//}}AFX_MSG_MAPEND_MESSAGE_MAP()///////////////////////////////////////////////////////////////////// ////////// CSnakeDlg message handlersvoid CSnakeDlg::OnGameStart() //游戏开始函数{// TODO: Add your command handler code hereSetTimer(1,speed,NULL); //SetTimer一种API函数,定时器InitSnake(&snake);nGameState=1; //游戏开始时为1}void CSnakeDlg::OnGamePauseStart() //游戏暂停函数{// TODO: Add your command handler code hereCDC *pDC =GetDC();if(nGameState==0){if(!GameOver()){SetTimer(1,speed,NULL);nGameState=1;}}else{if(!GameOver()){KillTimer(1);nGameState=0;}}pDC->TextOut(70,130,"Pause!!!");}void CSnakeDlg::OnGameExit() //游戏退出函数{// TODO: Add your command handler code hereAfxGetMainWnd()->SendMessage(WM_CLOSE);}//处理键盘按键消息void CSnakeDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {// TODO: Add your message handler code here and/or call default switch(nChar){case 'D':if(direct!=2&&d!=2)direct=0;break;case 'S':if(direct!=3&&d!=3)direct=1;break;case 'A':if(direct!=0&&d!=0)direct=2;break;case 'W':if(direct!=1&&d!=1)direct=3;break;}if(nChar==VK_SPACE){if(nGameState==0){if(!GameOver()){SetTimer(1,speed,NULL);nGameState=1;}}else{if(!GameOver()){KillTimer(1);nGameState=0;}}}CDialog::OnKeyDown(nChar, nRepCnt, nFlags);}void CSnakeDlg::OnPaint() //游戏界面的显示函数{if (IsIconic()){CPaintDC dc(this); // device context for paintingSendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);// Center icon in client rectangleint cxIcon = GetSystemMetrics(SM_CXICON); //获取系统分辨率int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect); //获取窗口客户区的大小int x = (rect.Width() - cxIcon + 1)/2 ;int y = (rect.Height() - cyIcon + 1)/2;// Draw the icondc.DrawIcon(x, y, m_hIcon);}else{CDialog::OnPaint();}CDC *pDC = GetDC();pDC->SetBkColor(RGB(50,230,100)); //设置游戏提示字体背景颜色pDC->TextOut(220,30,"得分:0");pDC->TextOut(260,80,"上:W");pDC->TextOut(300,110,"下:S");pDC->TextOut(340,140,"左:A");pDC->TextOut(380,170,"右:D");pDC->TextOut(420,210,"空格暂停");//pDC->Rectangle(10,10,210,320);UnDrawSnake(pDC,snake);DrawSnake(pDC,snake);}void AddSnake(Snake *snake) //增加蛇身长度函数(在MoveSnake()函数中调用){int t=1,tx,ty,xx,yy;if(snake->curr<100)snake->curr++; //控制长度蛇身长度小于100xx=snake->data[0].x; //xx,yy记录蛇头坐标yy=snake->data[0].y;do{tx=snake->data[t].x; //tx,ty记录蛇身第一节坐标ty=snake->data[t].y;snake->data[t].x=xx; //蛇头坐标赋给蛇身第一节snake->data[t].y=yy;xx=tx; //将蛇身第一节坐标赋给新的蛇头yy=ty;t++; //蛇增加一节}while(t<snake->curr);}void DrawFood(CDC *pDC, SnakeFood f) //绘制食物函数{CString ss;pDC->SetBkColor(RGB(50,230,100));ss.Format("得分:%d",score);pDC->TextOut(220,30,ss);pDC->Rectangle(f.x*10+11,f.y*10+11,f.x*10+18,f.y*10+18);}void DrawSnake(CDC *pDC,Snake snake) //绘制蛇函数{int t;t=snake.curr-1;pDC->SelectStockObject(BLACK_BRUSH);pDC->SelectStockObject(BLACK_PEN);pDC->Rectangle(snake.data[t].x*10+11,snake.data[t].y*10+11,snake. data[t].x*10+18,snake.data[t].y*10+18);t--;pDC->SelectStockObject(HOLLOW_BRUSH);while(t>=0){pDC->Rectangle(snake.data[t].x*10+11,snake.data[t].y*10+11,snake. data[t].x*10+18,snake.data[t].y*10+18);t--;}}int GameOver() //游戏结束函数{int t;if(x<0||x>19||y<0||y>30)return 1;t = snake.curr-2;while(t){if(snake.data[t].x==x&&snake.data[t].y==y)return 1;t--;}return 0;}void InitSnake(Snake *snake) //初始化蛇函数{int t;direct=0; //初始方向置为0nGameState=0; //初始化时状态变为0score=0;speed=200;//刷新运动的时间间隔(数值越大,移动速度越慢,数值越小,移动速度越快)d=0; //控制蛇身不能后退snake->curr=2; //初始蛇深长度(2节)x=4; //蛇的横坐标(初始值)y=4; //蛇的纵坐标snake->data[0].x=x; //蛇头横坐标snake->data[0].y=y; //蛇头纵坐标food.x=rand()%20; //随机产生食物food.y=rand()%30;switch(direct){case 0: x+=1;break; //右case 1: y+=1;break; //上case 2: x-=1;break; //左case 3: y-=1;break; //下}snake->data[1].x=x; //蛇身第一节坐标(上一步中x坐标加1了)snake->data[1].y=y; //蛇身第一节坐标(上一步中y坐标不变)t=snake->curr-1; //此时t=1while(t) //当蛇身长度不为0时{if(snake->data[t].x==food.x&&snake->data[t].y==food.y){food.x=rand()%20;food.y=rand()%31;}t--; //从最后一节依次往前判断蛇身食物的关系}}void MoveSnake(Snake *snake) //移动蛇函数{int t, xx, yy;int tx, ty;switch(direct){case 0: x+=1;break; //右case 1: y+=1;break;case 2: x-=1;break;case 3: y-=1;break;}if(GameOver())return;xx=x;yy=y;if(xx==food.x&&yy==food.y){t=snake->curr-1;food.y=rand()%31; //随机生成数函数随机产生函数food.x=rand()%20;while(t){if(snake->data[t].x==food.x&&snake->data[t].y==food.y){food.y=rand()%31;food.x=rand()%20;t=snake->curr-1;}t--;}score+=1;if((score%10)==0)speed-=20;AddSnake(snake);}t=snake->curr-1;do{tx=snake->data[t].x;ty=snake->data[t].y;snake->data[t].x=xx;snake->data[t].y=yy;xx=tx;yy=ty;t--;}while(t>=0);}void UnDrawSnake(CDC *pDC, Snake snake) //绘制蛇的显示框函数{pDC->Rectangle(10,10,210,320); //显示蛇移动的文本框}四、运行结果展示:五、总结与心得体会:通过对大一课程的学习,我已经了解了C语言和C++语言程序设计的一些基本方法,进入到大二的学习,开始接触VC++面向对象编程。

相关主题