快进来看看!!!C语言——扫雷小游戏(递归展开无雷区)

目录

前言

一、扫雷游戏规则 

二、展示效果

三、 游戏设计思路

四、代码展示

一、游戏交互界面

二、游戏主体

二、扫雷代码实现

1.游戏框架搭建

2.初始化雷盘

3.打印雷盘

4.放置雷

5.遍历获取坐标周围八个雷的个数

6.遍历打开不是雷的地方

7.寻找雷

完整代码

game.h

game.c

test.c


前言

说起扫雷,相信大家应该都不陌生吧。windows系统里的小游戏,扫雷有着不可撼动的地位。

今天我们就用c语言来复刻扫雷小游戏!

快进来看看!!!C语言——扫雷小游戏(递归展开无雷区)_第1张图片

一、扫雷游戏规则 

玩家需要排查出格子中的雷,点开一个方块后,显示数字,数字是几就表示它周围的八个方块有几个雷。

快进来看看!!!C语言——扫雷小游戏(递归展开无雷区)_第2张图片

比如说这个红色的方框里面就存在一个雷。

二、展示效果

 快进来看看!!!C语言——扫雷小游戏(递归展开无雷区)_第3张图片

三、 游戏设计思路

雷盘相当于一个二维的数组

一、游戏交互界面

  1. 创建游戏菜单
  2. 创建游戏逻辑主体

二、扫雷游戏实现

  1. 创建扫雷棋盘
  2. 初始化扫雷棋盘
  3. 布置雷
  4. 打印扫雷棋盘
  5. 用户排查雷
  6. 判断输赢

1.设计扫雷游戏的时候,二维数组的行数和列数需要比真正想要得到的棋盘多两行和多两列

为什么呢?

因为我们排查雷的时候,需要遍历坐标走位八个格子是否有雷,当输入坐标为雷盘边界坐标时,遍历周围的雷就会出现越界的问题!

快进来看看!!!C语言——扫雷小游戏(递归展开无雷区)_第4张图片

 2.创建两个雷盘,一个用于显示,一个用于存放地雷

只创建一个棋盘,那么这一个棋盘上就要放置3种信息。分别为雷、非雷、排查出周围雷的信息。虽然这种方法也没太大的问题,但是一个棋盘上放置3种信息会给之后打印棋盘时造成麻烦,不易打印。
 

 3.使用宏常量

方便雷盘大小的修改,不会写死程序,提高代码的灵活性。

四、代码展示

一、游戏交互界面

void menu()
{
	printf("**************************\n");
	printf("********1.开始游戏********\n");
	printf("********0.退出游戏********\n");
	printf("**************************\n");
}

二、游戏主体

int main()
{   
	srand((unsigned int)time(NULL));
	int intput = 0;
again:
	menu();
scanf("%d", &intput);
	do
	{ 
		switch (intput)
		{
		case 1:
				printf("游戏开始\n");
				game();
				goto again;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误请重新输入\n");
			break;
		}
	} while(intput);
	
	return 0;
}

二、扫雷代码实现

1.游戏框架搭建

void game()
{
	//设置两个数组,mine数组用来存放设置雷的信息,show数组用来存放排查雷的信息
	char mine[ROWS][COLS] = {0};
	char show[ROWS][COLS] = {0};
	init_board(show,ROWS,COLS,'*');
	init_board(mine, ROWS, COLS, '0');
	//display_board(mine, ROW, COL);
	display_board(show, ROW, COL);
	set_mine(mine,ROW,COL);
	//display_board(mine, ROW, COL);
	find_mine(mine,show,ROW,COL);
}

2.初始化雷盘

void init_board(char board[][COLS],int rows,int cols,char set)//初始化雷盘,set是需要初始化成什么字符
{   
	int i = 0;
	int j = 0;
	
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set;
		}
	}
}

3.打印雷盘

