vc小游戏的第五篇

我在一篇的博客上面说到扫雷游戏的编写,我因为实习和毕业答辩的一些事情耽搁了这么多天所以今天我就是加班也要这篇博客给大家呈上去,也让我言而有信。好了就说一下这个小游戏的的编写思路吧!一、咱们要编写一下资源,定义一下变量。二、画出界面。三、编写功能模块。四、测试一下就可以了。好了开始上代码:

定义变量和添加资源

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]; //最大雷区  资源就是那个扫雷的几个位图我在这里就不说明了

绘制界面:

1、把状态条工具条去掉(只要是把OnCreate的代码删除就行)。

2、设置窗口的大小:

 

 BOOL CMainFrame::PreCreateWindow(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.cx=400;

       cs.cy=340;  

       return TRUE;

}

3、界面的绘制:

 

void CMy2_1View::OnDraw(CDC* pDC)

{

       CMy2_1Doc* pDoc = GetDocument();

       ASSERT_VALID(pDoc);

    

    CBrush mybrush1;

      mybrush1.CreateSolidBrush(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); //显示时间和剩余雷数的黑框

 

       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);//画黑框的白线

 

    for(int i=0;i<m_RowCount;i++)

              for(int j=0;j<m_ColCount;j++)

              {

                     pDC->MoveTo(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));

    myoldPen2=pDC->SelectObject(&mypen2);

    for(int ii=0;ii<m_RowCount;ii++)

              for(int jj=0;jj<m_ColCount;jj++)

              {

                     pDC->MoveTo(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(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<m_RowCount;a++)

               for(int b=0;b<m_ColCount;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,SRCCOPY);

                            }

                            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,160,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(160,"Comic Sans MS"))

       {

              AfxMessageBox("Can't Create Font");

       }

       pDC->SelectObject(&font);

       CString str; 

    

       if(leftnum<10)//利用判断显示位数,不够三位前面加0

              str.Format("00%d",leftnum);

       else

              str.Format("0%d",leftnum);                              

       pDC->TextOut(25,10,str);

       if(second<10)

              str.Format("00%d",second);

       else if(second<100)

                     str.Format("0%d" ,second);

              else

                     str.Format("%d" ,second);

       pDC->TextOut(330,10,str);

       pDC->RestoreDC(nOldDC);

                      

 

 

功能模块的编写:

1、初始化一下变量和位图:

 

CMy2_1View::CMy2_1View()

{

     // TODO: add construction code here

     for(int ii=0;ii<16;ii++)

            m_Bitmap[ii].LoadBitmap(IDB_BITMAP14+ii);

    for(int jj=0;jj<4;jj++)

            m_anniu[jj].LoadBitmap(IDB_ANNIU1+jj);  

second=0;//计时  

secondstart=0; //1时开始计时

m_RowCount=25;//行数    

m_ColCount=16;//列数

leinum=80;//雷数      

leftnum=leinum;//剩余雷数      

jieshu=0;//jieshu=1时停止

      int aa=0; 

     for(int i=0;i<m_RowCount;i++)

     {

            for(int j=0;j<m_ColCount;j++)

            {

                   lei[i][j].shumu=0; //初始化为0

                   lei[i][j].weitu=0;

            }

     }     

     CTime time=GetCurrentTime();//获取当前时间

     int s;     

     s=time.GetSecond();//获取秒数

     //设置40个雷

     do

     {         

            int k=(rand()*s)%m_RowCount; //以当前秒数为产生随机算法

            int l=(rand()*s)%m_ColCount;

 

            if(lei[k][l].shumu!=-1)       //为了避免一个位置同时算两个雷只允许当前位置不是雷时赋值为雷

            {

                   lei[k][l].shumu=-1;

                aa++;

            }

      

     }while(aa!=leinum);  

     for(int a=0;a<m_RowCount;a++) //给方格赋值,计算雷数

            for(int b=0;b<m_ColCount;b++)

                   if(lei[a][b].shumu==0)

                   {

                          for(int c=a-1;c<a+2;c++)

                                 for(int d=b-1;d<b+2;d++)

                                        if(c>=0&&c<m_RowCount&&d>=0&&d<m_ColCount)

                                               if(lei[c][d].shumu==-1)

                                                      lei[a][b].shumu++;       

                   }

}

