C语言实现数字扫雷

C语言实现数字扫雷,第1张

目录

一、打印菜单

二、游戏实现

三、头文件(sl.h)

四、函数实现(slhs.c)

1、棋盘设置

2、打印棋盘

3、布置雷区

4、排雷

a.计算周围雷的个数

b.递归排雷

c.判断胜利

d.执行

五、补充 *** 作

1、标记雷区

2、取消标记

3、跳过第一次排雷被炸

4、定位光标与改换颜色

六、完整代码



话不所说,跟着来 *** 作……

一、打印菜单
//菜单
void menu(){
	printf("********************************\n");
	printf("****  1、play     0、exist  ****\n");
	printf("********************************\n");
}
//菜单选择
void test(){
	int input;
	srand((unsigned)time(NULL));//随机埋雷需用
	do{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input){
		case 1:game();
			break;
		case 0:printf("欢迎下次再玩\n");
			break;
		default:printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
}

二、游戏实现

分为两个棋盘,一个用来显示,一个用来存储扫雷信息

void game(){
	//雷的信息存储
	//1.布置好的雷的信息
	char mine[ROWS][COLS] = { 0 };
	//2.排查出的雷的信息
	char show[ROWS][COLS] = { 0 };
	//初始化
	InitBoard(mine, ROWS, COLS,'0');
	InitBoard(show, ROWS, COLS, '*');
	//打印棋盘
	//DisplayBoard(mine, ROW, COL);
	DisplayBoard(show, ROW, COL);
	//布置雷
	SetMine(mine, ROW, COL);
//	DisplayBoard(mine, ROW, COL);//显示埋雷位置
	//扫雷
	//DisplayBoard(mine, ROW, COL);
	FineMine(mine, show, ROW, COL);
}

三、头文件(sl.h)

为了方便,显得不那么乱,我们把所有的头文件、所定义函数、棋盘大小放在头文件中

#define ROW 9
#define COL 9    //棋盘大小9x9
#define ROWS ROW+2
#define COLS COL+2    //幕后棋盘实际要四周扩一格
#define EASY_COUNT 10  //埋雷个数


#include 
#include 
#include 

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 FineMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

四、函数实现(slhs.c) 1、棋盘设置
//棋盘设置
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set){
	int i, j;
	for (i = 0; i < rows; i++){
		for (j = 0; j < cols; j++){
			board[i][j] = set;
		}
	}
}
2、打印棋盘
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col){
	int i, j;
	//打印列号
	for (i = 0; i <= col; i++){
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++){
		printf("%d ", i);
		for (j = 1; j <= col; j++){
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}
3、布置雷区
//布置雷
void SetMine(char board[ROWS][COLS], int row, int col){
	int count = EASY_COUNT;
	while (count){
		int x = rand() % row + 1;//1-9
		int y = rand() % col + 1;
		if (board[x][y] == '0'){
			board[x][y] = '1';
			count--;
		}
	}
}
4、排雷 a.计算周围雷的个数
int get_mine_count(char mine[ROWS][COLS], int x, int y){
	return mine[x - 1][y] + mine[x - 1][y - 1] + 
           mine[x][y - 1] + mine[x + 1][y - 1] +
           mine[x + 1][y] + mine[x + 1][y + 1] + 
           mine[x][y + 1] + mine[x - 1][y + 1] - 8 * '0';
}
b.递归排雷
void Rd(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y){
	//判断坐标是否合法
	if (x==0 || y ==0 || x==ROWS-1 || y == COLS-1) return;
	//判断是否已被排出
	if (show[x][y] != '*') return;
	int count = get_mine_count(mine, x, y);
	if (count > 0){
		show[x][y] = count + '0';
		return;
	}
	else if (count == 0){
		show[x][y] = '0';
		Rd(mine, show, x, y - 1);
		Rd(mine, show, x, y + 1);
		Rd(mine, show, x + 1, y - 1);
		Rd(mine, show, x + 1, y + 1);
		Rd(mine, show, x + 1, y);
		Rd(mine, show, x - 1, y - 1);
		Rd(mine, show, x - 1, y);
		Rd(mine, show, x - 1, y + 1);
	}
}
c.判断胜利
int Victory(char show[ROWS][COLS],int row, int col){
	int i,j;
	int win = 0;
	for(i=1;i<=row;i++){
		for(j=1;j<=col;j++){
			if(show[i][j] == '*'){
				win++;
			}
		}
	}
	return win;
}
d.执行
void FineMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col){
	int x, y;
	size_t flag_count = 0;
	int win = 0;
	while (1){
		printf("请输入坐标并用空格隔开:>");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col){
			//坐标合法
			//踩雷
			if (mine[x][y] == '1'){
				printf("很遗憾,游戏失败!\n");
				puts("\n雷阵如下:\n");
				DisplayBoard(mine, row, col);
				break;
			}
			//不是雷
			else{
				Rd(mine, show, x, y);
				DisplayBoard(show, row, col);
			}
		}
		else{
			printf("坐标非法,请重新输入!\n");
		}
		win = Victory(show,row,col);
		if(win ==  EASY_COUNT) break;
	}
	if (win == EASY_COUNT){
		printf("恭喜,通关成功\n\n");
		printf("雷阵如下:\n");
		DisplayBoard(mine, row, col);
	}
}