void display_board(char board[][COLS], int row, int col)
{    
	printf("---------扫雷游戏-------------\n");
	printf("   ");
	for (int n = 1; n <= col; n++)
	{
		printf("%d ",n);
	}
	printf("\n");
	printf("------------------------------\n");

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

4.放置雷

void set_mine(char board[][COLS], int row, int col)
{
	
	int count = MINENUMS;
 	while (count)
	{   
		int x = rand() % row + 1;
		int y = rand() % col + 1;//设置1~9随机数布置雷
		if (board[x][y] != '1')
		{
			board[x][y] = '1';
			count--;
		}
	}
}

5.遍历获取坐标周围八个雷的个数


//获取坐标周围的雷数目(八个格子)
int get_minecount(char mine[][COLS], int x, int y)
{
	int n = mine[x - 1][y - 1] +
		mine[x - 1][y] +
		mine[x - 1][y + 1] +
		mine[x][y - 1] +
		mine[x][y + 1] +
		mine[x + 1][y - 1] +
		mine[x + 1][y] +
		mine[x + 1][y + 1] - 8 * '0';//减去八个字符零是因为八个字符相加,要转换成数字得到和
	    return n;
}

6.遍历打开不是雷的地方

void ergodic(char mine[][COLS],char show[][COLS],int x,int y,int *w)//遍历打开不是雷的区域
{
	int mine_num = get_minecount(mine, x, y);
	if (mine_num == 0)
	{   
		show[x][y] = ' ';//如果这个坐标周围都没有雷的话,显示为空格
		(*w)++;
		system("cls");
		display_board(show, ROW, COL);
		/*display_board(mine, ROW, COL);*/

		if ((x - 1 >= 1 && x - 1 <= ROW) && (y - 1 >= 1 && y - 1 <= COL) && show[x - 1][y - 1] == '*')
		{
			ergodic(mine,show,x-1,y-1,w);
		}
		if ((x - 1 >= 1 && x - 1 <= ROW) && (y >= 1 && y <= COL) && show[x - 1][y] == '*')
		{
			ergodic(mine, show, x - 1, y,w );
		}
		if ((x - 1 >= 1 && x - 1 <= ROW) && (y +1>= 1 && y+1 <= COL) && show[x - 1][y+1] == '*')
		{
			ergodic(mine, show, x - 1, y+1,w);
		}
		if((x>=1&&x<=ROW)&&(y - 1 >= 1 && y - 1 <= COL) && show[x ][y - 1] == '*')
		{
			ergodic(mine, show, x , y - 1,w);
		}
		if ((x >= 1 && x <= ROW) && (y + 1 >= 1 && y + 1 <= COL) && show[x][y + 1] == '*')
		{
			ergodic(mine, show, x, y + 1,w);
		}
		if ((x + 1 >= 1 && x + 1 <= ROW) && (y - 1 >= 1 && y - 1 <= COL) && show[x + 1][y - 1] == '*')
		{
			ergodic(mine, show, x + 1, y - 1,w);
		}
		if ((x + 1 >= 1 && x + 1 <= ROW) && (y >= 1 && y <= COL) && show[x + 1][y] == '*')
		{
			ergodic(mine, show, x + 1, y,w);
		}
		if ((x + 1 >= 1 && x + 1 <= ROW) && (y + 1 >= 1 && y + 1 <= COL) && show[x + 1][y + 1] == '*')
		{
			ergodic(mine, show, x + 1, y + 1,w);
		}
	}
	else
	{
		show[x][y] = mine_num + '0';
	///*	display_board(mine, ROW, COL);*/

		(*w)++;
	}

}

7.寻找雷

void find_mine(char mine[][COLS],char show[][COLS],int row,int col)//寻找雷
{
	int x = 0;
	int y = 0;
	int win = 0;
	int* w = &win;
	while (win < (row * col - MINENUMS))//判断是否已经排查完毕,win相当于一个计数器
	{
		printf("请输入需要排雷的坐标: ");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] == '*')
			{
				if (mine[x][y] == '1')
				{
					printf("你被炸死了!\n");
					display_board(show,row,col);
					break;
				}
				else
				{
				/*	int count = get_minecount(mine,x,y);
					show[x][y] = count + '0';*/

					ergodic(mine,show,x,y,w);
					system("cls");
					display_board(show, ROW, COL);
					/*display_board(mine, ROW, COL);*/
					/*win++;*/
					
				}
			}
			else
			{
				printf("坐标已经被排查过啦!\n");
			}
		}
		else
		{
			printf("输入的坐标有误!\n");
		}
	}
	if (win == row * col - MINENUMS)
	{
		printf("恭喜你,排雷成功!\n\n\n\n");
		display_board(show, ROW, COL);
	}
}

