1. 程式人生 > >掃雷 (防止第一次被炸死和展開)

掃雷 (防止第一次被炸死和展開)

寫了一個掃雷10*10格子,實現

 1.第一次不會被炸死 。

2.選擇座標後,實現周圍沒有雷格子的展開。

注:下文中提到  “ 區域 ” 均可理解為  “ 座標 ”

Mine Clearance.h(標頭檔案)

#ifndef __Mine_Clearance__
#define __Mine_Clearance__
#define _CRT_SECURE_NO_WARNINGS
#include  <stdio.h>
#include  <stdlib.h>
#include  <time.h>
#define M  9                                                      //定義炸彈數量。
#define ROW 11                                                    //定義棋盤大小。
#define COL 11

void init(char mine[ROW][COL], char show[ROW][COL]);            //宣告game.c中的函式。

void displayboard(char show[ROW][COL]);

void displaymine(char mine[ROW][COL]);

void  Set_Mine(char mine[ROW][COL], int m);

void sweep_Mine(char mine[ROW][COL], int x, int y);

int if_success(char mine[ROW][COL], char show[ROW][COL], int m );


void prevent_first_death(char mine[ROW][COL], int x, int y);

int Num_boms(char mine[ROW][COL], int x, int y);

void spread(char mine[ROW][COL], char show[ROW][COL], int x, int y);

#endif

game.c(函式檔案)

#include "Mine Clearance.h"
//printf("%3d\n", ' ');  32
//printf("%3d\n", '!');  33
//printf("%3d\n", '*');  42
//printf("%3d\n", '0');  48
//printf("%3d\n", '1');  49
//
void init(char mine[ROW][COL], char show[ROW][COL])     //初始化雷盤和展示盤陣列,大小設定為11*11.
{
	int i, j;


	for (i = 0; i < ROW-1 ; i++)
	{
		for (j = 0; j < COL-1; j++)               //ROW-1只設置10*10的雷盤,陣列未被初始化的部分會自動設為'0',
		{
			mine[i][j] = ' ';                 //方便之後對 邊界區域的展開函式 和 雷數統函式 的呼叫。
			show[i][j] = '*';

		}
	}

}
void displayboard(char show[ROW][COL])             //向用戶展示盤。
{
	int i, j;
	printf("  |");
	for (i = 1; i <= 10; i++)
	{
		printf("%d ", i);
	}
	printf("\n--|--------------------\n");
	for (i = 0; i < ROW-1; i++)
	{
		printf("%2d|", i + 1);
		for (j = 0; j < COL-1; j++)
		{
			printf("%c ",show[i][j]);
		}
		printf("\n");
	}
	

}
void displaymine(char mine[ROW][COL])                //展示雷盤,測試時使用。 (正常遊戲時在test.c中註釋掉即可)。

{


	int i, j;
	printf("  |");
	for (i = 1; i <= 10; i++)
	{
		printf("%d ", i);
	}
	printf("\n--|--------------------\n");
	for (i = 0; i < ROW-1; i++)
	{
		printf("%2d|", i + 1);
		for (j = 0; j < COL-1; j++)
		{
			printf("%c ", mine[i][j]);
		}
		printf("\n");
	}



}

void  Set_Mine(char mine[ROW][COL], int m)      //隨機放置雷,可以通過在標頭檔案中修改 M 的定義值從而修改 m的大小,即改變佈置的雷數。

{
	int x, y;
	while (m)
	{
		
			x = rand() % 10 + 0;
		    y = rand() % 10 + 0;
		
			if (mine[x][y] == ' ')
			{	
				mine[x][y] = '!';
				m--;
			}
	
		
		
	}
	m = M;
}
int Num_boms(char mine[ROW][COL], int x, int y)   //統計周邊的雷數。
{
	int count = 0;

		if (mine[x - 1][y - 1] == '!')
		{
			count++;
		}
		if (mine[x - 1][y] == '!')
		{
			count++;
		}
		if (mine[x - 1][y + 1] == '!')
		{
			count++;
		}
		if (mine[x][y + 1] == '!')
		{
			count++;
		}
		if (mine[x + 1][y + 1] == '!')
		{
			count++;
		}
		if (mine[x + 1][y] == '!')
		{
			count++;
		}
		if (mine[x + 1][y - 1] == '!')
		{
			count++;
		}
		if (mine[x][y - 1] == '!')
		{
			count++;
		}
	
	return count;
}

