1. 程式人生 > >用C語言實現掃雷部分功能(可連續展開)

用C語言實現掃雷部分功能(可連續展開)

用了用了兩天時間,寫了個掃雷的小程式,是不是有點慢了。不過我是真覺得用c寫小東西很有意思。
PS:重新遊戲那裡還沒開始寫,後面會補上。

**

感覺最困難,花費時間最多的在棋盤中無雷周邊區域顯示的演算法上。

**

具體程式見下:

標頭檔案

#ifndef   __SAOLEI_H
#define   __SAOLEI_H

#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>
#include<time.h>

#define X 9//棋盤大小
#define Y 9
#define LAND 10//地雷個數

int a[X][Y]={0} ;
char b[X][Y] ;
void menu_game(void);//列印選單欄
int mode_game(void);//功能
void generate_initgame(void);//生成初始棋盤
void generate_game(void);//生成棋盤
int start_game(void);
int judge_game(int x,int y);
void explore_game(void);
void updata_game(void);//更新棋盤
void euqal_game(int x,int y);
void extend_game(int x,int y);
int judge_game(int x,int y);
void disappear_game(int x,int y);
void printnew_game(void);
void show_game(int x,int y);
int check_game(int x,int y);

#endif // __SAOLEI_H

主程式

#include "saolei.h"

