扫雷游戏空白展开版(-v-)

扫雷游戏空白展开版(-v-),第1张

目录

一、全代码

game.h头文件

         game.c函数定义 

         test.c主调函数

 二、详细解剖代码段

 1.主函数

 2.初始化棋盘

 3.打印棋盘

 4.放置雷

 5.排查雷

6.统计周围雷的数量

7.展开周围

 8.判断是否已经赢了

三、测试 

结束语


一、全代码 game.h头文件
​
​
#include
#include
#include

#define ROW 9
#define COL 9

#define ROWS ROW+2        //外围再围上一圈用于之后方便判断雷的数量
#define COLS COL+2

#define EASY_COUNT 10     //确定雷的数目

//初始化棋盘
void InitBoard(char board[ROWS][COLS] , int rows ,int cols,char set);
//打印棋盘
void DisplayBoard(char board[ROWS][COLS],int row,int col);
//设置雷
void Setmine(char board[ROWS][COLS], int row, int col);
//排雷
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col);
//进阶排雷
void remove_NoMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);

​

​

game.c函数定义 
#include "game.h"

//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set) {
	int i = 0;
	int j = 0;
	for ( i = 0; i < rows ; i++)
	{
		for ( j = 0; j < cols; j++)
		{
			 board[i][j] = set;
		}
	}
}


//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col) {
	int i = 0;
	int j = 0;

	printf("--------扫雷---------\n");
	for (j = 0; j <= col; j++){
		printf("%d ",j);
	}
	printf("\n");

	for ( i = 1; i <= row; i++)
	{	
		printf("%d ",i);
		for ( j = 1; j <= col; j++)
		{
			printf("%c ",board[i][j]);
		}
		printf("\n");
	}
	printf("--------扫雷---------\n");
	
}

//放雷
void Setmine(char board[ROWS][COLS], int row, int col) {
	int count = EASY_COUNT;

	while (count)
	{
		int i =rand() % row + 1;
		int j =rand() % col + 1;
		if (board[i][j] == '0')
		{
			board[i][j] = '1';
			count--;
		}
	
	}

}

//统计周围雷的数量
int get_mine_count(char board[ROWS][COLS], int x, int y) {
	
	return (board[x - 1][y - 1] + board[x - 1][y] + board[x - 1][y + 1]+
			 board[x][y - 1] + board[x][y + 1]+
			 board[x + 1][y - 1] + board[x + 1][y] + board[x + 1][y + 1] - 8 * '0');

}


void Remove_NoMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)//附近都无雷,把棋盘扩展开来知道遇到雷
{
	
		int i = 0;
		int j = 0;
		show[x][y] = get_mine_count(mine, x, y) + '0';//将展示的数组里坐标更改为周围雷的个数
		if (show[x][y] == '0')
		{
			show[x][y] = ' ';//如果周围雷的个数为0,则设置此坐标为“空格”
							//判断此坐标周围坐标是否还有可设为空格的坐标 
			for (i = -1; i <= 1; i++)
			{
				for (j = -1; j <= 1; j++)
				{
					if (show[x + i][y + j] == '*')					
						Remove_NoMine(mine, show, x + i, y + j);//递归
				}
			}
		}
}

//判断是否已经赢了
int Is_win(char show[ROWS][COLS], int row, int col)
{
	int win = 0;
	int i = 0;
	int j = 0;
	for (i = 1; i <= row; i++)
	{
		for (j = 1; j <= col; j++) {
			if (show[i][j] == '*')
				win++;
		}
	}
	if (win == EASY_COUNT)
		return 1;
	else
		return 0;

}


//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
	int x = 0;
	int y = 0;
	int win = 0;
	
	while ( (win = Is_win(show,row,col)) != 1)
	{
		printf("请输入坐标:>");
		scanf("%d%d",&x,&y);
		if (x>=1 && x<= row && y >= 1 && y <= col )
		{	
			if (show[x][y] != '*')
			{
				printf("该坐标已被占用,请重新输入:>\n");
			}
			else
			{
				//是雷
				if (mine[x][y] == '1')
				{
					printf("很遗憾,被炸死了\n");
					DisplayBoard(mine, ROW, COL);
					break;
				}
				//如果不是雷
				else
				{
										
					//统计mine数组中,x,y周围有几个雷
																		 
					Remove_NoMine(mine,show,x,y);
					DisplayBoard(show, ROW, COL);
				}
			}
		
		}
		else
		{
			printf("非法坐标,请重新输入\n");
		}
	}if (win == 1)
	{
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, ROW, COL);
	}
	
}



