扫雷 (防止第一次被炸死和展开)

写了一个扫雷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;
}
 








就这样了 不足之处望大家指出。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值