void spread(char mine[ROW][COL], char show[ROW][COL], const x, const y)   //擴充套件函式,向(x,y)周邊的八個區域進行擴充套件。
{
	int ret, i, j;                                                     
     
	int a, b;                                                            
	a = x;
	b = y;
	if ((x >=0)                                                //x,y值得大小應在陣列座標內,不做限定的話會造成死迴圈,使系統崩潰。

		&& (x <= 9)
		&& (y >=0)                                                   
		&& (y <=9))
	{
		 

		if (mine[x - 1][y - 1] == ' ')                        //如果該區域不是雷。
		{
			a = x - 1;
			b = y - 1;
			ret = Num_boms(mine, a, b);                     //返回以該區域為中心雷的數量。
			
				if (ret == 0)                                 //若在這八個區域中哪個區域的返回炸彈數值為0,即ret==0,

				{
					show[a][b] = ' ';                     //如果周圍沒有雷就向玩家展示‘ ’空格。
					mine[a][b] = '0';                        //將雷盤中的區域改為 ‘0’可方便測試用。
					spread(mine, show, a, b);              //則將這個區域的座標賦值個x和y,再次進行展開。

				}
				else
				{
					show[a][b] = '0' + ret;
					mine[a][b] = '0';
				}
				
			
		}

		if (mine[x][y - 1] == ' ')                                //以下的另外七個區域均相同。
		{
			a = x;
			b = y - 1;
			ret = Num_boms(mine, a, b);

			if (ret == 0)
			{
				show[a][b] = ' ';
				mine[a][b] = '0';
				spread(mine, show, a, b);
			}
			else
			{
				show[a][b] = '0' + ret;
				mine[a][b] = '0';
			}
			
		}

		if (mine[x - 1][y] == ' ')
		{
			a = x - 1;
			b = y;
			ret = Num_boms(mine, a, b);
			if (ret == 0)
			{
				show[a][b] = ' ';
				mine[a][b] = '0';
				spread(mine, show, a, b);
			}
			else
			{
				show[a][b] = '0' + ret;
				mine[a][b] = '0';
			}

		}
		if (mine[x + 1][y - 1] == ' ')
		{
			a = x + 1;
			b = y - 1;
			ret = Num_boms(mine, a, b);
			if (ret == 0)
			{
				show[a][b] = ' ';
				mine[a][b] = '0';
				spread(mine, show, a, b);
			}
			else
			{
				show[a][b] = '0' + ret;
				mine[a][b] = '0';
			}
			
		}

		if (mine[x + 1][y] == ' ')
		{
			a = x + 1;
			b = y;
			ret = Num_boms(mine, a, b);
			if (ret == 0)
			{
				show[x + 1][y] = ' ';
				mine[a][b] = '0';
				spread(mine, show, a, b);
			}
			else
			{
				show[x + 1][y] = '0' + ret;
				mine[a][b] = '0';
			}
		}
		if (mine[x + 1][y + 1] == ' ')
		{
			a = x + 1;
			b = y + 1;
			ret = Num_boms(mine, a, b);
			if (ret == 0)
			{
				show[x + 1][y + 1] = ' ';
				mine[a][b] = '0';
				spread(mine, show, a, b);
			}
			else
			{
				show[x + 1][y + 1] = '0' + ret;
				mine[a][b] = '0';
			}
			

		}
		if (mine[x][y + 1] == ' ')
		{
			a = x;
			b = y + 1;
			ret = Num_boms(mine, a, b);
			if (ret == 0)
			{
				show[x][y + 1] = ' ';
				mine[a][b] = '0';
				spread(mine, show, a, b);
			}
			else
			{
				show[x][y + 1] = '0' + ret;
				mine[a][b] = '0';
			}
		}
		if (mine[x - 1][y + 1] == ' ')
		{
			a = x - 1;
			b = y + 1;
			ret = Num_boms(mine, a, b);
			if (ret == 0)
			{
				show[x - 1][y + 1] = ' ';
				mine[a][b] = '0';
				spread(mine, show, a, b);
			}
			else
			{
				show[x - 1][y + 1] = '0' + ret;
				mine[a][b] = '0';
			}
			
		}
		
	

}
}