void remove_NoMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)//附近都无雷,把棋盘扩展开来知道遇到雷
{
	if (x >= 1 && x <= ROW && y >= 1 && y <= COL)//判断坐标是否合法
	{
		int i = 0;
		int j = 0;
		show[x][y] = get_mine_count(mine, x, y) + '0';//将展示的数组里坐标更改为周围雷的个数
		if (show[x][y] == '0')
		{
			show[x][y] = ' ';//如果周围雷的个数为0,则设置此坐标为“空格”
			//判断此坐标周围坐标是否还有可设为空格的坐标 
			for (i = -1; i <= 1; i++)
			{
				for (j = -1; j <= 1; j++)
				{
					if (show[x + i][y + j] == '*')
						remove_NoMine(mine, show, x + i, y + j);//递归
				}
			}
		}
	}
}

 test.c主调函数
#include "game.h"

//菜单
void menu() {

	printf("************************\n");
	printf("******** 1.play ********\n");
	printf("******** 0.exit ********\n");
	printf("************************\n");

}

void gamm() {

	char mine[ROWS][COLS] = { 0 };		//存放布置好的雷的信息
	char show[ROWS][COLS] = { 0 };		//存放排查好雷的信息
	//初始化数组的内容为指定的内容

	//规定 mine 数组在没有布置雷的时候,都是 '0'
	InitBoard(mine,ROWS,COLS,'0');

	//规定 show 数组在没有排查雷的时候,都是 '*'
	InitBoard(show,ROWS,COLS,'*');

	//设置雷
	Setmine(mine,ROW,COL);

	打印放雷的棋盘
	DisplayBoard(mine,ROW,COL);

	//打印玩家棋盘
	DisplayBoard(show,ROW,COL);

	//排雷
	FindMine(mine,show,ROW,COL);
}

int main() {

	int input = 0;
	srand((unsigned int)time(NULL));

	do
	{	
		menu();
		printf("请选择:>");
		scanf("%d",&input);
		switch (input)
		{
		case 1:
			gamm();
			break;
		case 0 :
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择:>\n");
			break;
		}
	} while (input);

	return 0;
}
 二、详细解剖代码段  1.主函数
int main() {

	int input = 0;
	srand((unsigned int)time(NULL));        //引入时间戳来为之后的随机放雷服务

	do
	{	    
		menu();                            //打印菜单
		printf("请选择:>");
		scanf("%d",&input);                
		switch (input)
		{
		case 1:
			gamm();
			break;
		case 0 :
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择:>\n");
			break;
		}
	} while (input);                    //当输入为 0 时游戏退出

	return 0;
}
 2.初始化棋盘


//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set) {
	int i = 0;                                  //为了避免浪费,因此直接接受一个字符过来
	int j = 0;
	for ( i = 0; i < rows ; i++)
	{
		for ( j = 0; j < cols; j++)
		{
			 board[i][j] = set;
		}
	}
}

因此我们在使用的函数的时候把定义好的字符传送过来 

    //规定 mine 数组在没有布置雷的时候,都是 '0'
    InitBoard(mine,ROWS,COLS,'0');
    //规定 show 数组在没有排查雷的时候,都是 '*'
    InitBoard(show,ROWS,COLS,'*');

注意我们需要知道的是当我们定义好一个数组的时候,在传送数组的同时,无论如何都应该把原汁原味的数组来接收,比如定义好这样的数组,在传送过去后需要用相同的格式来接收

char mine[ROWS][COLS] = { 0 };        //存放布置好的雷的信息
char show[ROWS][COLS] = { 0 };        //存放排查好雷的信息 

类似于红色字体 

void InitBoard(char board[ROWS][COLS] , int rows ,int cols,char set); 

 3.打印棋盘
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col) {
	int i = 0;
	int j = 0;

	printf("--------扫雷---------\n");    //打印一个边框
	for (j = 0; j <= col; j++){          //打印一行数字,来让玩家更容易来找到坐标
		printf("%d ",j);                //这里从 0 开始可以对齐横纵坐标
	}
	printf("\n");

	for ( i = 1; i <= row; i++)
	{	    
		printf("%d ",i);                //打印纵坐标
		for ( j = 1; j <= col; j++)        
		{
			printf("%c ",board[i][j]);
		}
		printf("\n");
	}
	printf("--------扫雷---------\n");
	
}
 4.放置雷