void bye_game(void);
void replay_game(void);
int main()
{
    int mode,status;//記錄使用者選擇什麼功能
    memset(b, '*', X*Y*sizeof(char));
    START:
    menu_game();//列印選單欄
    mode = mode_game();//選擇功能
    generate_initgame();//生成棋盤(看不見地雷)
    generate_game();//生成原始地雷
    while(1)
    {
       switch(mode)
       {
          case 1:status = start_game();if(status == 0){goto END;}break;
          case 2:replay_game();goto END;break;
          case 0:bye_game();goto END;break;
       }
    }
  END:
    return 0;
}
void replay_game(void)
{
    printf("重新開始遊戲!\n");
}
void bye_game(void)
{
    printf("成功退出遊戲!\n");
}
int over_game()
{
    printf("踩到地雷了!Game Over!\n");
    return 0;
}
int judge_game(int x,int y)
{
  int aa = a[x][y],status;
  if(aa == 9) {status = over_game();return status;}
  if((x>=0)&(x<=8)&(y>=0)&(y<=8)){
     switch(aa)
     {
        case 0:disappear_game(x,y);show_game(x,y);extend_game(x,y);break;//檢測八個方向
        case 1:case 2:case 3:case 4:case 5:case 6:case 7:case 8:euqal_game(x,y);break;//檢測八個方向
        default: printf("\n未知錯誤!!\n");return 0;
     }
     status = 1;
  }
  return status;
}
void extend_game(int x,int y)
{
    int i ,j;
    i = x;j = y;
    if(((i-1)>=0)&((j-1)>=0)){if(b[i-1][j-1]==0) judge_game(i-1,j-1);else euqal_game(i-1,j-1);}
    if((i-1)>=0)             {if(b[i-1][j]==0) judge_game(i-1,j);    else euqal_game(i-1,j);}
    if(((i-1)>=0)&((j+1)<=8)){if(b[i-1][j+1]==0) judge_game(i-1,j+1);else euqal_game(i-1,j+1);}
    if((j-1)>=0)             {if(b[i][j-1]==0) judge_game(i,j-1);    else euqal_game(i,j-1);}
    if((j+1)<=8)             {if(b[i][j+1]==0) judge_game(i,j+1);    else euqal_game(i,j+1);}
    if(((i+1)<=8)&((j-1)>=0)){if(b[i+1][j-1]==0) judge_game(i+1,j-1);else euqal_game(i+1,j-1);}
    if((i+1)<=8)             {if(b[i+1][j]==0) judge_game(i+1,j);    else euqal_game(i+1,j);}
    if(((i+1)<=8)&((j+1)<=8)){if(b[i+1][j+1]==0) judge_game(i+1,j+1);else euqal_game(i+1,j+1);}
}
void euqal_game(int x,int y)
{
    if(b[x][y] != '$')
    b[x][y] = a[x][y];
}
void disappear_game(int x,int y)//當檢測到0,把這個值賦值'$'
{
    b[x][y] = '$';
}
//若所選位置周圍八個方向沒有雷(0),把周邊值給b;
void show_game(int x,int y)
{
    int i ,j;
    i = x;j = y;
    if(((i-1)>=0)&((j-1)>=0)& (b[i-1][j-1]=='*')) b[i-1][j-1] = a[i-1][j-1];
    if(((i-1)>=0)&(b[i-1][j]=='*'))               b[i-1][j] = a[i-1][j];
    if(((i-1)>=0)&((j+1)<=8)&(b[i-1][j+1]=='*'))  b[i-1][j+1] = a[i-1][j+1];
    if(((j-1)>=0)&(b[i][j-1]=='*'))               b[i][j-1] = a[i][j-1];
    if(((j+1)<=8)&(b[i][j+1]=='*'))               b[i][j+1] = a[i][j+1];
    if(((i+1)<=8)&((j-1)>=0)& (b[i+1][j-1]=='*')) b[i+1][j-1] = a[i+1][j-1];
    if(((i+1)<=8)&(b[i+1][j]=='*'))               b[i+1][j] = a[i+1][j];
    if(((i+1)<=8)&((j+1)<=8)& (b[i+1][j+1]=='*')) b[i+1][j+1] = a[i+1][j+1];
}
int start_game()
{
    int x,y,status,isc;
    printf("請輸入座標:");
    scanf("%d %d",&x,&y);
    fflush(stdin);
    x=x-1;y=y-1;
    //b[x][y] = a[x][y];
    isc = check_game(x,y);
    if(isc == 1) {
        status = judge_game(x, y);
        if(status == 1)
        printnew_game();
        else
        updata_game();
        }//該點並沒有被探索過!,然後列印棋盤
    else start_game();
    return status;
}
void printnew_game()
{
    char c[X][Y] = {NULL};
    printf("   1 2 3 4 5 6 7 8 9\n");
    for (int i=0; i<=X-1; i++)
    {
       printf("%2d", i+1);
       for(int j=0; j<=Y-1; j++)
       {
          if (b[i][j] == '*') printf("%2c", b[i][j]);
          else if (b[i][j] == '$') printf("%2c", c[i][j]);//'$'表示該點處周邊無雷,也就是0,這時候棋盤上顯示空
          else printf("%2d", b[i][j]);
          if(j == Y-1) printf("\n");
       }
    }
}
int check_game(int x,int y)
{
   int isc = 1;
   if(b[x][y] != '*')
        {printf("該點已經被探索過!請重新輸入!\n");isc = 0;}
   return isc;
}
//生成棋盤
void generate_initgame(void)
{
    printf("   1 2 3 4 5 6 7 8 9\n");
    printf(" 1 * * * * * * * * *\n");
    printf(" 2 * * * * * * * * *\n");
    printf(" 3 * * * * * * * * *\n");
    printf(" 4 * * * * * * * * *\n");
    printf(" 5 * * * * * * * * *\n");
    printf(" 6 * * * * * * * * *\n");
    printf(" 7 * * * * * * * * *\n");
    printf(" 8 * * * * * * * * *\n");
    printf(" 9 * * * * * * * * *\n");
}
//  生成原始地雷
void generate_game(void)
{
    int i,j,xc,yc,n;
    srand((unsigned) (time(NULL)));//呼叫time函式來獲取隨機數
    while (!(n == 10))//防止生成雷數少於10個
    {
       xc = rand()%9;
       yc = rand()%9;
       a[xc][yc] = 9;
  //     printf("%d  ",a[xc][yc]);
       n = 0;
       for(i=0; i<X; i++)
      {
         for(j=0; j<Y; j++)
         {
           if(a[i][j] == 9)
           n++;
         }
      }
    }
    //用於除錯
//    printf("   1 2 3 4 5 6 7 8 9\n");
//    for (i=0; i<=X-1; i++)
//    {
//       printf("%2d", i+1);
//       for(j=0; j<=Y-1; j++)
//       {
//          printf("%2d", a[i][j]);
//          if(j == Y-1) printf("\n");
//       }
//    }
    explore_game();
}
void explore_game(void)
{
    int n=0;
    int i,j;
    for(i=0; i<X; i++){
      for(j=0; j<Y; j++)
      {
        if(a[i][j] == 9)
        {
              if(((i-1)>=0)&((j-1)>=0)) {if(!(a[i-1][j-1]==9))  a[i-1][j-1]++;}
              if(((i-1)>=0)&((j)>=0))   {if(!(a[i-1][j]==9))    a[i-1][j]++;}
              if(((i-1)>=0)&((j+1)>=0)) {if(!(a[i-1][j+1]==9))  a[i-1][j+1]++;}
              if(((i)>=0)&((j-1)>=0))   {if(!(a[i][j-1]==9))    a[i][j-1]++;}
              if(((i)>=0)&((j+1)>=0))   {if(!(a[i][j+1]==9))    a[i][j+1]++;}
              if(((i+1)>=0)&((j-1)>=0)) {if(!(a[i+1][j-1]==9))  a[i+1][j-1]++;}
              if(((i+1)>=0)&((j)>=0))   {if(!(a[i+1][j]==9))    a[i+1][j]++;}
              if(((i+1)>=0)&((j+1)>=0)) {if(!(a[i+1][j+1]==9))  a[i+1][j+1]++;}
              n++;
              //printf("n = %d,", n);
        }
     }
   }
   //if(n==10) updata_game();//生成原始棋盤(用於除錯,使用者不可看到)
   if(n != 10) printf("棋盤生成發生錯誤!\n");
}
//生成原始棋盤
void updata_game(void)
{
    int i,j;
    printf("\n   1 2 3 4 5 6 7 8 9\n");
    for (i=0; i<=X-1; i++)
    {
       printf("%2d", i+1);
       for(j=0; j<=Y-1; j++)
       {
          printf("%2d", a[i][j]);
          if(j == Y-1) printf("\n");
       }
    }
}
//選擇功能
int mode_game(void)
{
   int j;
   while(1)
   {
      printf("請選擇想要進行的操作:");
      scanf("%d",&j);
      fflush(stdin) ;
      switch(j)
      {
         case 1: printf("開始遊戲!\n");return j;
         case 2: printf("重新開始遊戲!\n");return j;
         case 0: printf("退出遊戲!\n");return j;
         default:  printf("輸入有誤,請輸入1,2,3來選擇相應功能!(1.開始遊戲,2.重新開始,0.結束遊戲)!\n");
      }
   }
}
//列印選單欄
void menu_game(void)
{
    printf("*********************************\n");
    printf("***********1. 開始遊戲***********\n");
    printf("***********2. 重新開始***********\n");
    printf("***********0. 結束遊戲***********\n");
    printf("*********************************\n");
}

執行結果顯示
在這裡插入圖片描述