ImageVerifierCode 换一换
格式:DOC , 页数:15 ,大小:115.50KB ,
资源ID:11398158      下载积分:10 金币
快捷注册下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

开通VIP
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.zixin.com.cn/docdown/11398158.html】到电脑端继续下载(重复下载【60天内】不扣币)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

开通VIP折扣优惠下载文档

            查看会员权益                  [ 下载后找不到文档?]

填表反馈(24小时):  下载求助     关注领币    退款申请

开具发票请登录PC端进行申请

   平台协调中心        【在线客服】        免费申请共赢上传

权利声明

1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。

注意事项

本文(c语言编辑扫雷游戏.doc)为本站上传会员【仙人****88】主动上传,咨信网仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知咨信网(发送邮件至1219186828@qq.com、拔打电话4009-655-100或【 微信客服】、【 QQ客服】),核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载【60天内】不扣币。 服务填表

c语言编辑扫雷游戏.doc

1、          第二章 第二章   扫雷                                 1. 1.   游戏实现   扫雷,是附带在Window里面的游戏,是个简单的游戏。因此我们就从扫雷开始我们的游戏旅程。很多人都玩过这个游戏,只是不知道怎么用程序实现。不过还有人不知道怎么玩,下面就先说说游戏的规则:   ● 开始:按左键开始游戏,按按钮或菜单重新开始。 ● 左键:按下时,是雷则结束,非雷则显示数字。 ● 数字:代表此数字周围一圈八格中雷的个数。 ● 右键:奇次按下表示雷,偶数按下表示对上次的否定。 ●

2、 结束:左键按到雷结束,找出全部雷结束。   接下来就该介绍游戏的编程过程了。不过要先交代一下一些内容。   ● 添加位图。 ● 添加全局变量。 ● 画初始界面。 ● 添加函数。   为什么要按这种次序呢?因为我们在画初始界面时,可能要用到位图或变量,而变量的定义又可能要对位图进行定义。这样的步骤的好处还有:在做一步之后都可以运行,有错就改,无错就做下一步。 上图是扫雷的一个画面。 下面就一步一步地演示,以编程的思路进行,当然,由于编程过程中有一些函数中的代码是分成两三次写的,我们就不重复,全部代码在第一次讲到时列出,而后面讲到时就只是

3、提一下。   新建单文档工程2_1。   2. 2.   资源编辑   添加位图:   前十二幅是在雷区的,后四幅是按钮。为了便于加载,必须各自保证其连续性。另外,为什么不添加一个按钮而用位图呢?是因为即使我们添加了按钮也要添加四幅位图!   位图的ID号: 按扭位图: 30*30 IDB_ANNIU1、IDB_ANNIU 2、IDB_ANNIU3、 IDB_ANNIU4 雷区位图: 14*14 ID号按下图依次为:IDB_BITMAP14。。。。。。IDB_BITMAP25   位图:下图(图2-1)。

4、 图2-1   3. 3.   变量函数   定义新类:   对于雷,我们是单独定义一个类,这样有利于程序的操作。 class Lei { public: //显示哪一个位图 int weitu; //这个位置相应的值 int shumu; }; 并有如下规定(图2-2):   图2-2 视图类变量:

5、   接着是在View类添加变量和函数:   //剩下雷数 int leftnum; //雷数 int leinum; //结束 int jieshu; //计时 short second; //开始计时 int secondstart; //位图数组 CBitmap m_Bitmap[12]; //按扭位图数组 CBitmap m_anniu[4]; //雷区行数 int m_RowCount; //雷区列数 int m_ColCount; //最大雷区 Lei lei[50][50];   //

6、这个位置周围雷数为0 void leizero(); //计时器函数 afx_msg void OnTimer(UINT nIDEvent); //鼠标按下左键 afx_msg void OnLButtonDown(UINT nFlags, CPoint point); //鼠标按下右键 afx_msg void OnRButtonDown(UINT nFlags, CPoint point); //初始化函数 afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); //鼠标左键松开

7、 afx_msg void OnLButtonUp(UINT nFlags, CPoint point);   4. 4.   具体实现   删去状态栏和工具栏:   开始执行程序,就能见到一个有状态栏和工具栏的大的单文档,与上图不同,所以我们第一步就是整理框架: 打开下面函数,把里面的一些语句去掉。如下所示: int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; /*

8、if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create }   if (!m_wndSta

9、tusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) { TRACE0("Failed to create status bar\n"); return -1; // fail to create }   // TODO: Delete these three lines if you don't want the toolbar to // be dockable m_wndToolBar

10、EnableDocking(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_wndToolBar); */ return 0; }   设置窗口大小:   运行附加的代码,还能看到扫雷游戏的框架是不能调大小的,而且总是显示在最前面,这又是怎么实现的呢? 在下面函数里添加语句,你能说出前三句是什么意思吗?注释已经被我去掉了,如果不知道,不如按一下F1。 BOOL CMainFrame::PreCreat