//放雷
void Setmine(char board[ROWS][COLS], int row, int col) {
	int count = EASY_COUNT;             //在头文件中定义了雷的数目

	while (count)
	{
		int i =rand() % row + 1;        //使用了rand()函数,需要包含stdbli.h 头文件
		int j =rand() % col + 1;
		if (board[i][j] == '0')        //当不是雷的时候就放置一个雷
		{
			board[i][j] = '1';        //我们需要把雷定义为数字字符 '1' 因为是字符数组
			count--;                  //不过我们需要知道字符1 对应的ASCII值是 49
		}                             //这点我们在之后的排查雷的时候会用到
	
	}

}
 5.排查雷
​
​
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
	int x = 0;
	int y = 0;
	int win = 0;

	while ( (win = Is_win(show,row,col)) != 1)        //这里用到了函数的调用
	{
		printf("请输入坐标:>");
		scanf("%d%d",&x,&y);
		if (x>=1 && x<= row && y >= 1 && y <= col )
		{	
			if (show[x][y] != '*')
			{
				printf("该坐标已被占用,请重新输入:>\n");
			}
			else
			{
				//是雷
				if (mine[x][y] == '1')
				{
					printf("很遗憾,被炸死了\n");
					DisplayBoard(mine, ROW, COL);        //打印棋盘
					break;
				}
				//如果不是雷
				else
				{
																				                                                                                     
                                                     //统计mine数组中,x,y周围有几个雷
					Remove_NoMine(mine,show,x,y);    //并展开周围没有雷的坐标
                            
					DisplayBoard(show, ROW, COL);    //打印排查之后的棋盘
				}
			}
		
		}
		else
		{
			printf("非法坐标,请重新输入\n");
		}
	}if (win == 1)
	{
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, ROW, COL);            //打印布置雷的棋盘
	}
	
}

​

​

  

6.统计周围雷的数量
//统计周围雷的数量

int get_mine_count(char board[ROWS][COLS], int x, int y) {
	
	return (board[x - 1][y - 1] + board[x - 1][y] + board[x - 1][y + 1]+
			 board[x][y - 1] + board[x][y + 1]+
			 board[x + 1][y - 1] + board[x + 1][y] + board[x + 1][y + 1] - 8 * '0');

}

这个就是一个八面相加然后减去8 * ‘0’  的值就行了

7.展开周围
//当周围有雷时显示周围有多少雷,并展开没有周围数字显示的"空格"

void Remove_NoMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
//附近都无雷,把棋盘扩展开来知道遇到雷
{
	
		int i = 0;
		int j = 0;
		show[x][y] = get_mine_count(mine, x, y) + '0';//将展示的数组里坐标更改为周围雷的个数
                                                     //转换成数字字符
                                                    //字符0,与数字0 相隔48 ,因此减去就行
                                                    //这个方法同样的也适用与其他数字字符的转换

		if (show[x][y] == '0')
		{
			show[x][y] = ' ';    //如果周围雷的个数为0,则设置此坐标为“空格”
			                    //判断此坐标周围坐标是否还有可设为空格的坐标 
			for (i = -1; i <= 1; i++)
			{
				for (j = -1; j <= 1; j++)
				{
					if (show[x + i][y + j] == '*')					
						Remove_NoMine(mine, show, x + i, y + j);    //递归直到遇到数字
				}
			}
		}
}

​
 8.判断是否已经赢了

​
//判断是否已经赢了
int Is_win(char show[ROWS][COLS], int row, int col)
{
	int win = 0;            //用于统计剩下的*与雷相比较,相同即排雷成功
	int i = 0;
	int j = 0;
	for (i = 1; i <= row; i++)
	{
		for (j = 1; j <= col; j++) {
			if (show[i][j] == '*')
				win++;
		}
	}
	if (win == EASY_COUNT)        //用于判断是否需要继续循环
		return 1;
	else
		return 0;

}

​
三、测试 

结束语

为了理解到这个扫雷的代码,还是得花上一点时间啊……

 未完持续……

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/874614.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存