如何使用C++實現(xiàn)掃雷經(jīng)典小游戲

這篇文章主要介紹如何使用C++實現(xiàn)掃雷經(jīng)典小游戲,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

創(chuàng)新互聯(lián)服務項目包括軹城網(wǎng)站建設、軹城網(wǎng)站制作、軹城網(wǎng)頁制作以及軹城網(wǎng)絡營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關系等,向廣大中小型企業(yè)、政府機構等提供互聯(lián)網(wǎng)行業(yè)的解決方案,軹城網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務的客戶以成都為中心已經(jīng)輻射到軹城省份的部分城市,未來相信會繼續(xù)擴大服務區(qū)域并繼續(xù)獲得客戶的支持與信任!

主要是dfs實現(xiàn)打開一片的操作,數(shù)字帶有顏色,很真實。
windows掃雷中鼠標左右鍵同時按也實現(xiàn)了,即試探。

先上圖,詳見下面代碼:

如何使用C++實現(xiàn)掃雷經(jīng)典小游戲

代碼中有詳細注釋,編譯無任何錯誤警告。
Ps.有bug請評論指出,謝謝啦~
另外我覺得代碼比較臃腫,有什么可以優(yōu)化的也請?zhí)岢鰚

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<conio.h>
#include<windows.h>
#include<cstdlib>
#include<ctime>
using namespace std;

#define MAXN 35
#define MIDX 10
#define MIDY 40
#define CG 25
#define CK 80

int G,K,Lnum,Wnum;//G為地圖高,K為地圖,Lnum為地圖中的雷數(shù),Wnum為剩余的小旗數(shù)
int nx,ny;//現(xiàn)在光標所在的位置
bool QR=0,Lose=0,is_flag_true[MAXN][MAXN];//QR為確認模式是否打開,Lose為是否輸,第三個是這個位置上的旗是否放對
char map[MAXN][MAXN],tmap[MAXN][MAXN];//第一個是只有雷和空地的地圖,第二個是玩家能看到的地圖
int map1[MAXN][MAXN],mapc[MAXN][MAXN];//map1為數(shù)字的地圖,其中0代表空地,-1為雷,1-8為周圍雷的個數(shù)
//mapc為當前格子的顏色
int col[10]={240,249,242,252,241,244,243,240,248};//col[i]表示windows掃雷中i的顏色,col[0]為空格的顏色
int d[10][4]={{0},{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};//8個方向
bool ZB;//作弊是否打開

/*各種函數(shù)*/
void color(int);//顏色
void gto(int,int);//光標位置
void make();//制作隨機地圖
void print();//打印地圖等
bool check(int,int);//判斷坐標是否合法
bool is_win();//判斷是否贏
bool is_lose();//是否輸
void dfs(int,int);//用深搜來打開方塊
void st(int,int);//試探,即windows掃雷中的左右鍵同時按
void flag(int,int);//小旗
void bj(int,int);//標記
void swt();//確認模式
void again();//重新開始
void zb();//作弊模式
void mainmain();//主函數(shù)
void print_real_map();//打印最終的地圖
void begin();//各種操作

int main()
{
 mainmain();
}


void color(int a){SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),a);}
void gto(int x,int y)
{
 COORD pos;pos.X=y;pos.Y=x;
 SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
}

void make()
{
 for(int i=1;i<=G;i++)
 for(int j=1;j<=K;j++)
  map[i][j]='#';//初始化
 for(int i=1;i<=Lnum;i++)
 {
 int x=rand()%G+1,y=rand()%K+1;
 while(map[x][y]=='O')
  x=rand()%G+1,y=rand()%K+1;
 map[x][y]='O';
 }//隨機放雷
 for(int i=1;i<=G;i++)
 for(int j=1;j<=K;j++)
 {
  if(map[i][j]=='O')map1[i][j]=-1,mapc[i][j]=240;//如果是雷
  else
  {
  for(int k=1;k<=8;k++)
   if(map[i+d[k][0]][j+d[k][1]]=='O')
   map1[i][j]++;//計算周圍雷的個數(shù)
  mapc[i][j]=col[map1[i][j]];//根據(jù)格子上的數(shù)設置顏色
  }
 }
 for(int i=1;i<=G;i++)
 for(int j=1;j<=K;j++)
  if(mapc[i][j]==0)//空地
  mapc[i][j]=240;
}
void print()
{
 system("cls");
 gto(0,MIDY-4); color(233); printf("掃雷");
 color(240);
 gto(1,MIDY);
 for(int i=2;i<=G+1;i++)
 {
 gto(i,0);
 for(int j=1;j<=K;j++)
  printf("#"),tmap[i-1][j]='#';//初始化玩家所看到的地圖
 }

 gto(2,0);
 nx=2,ny=0;
 color(15);
 printf("@");

 color(15);
 gto(2,2*K+5);printf("-----規(guī)則-----");
 gto(3,2*K+5);printf("wasd:選擇位置");
 gto(4,2*K+5);printf("空格:打開");
 gto(5,2*K+5);printf("1鍵:試探周圍8個方塊,如果其中有雷則不會打開,無");
 gto(6,2*K+5);printf(" 雷或旗幟標對了則會將周圍無雷的位置打開,");
 gto(7,2*K+5);printf(" 如果試探時周圍有標錯的旗幟,則會游戲失敗");
 gto(8,2*K+5);printf(" 必須額外確認一次,以便查看周圍被試探的區(qū)域");
 gto(9,2*K+5);printf("2鍵:放置/取消小旗(F)");
 gto(10,2*K+5);printf("3鍵:放置/取消標記(?)");
 gto(11,2*K+5);printf("4鍵:打開/關閉確認模式,即每次操作需再按一次確認");
 gto(12,2*K+5);printf("5鍵:打開/關閉作弊模式,即顯示原本地圖");
 gto(13,2*K+5);printf("0鍵:重新開始");//打印規(guī)則

 gto(G+4,0);printf("-----操作提示-----\n");
 printf("請選擇方塊進行操作");

 gto(1,2*K+10);color(12);printf("剩余小旗數(shù):%d",Wnum=Lnum);
}