五、补充 *** 作

本程序未添加这几项功能,感兴趣的盆友可自行发挥,添加……

当然,若博主后期比较闲的话也可能来优化

1、标记雷区
int Flagmine(char show[ROWS][COLS], int row, int col, size_t flag){
	int x = 0, y = 0;
	if (flag == EASY_COUNT){
		printf("标记的雷与实际存在的雷数量相等,无法标记\n");
		return 0;
	}
	printf("请输入你要标记的坐标:> ");
	scanf("%d %d", &x, &y);
	//判断坐标的合法性
	if (x >= 1 && x <= row && y >= 1 && y <= col){
		//判断是否已被确认为雷
		if (show[x][y] == '*'){
			show[x][y] = '!';//以!作为标记
			flag++;
		}
		else{
			printf("该坐标不可能是雷,请重新输入!\n");
		}
	}
	else{
		printf("该坐标不合法,请重新输入!\n");
	}
	return flag;
}
2、取消标记
int Cancelflag(char show[ROWS][COLS], int row, int col, int flag_count){
	int x = 0, y = 0;
	printf("请输入需要取消的坐标:> ");
	scanf("%d %d", &x, &y);
	//判断坐标是否合法
	if (x >= 1 && x <= row && y >= 1 && y <= col){
		//判断是否被标记过
		if (show[x][y] == '!'){
			show[x][y] = '*';
			flag_count--;
		}
		else
			printf("该位置未被标记过,无需取消标记\n");
	}
	else
		printf("该坐标不合法,请重新输入!\n");
	return flag_count;
}
3、跳过第一次排雷被炸
void Change(char mine[ROWS][COLS],int row, int col,int x,int y){
	x=rand()%row;
	y=rand()%col;
	mine[x][y]='1';
	printf("第一次就踩雷了哟,请重新选择!\n");
}
4、定位光标与改换颜色

此两项 *** 作请阅读孤的“迷宫小游戏”C语言实现初级小迷宫_一段路的博客-CSDN博客_c语言制作小迷宫


六、完整代码
//sl.h

#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 10


#include 
#include 
#include 

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 FineMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

