C语言编写扫雷游戏【W5+字详细教学版,包教包会】

目录

前言

一、扫雷游戏

二、整体分析

三、游戏的实现

1.实现test文件

2.实现game.h文件

3.实现game.c文件

3.1 初始化棋盘

3.2 打印棋盘

3.3 埋放地雷

3.4 判断行动(选择操作方式)

四、总结

五、全部代码


前言

        要学习扫雷游戏,可以先学会我写的五子棋详细教学,这个看起来就简单很多很多,但其实这个也不难,只不过这个稍微复杂一点点,根据自己的能力来进行学习~

一、扫雷游戏

        扫雷游戏是作者在小学微机课天天玩的游戏,多么值得回忆的一款游戏,因为win11没有扫雷小游戏了~!于是我现在就把它用自己的方式写出来了~!!!不仅我要写出来,我还要帮助你们学会这个小游戏,包学包会,学不会给我评论,我手把手教会你~!

        想必这个游戏也不需要我教学吧,大家应该都会玩,就是n×n的表格,然后在雷区中把所有地雷排查出来,就是这么简单~

        我们先看看下面的图片~!


二、整体分析

        我先说明我要设计一个12×12的雷区,可能你们会好奇为什么不是9×9的大众方式,那是因为……我就喜欢剑走偏锋~

        当然这时骗你们的,因为9×9的每个格子对应给的坐标比较好设计,10以上的就稍微细节一点,10以上的都会写了,那9×9岂不是信手拈来~

        我是用多文件进行编写的,我也希望你们也这样写,因为到以后工作的时候都是分工完成一个项目,所以要学会封装自己的代码~!我将我每一个文件名先列出来,后面我也会写到~!

  1. game.h(用来定义和函数说明)
  2. test.c(用来执行程序)
  3. game.c(用来实现执行程序里的函数)

        好~!接下来正式分析。

        首先你开始就有三个操作方式

  1. 可以直接点格子,进行排查雷区;
  2. 可以右键格子进行插小旗子进行标识;
  3. 可以右键插小旗子的格子进行解除标识;

        当我们排查雷区的时候又有三种情况

  1. 排查的地方不是雷,而且周围8个格子也不是雷,这时一下翻开一大片区域;
  2. 排查的地方不是雷,但是周围的8个格子中有雷,这时候只翻开一个区域;
  3. 排查的时候正好是雷,你直接就被炸飞了;

        到这里,已经大概分析出来了,还有最基础的一点就是因为你每次排查雷区的时候,要有一个模板进行对照,再对是雷或者不是雷进行判断,所以要用到两个二维数组进行表示一个用来展示给玩家看加密的,一个用来存放地雷(当然这个不能给玩家看,要不就是等于开挂了~),然后就是改将分析换算成代码,并且再添加细节,就大功告成了,接下来让我来详细讲解~!


三、游戏的实现

1.实现test文件

        玩家进入后会展示一个菜单供玩家选择,如果进入游戏PLAY就开始游戏,没玩过瘾就继续PLAY,被炸飞了,炸蒙了就可以退出EXIT。

        所以这里要用到循环语句并对选择加以判断。

        我们看game()这个函数,先是要定义两个二维函数,一个是用来埋放地雷的,一个是供给玩家看的。

        然后就是初始化棋盘,你们可以看到不仅传了棋盘和ROWS、COLS(这个后面就会讲,先不要着急),还传了'0'和'*',这里'0'代表的是埋放地雷的二维数组用它来初始化,代表的是0个地雷,这里'*'代表的是给玩家看的,没有被排查的地方用它来表示。

        然后就是设置雷,用时间戳(跟我用五子棋的那里一样~)生成随机坐标进行埋雷,然后将'0'变为'1'。

        然后就是打印棋盘,这个下面详细讲。

        然后就是判断行动,这里面也有一个菜单,分别是:

        1.排查雷(外加拓展)

        2.插旗子

        3.取消旗子

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"