11、eWindow(CREATESTRUCT& cs) { if( !CFrameWnd::PreCreateWindow(cs) ) return FALSE; // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs cs.dwExStyle=cs.dwExStyle|WS_EX_TOPMOST; // cs.style=WS_SYSMENU|WS_OVERLAPPED|WS_MINIMIZEBOX;//; //设置窗口大小:400*340 cs

12、cx=400; cs.cy=340; return TRUE; }   构造函数:   由于构造函数是程序运行时就执行的,所以,除了对变量赋值之外,我们还可以把游戏的核心结构即内部数组赋值:先是把全部格子的位图和雷数赋值为0,然后调用随机函数按指定雷数赋值为-1,最后把不是雷的格子的雷数赋值为相应的值。   CMy2_1View::CMy2_1View() { // TODO: add construction code here for(int ii=0;ii<16;ii++) m_Bitmap[ii].LoadBitmap(IDB_BITMA

13、P14+ii); for(int jj=0;jj<4;jj++) m_anniu[jj].LoadBitmap(IDB_ANNIU1+jj); //计时 second=0; //1时开始计时 secondstart=0; //行数 m_RowCount=25; //列数 m_ColCount=16; //雷数 leinum=80; //剩余雷数 leftnum=leinum; //jieshu=1时停止 jieshu=0;   int aa=0;   //初始化为0 for(int

14、 i=0;i

15、nt; //为了避免一个位置同时算两个雷 //只允许当前位置不是雷时赋值为雷 if(lei[k][l].shumu!=-1) { lei[k][l].shumu=-1; aa++; } }while(aa!=leinum); //给方格赋值,计算雷数 for(int a=0;a

16、c++) for(int d=b-1;d=0&&c=0&&d

17、盖了原来的程序时,必须重画。我们调用重画函数,它都要重新执行OnDraw(CDC* pDC)函数,那么,此时它就必须把已经显示出来的位图也显示出来。而开始时雷区位图是不可见的,并不影响界面的初始化。   void CMy2_1View::OnDraw(CDC* pDC) { CMy2_1Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here //画背景 CBrush mybrush1; mybrush1.CreateSoli

18、dBrush(RGB(192,192,192)); CRect myrect1(0,0,1200,800); pDC->FillRect(myrect1,&mybrush1); //画黑框 CBrush mybrush; mybrush.CreateSolidBrush(RGB(0,0,0)); CRect myrect(20,10,70,40); pDC->FillRect(myrect,&mybrush);   CRect myrect2(325,10,375,40); pDC->FillRect(myrect2,&mybrush);

19、  CPen mypen; CPen*myoldPen; mypen.CreatePen(PS_SOLID,2,RGB(255,255,255)); myoldPen=pDC->SelectObject(&mypen); //画黑框的白线 pDC->MoveTo(20,40); pDC->LineTo(70,40); pDC->LineTo(70,10); pDC->MoveTo(325,40); pDC->LineTo(375,40); pDC->LineTo(375,10); //画雷区边线 //左上角是白线,右下角是黑线,以显示立体感

20、 for(int i=0;iMoveTo(10+i*15,50+j*15+14); pDC->LineTo(10+i*15,50+j*15); pDC->LineTo(10+i*15+14,50+j*15); } pDC->SelectObject(myoldPen);   CPen mypen2; CPen*myoldPen2; mypen2.CreatePen(PS_SOLID,1,RGB(0,0,0));

21、 myoldPen2=pDC->SelectObject(&mypen2); for(int ii=0;iiMoveTo(10+ii*15,50+jj*15+14); pDC->LineTo(10+ii*15+14,50+jj*15+14); pDC->LineTo(10+ii*15+14,50+jj*15); } pDC->SelectObject(myoldPen2);   CDC Dc; if

22、Dc.CreateCompatibleDC(pDC)==FALSE) AfxMessageBox("Can't create DC"); //显示按钮 Dc.SelectObject(m_anniu[0]); pDC->BitBlt(180,10,160,160,&Dc,0,0,SRCCOPY); //判断显示什么位图 //weitu=1已按下的数字区 //weitu=2显示旗 //weitu=3显示问号 for(int a=0;a

23、b++) { if(lei[a][b].weitu==1) { Dc.SelectObject(m_Bitmap[lei[a][b].shumu]); pDC->BitBlt(a*15+10,b*15+50,160,160,&Dc,0,0,SRCCOPY); } if(lei[a][b].weitu==2) { Dc.SelectObject(m_Bitmap[9]); pDC->BitBlt(a*15+10,b*15+50,160,160,&Dc,0,0,S

24、RCCOPY); } if(lei[a][b].weitu==3) { Dc.SelectObject(m_Bitmap[10]); pDC->BitBlt(a*15+10,b*15+50,160,160,&Dc,0,0,SRCCOPY); } //结束 if(jieshu==1&&lei[a][b].shumu==-1) { Dc.SelectObject(m_Bitmap[11]); pDC->BitBlt(a*15+10,b*15+50,16

25、0,160,&Dc,0,0,SRCCOPY); Dc.SelectObject(m_anniu[3]); pDC->BitBlt(180,10,160,160,&Dc,0,0,SRCCOPY); } }   //显示黑框里的数字 int nOldDC=pDC->SaveDC(); pDC->SetTextColor(RGB(255,0,0)); pDC->SetBkColor(RGB(0,0,0)); CFont font; if(0==font.CreatePointFont(