这里的win相当于计数器,排一个格子,win就加一,作为判断输赢的条件

完整代码

game.h

#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
#include
#include
#define ROW 9
#define COL 9//雷盘大小
#define ROWS ROW+2
#define COLS COL+2
#define MINENUMS 10//布置雷数
void game();

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

void display_board(char board[][COLS], int row, int col);

void set_mine(char board[][COLS], int row, int col);

void find_mine(char mine[][COLS], char show[][COLS], int row, int col);

game.c


#include"game.h"

void game()
{
	//设置两个数组,mine数组用来存放设置雷的信息,show数组用来存放排查雷的信息
	char mine[ROWS][COLS] = {0};
	char show[ROWS][COLS] = {0};
	init_board(show,ROWS,COLS,'*');
	init_board(mine, ROWS, COLS, '0');
	//display_board(mine, ROW, COL);
	display_board(show, ROW, COL);
	set_mine(mine,ROW,COL);
	//display_board(mine, ROW, COL);
	find_mine(mine,show,ROW,COL);
}


void init_board(char board[][COLS],int rows,int cols,char set)//初始化雷盘,set是需要初始化成什么字符
{   
	int i = 0;
	int j = 0;
	
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set;
		}
	}
}

//打印雷盘,制作的是9x9的雷盘
//把雷盘看成一个二维数组打印,为了防止数组越界,我们数组的行和列分别要比想要棋盘的行和列多2
void display_board(char board[][COLS], int row, int col)
{    
	printf("---------扫雷游戏-------------\n");
	printf("   ");
	for (int n = 1; n <= col; n++)
	{
		printf("%d ",n);
	}
	printf("\n");
	printf("------------------------------\n");

	for (int i = 1; i <= row; i++)
	{   
		printf("%d |",i);
		for (int j = 1; j <= col; j++)
		{
			printf("%c ",board[i][j]);
		}
		printf("|");
		printf("\n");
	}
	printf("-----------------------------\n");
	
}
void set_mine(char board[][COLS], int row, int col)
{
	
	int count = MINENUMS;
 	while (count)
	{   
		int x = rand() % row + 1;
		int y = rand() % col + 1;//设置1~9随机数布置雷
		if (board[x][y] != '1')
		{
			board[x][y] = '1';
			count--;
		}
	}
}