void menu()
{
	printf("\n");
	printf("************     菜单    *************\n");
	printf("**************************************\n");
	printf("******  1.PLAY  ******  0.EXIT  ******\n");
	printf("**************************************\n");
	printf("\n");
}

void game()
{
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };

	//初始化棋盘
	Init_Board(mine, ROWS, COLS, '0');
	Init_Board(show, ROWS, COLS, '*');

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

	//打印棋盘
	Display_Board(show, ROW, COL);

	//判断行动
	Judge_Action(mine, show, ROW, COL);

	//排查雷
	//Find_Mine(mine, show, ROW, COL);
	插旗子
	//Set_Flag(show, ROW, COL);
	//拓展(重要~!)
	//Expansion(show, ROW, COL);
	
}


int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));//生成随机数
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("已经成功退出游戏~!\n");
		default:
			printf("输入错误,请重新输入~!\n");
		}
	} while (input);
	return 0;
}

2.实现game.h文件

        首先由下面的代码ROW、COL、ROWS、COLS,定义的这四个常数的意思是如图:

         然后就是定义MINE_COUNT也就是雷的个数,用于调试难度,

        下面的就是对游戏中用到的函数进行说明,方便再game.c中实现。

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

//扫雷界面的行和列
#define ROW 12
#define COL 12

//实际的行和列
#define ROWS ROW + 2
#define COLS COL + 2

//雷的个数
#define MINE_COUNT 20

void Init_Board(char board[ROWS][COLS], int rows, int cols, int set);//初始化棋盘


void Display_Board(char board[ROWS][COLS], int row, int col);//打印棋盘


void Set_Mine(char board[ROWS][COLS], int row, int col);//埋放地雷


void Judge_Action(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);//选择以下三个条件中的一个进行运行

//void Find_Mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);//排查雷
//void Set_Flag(char board[ROWS][COLS], int row, int col);//插旗子
//void Cancel_Set_Flag(char board[ROWS][COLS], int row, int col)//取消插旗子

3.实现game.c文件

3.1 初始化棋盘

        将二维数组初始化为想要的情况。

void Init_Board(char board[ROWS][COLS], int rows, int cols, int set)//初始化棋盘
{
	int i = 0;
	for (i = 0; i < rows; i++)
	{
		int j = 0;
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set;//注意set是传过来的 '0'和'*'
		}
	}
}

3.2 打印棋盘

        用循环函数嵌套进行对棋盘的打印,注意看代码给的注解,里面说明了为什么这么写,这也是12×12需要考虑的地方~!

void Display_Board(char board[ROWS][COLS], int row, int col)//打印棋盘
{
	int i = 0;
	int j = 0;
	printf("---------------扫雷游戏---------------\n");
	for (j = 0; j <= col; j++)
	{
		if (j == 0)
		{
			printf("  ");
		}
		else
		{
			printf("%2d ", j);//2d是为了棋盘是10以上的时候与棋盘一一对应,否则对应不上~!
		}
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%2d ", i);//2d是为了棋盘是10以上的时候与棋盘一一对应,否则对应不上~!
		for (j = 1; j <= col; j++)
		{
			printf("%c  ", board[i][j]);//按照要求打印棋盘
		}
		printf("\n");
	}
	printf("\n");
}

        这就是打印出棋盘的样子~左边是玩家看到的右边是埋下的雷~!

3.3 埋放地雷

        采用时间戳的方式埋放地雷。

void Set_Mine(char board[ROWS][COLS], int row, int col)//设置炸弹
{
	int count = MINE_COUNT;//设置炸弹的个数
	while (count)
	{
		int x = rand() % row + 1;//采用时间戳,产生随机坐标
		int y = rand() % col + 1;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';//用'1'代表炸弹
			count--;
		}
	}
}

3.4 判断行动(选择操作方式)

        根据菜单对:

  1. 排雷.
  2. 插旗子.
  3. 取消旗子.
  4. 重新开始.

    进行实施操作~!