2、鼠标左键按下模块:

如果在按钮上面,则显示按钮按下位图;如果在扫雷区,先把按钮位图改为张口位图,再判断按下的是否是雷,是就结束,重画,以显示所有的雷;否则,重画相应格子以显示数字

 

    void CMy2_1View::OnLButtonDown(UINT nFlags, CPoint point)

{

     CDC *pDC=GetDC();//获取指针pdc

    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)&&(point.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; // secondstart1时计时有效    

          int a=(point.x-10)/15;

          int b=(point.y-50)/15; //鼠标坐标转换为数组坐标

          if(lei[a][b].weitu==0||lei[a][b].weitu==3)

        {

              if(lei[a][b].shumu==-1)

                 {

                        jieshu=1;

KillTimer(1); //结束时,释放Timer

                        Invalidate();//重画,因为这次重画将显示全部的雷,不能用部分重画

                 }

         else

                 {

                        lei[a][b].weitu=1;

                        CRect rect;

                        rect.left=a*15+10;

                        rect.right=a*15+25;

                        rect.top=b*15+50;

                        rect.bottom=b*15+65;

                        InvalidateRect(&rect);

                 }    

          }

         

   }     CView::OnLButtonDown(nFlags, point);

}  

3鼠标左键抬起模块:

因为如果左键按下以后位图需要显示按下的状态,如果没有抬起的这个模块,那么位图就要显示按下的状态了

 void CMy2_1View::OnLButtonUp(UINT nFlags, CPoint point)

{

  CDC *pDC=GetDC();

   CDC Dc;

   if(Dc.CreateCompatibleDC(pDC)==FALSE)

     AfxMessageBox("Can't 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<40) //如果按下的是按扭,重新开始

       OnStart();

 

   CView::OnLButtonUp(nFlags, point);

}

 

4、鼠标右键的模块:

 

void CMy2_1View::OnRButtonDown(UINT nFlags, CPoint point)

{ 

   if(jieshu==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)

                 {

                        lei[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;

          InvalidateRect(&rect);     //重画打击格子      

   }

   CView::OnRButtonDown(nFlags, point);

}

 

4、显示没有雷得区域:

 

void CMy2_1View::leizero()//扫描,如果是已经被按下且雷数为0,显示它周围的八个格,并重画

{

    for(int i=0;i<m_RowCount;i++)

          for(int j=0;j<m_ColCount;j++)

                 if(lei[i][j].shumu==0&&lei[i][j].weitu==1)

                 {

                        for(int n=i-1;n<i+2;n++)

                               for(int m=j-1;m<j+2;m++)

                                      if(n>=0&&n<25&&m>=0&&m<m_ColCount)

                                             if(lei[n][m].shumu!=-1&&lei[n][m].weitu==0)

                                             {

                                                    lei[n][m].weitu=1;

                                                    CRect rect;

                                                    rect.left=n*15+10;

                                                    rect.right=n*15+25;

                                                    rect.top=m*15+50;

                                                    rect.bottom=m*15+65;

                                                    InvalidateRect(&rect);         

                                             }

                 }

}

5、计时器模块:

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)

{ 

   if(jieshu==1)//结束,返回

          return;

   leizero();   //显示个数为0的方格   

   if(secondstart>0)//计时

          secondstart++;  

   if(secondstart==20)//二十次为一秒

   {

          secondstart=1;

          second++;              

       CRect rect3;

          rect3.left=325;

          rect3.right=375;

          rect3.top=10;

          rect3.bottom=40;

          InvalidateRect(&rect3); //重画时间

   }

   CView::OnTimer(nIDEvent);

}

好了以上就是五子棋的精华所在了,如果想要更完美一些就可以在菜单上面在添加重新开始模块(也就是重新初始化一次)。

 

       

 

      

 

     

 

       

 

       

 

              

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值