//获取坐标周围的雷数目(八个格子)
int get_minecount(char mine[][COLS], int x, int y)
{
	int n = mine[x - 1][y - 1] +
		mine[x - 1][y] +
		mine[x - 1][y + 1] +
		mine[x][y - 1] +
		mine[x][y + 1] +
		mine[x + 1][y - 1] +
		mine[x + 1][y] +
		mine[x + 1][y + 1] - 8 * '0';//减去八个字符零是因为八个字符相加,要转换成数字得到和
	    return n;
}
 void ergodic(char mine[][COLS],char show[][COLS],int x,int y,int *w)//遍历打开不是雷的区域
{
	int mine_num = get_minecount(mine, x, y);
	if (mine_num == 0)
	{   
		show[x][y] = ' ';//如果这个坐标周围都没有雷的话,显示为空格
		(*w)++;
		system("cls");
		display_board(show, ROW, COL);
		/*display_board(mine, ROW, COL);*/

		if ((x - 1 >= 1 && x - 1 <= ROW) && (y - 1 >= 1 && y - 1 <= COL) && show[x - 1][y - 1] == '*')
		{
			ergodic(mine,show,x-1,y-1,w);
		}
		if ((x - 1 >= 1 && x - 1 <= ROW) && (y >= 1 && y <= COL) && show[x - 1][y] == '*')
		{
			ergodic(mine, show, x - 1, y,w );
		}
		if ((x - 1 >= 1 && x - 1 <= ROW) && (y +1>= 1 && y+1 <= COL) && show[x - 1][y+1] == '*')
		{
			ergodic(mine, show, x - 1, y+1,w);
		}
		if((x>=1&&x<=ROW)&&(y - 1 >= 1 && y - 1 <= COL) && show[x ][y - 1] == '*')
		{
			ergodic(mine, show, x , y - 1,w);
		}
		if ((x >= 1 && x <= ROW) && (y + 1 >= 1 && y + 1 <= COL) && show[x][y + 1] == '*')
		{
			ergodic(mine, show, x, y + 1,w);
		}
		if ((x + 1 >= 1 && x + 1 <= ROW) && (y - 1 >= 1 && y - 1 <= COL) && show[x + 1][y - 1] == '*')
		{
			ergodic(mine, show, x + 1, y - 1,w);
		}
		if ((x + 1 >= 1 && x + 1 <= ROW) && (y >= 1 && y <= COL) && show[x + 1][y] == '*')
		{
			ergodic(mine, show, x + 1, y,w);
		}
		if ((x + 1 >= 1 && x + 1 <= ROW) && (y + 1 >= 1 && y + 1 <= COL) && show[x + 1][y + 1] == '*')
		{
			ergodic(mine, show, x + 1, y + 1,w);
		}
	}
	else
	{
		show[x][y] = mine_num + '0';
	///*	display_board(mine, ROW, COL);*/

		(*w)++;
	}

}

void find_mine(char mine[][COLS],char show[][COLS],int row,int col)//寻找雷
{
	int x = 0;
	int y = 0;
	int win = 0;
	int* w = &win;
	while (win < (row * col - MINENUMS))//判断是否已经排查完毕,win相当于一个计数器
	{
		printf("请输入需要排雷的坐标: ");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] == '*')
			{
				if (mine[x][y] == '1')
				{
					printf("你被炸死了!\n");
					display_board(show,row,col);
					break;
				}
				else
				{
				/*	int count = get_minecount(mine,x,y);
					show[x][y] = count + '0';*/

					ergodic(mine,show,x,y,w);
					system("cls");
					display_board(show, ROW, COL);
					/*display_board(mine, ROW, COL);*/
					/*win++;*/
					
				}
			}
			else
			{
				printf("坐标已经被排查过啦!\n");
			}
		}
		else
		{
			printf("输入的坐标有误!\n");
		}
	}
	if (win == row * col - MINENUMS)
	{
		printf("恭喜你,排雷成功!\n\n\n\n");
		display_board(show, ROW, COL);
	}
}





test.c


#include"game.h"
void menu()
{
	printf("**************************\n");
	printf("********1.开始游戏********\n");
	printf("********0.退出游戏********\n");
	printf("**************************\n");
}
int main()
{   
	srand((unsigned int)time(NULL));
	int intput = 0;
again:
	menu();
scanf("%d", &intput);
	do
	{ 
		switch (intput)
		{
		case 1:
				printf("游戏开始\n");
				game();
				goto again;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误请重新输入\n");
			break;
		}
	} while(intput);
	
	return 0;
}


制作不易,给博主一键3连吧!蟹蟹!!!

制作不易,给博主一键3连吧!蟹蟹!!!

制作不易,给博主一键3连吧!蟹蟹!!!

你可能感兴趣的:(重新学习编程,c语言,开发语言)