void Menu()
{
	printf("\n");
	printf("**************************\n");
	printf("*****    1.排雷      *****\n");
	printf("****     2.插旗子    *****\n");
	printf("****     3.取消旗子  *****\n");
	printf("***   0.重新开始游戏   ***\n");
	printf("**************************\n");
	printf("\n");
}

void Judge_Action(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//判断
{
	int input = 0;
	int win = 0;
	int ret = 0;
	do
	{
		Menu();
		printf("\n请选择操作:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			ret = Find_Mine(mine, show, row, col, &win);
			if (ret == 1)
			{
				return;
			}
			break;
		case 2:
			Set_Flag(show, row, col);//设置旗子
			break;
		case 3:
			Cancel_Set_Flag(show, row, col);//取消旗子
			break;
		case 0:
			printf("\n已经为你跳转到菜单~!\n");
			break;
		default:
			printf("\n输入错误,请重新输入~!\n");
			Display_Board(show, row, col); //每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
			break;
		}
	} while (input);
}

3.4.1 排雷

        先输入要排雷的坐标,并判断在不在棋盘有效范围内,在的话进行排雷,不在重新输入。

        进行一系列的对坐标合法性的判断,下面的代码注解也的很详细,跟着看就能看懂。

        重要的是Expansion(拓展),这个是用来实现点一下,如果这个坐标周围没有雷,直接展开一片,这样就会节省很多不必要的麻烦。

        因为我们要的效果是一展一片,但是这样会很繁琐,所以我们就会想到用递归的方式去解决这个问题,因为递归的特点就是“把大事化小”

        写出一个你想要的效果,然后让坐标+1  -1,进行重复调用自己实现递归,这样就完成的展开一片的效果。

        因为我们在排雷的时候要考虑到赢的情况,但是如果盲目的排雷,到最后剩余的都是雷你也胜利不了,所以这里一边拓展的时候,一边要用win++来代替我们拓展了多少个,也就是我们已经排了多少不是雷的地方,然后因为COL*ROW也就是游戏中格子的个数就应该等于MINE_COUNT雷的个数+win排查不是雷的个数,当他们相等的时候,就说明你已经排完所有的雷了,你就胜利了。

        还要注意的就是我们获取雷的个数时,因为我们是以'1','0'来存放的,存放的是ASCII码,不是数字0和1,所以我们要用'1'和'0'分别减去'0'即可得到数字也就是雷的个数。(原理就是:'1'的ASCII码是49,'0'的ASCII码是48,相减得到的就是数字啦~!)

int Get_Mine_Count(char mine[ROWS][COLS], int x, int y)//获取周围炸弹的数量
{
	return 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';
}


void Expansion(char mine[ROWS][COLS],char show[ROWS][COLS], int x, int y, int *win)//如果周围没有炸弹就拓展
{
	{//防止和下面的else混淆
		if (x<1 || x>ROW || y<1 || y>COL)//防止边上一圈也被赋值
		{
			return;
		}
		if (show[x][y] != '*')
		{
			return;
		}
	}//防止和下面的else混淆

	int count = Get_Mine_Count(mine, x, y);
	if (count > 0)
	{
		(*win)++;
		show[x][y] = count + '0';
		return;
	}
	else//采用递归的方式进行拓展,上面的条件是为了防止死递归~!
	{
		(*win)++;
		show[x][y] = ' ';
		Expansion(mine, show, x - 1, y - 1, win);//win这里就是地址
		Expansion(mine, show, x - 1, y, win);
		Expansion(mine, show, x - 1, y + 1, win);
		Expansion(mine, show, x, y - 1, win);
		Expansion(mine, show, x, y + 1, win);
		Expansion(mine, show, x + 1, y - 1, win);
		Expansion(mine, show, x + 1, y, win);
		Expansion(mine, show, x + 1, y + 1, win);
	}

}

int Find_Mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int* win)//排查雷
{
	int x = 0;
	int y = 0;
	again:
		printf("\n请输入一个坐标:>");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] != '*' && show[x][y] != '!')//排查的条件~!
			{
				printf("\n该坐标已经被排查过,或者这里有标记,请排查其他位置~!\n");
				printf("如果需要排查,请先取消标记后再排查~!\n");
				Display_Board(show, row, col);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
				goto again;//跳转到again
			}
			else
			{
				if (mine[x][y] == '1')
				{
					system("cls");
					printf("\n游戏结束,你被炸飞了~!\n");
					Display_Board(mine, ROW, COL);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
					return 1;
				}
				else
				{
					Expansion(mine, show, x, y, win);//展开
					Display_Board(show, ROW, COL);//打印棋盘
				}
			}
		}
		else
		{
			printf("\n输入的坐标非法,请重新输入合法坐标\n");
			Display_Board(show, row, col);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
			goto again;//跳转到again
		}
	if (*win == row * col - MINE_COUNT)//胜利条件是雷的个数加上排查过的坐标的个数与总格数相同~!
	{
		system("cls");//清屏
		printf("\n恭喜你,排雷成功,没有别炸飞~!\n");
		Display_Board(mine, ROW, COL);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
		return 1;
	}
}

