C语言扫雷最新 递归展开 超详解(附源码)

文章目录

    • 一、前言
          • 游戏说明
          • 游戏效果
    • 二、实现步骤
          • 1、头文件、宏定义、全局变量及函数声明
          • 2、初始化游戏界面
          • 3、布置地雷
          • 4、扫雷
          • 5、扫雷完成判断
          • 6、主函数
    • 三、完结撒花
    • 四、完整源码

一、前言

什么!写C语言扫雷游戏?只需要100行代码、只需要C语言基础?没错!对新手超级友好、超详细的教程来了,通过这个小项目的练习你的编程能力又能得到更大的提升。太简单还是不够过瘾?
C语言写俄罗斯方块在这里 :https://blog.csdn.net/qq_41796226/article/details/125818224

游戏说明

1.输入对应的横纵坐标 x y (含输入合法性检查)
2.坐标为(x , y)的点显示周围地雷的数量
3.如果为周围地雷数量为 0,程序自动点开 0 位置周围各点(递归算法)
4.游戏界面显示剩余不确定的位置个数,和已知的地雷数量
5.可自定义界面大小和地雷数量
6.快去拓展更多功能吧

游戏效果

C语言扫雷最新 递归展开 超详解(附源码)_第1张图片

二、实现步骤

1、头文件、宏定义、全局变量及函数声明
#include
#include
#include

#define HEIGHT 10	//行
#define WIDTH 10	//列
#define BOOM_NUM 10
int count_last = HEIGHT*HEIGHT;
char user_map[HEIGHT][WIDTH];	//玩家界面
char mine_map[HEIGHT][WIDTH];	//设计者界面

void initial_map();
void put_map(char (*p)[WIDTH]);
void set_bom();
void sweep(int x,int y);
int check();
int count_here(int m,int n);
2、初始化游戏界面

C语言扫雷最新 递归展开 超详解(附源码)_第2张图片

全局变量:
char user_map[HEIGHT][WIDTH];
char mine_map[HEIGHT][WIDTH];

/*
功能:给全局变量两个二维数组赋初始值
*/
void initial_map()
{
	int i,j;
	for(i=0;i<HEIGHT;i++)
	{
		for(j=0;j<WIDTH;j++)
		{
			user_map[i][j] = '*';//玩家界面的点
			mine_map[i][j] = '-';//开发者界面的点
		}
	}
}
/*
功能:打印游戏界面
参数:传入mine_map或者user_map
*/
void put_map(char (*p)[WIDTH])			//对数组指针不太了解的可以分成put_minemap和put_usermap两个函数写
{
	check();				//函数中计算user_map剩余'*'的数量count_last
	printf("  Remain: %2d     Boom: %2d\n",count_last,BOOM_NUM);
	int i,j;
	for(i=0;i<2;i++)			//界面前两行打印辅助标示
	{
		printf("    ");
		for(j=0;j<WIDTH;j++)
		{
			if(i==0)
				printf("%2d",j);
			else
				printf(" v");
		}
		printf("\n");
	}
	for(i=0;i<HEIGHT;i++)
	{
		printf("%2d >",i); 		//界面前两列打印辅助标示
		for(j=0;j<WIDTH;j++)
		{
			printf(" %c",p[i][j]);
		}
		printf("\n");
	}
}
3、布置地雷

#include
#include
#define BOOM_NUM 10

/*
功能:给mine_map坐标系中随机布置BOM_NUM个地雷
*/
void set_bom()
{
	srand(time(0));				//随机时间种子
	int x,y;
	int bom_num = BOOM_NUM;
	while(bom_num)
	{
		x = rand()%HEIGHT;		//随机出一个数 0~HEIGHT-1
		y = rand()%WIDTH;		//随机出一个数 0~WIDTH-1
		if(mine_map[x][y]=='@')	//避免一个位置重复布雷
			continue;
		mine_map[x][y] = '@';
		bom_num--;				//每布下一个雷,自减一次
	}
}
4、扫雷
/*
功能:计算user_map[y][x]周围地雷数量
参数:玩家输入的横坐标x,纵坐标y
返回值:(x,y)周围地雷的数量
*/
int count_here(int x,int y) 
{
	int count = 0;
	int i,j;
	for(i=(y==0?0:y-1);i<=(y==HEIGHT-1?HEIGHT-1:y+1);i++)
	{
		for(j=(x==0?0:x-1);j<=(x==WIDTH-1?WIDTH:x+1);j++)//考虑越界问题,下图详解
		{
			if(mine_map[i][j]=='@')		//通过mine_map[i][j]来映射user_map[i][j]
				count++;
		}
	}
	return count;
}