void sweep_Mine(char mine[ROW][COL], char show[ROW][COL],   int x, int y)   //該函式為掃雷函式:

{
	int ret = 0;
	
	if ( mine[x][y] == ' ')                                            //玩家沒有踩到雷,即展示該區域周邊的雷數,如果雷數為0就顯示‘ ’空格。
	{
		ret=Num_boms(mine, x, y);
		if (ret == 0)
		{
			show[x][y] = ' ';
			
			
		}
		else
		{
			show[x][y] = '0' + ret;                           //如果有炸彈就顯示炸彈的數量。
			
		}
		spread(mine, show, x, y);                               // 並在此呼叫展開函式,對周邊區域進行展開。

	}
	else if(mine[x][y] == '!')
	{

		show[x][y] = mine[x][y];                             //如果玩家踩到炸彈就顯示感嘆號。
		
	}

}



void prevent_first_death(char mine[ROW][COL],int x,int y)      //防止玩家第一次被炸死。
{
	int m, n;
	
	if(mine[x][y] == '!')
	{
		do 
		{
			m = rand() % 11 + 0;
			n = rand() % 11 + 0;                  //如果玩家踩到雷,就重新隨機一個沒有雷的地方,將炸彈移動到那裡。

			  if (mine[m][n] == ' ')
			{
				mine[x][y] = ' ';             //將該區域設定為空格。
				mine[m][n] = '!';
				break;
			}
		} while (1);
				
	}


}

int if_success(char mine[ROW][COL], char show[ROW][COL], int m )  //判斷是否輸贏的函式。
{
	int i, j,num;
	num = M;
	for (i = 0; i < ROW; i++)
	{
         for (j = 0; j < COL;j++)
       {
			 if (show[i][j]=='*')                //如果在展示棋盤上剩餘 ‘*’的數量和雷數相同,那麼就表示掃雷成功了!    
			 {
				 num--;
			 }
			else if (show[i][j] == '!')         //如果顯示盤上出現了 ‘!’說明玩家踩到了雷。
	         {
		      return 1;
	         }
	
        }
   }
	
	if (num == 0)
	{
		return 0;
	}

}


test.c(執行檔案)

#include "Mine Clearance.h"


void mune()     //介面。
{

	printf("  \n  *******************************************************************\n");
	printf("  ********** Do you want to play the Mine_Clearance Game?  **********\n");
	printf("  ***********                                          **************\n");
	printf("  *************   1.play                2.exit        ***************\n");
	printf("  *******************************************************************\n");




}


game()                                         //玩遊戲的函式。
{
	
	char mine[ROW][COL];
	char show[ROW][COL] ;
	char spread[ROW][COL];
	int x, y,m;
	int row, col;
	int count=0;
	int ret;
	row = ROW;
    col = COL;
	m = M;                               //將定義中的M賦值給 m
	init(mine, show, spread);
	
	Set_Mine(mine, m);
    
	displaymine(mine);                   //在測試中使用,遊戲中可註釋掉。
	do
	{
	   displayboard(show);
	   count++;
	   printf("Please enter coordinates(x,y):");
	   scanf("%d %d", &x, &y);
	   getchar();
	   x = x - 1;
	   y= y - 1;
	   if (count == 1)
	  {
		prevent_first_death(mine, x, y);
	  
	   } 
	   sweep_Mine(mine, show,  x, y);
	
	   ret=if_success(mine,show,x,y);
	   if (ret == 1)
	   {
		   displayboard(show);
		   printf("\n  Sorry, you were killed by mine.\n");
		   break;
	   }
	   else if (ret == 0)
	   {
		   displayboard(show);
		   printf("\n  Congratulations! Mineclearance success.\n ");
		   break;
	   }
	
	
	
	
	
	} while (1);




}



int main()                              //主函式 ,選單的選擇與遊戲的呼叫。
{
	int n;

	do
	{
		mune();
		scanf("%d",&n);
		getchar();
		if (n == 1)
		{
			game();
		}
		else if (n==2)
		{
			break;
		}
		else
		{
			;
		}
    } while (1);


	return 0;
}
 


就這樣了 不足之處望大家指出。