26、160,"Comic Sans MS")) { AfxMessageBox("Can't Create Font"); } pDC->SelectObject(&font); CString str; //利用判断显示位数,不够三位前面加0 if(leftnum<10) str.Format("00%d",leftnum); else str.Format("0%d",leftnum); pDC->TextOut(25,10,str); if(second<10) str.Format("00%d",second

27、); else if(second<100) str.Format("0%d" ,second); else str.Format("%d" ,second); pDC->TextOut(330,10,str); pDC->RestoreDC(nOldDC); } 运行一下,外观已经出来了,只是还不能玩。那我们就来添加一些功能函数,使它可以玩。 当然,如果你对程序已经有一定的经验的话,你就会指出上面的函数太长了。这并不太符合我们编程的要求。我们编程有一个讲究,就是尽量使函数的代码少,一般为一页左右,便于查看。那么,我们可以把上面的函数细分为几

28、个小函数,然后在这个函数里面分别调用。   按下鼠标左键:   用if语句判断,如果在按钮上面,则显示按钮按下位图;如果在扫雷区,先把按钮位图改为张口位图,再判断按下的是否是雷,是就结束,重画,以显示所有的雷;否则,重画相应格子以显示数字。   void CMy2_1View::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default //获取指针pdc CDC *pDC=GetDC();

29、CDC Dc; if(Dc.CreateCompatibleDC(pDC)==FALSE) AfxMessageBox("Can't create DC"); //显示按下按钮 if(point.x>180&&point.x<210&&point.y>10&&point.y<40) { Dc.SelectObject(m_anniu[3]); pDC->BitBlt(180,10,160,160,&Dc,0,0,SRCCOPY); } if((point.x>=10)&&(point.x<=385)&&(poi

30、nt.y>=50)&&(point.y<=290)) { if(jieshu==1) return;   //显示张口按钮 Dc.SelectObject(m_anniu[1]); pDC->BitBlt(180,10,160,160,&Dc,0,0,SRCCOPY); // secondstart为1时计时有效 secondstart=1; //鼠标坐标转换为数组坐标 int a=(point.x-10)/15; int b=(point.y-50)/15; if(lei[a][b].we

31、itu==0||lei[a][b].weitu==3) { if(lei[a][b].shumu==-1) { jieshu=1; //结束时,释放Timer KillTimer(1); //重画,因为这次重画将显示全部的雷, //不能用部分重画 Invalidate(); } else { lei[a][b].weitu=1; CRect rect; rect.left=a*15+10; rect.right=a*15+25;

32、 rect.top=b*15+50; rect.bottom=b*15+65; InvalidateRect(&rect); } } } CView::OnLButtonDown(nFlags, point); } 如果你现在运行的话,你会发现按下按钮时并不还原,这就涉及到鼠标函数:OnLButtonUp(UINT nFlags, CPoint point)   松开鼠标左键:   松开左键时,显示按钮没有按下的位图;再判断,如果结束,就要显示失败的位图;另外,如果是在按钮上松开按钮,即表示我们已经按下了重新开始的按钮,必须