C语言扫雷最新 递归展开 超详解(附源码)_第3张图片

/*
功能:给user_map[y][x]赋值为该点周围地雷数量,若为0,调用自身给0周围的点赋值,依次递归
参数:玩家输入的横坐标x,纵坐标y
*/
void sweep(int x,int y) 
{

		if(user_map[y][x]!='*')
			return;
		int count = count_here(x,y);
		user_map[y][x] = count+'0';	//把int类型转换为char类型
		system("clear");		//清屏(非linux终端注释这行代码)
		fflush(stdout);			//清理终端缓存(非linux终端注释这行代码)
		put_map(user_map);
		usleep(1000*50);		//微秒级延时(非linux终端注释这行代码)
		if(count!=0)			//若count为0,递归调用
			return;
		int i,j;
		for(i=(y==0?0:y-1);i<=(y==HEIGHT-1?HEIGHT-1:y+1);i++)//考虑越界问题,上图详解
		{
			for(j=(x==0?0:x-1);j<=(x==WIDTH-1?WIDTH-1:x+1);j++)
			{
				sweep(j,i);
			}
		}
		return;
}
5、扫雷完成判断

C语言扫雷最新 递归展开 超详解(附源码)_第4张图片

全局变量
int count_last = HEIGHT*HEIGHT;

/*
功能:通过计算user_map[y][x]中剩余的'*'的数量,对比地雷数量,实现对游戏结束的判断
返回值:扫雷完成返回 1,  未完成返回 0
*/
int check()
{	
	count_last = 0;
	int i,j;
	for(i=0;i<HEIGHT;i++)
	{
		for(j=0;j<WIDTH;j++)
		{
			if(user_map[i][j]=='*')
				count_last++;
		}
	}
	if(count_last==BOOM_NUM)
		return 1;
	else
		return 0;
}
6、主函数
int main()
{
	system("clear");		//清屏(非linux终端注释这行代码)
	initial_map();
	set_bom();
	put_map(mine_map);
	usleep(1000*2000);		//微秒级延时(非linux终端注释这行代码)
	system("clear");		//清屏(非linux终端注释这行代码)
	put_map(user_map);
	while(1)
	{
		if(check())			//扫雷完成判断(游戏结束条件1)
		{
			printf("Congratulations! You Win!\n");
			put_map(mine_map);
			break;
		}
		int x,y;
		printf("Input coordinates: x y\n");
		while(1)							//检查输入合法性
		{
			scanf("%d%d",&x,&y);
			if(x<0||x>WIDTH||y<0||y>HEIGHT)
				printf("Coordinates nagative,input again:\n");
			else		
				break;
		}
		if(mine_map[y][x]=='@')				//踩雷判断(游戏结束条件2)
		{
			printf("Oh no! You are on the Boom!\n");
			put_map(mine_map);
			break;
		}
		sweep(x,y);
	}
	return 0;
}

三、完结撒花

1.笔者因水平限制如有误导大家的地方非常抱歉哈
2.欢迎下方留言讨论,谢谢大家的支持
3.来“华清远见” http://www.hqyj.com/学习更多编程知识
C语言扫雷最新 递归展开 超详解(附源码)_第5张图片

四、完整源码

#include
#include
#include

#define HEIGHT 10	//行
#define WIDTH 10	//列
#define BOOM_NUM 10
int count_last = HEIGHT*HEIGHT;
char user_map[HEIGHT][WIDTH];	//玩家界面
char mine_map[HEIGHT][WIDTH];	//设计者界面

void initial_map();
void put_map(char (*p)[WIDTH]);
void set_bom();
void sweep(int x,int y);
int check();
int count_here(int m,int n);