bool check(int x,int y){return y>=0&&y<K&&x>=2&&x<G+2;}
//因為地圖是從2行0列開始打的,而地圖是從1行1列開始存的,所以gto(x,y)走到的是map[x-1][y+1]
bool is_win()
{
 int cnt=0;
 for(int i=1;i<=G;i++)
 for(int j=1;j<=K;j++)
  if(map[i][j]=='#'&&map1[i][j]==-1)
  cnt++;
 if(cnt==Lnum) return 1;
 //所有沒被打開的方塊都是雷=>勝利
 for(int i=1;i<=G;i++)
 for(int j=1;j<=K;j++)
  if((tmap[i][j]!='F'&&map1[i][j]==-1)||(tmap[i][j]=='F'&&map1[i][j]!=-1))
  return 0;
 return 1;
 //所有雷都標有旗
}
bool is_lose(){return Lose;}

void dfs(int x,int y)
{
 if(map1[x-1][y+1]>0)//只要邊界全部是數(shù)字就return
 {
 gto(x,y),color(mapc[x-1][y+1]),printf("%d",map1[x-1][y+1]);
 tmap[x-1][y+1]=map1[x-1][y+1]+'0';
 return;
 }
 gto(x,y);color(255);
 tmap[x-1][y+1]=' ';
 printf(" ");//因為下面判斷了雷,上面判斷了數(shù)字,這里就一定是空地
 for(int i=1;i<=8;i++)
 {
 int xx=x+d[i][0]-1,yy=y+d[i][1]+1;//這里的xx和yy是在map中的,而不是gto中的
 if(check(xx+1,yy-1)&&tmap[xx][yy]=='#'&&map1[xx][yy]!=-1)//所以check和dfs的參數(shù)要變化
  dfs(xx+1,yy-1);
 }
}
void st(int x,int y)
{
 for(int i=1;i<=8;i++)
 {
 int xx=x+d[i][0],yy=y+d[i][1];
 if(check(xx,yy))
 {
  gto(xx,yy);
  if(tmap[xx-1][yy+1]!='#')
  color(mapc[xx-1][yy+1]-128);//減去128使周圍的8個格子的背景顏色變?yōu)榛疑?
  else
  color(112);//這里特判一下'#',應該可以不用
  printf("%c",tmap[xx-1][yy+1]);
 }
 }
 gto(G+5,0),color(15),printf("請確認     ");
 //試探必須額外確認一次,規(guī)則上有說
 char c=getch();
 if(c=='1')
 {
 for(int i=1;i<=8;i++)
 {
  int xx=x+d[i][0],yy=y+d[i][1];
  if(check(xx,yy))
  if(tmap[xx-1][yy+1]=='F'&&map1[xx-1][yy+1]!=-1)//試探時有格子的小旗標錯了=>失敗
  {
   Lose=1;
   return;
  }
 }
 for(int i=1;i<=8;i++)
 {
  int xx=x+d[i][0],yy=y+d[i][1];
  if(check(xx,yy))
  if(map1[xx-1][yy+1]==-1&&tmap[xx-1][yy+1]!='F')//試探是有格子為雷=>取消打開
   return;
 }
 for(int i=1;i<=8;i++)
 {
  int xx=x+d[i][0],yy=y+d[i][1];
  if(check(xx,yy)&&tmap[xx-1][yy+1]=='#')//打開周圍8個格子
  dfs(xx,yy);
 }
 }
}
void flag(int x,int y)
{
 x-=1,y+=1;
 if(tmap[x][y]=='F')//原本為小旗=>取消小旗
 {
 tmap[x][y]='#';mapc[x][y]=240;
 gto(x+1,y-1),color(240),printf("#");
 Wnum++;//更新小旗數(shù)
 }
 else//否則就放置小旗
 {
 is_flag_true[x][y]=map1[x][y]==-1;//判斷小旗是否放對
 tmap[x][y]='F';mapc[x][y]=253;
 gto(x+1,y-1),color(253),printf("F");
 Wnum--;//更新小旗數(shù)
 }
 gto(1,2*K+10);color(12);printf("剩余小旗數(shù): ");
 gto(1,2*K+22);printf("%d",Wnum);//更新小旗數(shù)
}
void bj(int x,int y)//和放小旗差不多,只是不用更新is_flag_true
{
 x-=1,y+=1;
 if(tmap[x][y]=='?')
 {
 gto(x+1,y-1),color(240),printf("#");
 tmap[x][y]='#';mapc[x][y]=240;
 }
 else
 {
 if(tmap[x][y]=='F')//如果原本這個位置上是小旗,而你把它變?yōu)榱藰擞?,就要更新小旗?shù)
 {
  Wnum++;
  gto(1,2*K+10);color(12);printf("剩余小旗數(shù): ");
  gto(1,2*K+22);printf("%d",Wnum);
 }
 gto(x+1,y-1),color(240),printf("?");
 tmap[x][y]='?';mapc[x][y]=240;
 }
}
void swt(){QR=!QR;}
void zb()
{
 if(ZB)//如果本來作弊打開了就把作弊地圖清除
 {
 for(int i=1;i<=G;i++)
 {
  gto(i+1,K+2);
  for(int j=1;j<=K;j++)
  color(15),printf(" ");
 }
 ZB=0;
 }
 else//否則打印作弊地圖
 {
 for(int i=1;i<=G;i++)
 {
  gto(i+1,K+2);
  for(int j=1;j<=K;j++)
  {
  color(mapc[i][j]);
  if(map1[i][j]==-1) printf("O");
  else if(map1[i][j]>0) printf("%d",map1[i][j]);
  else printf(" ");
  }
 }
 ZB=1;
 }
}
void again()
{
 G=K=Lnum=nx=ny=Lose=ZB=0;
 QR=0;
 memset(is_flag_true,0,sizeof(is_flag_true));
 memset(map,0,sizeof(map));
 memset(tmap,0,sizeof(tmap));
 memset(map1,0,sizeof(map1));
 memset(mapc,0,sizeof(mapc));
 color(15);
 system("cls");//初始化
 mainmain();
}