33、调用重新开始函数OnStart()。 由于OnStart()函数是与菜单里的开始共有的,此处先保留不说,若有必要运行,可以先去掉最后两行。   void CMy2_1View::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CDC *pDC=GetDC(); CDC Dc; if(Dc.CreateCompatibleDC(pDC)==FALSE) AfxMessageBox("Can't

34、 create DC"); //显示按钮 Dc.SelectObject(m_anniu[0]); pDC->BitBlt(180,10,160,160,&Dc,0,0,SRCCOPY); if(jieshu==1) { //显示按扭位图 Dc.SelectObject(m_anniu[2]); pDC->BitBlt(180,10,160,160,&Dc,0,0,SRCCOPY); } //如果按下的是按扭,重新开始 if(point.x>180&&point.x<210&&point.y>10&&point.y<

35、40) OnStart();   CView::OnLButtonUp(nFlags, point); }   按下鼠标右键:   如果是雷,我们按右键,显示旗子,并减少一个剩下雷数;如果我们认为那旗子的格子不是雷,我们按右键,显示问号,并在剩下雷数加上1。有关函数:   void CMy2_1View::OnRButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default //结束,返回 if(jies

36、hu==1) return; if((point.x>=10)&&(point.x<=385)&&(point.y>=50)&&(point.y<=290)) { int a=(point.x-10)/15; int b=(point.y-50)/15;   if(lei[a][b].weitu==0||lei[a][b].weitu==3) { lei[a][b].weitu=2; leftnum--; } else if(lei[a][b].weitu==2) { le

37、i[a][b].weitu=3; leftnum++; }   //重画剩下雷数 CRect rect2; rect2.left=20; rect2.right=70; rect2.top=10; rect2.bottom=40; InvalidateRect(&rect2); //重画打击格子 CRect rect; rect.left=a*15+10; rect.right=a*15+25; rect.top=b*15+50; rect.bottom=b*15+65;

38、 InvalidateRect(&rect); } CView::OnRButtonDown(nFlags, point); } 显示没有雷的区域:   运行,玩一下,你会发现当按下的是一个周围没有雷的格子是它并不会象Window里面的扫雷游戏一样显示它周围的格子雷数。怎么实现呢? 添加一个如下函数:   //扫描,如果是已经被按下且雷数为0,显示它周围的八个格,并重画 void CMy2_1View::leizero() { for(int i=0;i

39、) if(lei[i][j].shumu==0&&lei[i][j].weitu==1) { for(int n=i-1;n=0&&n<25&&m>=0&&m

40、 rect.right=n*15+25; rect.top=m*15+50; rect.bottom=m*15+65; InvalidateRect(&rect); } } } 再运行,效果是有的,只是它只显示一部分,即这个周围的几个。那么我们应该怎样使它显示全部呢?可以利用计时器函数。   计时器函数:   OnTimer(UINT nIDEvent)函数,同时也可以实现计时显示。添加OnCreate(LPCREATESTRUCT lpCreateStruct)和 OnTimer(UI

41、NT nIDEvent):   int CMy2_1View::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; // TODO: Add your specialized creation code here //20次为一秒 SetTimer(1,50,NULL); return 0; }   void CMy2_1View::OnTimer(UINT nIDEvent) { // TODO: Add

42、 your message handler code here and/or call default //结束,返回 if(jieshu==1) return; //显示个数为0的方格 leizero(); //计时 if(secondstart>0) secondstart++; //二十次为一秒 if(secondstart==20) { secondstart=1; second++; //重画时间 CRect rect3; rect3.left=325; rect3.right=375;

43、 rect3.top=10; rect3.bottom=40; InvalidateRect(&rect3); } CView::OnTimer(nIDEvent); }   扫雷游戏就这样就是了。下面是附加内容,它将说明菜单的添加和重新开始函数的算法。     5. 5.   附加内容   修改菜单:   游戏已经可以玩了,只是点到雷之后就完了,无法重新开始。还有,菜单还没有改。下面就修改菜单并实现重新开始功能: 把菜单改为如下图2-3。   图2-3   并在View()函数中

44、按下图添加OnStart()函数(图2-4): 图2-4   开始函数:   OnStart()函数其实只是构造函数的再版。   void CMy2_1View::OnStart() { SetTimer(1,50,NULL); // TODO: Add your command handler code here second=0;//计时 secondstart=0;//1时开始计时 // num=0; leftnum=leinum;//剩余雷数 jieshu=0;//jieshu=1时停止 int aa=0; //

45、初始化0 for(int i=0;i

46、le(aa!=leinum); //给方格赋值 for(int a=0;a=0&&c=0&&d

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服