int main()
{
	system("clear");			//清屏(非linux终端注释这行代码)
	initial_map();
	set_bom();
	put_map(mine_map);
	putchar('\n');
	usleep(1000*2000);			//微秒级延时(非linux终端注释这行代码)
	system("clear");
	put_map(user_map);
	while(1)
	{
		if(check())			//扫雷完成判断(游戏结束条件1)
		{
			printf("Congratulations! You Win!\n");
			put_map(mine_map);
			break;
		}
		int x,y;
		printf("Input coordinates: x y\n");
		while(1)			//检查输入合法性
		{
			scanf("%d%d",&x,&y);
			if(x<0||x>WIDTH||y<0||y>HEIGHT)
				printf("Coordinates nagative,input again:\n");
			else		
				break;
		}
		if(mine_map[y][x]=='@')		//踩雷判断(游戏结束条件2)
		{
			printf("Oh no! You are on the Boom!\n");
			put_map(mine_map);
			break;
		}
		sweep(x,y);
	}
	return 0;
}
/*
功能:给全局变量两个二维数组赋初始值
*/
void initial_map()
{
	int i,j;
	for(i=0;i<HEIGHT;i++)
	{
		for(j=0;j<WIDTH;j++)
		{
			user_map[i][j] = '*';//玩家界面的点
			mine_map[i][j] = '-';//开发者界面的点
		}
	}
}
/*
功能:打印游戏界面
参数:传入mine_map或者user_map
*/
void put_map(char (*p)[WIDTH])			//对数组指针不太了解的可以分成put_minemap和put_usermap两个函数写
{
	check();				//函数中计算user_map剩余'*'的数量count_last
	printf("  Remain: %2d     Boom: %2d\n",count_last,BOOM_NUM);
	int i,j;
	for(i=0;i<2;i++)			//界面前两行打印辅助标示
	{
		printf("    ");
		for(j=0;j<WIDTH;j++)
		{
			if(i==0)
				printf("%2d",j);
			else
				printf(" v");
		}
		printf("\n");
	}
	for(i=0;i<HEIGHT;i++)
	{
		printf("%2d >",i); 		//界面前两列打印辅助标示
		for(j=0;j<WIDTH;j++)
		{
			printf(" %c",p[i][j]);
		}
		printf("\n");
	}
}
/*
功能:给mine_map[y][x]中随机布置BOM_NUM个地雷
*/
void set_bom()
{
	srand(time(0));
	int x,y;
	int bom_num = BOOM_NUM;
	while(bom_num)
	{
		x = rand()%HEIGHT;
		y = rand()%WIDTH;
		if(mine_map[x][y]=='@')
			continue;
		mine_map[x][y] = '@';
		bom_num--;
	}
}
/*
功能:计算user_map[y][x]周围地雷数量
参数:玩家输入的横坐标x,纵坐标y
返回值:(x,y)周围地雷的数量
*/
int count_here(int x,int y) 
{
	int count = 0;
	int i,j;
	for(i=(y==0?0:y-1);i<=(y==HEIGHT-1?HEIGHT-1:y+1);i++)
	{
		for(j=(x==0?0:x-1);j<=(x==WIDTH-1?WIDTH:x+1);j++)//考虑越界问题
		{
			if(mine_map[i][j]=='@')
				count++;
		}
	}
	return count;
}
/*
功能:给user_map[y][x]赋值为该点周围地雷数量,若为0,调用自身给0周围的点赋值,依次递归
参数:玩家输入的横坐标x,纵坐标y
*/
void sweep(int x,int y) 
{

		if(user_map[y][x]!='*')
			return;
		int count = count_here(x,y);
		user_map[y][x] = count+'0';	//把int类型转换为char类型
		system("clear");		//清屏(非linux终端注释这行代码)
		fflush(stdout);			//清理终端缓存(非linux终端注释这行代码)
		put_map(user_map);
		usleep(1000*50);		//微秒级(非linux终端注释这行代码)
		if(count!=0)			//若count为0,递归调用
			return;
		int i,j;
		for(i=(y==0?0:y-1);i<=(y==HEIGHT-1?HEIGHT-1:y+1);i++)
		{
			for(j=(x==0?0:x-1);j<=(x==WIDTH-1?WIDTH-1:x+1);j++)
			{
				sweep(j,i);
			}
		}
		return;
}
/*
功能:通过计算user_map[y][x]中剩余的'*'的数量,对比地雷数量,实现对游戏结束的判断
返回值:扫雷完成返回 1,  未完成返回 0
*/
int check()
{	
	count_last = 0;
	int i,j;
	for(i=0;i<HEIGHT;i++)
	{
		for(j=0;j<WIDTH;j++)
		{
			if(user_map[i][j]=='*')
				count_last++;
		}
	}
	if(count_last==BOOM_NUM)
		return 1;
	else
		return 0;
}

你可能感兴趣的