c++控制台程序实现扫雷

来源:互联网 发布:ram rom 单片机 编辑:程序博客网 时间:2024/05/21 15:44

  无聊写了个扫雷小游戏,输入非雷坐标(x,y),清除掉非雷的区域,剩下地雷。算法很简单的,关键是空白区域的处理,即如果输入的坐标四周不存在雷,则连通的空白区域自动清除。这个模型与计算机图形学中的区域填充相当类似。填充算法一般有扫描线填充,种子填充等等。在这里借鉴种子填充算法。实现如下:输入一个点,从左右两个方向遍历改点所处的水平线,遇到雷终止,得到一个x的区间,扫描该线的上方和下方的水平线,如果在该区间内发现有空白点,则以该点为种子,递归调用。

     附上代码。代码有点烂,程序还有小bug。不过大致的算法就是那么回事吧。小问题懒得改了。

 

// play.cpp : Defines the entry point for the console application.///*   如果认为(x,y)不是雷,输入坐标(x,y)清除,不可以标记雷。可以实现,只是操作起来会比较麻烦   本程序的坐标系:   |------>y   |   |   |   |   ∨   x   '.':为清除的点;'*'地雷;空白(四周没有雷)用空格代替。*/#include "stdafx.h"#include <time.h>#include <stdlib.h>#include <iostream>using namespace std;bool g_Llimet = false;bool g_Rlimet = false;int top_line = 0;int bottom_line = 0;struct coor{   int x;        int y;};struct mask{ int x;      int y;   bool isshow;//是否展示    bool isblank;//是否空白区域的点};      int xx,yy;int recursion = 0;mask masks[500];char mines[100][100];#define DEFAULT_X 16#define DEFAULT_Y 30#define DEFAULT_MINESNUMBER 100int COORDINATE_X = DEFAULT_X;int COORDINATE_Y = DEFAULT_Y;int  MINE_NUMBER = DEFAULT_MINESNUMBER;void initialization(){     for(int a = 0;a<COORDINATE_X;a++)   {              for(int b = 0;b<COORDINATE_Y;b++)          {                  mines[a][b] = '.';                     masks[a*COORDINATE_Y+b].x = a;                    masks[a*COORDINATE_Y+b].y = b;                   masks[a*COORDINATE_Y+b].isshow = false;                   masks[a*COORDINATE_Y+b].isblank = false;                               }        }         srand(time(NULL));        int cc=MINE_NUMBER,aa[1000],bb[1000],ii=0,jj=0;       while(cc--)//生成随机地雷坐标    {             aa[++ii]=rand()%(0-COORDINATE_X);              bb[++jj]=rand()%(0-COORDINATE_Y);              mines[aa[ii]][bb[jj]] = '*';                //masks[aa[ii]*y + bb[jj]].isshow = true;          }}void SetMinesShow(){     for(int cc = 0;cc<500;cc++) {         masks[cc].isshow = true;      }}void FreshScrean(){    system("CLS");       //printf("   ");    for(int c = 0;c<=COORDINATE_Y;c++) {         printf("%3d",c);  }  printf("\n");      printf("\n");  for(int i = 0;i<COORDINATE_X;i++)        {           printf("%3d",i+1);                for(int j = 0;j<COORDINATE_Y;j++)              {                      if(masks[i*COORDINATE_Y+j].isshow == true)                 {                         printf("%3c",mines[i][j]);                        }//                         else if(mines[i][j] == '*')//                    {//                           printf("%3c",'*');//                                 //                         }                       else                    {                            printf("%3c",'.');                   }           }           printf("\n");               printf("\n");   }   }int CheckSingle(int x,int y,bool needcharge){      bool bFind = false;  int count = 0;   coor coor_xy[9] =       {{x-1,y-1},{x-1,y},{x-1,y+1},   {x,y-1},{x,y},{x,y+1},      {x+1,y-1},{x+1,y},{x+1,y+1}    };        for (int i = 0;i<9;i++)//取雷个数        {        if( coor_xy[i].x >=0 && coor_xy[i].x<COORDINATE_X                        && coor_xy[i].y >=0 && coor_xy[i].y<COORDINATE_Y                 && mines[coor_xy[i].x][coor_xy[i].y] == '*')            {            count ++;                      bFind = true;                        if(needcharge)                  {                            if(i == 3)g_Llimet = true;                            if(i == 5)g_Rlimet = true;                  }          }  }     if((!bFind) && needcharge)//没有发现边上有雷,则该点是空白点,周围的点都该展示出来 {         for (int j = 0;j<9;j++)           {                   if( coor_xy[j].x >=0 && coor_xy[j].x<COORDINATE_X                           && coor_xy[j].y >=0 && coor_xy[j].y<COORDINATE_Y                            && mines[coor_xy[j].x][coor_xy[j].y] != '*')                       {                               masks[coor_xy[j].x*COORDINATE_Y+coor_xy[j].y].isshow = true;                                masks[coor_xy[j].x*COORDINATE_Y+coor_xy[j].y].isblank = true;                        }                }        }        return count;}int ccc = 0;void CheckLogic(int coor_x,int coor_y){      int realCoor_x = coor_x -1;    int realCoor_y = coor_y -1;  int imin = realCoor_y;   int imax = realCoor_y;    int icount = 0;    char num[2] = {'0'};       ////////////////////////////////////////////////////////////////// -- new test.       if(coor_x ==xx && coor_y == yy && mines[realCoor_x][realCoor_y] != '*' )//选择的点无论如何展示出来      {                                                                       //加上!= ‘*’的条件是递归可能会扫到该点,导致是雷也展示          masks[realCoor_x*COORDINATE_Y+realCoor_y].isshow = true;           }        //////////////////////////////////// --以下两个while遍历一行,一个往左,一个往右。    while('0'==num[0] && realCoor_y - icount >=0)  {          sprintf(num,"%d",CheckSingle(realCoor_x,realCoor_y-icount,true));          if('0'!=num[0] )             {                     icount ++;                      if(mines[realCoor_x][realCoor_y-icount+1] != '*' && (mines[realCoor_x][realCoor_y-icount+1] <'0' || mines[realCoor_x][realCoor_y-icount+1] >'8'))                              mines[realCoor_x][realCoor_y-icount+1] = num[0];                   if(g_Llimet)                        {                                imin --;                   }                       if( icount == 0 || g_Llimet || mines[realCoor_x][realCoor_y-icount+1] != '*')                  {                          masks[realCoor_x*COORDINATE_Y+(realCoor_y-icount)+1].isshow = true;                    }                    break;               }               else            {                    if(mines[realCoor_x][realCoor_y-icount] != '*' && mines[realCoor_x][realCoor_y-icount] == '.')                           mines[realCoor_x][realCoor_y-icount] = ' ';                       imin --;                  icount ++;           }   }   if(imin <0)imin=0;                 int temmp =icount;                g_Llimet = false;            icount = 1;        num[0] = '0';              while(('0'==num[0]) && temmp >=1 && realCoor_y+icount<=COORDINATE_Y)             {                     sprintf(num,"%d",CheckSingle(realCoor_x,realCoor_y+icount,true));                     if('0'!=num[0]  )                        {                                if(mines[realCoor_x][realCoor_y+icount] != '*' && (mines[realCoor_x][realCoor_y+icount] <'0' || mines[realCoor_x][realCoor_y+icount] >'8'))                                      mines[realCoor_x][realCoor_y+icount] = num[0];                             if(!g_Rlimet)                         {                      imax ++;                            }                            if( g_Rlimet && mines[realCoor_x][realCoor_y+icount] != '*')                           {                                   masks[realCoor_x*COORDINATE_Y+(realCoor_y+icount)].isshow = true;                               }                               icount ++;                                break;                   }                   else                        {                                if(mines[realCoor_x][realCoor_y+icount] != '*' && mines[realCoor_x][realCoor_y+icount] == '.')                                       mines[realCoor_x][realCoor_y+icount] = ' ';                           imax ++;                              icount ++;                       }               }               if(imax>COORDINATE_Y)imax = COORDINATE_Y;                                       g_Rlimet = false;                temmp =icount;             icount = 0;           ////////////////////////////// 以下递归调用处理空白区域,借鉴种子填充算法。    /*分上下遍历所有行,如果发现有空白的点,以该点为种子,递归遍历 */      for(int t = imin; t<= imax+1;t++ ) {         //往上              if(realCoor_x-1>=0 && realCoor_x-1<xx-1 /*&&temmp>2*/                         && masks[(realCoor_x-1-1)*COORDINATE_Y+t].isshow == false)              {                      sprintf(num,"%d",CheckSingle(realCoor_x-1,t,false));                   if( masks[(realCoor_x-1)*COORDINATE_Y+t].isblank == true)CheckLogic(realCoor_x,t+1);              }              //往下           if( realCoor_x+1<=COORDINATE_X-1 && realCoor_x+1>xx-1 /*&&temmp>2*/                  && masks[(realCoor_x+1+1)*COORDINATE_Y+t].isshow == false)               {                       sprintf(num,"%d",CheckSingle(realCoor_x+1,t,false));                    if(  masks[(realCoor_x+1)*COORDINATE_Y+t].isblank == true)CheckLogic(realCoor_x+1+1,t+1);           }       }    recursion ++;  return;         //////////////////////////////////////////////////////////////////    }void init(){     int len = 0,weidth = 0;       int iParam  = 0;       cout<<"Please select : [1] Start game;[2] Setting"<<endl;                 cin>>iParam;     switch(iParam)      {      case 1:          {                  initialization();                  FreshScrean();                     break;                }                 case 2:             {                     cout<<"Please input Length:"<<endl;                       cin>>COORDINATE_X;                      cout<<"Please input weidth:"<<endl;                        cin>>COORDINATE_Y;                       cout<<"Please input mine's number:"<<endl;                    cin>>MINE_NUMBER;                    initialization();                    FreshScrean();                       break;          }  default:           {                   initialization();                   FreshScrean();                      break;         }           }}int main(int argc, char* argv[]){        init();  while(true)        {                cout<<"Please input coordinate (x,y).recursion's time:"<<recursion<<endl;                recursion = 0;               scanf("%d,%d",&xx,&yy);           if(xx>COORDINATE_X || xx<0 || yy>COORDINATE_Y || yy<0)         {                 printf("coordinate error! Please input again!\n");                        continue;                }                if(mines[xx-1][yy-1] == '*')         {                 SetMinesShow();            FreshScrean();                      printf("\n");                  printf("You got a mine,asshole!\n");                     printf("Please select : [1] Play again;[2] quit.\n");                     int iParam = 0;                     scanf("%d",&iParam);                  if(iParam == 1)                        {                                init();                          continue;                  }                  else exit(0);                 }        CheckLogic(xx,yy);                FreshScrean();   }   return 0;} <span style="FONT-SIZE: 10pt" dir="ltr"></span>
运行效果如下:
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 做b超查出囊肿怎么办 解大便时肛门痒怎么办 生完孩子肛门痒怎么办 把达克宁软膏摸到肛门怎么办 痔疮手术后肛门痒怎么办 便秘拉完屁股疼怎么办 屁股拉屎拉破了怎么办 6岁小朋友屁眼痒怎么办 孩子屁屁偶尔痒怎么办 1岁半宝宝屁眼痒怎么办 3岁宝宝肛门痒怎么办 得痔疮发烧了怎么办啊 痔疮手术后肚子胀气怎么办 乙肝引起的发烧头痛怎么办 肠癌手术后吃了会胃疼怎么办 来月经肛门坠痛怎么办 总想排便还有血怎么办 闻了别人的口臭怎么办 有内痔肛门经常不舒服怎么办 做完肠镜肛门疼怎么办 3周宝宝得皮彦怎么办 痔疮有蚕豆大了怎么办 顺生肛门坠胀怎么办 生孩子痔疮脱出不能回纳怎么办 痔疮犯了屁眼疼怎么办 孕晚期得痔疮了怎么办 孕39周痔疮严重怎么办 顺产后长痔疮了怎么办 怀孕了犯痔疮了怎么办 怀孕了痔疮犯了怎么办 痔疮手术后肛裂怎么办 痔疮引起的肛裂怎么办 痔疮手术后伤口不愈合怎么办 痔疮手术后伤口痒怎么办 肛瘘手术十五天后伤口疼怎么办 leep刀后hpv还是阳性怎么办 结肠息肉钳除后怎么办 痔疮手术后排便困难怎么办 住院未结账跑了怎么办 来月经痔疮犯了怎么办 安保压不下宫缩怎么办