void begin()//各種操作
{
 char c=getch(); 
 gto(G+5,0),color(15),printf("請選擇方塊進行操作");
 color(240);
 if(c=='w'&&check(nx-1,ny))
 {
 gto(nx,ny);
 if(tmap[nx-1][ny+1]!='#'||tmap[nx-1][ny+1]==' ')
  color(mapc[nx-1][ny+1]);
 printf("%c",tmap[nx-1][ny+1]);
 gto(nx-=1,ny);color(15);printf("@");
 }
 else if(c=='s'&&check(nx+1,ny))
 {
 gto(nx,ny);if(tmap[nx-1][ny+1]!='#'||tmap[nx-1][ny+1]==' ')color(mapc[nx-1][ny+1]);printf("%c",tmap[nx-1][ny+1]);
 gto(nx+=1,ny);color(15);printf("@");
 }
 else if(c=='a'&&check(nx,ny-1))
 {
 gto(nx,ny);if(tmap[nx-1][ny+1]!='#'||tmap[nx-1][ny+1]==' ')color(mapc[nx-1][ny+1]);printf("%c",tmap[nx-1][ny+1]);
 gto(nx,ny-=1);color(15);printf("@");
 }
 else if(c=='d'&&check(nx,ny+1))
 {
 gto(nx,ny);if(tmap[nx-1][ny+1]!='#'||tmap[nx-1][ny+1]==' ')color(mapc[nx-1][ny+1]);printf("%c",tmap[nx-1][ny+1]);
 gto(nx,ny+=1);color(15);printf("@");
 }
 //上下左右移動
 else
 {
 if(c==' '&&(!(tmap[nx-1][ny+1]<='9'&&tmap[nx-1][ny+1]>='0'))&&tmap[nx-1][ny+1]!='F')
 {
  mapc[nx-1][ny+1]=col[map1[nx-1][ny+1]];//如果本來放了標記,mapc[nx-1][ny+1]的顏色為黑色,在打開時里面的顏色卻不一定是黑色
  if(QR)
  {
  gto(G+5,0),color(15),printf("請確認     ");
  if(getch()==' ')
  {
   if(map1[nx-1][ny+1]==-1) {Lose=1;return;}
   dfs(nx,ny);
  }
  }
  else
  {
  if(map1[nx-1][ny+1]==-1) {Lose=1;return;}
  dfs(nx,ny);
  }
 }
 else if(c=='1')
 {
  if(QR)
  {
  gto(G+5,0),color(15),printf("請確認     ");
  if(getch()=='1') st(nx,ny);
  }
  else st(nx,ny);
  for(int i=1;i<=8;i++)
  {
  int xx=nx+d[i][0],yy=ny+d[i][1];
  if(check(xx,yy))
  {
   gto(xx,yy);
   if(tmap[xx-1][yy+1]!='#') color(mapc[xx-1][yy+1]);
   else color(240);
   printf("%c",tmap[xx-1][yy+1]);
  }
  }
 }
 else if(c=='2'&&(tmap[nx-1][ny+1]>'9'||tmap[nx-1][ny+1]<'1'))
 {
  if(QR)
  {
  gto(G+5,0),color(15),printf("請確認     ");
  if(getch()=='2') flag(nx,ny);
  }
  else flag(nx,ny);
 }
 else if(c=='3'&&(tmap[nx-1][ny+1]>'9'||tmap[nx-1][ny+1]<'1'))
 {
  if(QR)
  {
  gto(G+5,0),color(15),printf("請確認     ");
  if(getch()=='3') bj(nx,ny);
  }
  else bj(nx,ny);
 }
 else if(c=='4')
 {
  if(QR)
  {
  gto(G+5,0),color(15),printf("請確認     ");
  if(getch()=='4') swt();
  }
  else swt();
 }
 else if(c=='5')
 {
  if(QR)
  {
  gto(G+5,0),color(15),printf("請確認     ");
  if(getch()=='5') zb();
  }
  else zb();
 }
 else if(c=='0')
 {
  if(QR)
  {
  gto(G+5,0),color(15),printf("請確認     ");
  if(getch()=='0') again();
  }
  else again();
 }
 }
}