3.4.2 插旗子

        一样的道理,先判断坐标的非法性,如果这个坐标是'*'但不是'!'那就可以插旗子('!'就是旗子的标识,已经插过就不要再插旗了嘛),如果不是就不能插旗子(因为要是数字的话说明周围有雷,但是这个数字不是雷,空格的话这个空格也不是雷,所以没有意义,所以只是'*')

void Set_Flag(char board[ROWS][COLS], int row, int col)//插旗子
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("\n请输入要标记的坐标:>");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (board[x][y] == '!')
			{
				printf("\n该坐标已标记,请重新输入~!\n");
				Display_Board(board, row, col);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
				break;
			}
			else if (board[x][y] == ' ')
			{
				printf("\n该坐标不需要被标记,请重新输入~!\n");
				Display_Board(board, row, col);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
				break;
			}
			else
			{
				board[x][y] = '!';
				Display_Board(board, row, col);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
				break;
			}
		}
		else
		{
			printf("\n输入坐标非法,请重新输入~!\n");
			Display_Board(board, row, col);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
			break;
		}
	}


}

3.4.3 取消旗子

        这里跟上面插旗子差不了多少,就是如果是旗子就可以取消,不是旗子就不可以取消,然后旗子取消之后就换成'*',因为'*'是没有排查的标志嘛~

void Cancel_Set_Flag(char board[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("\n请输入要取消标记的坐标:>");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (board[x][y] == '!')//有'!'就取消,没有就取消不了~!
			{
				board[x][y] = '*';
				Display_Board(board, row, col);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
				break;
			}
			else
			{
				printf("\n该坐标没有被标记,无需取消标记~!\n");
				Display_Board(board, row, col);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
				break;
			}
		}
		else
		{
			printf("\n输入坐标非法,请重新输入~!\n");
			Display_Board(board, row, col);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
			break;
		}
	}
}

四、总结

       我以文字打再外面的都是很重要的,代码里面的都是详细解释,可以根据详细解释进行理解,如果还有看不懂的,可以在评论区留言,我都会看,如果有问题,我都会解答~!

        扫雷和五子棋一样,都是对数组的考察,只要你数组认识的还可以,你就可以写出这两个小游戏,当然你如果写出来这两个小游戏后,你会发现数组你已经了如指掌了~!

        还有就是锻炼逻辑思维能力,如果这个你能搞懂,那么你现在的脑袋瓜肯定可以飞速运转,并且再将来遇到这种用逻辑写的题或者游戏,那不都是小喽喽么~

五、全部代码

| game.h |

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

//扫雷界面的行和列
#define ROW 12
#define COL 12

//实际的行和列
#define ROWS ROW + 2
#define COLS COL + 2

//雷的个数
#define MINE_COUNT 20

void Init_Board(char board[ROWS][COLS], int rows, int cols, int set);//初始化棋盘


void Display_Board(char board[ROWS][COLS], int row, int col);//打印棋盘


void Set_Mine(char board[ROWS][COLS], int row, int col);//埋放地雷


