所谓扫雷游戏,我们大家应该都玩过,接下来我们先看看扫雷游戏的规则以及线上扫雷游戏:
游戏棋盘:

我们不难发现,扫雷游戏简单版的游戏棋盘是9 x 9的格子,这让我们可以联想到有关二维数组的知识。
扫雷游戏成功画面:

从这我们可以看出,扫雷成功的标志是将所有不是雷的部分全部点击完毕,就可以完成这个游戏。
扫雷游戏失败画面:

由此我们可以看出,当我们点击了雷放置的位置,游戏结束,表示你被雷炸死了。
了解到了这些,我们就可以来开始实现简单的扫雷游戏了。
/1.为了方便观察,我们可以创建三个文件,第一个是test.c,用于完成对扫雷游戏的测试,第二个是game.c,用于写游戏模块,第三个是game.h,用于声明函数与头文件,这样会让我们的思路更清晰不会遗漏。(注意要在game.c和test.c中声明game.h的头文件,这样就可以用game.h中的声明的头文件)

/2.创建完文件之后,我们下一步就是需要打印一个菜单,便于玩家选择进行游戏还是退出游戏,如果玩家还想玩的话可以继续,不想玩了就可以退出。这里我们创建一个函数void menu()来打印一个菜单,接着用switch语句加do while循环来让玩家选择,创建一个game()函数来进行后面的游戏操作,我们就可以这样写:

/3.创建完菜单之后,接下来我们就需要开始设计游戏模块了,也就是上面提到的game()。进行扫雷游戏,我们的第一步应该设计什么呢?当然是设计棋盘啦,所以我们现在应该设计一个9 x 9的棋盘,也就是运用二维数组的知识。但我们发现一个问题,如果仅仅设计9 x 9的棋盘用于玩游戏,我们不难发现,我们设计雷的时候,需要算出那个坐标周围有多少个雷然后相加,但当我们排查边缘的雷时,发现会有越界的问题,导致我们无法获取边缘雷的信息,而且,我们如果只弄9 x 9的棋盘的话,这样会让玩家难看出他自己想要排查的坐标,所以解决这个问题的同时我们 也可以对这个棋盘进行标记,这样会让玩家更加清楚,所以我们需要写一个这样的棋盘:

所以我们应该写一个11 x 11的棋盘,这样就解决了所有的问题,那么我们该如何写呢?
/4.接下来我们就是写一个11 x 11的棋盘。我们知道,一开始,我们看棋盘就是一脸懵逼,你也不知道雷在哪,也不知道哪里是安全的,所以我们应该做出一种神秘的效果,我们可以用'*'来初始化棋盘,来达成这种神秘的效果。再然后呢,我们每次排查完一次雷,当然就会显示周围有多少个雷,同时,我们完成游戏后,要么被炸死要么胜利,我们都想看看全部雷的位置,这样思路下来,我们需要设置两个11 x 11的棋盘,我们可以设置两次棋盘,一个存放'*',另一个存放数字,但是呢,我们又为了方便,我们可以将他们放在一个二维数组里面,这样我们就更加简单的完成棋盘设置,这样的话,我们就需要将数字转变成字符类型的数字,这样就很好的解决了存放数据的类型太多,容易引发歧义的问题。
当然,考虑到如果后续还需要变更难度的问题,也就是将二维数组扩大,如果只用数字的话,那要改很多,所以我们采取宏定义的方法,用字母替代,到时候我们要改变难度的话,我们只需要改变宏定义的数字就行了,这里我们用ROW来表示9行,COL来表示9列,ROWS表示11行,COLS表示11列,我们分别用mine和show来表示雷棋盘和答案棋盘。然后进行初始化棋盘,为了方便,我们分别加一个参数即可,这样可以控制想要'0'还是'*',然后再void InitBoard中设置一个char set来实现想要哪个就哪个,然后在game.h中进行声明函数

/5.进行完创建与声明之后,接下来我们就到game.c中去打印这个棋盘:

/6.打印完我们想让玩家看到的棋盘之后,接下来要打印我们原来的答案棋盘,我们命名为DisplayBoard,一样的我们需进行声明和打印:

这样不仅做到了序列标号,还打印了棋盘。
/7.弄完了棋盘这个大人物,接下来就是布置雷啦!我们可以将字符'0'标记为这个位置不是雷,把字符'1'标记为这个位置是雷。 我们又可以设计一个函数,叫SetMine,表示我们布置雷,一样的进行声明和打印,我们设置count为10,也就是10个雷,这里利用while循环,然后在main函数中用srand生成随机数,这里需要包含两个头文件:stdlib.h和time.h,然后我们就可以用于在棋盘中生成随机数。然后我们需要以x,y充当坐标,由于坐标只可能是1~9,所以我们需要生成1~9的数字以赋给x,y,所以我们可以这样写:

记得在main函数中调用srand生成随机数:

/8.生成完雷之后,我们就可以进行排查雷了,这里我们又可以设置一个函数叫FindMine,一样的先去game.h中声明,这里将循环条件设置为win-row*col-10是因为总共是9 x 9个格子,然后有10个雷,所以如果要win的话,就得把这些格子给排查掉。然后根据思路依次往下写,直到把这些点给排查完,就win了,否则就被炸死了,当我们输或者赢,都要DisplayBoard,然后我们也需设置一个函数GetMineCount,用来计算一个坐标周围八个坐标有没有雷,来计算该坐标需输入什么值:
 
根据这个,我们就可以通过getMineCount函数计算周围八个坐标的和,然后用字符来呈现,所以综上,我们可以写成这样:

至此,我们扫雷的代码就完成了,来看看运行效果吧!

现在把完整代码演示放在这里:
//game.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
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);
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	for (i = 0; i < rows; i++)
	{
		int j = 0;
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set;
		}
	}
}
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	for (i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		int j = 0;
		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 = 10;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
	return (mine[x - 1][y] + mine[x - 1][y - 1] + 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');
}
//game.c
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 < row * col - 10)
	{
		printf("请输入要排查的坐标:--->");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,你被炸死了\n");
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else
			{
				int count = GetMineCount(mine, x, y);
				show[x][y] = count + '0';
				DisplayBoard(show, ROW, COL);
				win++;
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}
	if (win == row * col - 10)
	{
		printf("恭喜你,获胜了!\n");
		DisplayBoard(mine, ROW, COL);
	}
}
//test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
	printf("**********************************\n");
	printf("*********   1.play   *************\n");
	printf("*********   0.exit   *************\n");
	printf("**********************************\n");
}
void game()
{
	char mine[ROWS][COLS];
	char show[ROWS][COLS];
	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');
	DisplayBoard(show, ROW, COL);
	SetMine(mine, ROW, COL);
	FindMine(mine, show, ROW, COL);
}
int main()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();
		printf("Please choose---> ");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("You have been exiting the game.\n");
			break;
		default:
			printf("Choose wrong,please choose again.\n");
			break;
		}
	} while (input);
	return 0;
}
扫雷代码是不是非常复杂哈哈哈!但是只要认真分析,然后按照思路一步一步的去完成,肯定可以实现的,祝屏幕前的你加油哦!
                  
                  
                  
                  
      
          
                
                
                
                
              
                
                
                
                
                
              
                
                
                    
              
            
                  
					163
					
被折叠的  条评论
		 为什么被折叠?
		 
		 
		
    
  
    
  
					
					
					


            