void mainmain()
{
 system("mode con cols=120 lines=35");//設置窗口大小
 srand((unsigned)time(NULL));
 int mode;
 printf("1.初級\n2.中級\n3.高級\n4.自定義\n");
 scanf("%d",&mode);if(mode>4) mode=4;
 if(mode==1) G=9,K=9,Lnum=10;
 else if(mode==2) G=16,K=16,Lnum=40;
 else if(mode==3) G=16,K=30,Lnum=99;//三種等級的參數(shù)
 else
 {
 printf("請輸入雷區(qū)高度:");scanf("%d",&G);
 printf("請輸入雷區(qū)寬度:");scanf("%d",&K);
 printf("請輸入雷個數(shù)(建議不超過總大小的三分之一):");scanf("%d",&Lnum);
 if(G>24) G=24;if(K>30) K=30;
 if(G<9) G=9;if(K<9) K=9;
 if(Lnum<10) Lnum=10;if(Lnum>G*K*9/10) Lnum=G*K*9/10;
 //控制參數(shù)的范圍,最后一個if是雷的數(shù)量不超過地圖大小的9/10
 }
 make();
 print();
 while(1)
 {
 begin();
 bool f1=is_win(),f2=is_lose();
 if(f1||f2)
 {
  gto(0,0);
  if(f1)
  color(202),gto(0,0),printf("你 贏 了!!是否重來?(y/n)");
  if(f2)
  color(137),gto(0,0),printf("你 輸 了?。∈欠裰貋??(y/n)");//輸贏
  print_real_map();
  char c=getch();
  if(c=='y'||c=='Y') again();
  else
  {
  color(15);
  system("cls");
  gto(MIDX,MIDY-5);
  printf("歡迎下次再來");
  return;
  }
 }
 }
}
void print_real_map()
{
 color(240);
 for(int i=1;i<=G;i++)
 {
 gto(i+1,0);
 for(int j=1;j<=K;j++)
 {
  if(tmap[i][j]=='F'&&is_flag_true[i][j]==0)//如果旗標錯了顯示紅色的X
  color(252),printf("X");
  else if(map1[i][j]==-1)//雷為黑色O
  color(240),printf("O");
  else if(map1[i][j]==0)//空
  color(240),printf(" ");
  else//數(shù)字
  color(mapc[i][j]),printf("%d",map1[i][j]);
 }
 }
}

以上是“如何使用C++實現(xiàn)掃雷經(jīng)典小游戲”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

分享文章:如何使用C++實現(xiàn)掃雷經(jīng)典小游戲
網(wǎng)頁網(wǎng)址:http://muchs.cn/article44/jsogee.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供云服務器、網(wǎng)站營銷、網(wǎng)站策劃、面包屑導航、域名注冊自適應網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設公司