//sl.c
void menu(){
	printf("********************************\n");
	printf("****  1、play     0、exist  ****\n");
	printf("********************************\n");
}
void game(){
	//雷的信息存储
	//1.布置好的雷的信息
	char mine[ROWS][COLS] = { 0 };
	//2.排查出的雷的信息
	char show[ROWS][COLS] = { 0 };
	//初始化
	InitBoard(mine, ROWS, COLS,'0');
	InitBoard(show, ROWS, COLS, '*');
	//打印棋盘
	//DisplayBoard(mine, ROW, COL);
	DisplayBoard(show, ROW, COL);
	//布置雷
	SetMine(mine, ROW, COL);
	//DisplayBoard(mine, ROW, COL);
	//扫雷
	//DisplayBoard(mine, ROW, COL);
	FineMine(mine, show, ROW, COL);
}
//执行
void test(){
	int input;
	srand((unsigned)time(NULL));
	do{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input){
		case 1:game();
			break;
		case 0:printf("欢迎下次再玩\n");
			break;
		default:printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
}
//主函数
int main(){
	test();
	return 0;
}

//slhs.c
//棋盘设置
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set){
	int i, j;
	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, j;
	//打印列号
	for (i = 0; i <= col; i++){
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++){
		printf("%d ", i);
		for (j = 1; j <= col; j++){
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}
//布置雷
void SetMine(char board[ROWS][COLS], int row, int col){
	int count = EASY_COUNT;
	while (count){
		int x = rand() % row + 1;//1-9
		int y = rand() % col + 1;
		if (board[x][y] == '0'){
			board[x][y] = '1';
			count--;
		}
	}
}
//排雷
int get_mine_count(char mine[ROWS][COLS], int x, int y){
	return mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x + 1][y] +
		mine[x + 1][y + 1] + mine[x][y + 1] + mine[x - 1][y + 1] - 8 * '0';
}
//递归
void Rd(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y){
	//判断坐标是否合法
	if (x==0 || y ==0 || x==ROWS-1 || y == COLS-1) return;
	//判断是否已被排出
	if (show[x][y] != '*') return;
	int count = get_mine_count(mine, x, y);
	if (count > 0){
		show[x][y] = count + '0';
		return;
	}
	else if (count == 0){
		show[x][y] = '0';
		Rd(mine, show, x, y - 1);
		Rd(mine, show, x, y + 1);
		Rd(mine, show, x + 1, y - 1);
		Rd(mine, show, x + 1, y + 1);
		Rd(mine, show, x + 1, y);
		Rd(mine, show, x - 1, y - 1);
		Rd(mine, show, x - 1, y);
		Rd(mine, show, x - 1, y + 1);
	}
}
//标记雷
int Flagmine(char show[ROWS][COLS], int row, int col, size_t flag){
	int x = 0, y = 0;
	if (flag == EASY_COUNT){
		printf("标记的雷与实际存在的雷数量相等,无法标记\n");
		return 0;
	}
	printf("请输入你要标记的坐标:> ");
	scanf("%d %d", &x, &y);
	//判断坐标的合法性
	if (x >= 1 && x <= row && y >= 1 && y <= col){
		//判断是否已被确认为雷
		if (show[x][y] == '*'){
			show[x][y] = '!';//以!作为标记
			flag++;
		}
		else{
			printf("该坐标不可能是雷,请重新输入!\n");
		}
	}
	else{
		printf("该坐标不合法,请重新输入!\n");
	}
	return flag;
}
//取消标记
int Cancelflag(char show[ROWS][COLS], int row, int col, int flag_count){
	int x = 0, y = 0;
	printf("请输入需要取消的坐标:> ");
	scanf("%d %d", &x, &y);
	//判断坐标是否合法
	if (x >= 1 && x <= row && y >= 1 && y <= col){
		//判断是否被标记过
		if (show[x][y] == '!'){
			show[x][y] = '*';
			flag_count--;
		}
		else
			printf("该位置未被标记过,无需取消标记\n");
	}
	else
		printf("该坐标不合法,请重新输入!\n");
	return flag_count;
}
//判断胜利
int Victory(char show[ROWS][COLS],int row, int col){
	int i,j;
	int win = 0;
	for(i=1;i<=row;i++){
		for(j=1;j<=col;j++){
			if(show[i][j] == '*'){
				win++;
			}
		}
	}
	return win;
}
void FineMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col){
	int x, y;
	size_t flag_count = 0;
	int win = 0;
	while (1){
		printf("请输入坐标并用空格隔开:>");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col){
			//坐标合法
			//踩雷
			if (mine[x][y] == '1'){
				printf("很遗憾,游戏失败!\n");
				puts("\n雷阵如下:\n");
				DisplayBoard(mine, row, col);
				break;
			}
			//不是雷
			else{
				Rd(mine, show, x, y);
				DisplayBoard(show, row, col);
			}
		}
		else{
			printf("坐标非法,请重新输入!\n");
		}
		win = Victory(show,row,col);
		if(win ==  EASY_COUNT) break;
	}
	if (win == EASY_COUNT){
		printf("恭喜,通关成功\n\n");
		printf("雷阵如下:\n");
		DisplayBoard(mine, row, col);
	}
}

         


                     

 


不足之处,请多多指教,欢迎留言……

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

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

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

发表评论

登录后才能评论

评论列表(0条)

保存