void Judge_Action(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);//选择以下三个条件中的一个进行运行

//void Find_Mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);//排查雷
//void Set_Flag(char board[ROWS][COLS], int row, int col);//插旗子
//void Cancel_Set_Flag(char board[ROWS][COLS], int row, int col)//取消插旗子

| text.c |

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"

void menu()
{
	printf("\n");
	printf("************     菜单    *************\n");
	printf("**************************************\n");
	printf("******  1.play  ******  0.exit  ******\n");
	printf("**************************************\n");
	printf("\n");
}

void game()
{
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };

	//初始化棋盘
	Init_Board(mine, ROWS, COLS, '0');
	Init_Board(show, ROWS, COLS, '*');

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

	//打印棋盘
	Display_Board(show, ROW, COL);
	Display_Board(mine, ROW, COL);

	Judge_Action(mine, show, ROW, COL);


	//排查雷
	//Find_Mine(mine, show, ROW, COL);
	插旗子
	//Set_Flag(show, ROW, COL);
	//拓展(重要~!)
	//Expansion(show, ROW, COL);
	
}



int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));//生成随机数
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("已经成功退出游戏~!\n");
		default:
			printf("输入错误,请重新输入~!\n");
		}
	} while (input);
	return 0;
}

| game.c |

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"

void Menu()
{
	printf("\n");
	printf("**************************\n");
	printf("*****    1.排雷      *****\n");
	printf("****     2.插旗子    *****\n");
	printf("****     3.取消旗子  *****\n");
	printf("***   0.重新开始游戏   ***\n");
	printf("**************************\n");
	printf("\n");
}

void Init_Board(char board[ROWS][COLS], int rows, int cols, int set)//初始化棋盘
{
	int i = 0;
	for (i = 0; i < rows; i++)
	{
		int j = 0;
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set;//注意set是传过来的 '0'和'*'
		}
	}
}

void Display_Board(char board[ROWS][COLS], int row, int col)//打印棋盘
{
	int i = 0;
	int j = 0;
	printf("---------------扫雷游戏---------------\n");
	for (j = 0; j <= col; j++)
	{
		if (j == 0)
		{
			printf("  ");
		}
		else
		{
			printf("%2d ", j);//2d是为了棋盘是10以上的时候与棋盘一一对应,否则对应不上~!
		}
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%2d ", i);//2d是为了棋盘是10以上的时候与棋盘一一对应,否则对应不上~!
		for (j = 1; j <= col; j++)
		{
			printf("%c  ", board[i][j]);//按照要求打印棋盘
		}
		printf("\n");
	}
	printf("\n");
}


void Set_Mine(char board[ROWS][COLS], int row, int col)//设置炸弹
{
	int count = MINE_COUNT;//设置炸弹的个数
	while (count)
	{
		int x = rand() % row + 1;//采用时间戳,产生随机坐标
		int y = rand() % col + 1;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';//用'1'代表炸弹
			count--;
		}
	}
}

int Get_Mine_Count(char mine[ROWS][COLS], int x, int y)//获取周围炸弹的数量
{
	return 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';
}


void Expansion(char mine[ROWS][COLS],char show[ROWS][COLS], int x, int y, int *win)//如果周围没有炸弹就拓展
{
	{//防止和下面的else混淆
		if (x<1 || x>ROW || y<1 || y>COL)//防止边上一圈也被赋值
		{
			return;
		}
		if (show[x][y] != '*')
		{
			return;
		}
	}//防止和下面的else混淆

	int count = Get_Mine_Count(mine, x, y);
	if (count > 0)
	{
		(*win)++;
		show[x][y] = count + '0';
		return;
	}
	else//采用递归的方式进行拓展,上面的条件是为了防止死递归~!
	{
		(*win)++;
		show[x][y] = ' ';
		Expansion(mine, show, x - 1, y - 1, win);//win这里就是地址
		Expansion(mine, show, x - 1, y, win);
		Expansion(mine, show, x - 1, y + 1, win);
		Expansion(mine, show, x, y - 1, win);
		Expansion(mine, show, x, y + 1, win);
		Expansion(mine, show, x + 1, y - 1, win);
		Expansion(mine, show, x + 1, y, win);
		Expansion(mine, show, x + 1, y + 1, win);
	}

}

