《猫捉老鼠小游戏》程序设计基础课程设计报告专业:计算机科学与技术班级:09级2班姓名:马建南学号: 2009082230 2009082233指导教师:郭攀2010年9月18日目录1 课程设计目的 (2)1.1课程设计目的 (2)1.2课程设计题目 (2)1.3题目要求 (2)2 总体设计 (2)(画出设计课题程序总体组成框图、流程图)3详细设计 (3)(各个模块功能说明(如函数功能、入口及出口参数说明,函数调用关系描述等)及模块程序流程图)4 课程设计的原程序代码 (4)(程序代码清单中应有足够的注释)5 运行结果............................................ .22(截图及说明)6 课程设计总结 (25)7 参考书目 (26)1 课程设计目的1.1课程设计目的设计一个猫和老鼠迷宫,显示猫和老鼠图像;设置游戏菜单、控制按钮、游戏时间、老鼠个数;进而实现游戏效果。
1.2课程设计题目猫捉老鼠小游戏1. 3 题目要求1)设计一个猫捉老鼠迷宫。
2)要求猫的速度大于老鼠的速度。
3)计算最短路径,每走一步,猫按最短路径抓获老鼠;最短路径可运用数据结构中的队列实现。
附加功能:1)迷宫随机生成。
2)增加老鼠个数。
2 总体设计框架图:3.详细设计1. OnDraw()函数显示迷宫及猫和老鼠。
2. OnTimer()函数判定结束标志,设置游戏时间。
3. OnKeyDown()函数实现猫的手动控制。
4. CDC *pDC 需要画位图的CDC指针UINT IDImage 位图资源IDCrect &rect 指定位图在pDC中的位置COLORREF rgbMask 位图的透明色atCatchRatView::CCatCatchRatView(){m_bmWall.LoadBitmap(IDB_Wall); //载入迷宫位图}6.void CCatCatchRatView::OnUpdateStop(CCmdUI* pCmdUI) {pCmdUI->Enable(StartFlag==1); //游戏过程中可以选停止菜单}通过不断改变猫鼠位图显示区域坐标,实现猫和老鼠的动态实现4.课程设计的源程序代码(主要代码)// CatCatchRatView.h : interface of the CCatCatchRatView class#if !defined(AFX_CATCATCHRATVIEW_H__B4196808_4145_49DF_ 99D0_45F38E4512CB__INCLUDED_)#defineAFX_CATCATCHRATVIEW_H__B4196808_4145_49DF_99D0_45F38 E4512CB__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#include "SelectDlg.h"#define RATMAX 5 //宏定义,老鼠的最大个数class CCatCatchRatView : public CView{public:CBitmap m_bmCat[4],m_bmRat[4]; //猫和老鼠的位图CBitmap m_bmWall;int StartFlag; //程序运行状态,-1:初始,0:暂停,1:开始,2:结束bool m_bRatLive[RATMAX]; //老鼠存活标志int m_nWallw,m_nWallh;int m_nWallx,m_nWally;int m_nCatw,m_nCath; //猫位图的宽和高int m_nCatx,m_nCaty; //猫位图的左上角坐标//猫和老鼠的运动方向int m_nRatDirection[RATMAX],m_nCatDirection;int m_nRatw,m_nRath; //老鼠位图的宽和高//老鼠位图的左上角坐标int m_nRatx[RATMAX],m_nRaty[RATMAX];CRect m_rectClient; //场地矩形CRect m_rectWall; //墙矩形CRect m_rectRat[RATMAX],m_rectCat; //猫鼠位图的矩形int m_nRat; //待抓老鼠数int m_nRatSpeed,m_nCatSpeed; //运动速度CTime m_timeStart,m_timeEnd; //游戏开始和结束时间CTimeSpan m_timeWork,m_timeSet; //游戏剩余时间和设定时间int m_nDifficulty; //难度0:低,1:中,2:高int m_nWinFlag; //游戏获胜者,0:猫获胜,1:老鼠获胜protected: // create from serialization onlyCCatCatchRatView();DECLARE_DYNCREATE(CCatCatchRatView)public:CCatCatchRatDoc* GetDocument();public:protected:这是一个用来画透明位图的函数CDC *pDC 需要画位图的CDC指针UINT IDImage 位图资源IDCrect &rect 指定位图在pDC中的位置COLORREF rgbMask 位图的透明色*/void DrawTransparentBitmap(CDC *pDC,CBitmap &Image,CRect &rect, COLORREF rgbMask);// Overrides// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CCatCatchRatView)public:virtual void OnDraw(CDC* pDC);virtual BOOL PreCreateWindow(CREATESTRUCT& cs);protected:virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);//}}// Implementationpublic:virtual ~CCatCatchRatView();#ifdef _DEBUGvirtual void AssertValid() const;virtual void Dump(CDumpContext& dc) const;#endifprotected:// Generated message map functionsprotected://{{AFX_MSG(CCatCatchRatView)afx_msg void OnTimer(UINT nIDEvent);afx_msg void OnRestart();afx_msg void OnStart();afx_msg void OnStop();afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);afx_msg void OnUpdateStop(CCmdUI* pCmdUI);afx_msg void OnSelect();afx_msg void OnUpdateStart(CCmdUI* pCmdUI);//}}AFX_MSGDECLARE_MESSAGE_MAP()};//view.Cpp#include "stdafx.h" //创建MFC.EXE后系统自动生成******** #include "CatCatchRat.h"#include "CatCatchRatDoc.h"#include "CatCatchRatView.h"//********************************// CCatCatchRatViewCCatCatchRatView::CCatCatchRatView(){//载入迷宫位图******************************************* m_bmWall.LoadBitmap(IDB_Wall);//载入猫和老鼠的位图资源m_bmCat[0].LoadBitmap(IDB_CatUp);m_bmCat[1].LoadBitmap(IDB_CatDown);m_bmCat[2].LoadBitmap(IDB_CatLeft);m_bmCat[3].LoadBitmap(IDB_CatRight);m_bmRat[0].LoadBitmap(IDB_RatUp);m_bmRat[1].LoadBitmap(IDB_RatDown);m_bmRat[2].LoadBitmap(IDB_RatLeft);m_bmRat[3].LoadBitmap(IDB_RatRight);//设置迷宫高和宽BITMAP bmWall;m_bmWall.GetBitmap(&bmWall);m_nWallw=bmWall.bmWidth;m_nWallh=bmWall.bmHeight;//计算猫和老鼠位图的高和宽BITMAP bmCat;m_bmCat[2].GetBitmap(&bmCat);m_nCatw=bmCat.bmWidth;m_nCath=bmCat.bmHeight;BITMAP bmRat[4];m_bmRat[0].GetBitmap(&bmRat[0]);m_bmRat[1].GetBitmap(&bmRat[1]);m_bmRat[2].GetBitmap(&bmRat[2]);m_bmRat[3].GetBitmap(&bmRat[3]);m_nRatw=bmRat[0].bmWidth;m_nRath=bmRat[0].bmHeight;//场地矩形和老鼠数目设置m_rectClient=CRect(20,20,1188,666);m_nRat=RATMAX;StartFlag=-1;//计算猫和老鼠位图的初时位置和运动方向m_nCatx=m_rectClient.left+m_rectClient.Width()/2;m_nCaty=m_rectClient.top+m_rectClient.Height()/2;m_rectCat=CRect(m_nCatx,m_nCaty,m_nCatx+m_nCatw,m_nCaty+ m_nCath);m_nCatDirection=2;srand((unsigned)time(NULL));for(int i=0;i<RATMAX;i++)//计算老鼠初始位置m_nRatx[i]=m_rectClient.left+rand()%(m_rectClient.Width() -m_nRatw);m_nRaty[i]=m_rectClient.top+rand()%(m_rectClient.Height()-m_nRath);m_rectRat[i]=CRect(m_nRatx[i],m_nRaty[i],m_nRatx[i]+m_nRat w,m_nRaty[i]+m_nRath);m_nRatDirection[i]=rand()%4;m_bRatLive[i]=TRUE;}//初始难度设为中m_nDifficulty=1;m_timeWork=m_timeSet=120;//游戏时间120秒m_nCatSpeed=5;m_nRatSpeed=3;m_nWinFlag=-1;//显示猫和老鼠及迷宫****************************void CCatCatchRatView::OnDraw(CDC* pDC){CCatCatchRatDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);pDC->Rectangle(CRect(19,19,1189,667));//显示游戏状态CString strTime;CString strRat;strTime.Format("剩余时间: %2d:%2d:%2d",m_timeWork.GetHours(),m_timeWork.GetMin utes(),m_timeWork.GetSeconds());strRat.Format("待抓老鼠:%3d",m_nRat);pDC->TextOut(200,0,strTime);pDC->TextOut(400,0,strRat);//*******************迷宫外围**********************//迷宫指针CDC memWallDC;CBitmap *MgDC;//*********位图指针*********memWallDC.CreateCompatibleDC(NULL);//计算迷宫初始位置m_rectWall=CRect(m_nWallx,m_nWally,m_nWallx+m_nWallw,m_n Wally+m_nWallh);//显示迷宫代码过长且重复,省略部分代码***m_nWallx=m_rectClient.left+0;m_nWally=m_rectClient.top+0;MgDC=memWallDC.SelectObject(&m_bmWall);pDC->BitBlt(m_nWallx,m_nWally,m_nWallw,m_nWallh,&memWall DC,0,0,SRCAND);memWallDC.SelectObject(MgDC);//显示猫和老鼠CDC memDC[RATMAX];CDC memCatDC;CBitmap *pOldDC;//猫位图指针*****************memCatDC.CreateCompatibleDC(NULL);pOldDC=memCatDC.SelectObject(&m_bmCat[m_nCatDirection]);pDC->BitBlt(m_nCatx,m_nCaty,m_nCatw,m_nCath,&memCatDC,0, 0,SRCAND);memCatDC.SelectObject(pOldDC);//r.left=m_nCatx;r.top=m_nCaty;r.right=r.left+m_nCatw;r.bottom=r.top+m_nCath;for(int i=0;i<RATMAX;i++){if(m_bRatLive[i]){memDC[i].CreateCompatibleDC(NULL);pOldDC=memDC[i].SelectObject(&m_bmRat[m_nRatDirection[i]; pDC->BitBlt(m_nRatx[i],m_nRaty[i],m_nRatw,m_nRath,&memDC[i ],0,0,SRCAND);memDC[i].SelectObject(pOldDC);}}//游戏结束标志if(StartFlag==2){pDC->TextOut(40,50,"Game Over!");if(m_nWinFlag==0){pDC->TextOut(40,100,"猫获胜!");}if(m_nWinFlag==1){pDC->TextOut(50,100,"老鼠获胜!");}m_nWinFlag=-1;}if(m_nRat>0){//有老鼠未被抓住srand((unsigned)time(NULL));for(int i=0;i<RATMAX;i++){if(m_bRatLive[i]){//对未被抓住的老鼠进行处理switch(nIDEvent)//参考贪吃蛇***********************{case 2://该变老鼠运动方向m_nRatDirection[i]=rand()%4;break;case 1: //改变老鼠位置InvalidateRect(m_rectRat[i]);int nRatMoveStep=m_nRatSpeed+rand()%5;//老鼠移动的距离if((abs(m_nRatx[i]-m_nCatx)<3*m_nRatw)&&(abs(m_nRaty[i]-m_nCaty)<3*m_nRath)){ //如果老鼠靠近了猫就改变方向m_nRatDirection[i]=rand()%4;}switch(m_nRatDirection[i]){case 0: //向上移动if(m_rectRat[i].top-nRatMoveStep>89){m_rectRat[i].top-=nRatMoveStep;m_rectRat[i].bottom-=nRatMoveStep;m_nRaty[i]-=nRatMoveStep;}else{//运动到边界侧改变方向m_nRatDirection[i]=rand()%4;}break;case 1: //向下移动if(m_rectRat[i].bottom+nRatMoveStep<589){m_rectRat[i].top+=nRatMoveStep;m_rectRat[i].bottom+=nRatMoveStep;m_nRaty[i]+=nRatMoveStep;}else{//运动到边界侧改变方向m_nRatDirection[i]=rand()%4;}break;case 2: //向左移动if(m_rectRat[i].left-nRatMoveStep>93){m_rectRat[i].left-=nRatMoveStep;m_rectRat[i].right-=nRatMoveStep;m_nRatx[i]-=nRatMoveStep;}else{//运动到边界侧改变方向m_nRatDirection[i]=rand()%4;}break;case 3: //向右移动if(m_rectRat[i].right+nRatMoveStep<1120) {m_rectRat[i].left+=nRatMoveStep;m_rectRat[i].right+=nRatMoveStep;m_nRatx[i]+=nRatMoveStep;}else{//运动到边界侧改变方向m_nRatDirection[i]=rand()%4;}break;}//计算游戏剩余时间m_timeEnd=m_timeEnd.GetCurrentTime();m_timeWork=m_timeSet-(m_timeEnd-m_timeStart)InvalidateRect(CRect(200,0,560,160));// 时间显示位置if(!(m_timeWork.GetTotalSeconds())){ KillTimer(1);KillTimer(2);StartFlag=2;if(m_nRat>0){//游戏时间以到,老鼠还没抓完,失败m_nWinFlag=1;}else{//游戏时间未到,老鼠已经抓完,成功m_nWinFlag=0;}Invalidate();}}else if(m_timeWork.GetTotalSeconds()){ KillTimer(1);KillTimer(2);StartFlag=2;Invalidate();m_nWinFlag=0; }CView::OnTimer(nIDEvent);}void CCatCatchRatView::OnRestart(){//重新开始游戏的初始化工作,设置初始参数StartFlag=-1;m_nRat=RATMAX;m_timeWork=m_timeSet;m_nCatDirection=2;//计算猫和老鼠位图的初时位置和运动方向m_nCatx=m_rectClient.left+m_rectClient.Width()/2;m_nCaty=m_rectClient.top+m_rectClient.Height()/2;m_rectCat=CRect(m_nCatx,m_nCaty,m_nCatx+m_nCatw,m_nCaty+ m_nCath);srand((unsigned)time(NULL));for(int i=0;i<RATMAX;i++){m_nRatx[i]=m_rectClient.left+rand()%(m_rectClient.Width ()-m_nRatw);m_nRaty[i]=m_rectClient.top+rand()%(m_rectClient.Height( )-m_nRath);m_rectRat[i]=CRect(m_nRatx[i],m_nRaty[i],m_nRatx[i]+m_nR atw,m_nRaty[i]+m_nRath);m_nRatDirection[i]=rand()%4;m_bRatLive[i]=TRUE;}void CCatCatchRatView::OnKeyDown(UINT nChar, UINT nRepCnt,UINT nFlags){ if(StartFlag==1){//游戏开始时猫才可以移动InvalidateRect(m_rectCat,TRUE);switch(nChar)//代码过长且基本类似省略部分代码******************** {case VK_UP: //向上移动if(m_rectCat.top-m_nCatSpeed>89&&m_rectCat.top-m_nCatSpe ed<161&&m_rectCat.left<430){m_rectCat.top-=m_nCatSpeed;m_rectCat.bottom-=m_nCatSpeed;m_nCaty-=m_nCatSpeed;m_nCatDirection=0;if(***********)*************}break;case VK_DOWN: //向下移动if(m_rectCat.bottom-m_nCatSpeed<589){m_rectCat.top+=m_nCatSpeed;m_rectCat.bottom+=m_nCatSpeed;m_nCaty+=m_nCatSpeed;m_nCatDirection=1;if(***********)*************}break;case VK_LEFT: //向左移动if(m_rectCat.left-m_nCatSpeed>93){m_rectCat.left-=m_nCatSpeed;m_rectCat.right-=m_nCatSpeed;m_nCatx-=m_nCatSpeed;m_nCatDirection=2;if(***********)*************}}break;case VK_RIGHT: //向右移动if(m_rectCat.right+m_nCatSpeed<1120){m_rectCat.left+=m_nCatSpeed;m_rectCat.right+=m_nCatSpeed;m_nCatx+=m_nCatSpeed;m_nCatDirection=3;if(***********)*************}}break;}teRect(m_rectCat,FALSE);//判断猫的移动后是否抓住老鼠for(int i=0; i<RATMAX; i++){if(m_bRatLive[i] && (abs(m_nRatx[i]-m_nCatx)<m_nRatw) && (abs(m_nRaty[i]-m_nCaty)<m_nRath)){m_bRatLive[i]=FALSE;m_nRat--;InvalidateRect(m_rectRat[i]);InvalidateRect(CRect(410,100,560,160));} }} CView::OnKeyDown(nChar, nRepCnt, nFlags);}void CCatCatchRatView::OnUpdateStop(CCmdUI* pCmdUI) {pCmdUI->Enable(StartFlag==1);}//游戏过程中可以选停止菜单void CCatCatchRatView::OnSelect(){ CSelectDlg dlg;if(dlg.DoModal()==IDOK){m_nDifficulty=dlg.m_nDifficulty;switch(m_nDifficulty){case 2:m_nCatSpeed=8;m_nRatSpeed=2;m_timeSet=40;break;}5 运行结果1)创建位图资源(如图1所示):图1 2)显示迷宫(如图2所示):图2)3)窗口及控制按钮(如图3所示):图3参考贪吃蛇,可改变难度和时间(如图3所示):4)游戏运行界面(如图4所示):图46.总结在本次课程设计初期,我们遇到了许多难以解决的问题。