int Find_Mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int* win)//排查雷
{
	int x = 0;
	int y = 0;
	again:
		printf("\n请输入一个坐标:>");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] != '*' && show[x][y] != '!')//排查的条件~!
			{
				printf("\n该坐标已经被排查过,或者这里有标记,请排查其他位置~!\n");
				printf("如果需要排查,请先取消标记后再排查~!\n");
				Display_Board(show, row, col);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
				goto again;
			}
			else
			{
				if (mine[x][y] == '1')
				{
					system("cls");
					printf("\n游戏结束,你被炸飞了~!\n");
					Display_Board(mine, ROW, COL);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
					return 1;
				}
				else
				{
					Expansion(mine, show, x, y, win);//展开
					Display_Board(show, ROW, COL);//打印棋盘
				}
			}
		}
		else
		{
			printf("\n输入的坐标非法,请重新输入合法坐标\n");
			Display_Board(show, row, col);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
			goto again;
		}
	/*}*/
	if (*win == row * col - MINE_COUNT)//胜利条件是雷的个数加上排查过的坐标的个数与总格数相同~!
	{
		system("cls");
		printf("\n恭喜你,排雷成功,没有别炸飞~!\n");
		Display_Board(mine, ROW, COL);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
		return 1;
	}
}

void Set_Flag(char board[ROWS][COLS], int row, int col)//插旗子
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("\n请输入要标记的坐标:>");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (board[x][y] == '!')
			{
				printf("\n该坐标已标记,请重新输入~!\n");
				Display_Board(board, row, col);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
				break;
			}
			else if (board[x][y] == ' ')
			{
				printf("\n该坐标不需要被标记,请重新输入~!\n");
				Display_Board(board, row, col);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
				break;
			}
			else
			{
				board[x][y] = '!';
				Display_Board(board, row, col);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
				break;
			}
		}
		else
		{
			printf("\n输入坐标非法,请重新输入~!\n");
			Display_Board(board, row, col);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
			break;
		}
	}


}

void Cancel_Set_Flag(char board[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("\n请输入要取消标记的坐标:>");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (board[x][y] == '!')//有'!'就取消,没有就取消不了~!
			{
				board[x][y] = '*';
				Display_Board(board, row, col);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
				break;
			}
			else
			{
				printf("\n该坐标没有被标记,无需取消标记~!\n");
				Display_Board(board, row, col);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
				break;
			}
		}
		else
		{
			printf("\n输入坐标非法,请重新输入~!\n");
			Display_Board(board, row, col);//每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
			break;
		}
	}
}


void Judge_Action(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//判断
{
	int input = 0;
	int win = 0;
	int ret = 0;
	do
	{
		Menu();
		printf("\n请选择操作:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			ret = Find_Mine(mine, show, row, col, &win);
			if (ret == 1)
			{
				return;
			}
			break;
		case 2:
			Set_Flag(show, row, col);//设置旗子
			break;
		case 3:
			Cancel_Set_Flag(show, row, col);//取消旗子
			break;
		case 0:
			printf("\n已经为你跳转到菜单~!\n");
			break;
		default:
			printf("\n输入错误,请重新输入~!\n");
			Display_Board(show, row, col); //每次错误后都打印一遍棋盘,更容易观看,不用往上翻找~!
			break;
		}
	} while (input);
}

       

        到这里已经接近尾声了,作者也是用了一天的时候想出来,写出来,然后各种测试代码然后发教学,如果可以的话,我想要你们的点赞、留言和收藏,当然你们也可以关注我,我也会出更多更多有用东西,现在把这两个游戏都做完,我就要开始整理知识点了,喜欢的朋友可以多多关注我哦,我说的有问题的地方也可以告诉我,我们一起进步,一起秃头~

  • 13
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NPC Online

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值