扫雷游戏 c语言

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了扫雷游戏 c语言相关的知识,希望对你有一定的参考价值。

本人学生一个,需要一个c语言的扫雷游戏,要求能在win7环境下运行,本人有win-Tc 和dev c++ 关于c++的代码最好没有,如果必须最好少一点,dos界面下的就不用了。如果那位大神能够急人所难,感激不尽。我只有10财富值,请不要嫌弃、。。。。

参考技术A 10块钱都没人搞 真心话 参考技术B c语言编写gui界面程序???开玩笑么追问

首先我是一个小白,我刚才还百度了一下gui界面是什么,不过我同学自己用C语言遍了一个贪吃蛇出来,不是doc界面哦。

追答

你同学可能用的mfc,或者也想上面那样用win32写的,调用api图形库函数,设计窗口注册窗口什么的,你要单纯用c写,绝对不可能,要写出来的话,你已经进微软了

参考技术C #include <windows.h>
#include <CommCtrl.h>                 // 用于InitCommonControls
#pragma comment(lib, "comctl32.lib")  // 用于InitCommonControls

// 常量
const int WINDOW_STYLES = WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION;  // 窗口风格
const int MAX_WIDTH     = 30;                                       // 雷区最大宽度
const int MAX_HEIGHT    = 25;                                       // 雷区最大高度
const int FLAF_NULL     = 0;               // 格子无标记
const int FLAG_CAVEAT   = 1;                                        // 警告标记
const int FLAG_QUERY    = 2;                                        // 疑问标记
const int FLAG_OVERT    = 3;                                        // 已经打开的格子标记
const int FLAF_MINE     = -1;                                       // 地雷标记
const int CELL_SIZE     = 25;                                       // 格子大小

// 全局变量
static struct 
HINSTANCE hInst;                              // 应用程序句柄实例
HWND hWnd;                                    // 主窗口句柄
HWND Button;                                  // 重新开始按钮句柄
HWND lButton;                                 // 左边剩余地雷按钮
HWND rButton;                                 // 右边时间显示按钮
 Win;
static struct 
HWND    hWnd [MAX_WIDTH][MAX_HEIGHT];         // 雷区按钮句柄
WNDPROC Proc;                                 // 按钮原来消息处理函数地址
int     Code [MAX_WIDTH][MAX_HEIGHT];         // 存储数据
int     Flag [MAX_WIDTH][MAX_HEIGHT];         // 用户标记
MineField;
static struct 
int Width;                                    // 雷区宽度
int Height;                                   // 雷区高度
int CellNum;                                  // 剩下的安全格子数量
int Rated_MineNum;                            // 额定地雷数量
int MineNum;                                  // 剩余地雷数量
int time;                                     // 时间
bool timeOn;
Game;

void toString(int val, char* string, int StringLen) 
                        // 整数转换文本,本程序使用Unicode字符集,字符串长度需要大于2
char str [32];
int  i = 0;

if (StringLen < 2)
return;


_itoa_s(val, str, 10);
while ((i < 32) && (i < (StringLen / 2 - 1))) 
string [i * 2] = str [i];
string [i * 2 + 1] = 0;
i ++;

string [i] = string [i + 1] = 0;


int GetMineNum(int x, int y)      // 寻找周围地雷的数目

int i, j, a, b, num = 0;

for (i = -1; i < 2; i++) 
for (j = -1; j < 2; j++) 
a = x + i;
b = y + j;
if ((a > -1) && (b > -1) && (a < Game.Width) && (b < Game.Height)) 
if (MineField.Code [a][b] == FLAF_MINE)
num ++;




return num;


void NewGame(void) // 新游戏

int i, j;
char text[32];

// 清空数组
for (i = 0; i < Game.Width; i++) 
for (j = 0; j < Game.Height; j++) 
MineField.Flag [i][j] = FLAF_NULL;
MineField.Code [i][j] = 0;
SetWindowText(MineField.hWnd [i][j], L" ");


// 埋放地雷
srand(GetTickCount());                          // 使用系统时间作为随机数种子
for (int k = 0; k < Game.Rated_MineNum; k++) 
i = rand() % Game.Width;
j = rand() % Game.Height;
if (MineField.Code [i][j] == FLAF_MINE)
k --;                                  // 已经有地雷,埋放失败
else 
    MineField.Code [i][j] = FLAF_MINE;


// 设置数字 显示周围地雷数量
for (i = 0; i < Game.Width; i++) 
for (j = 0; j < Game.Height; j++) 
if (MineField.Code [i][j] != FLAF_MINE)
MineField.Code [i][j] = GetMineNum(i, j);




toString(Game.Rated_MineNum, text, 32);
SetWindowText(Win.lButton, (LPCTSTR) text);
SetWindowText(Win.rButton, L"0");
SetWindowText(Win.Button, L"∩_∩");
Game.time = 0;
Game.timeOn = false;
Game.MineNum = Game.Rated_MineNum;
Game.CellNum = Game.Width * Game.Height - Game.Rated_MineNum;


void OvertMine(void) // 显示地雷

char text[6], num;

Game.timeOn = false;
for (int i = 0; i < Game.Width; i++) 
for (int j = 0; j < Game.Height; j++) 
num = MineField.Code [i][j];
toString(num, text, 6);
SetWindowText(MineField.hWnd [i][j], num == FLAF_MINE ? L"雷" : (LPCTSTR) text);




// 雷区按键处理
void MineSub(int x, int y, bool LButton = true) 
int i, j, Num;
char text[32];

// 坐标范围检查
if ((x < 0) || (x >= Game.Width) ||
(y < 0) || (y >= Game.Height)) 
return;


Num = MineField.Code [x][y];
if (LButton) 
if ((MineField.Flag [x][y] == FLAG_CAVEAT) ||
 MineField.Flag [x][y] == FLAG_OVERT) 
return;

Game.timeOn = true;
MineField.Flag [x][y] = FLAG_OVERT;

if (Num == FLAF_MINE) 
OvertMine();
SetWindowText(Win.Button, L">_<");
MessageBox(Win.hWnd, L"您踩到地雷啦,哈哈", L"您输了", 0);
NewGame();
return;
else 
toString(Num, text, 6);
SetWindowText(MineField.hWnd [x][y], (LPCTSTR) text);
Game.CellNum --;
if (Game.CellNum == 0) 
OvertMine();
MessageBox(Win.hWnd, L"恭喜你过关!", L"过关", 0);
NewGame();
return;

if (Num == 0) 
for (i = -1; i < 2; i++) 
for (j = -1; j < 2; j++) 
if (Game.timeOn)          // 递归函数在重新开始后可能进入死循环
MineSub(x + i, y + j);





else 
i = MineField.Flag [x][y];

if (i != FLAG_OVERT) 
if (i == FLAG_CAVEAT) 
Game.MineNum ++;

i = (i + 1) % 3;
MineField.Flag [x][y] = i;
SetWindowText(MineField.hWnd [x][y],
          i == FLAF_NULL ? L" " : i == FLAG_CAVEAT ? L"×" : L"?");
if (i == FLAG_CAVEAT) 
Game.MineNum --;

toString(Game.MineNum, text, 32);
SetWindowText(Win.lButton, (LPCTSTR) text);




// 雷区按钮事件捕捉过程
static LRESULT CALLBACK MineFieldProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 

int x = 0, y = 0, i, j;

for (i = 0; i < Game.Width; i++) 
for (j = 0; j < Game.Height; j++) 
if (MineField.hWnd [i][j] == hWnd) 
x = i;
y = j;



switch(uMsg) 
case WM_RBUTTONDOWN:               // 鼠标右键按下
MineSub(x, y, false);
break;
case WM_KEYDOWN:                  // 键盘按键事件
switch(wParam) 
case VK_UP:                   // 上
y = y > 0 ? y - 1 : 0;
break;
case VK_DOWN:                 // 下
y = y < (Game.Height - 1) ? y + 1 : Game.Height - 1;
break;
case VK_LEFT:                 // 左
x = x > 0 ? x - 1 : 0;
break;
case VK_RIGHT:                // 右
x = x < (Game.Width - 1) ? x + 1 : Game.Width - 1;
break;

SetFocus(MineField.hWnd [x][y]); // 设置焦点控件

return CallWindowProc(MineField.Proc, hWnd, uMsg, wParam, lParam);


// 窗体事件捕捉过程
static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 

int id, msg;
char text[32];

switch (uMsg) 
case WM_TIMER:
if (Game.timeOn) 
Game.time ++;
toString(Game.time, text, 32);
SetWindowText(Win.rButton, (LPCTSTR) text);

break;
case WM_COMMAND:              // 按钮发送的消息
id = LOWORD(wParam);      // 获取按钮编号
msg = HIWORD(wParam);     // 获取消息值

if (msg == BN_CLICKED)   // 单击消息
   if ((HWND) lParam == Win.Button) 
   NewGame();
else if (((HWND)lParam != Win.lButton) && ((HWND)lParam != Win.rButton)) 
MineSub(id & 255, id >> 8);
   

break;
case WM_DESTROY:           // 退出
PostQuitMessage(0);
break;
default:                // 其他事件
return DefWindowProc(hWnd, uMsg, wParam, lParam);

return FALSE;


// 入口过程
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

int w, h;
char text[32];
MSG msg;
WNDCLASSEX wce;
RECT rect;

// 初始化全局变量
Win.hInst = hInstance;
Game.Width = 15;
Game.Height = 10;
Game.Rated_MineNum = 15;
InitCommonControls();   // 初始化通用组件库
// 设置窗口
wce.cbSize = sizeof(WNDCLASSEX);
wce.style = 0;
wce.lpfnWndProc = (WNDPROC) WndProc;
wce.cbClsExtra = wce.cbWndExtra = 0;
wce.hInstance = hInstance;
wce.hIcon = LoadIcon(NULL,IDI_APPLICATION); // 窗口的最小化图标为默认图标
wce.hCursor = LoadCursor(NULL,IDC_ARROW);   // 窗口采用箭头光标
wce.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
wce.lpszMenuName = NULL; 
wce.lpszClassName = L"Window";
wce.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wce);

// 打开窗口
Win.hWnd = CreateWindow(L"Window", L"扫雷", WINDOW_STYLES, CW_USEDEFAULT, 
CW_USEDEFAULT, 100, 100, NULL, NULL, hInstance, NULL);
if (Win.hWnd == NULL) 
return -1;

ShowWindow(Win.hWnd, nCmdShow);
// 调整客户区大小
GetWindowRect(Win.hWnd, &rect);
rect.right = rect.left + Game.Width * CELL_SIZE;
rect.bottom = rect.top + (Game.Height + 2) * CELL_SIZE;
AdjustWindowRect(&rect, WINDOW_STYLES, FALSE);    // 根据客户区大小计算窗口大小
w = rect.right - rect.left;                       // 宽度 20*25 应该是 大于500
h = rect.bottom - rect.top;                       // 高度 15*25 应该是 大于375
MoveWindow(Win.hWnd, rect.left, rect.top, w, h, TRUE);

toString(Game.Rated_MineNum, text, 32);
Win.lButton = CreateWindow(L"Button", (LPCTSTR) text, WS_CHILD | WS_VISIBLE, 10, 5,
CELL_SIZE * 2, CELL_SIZE * 2 - 10, Win.hWnd, 0, hInstance, NULL);
Win.Button = CreateWindow(L"Button", L"∩_∩", WS_CHILD | WS_VISIBLE, (Game.Width - 2) / 2 * CELL_SIZE,
5, CELL_SIZE * 2, CELL_SIZE * 2 - 10, Win.hWnd, 0, hInstance, NULL);
Win.rButton = CreateWindow(L"Button", L"0", WS_CHILD | WS_VISIBLE, (Game.Width - 2) * CELL_SIZE - 5,
5, CELL_SIZE * 2, CELL_SIZE * 2 - 10, Win.hWnd, 0, hInstance, NULL);
if ((Win.lButton == NULL) || (Win.Button == NULL) || (Win.rButton == NULL))
return -1;

SetTimer(Win.hWnd, 0, 1000, NULL);  // 设置时钟

// 创建按钮,成为雷区
for (int y = 0; y < Game.Height; y++) 
for (int x = 0; x < Game.Width; x++) 
MineField.hWnd [x][y] = CreateWindow(L"Button", L" ", WS_CHILD | WS_VISIBLE,
x * CELL_SIZE, (y + 2)* CELL_SIZE, CELL_SIZE, CELL_SIZE, Win.hWnd, 
(HMENU)(y * 256 + x), hInstance, NULL);

if (MineField.hWnd [x][y] == NULL) 
return -1;
   // end if
// 改变按钮消息接收函数地址,在此之前,记录原地址
MineField.Proc = (WNDPROC)GetWindowLong(MineField.hWnd [x][y], GWL_WNDPROC);
SetWindowLong(MineField.hWnd [x][y], GWL_WNDPROC, (LONG)MineFieldProc);
   // next x
   // next y
NewGame();
SetFocus(MineField.hWnd [0][0]);
// 接收消息
while (GetMessage(&msg, NULL, 0, 0)) 
TranslateMessage(&msg);
DispatchMessage(&msg);

return msg.wParam;


代码很乱,将就看吧

本回答被提问者和网友采纳

C语言游戏超详解扫雷游戏完整版,细节满满!!

目录

 

扫雷

扫雷游戏规则介绍

如何将扫雷游戏实现代码

基本思路

分步代码实现

创建和打印游戏菜单

初始化棋盘

打印棋盘

布置雷

排查雷

游戏主体——game()函数

总代码实现

game.h

test.c

game.c

总结


扫雷

实现扫雷的算法有很多种,我在这里给大家最详细的代码介绍以及思考方法,细节满满哦!!


扫雷游戏规则介绍

每个格子有两种状态,有地雷或者没有地雷。玩家点到地雷游戏结束,玩家标记出所有地雷游戏胜利。

每个没有地雷的格子点开后显示相邻8个格子里面存在地雷的数目,周边没有地雷则可以递归地打开与空相邻的方块;如果不幸触雷,则游戏结束。

如何将扫雷游戏实现代码

与上次三子棋游戏模块一致,分类创建:

game.h:相关游戏函数的声明,变量的宏定义等;

game.c:游戏相关函数的功能实现;

test.c:游戏的测试,游戏的主题体;


基本思路

1.创建和打印游戏菜单

2.创建两个棋盘数组,一个是布置雷的棋盘数组,一个是排查雷的棋盘数组

3.初始化两个棋盘,为了防止后期统计排查雷的个数出现矛盾,所以我这里把布置雷的那个棋盘全部初始为'0',把排查雷的棋盘全部初始化为'*'

4.打印棋盘

5.布置雷,由电脑自主完成随机布置雷的个数,个数可以自己在头文件中定义

6.排查雷,在布置雷的数组里排查,如果是雷则打印被炸死,并退出游戏,打印排查雷的棋盘;如果不是雷,则统计雷的个数,是0则展开空白,不是0则将雷的个数传给排查雷的那个数组

7.判断输赢,如果空格的总的个数于行和列的乘积减去布雷的个数,则表示排雷成功


分步代码实现

创建和打印游戏菜单

void menu()

	printf("**********************\\n");
	printf("******* 1.play *******\\n");
	printf("******* 0.exit *******\\n");
	printf("**********************\\n");

int main()

	int input = 0;
	srand((unsigned int)time(NULL));//用于随机函数rand的调用
	do
	
		menu();
		scanf_s("%d", &input);
		switch (input)
		
		case 1:
			printf("扫雷游戏开始\\n");
			game();
			break;
		case 0:
			printf("退出游戏\\n");
			break;
		default:
			printf("输入错误,请重新选择!\\n");

		

	 while (input);
	return 0;

初始化棋盘

	//两个数组初始化数组的实现,char board[ROWS][COLS]接收mine数组和show数组
	//这里设置一个字符set接收mine和show数组传参过来的‘0’和‘*’
void Initboard(char board[ROWS][COLS], int rows, int cols,char set)

	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	
		for (j = 0; j < cols; j++)
		
			board[i][j] = set;
		
	

这里的初始化函数调用两次,分别初始化布雷数组和排雷数组,字符set分别接收'0'和'*';

打印棋盘

void Displayboard(char board[ROWS][COLS], int row, int col)

	int i = 0;
	int j = 0;
	printf("————扫雷游戏 ————\\n");
	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");
	
	printf("————扫雷游戏————\\n");

打印棋盘结果如下:

这样打印出来的棋盘好看也方便用户写入坐标

布置雷

void Setmine(char mine[ROWS][COLS], int row, int col)

	int count = SETCOUNT;	//为了灵活变通,可以自己设置布置雷的个数,在头文件中自定义个数
	
     while (count)           //直到count为0才退出循环,并且每次都是随机坐标布置雷,count是几,
                              x和y就要随机几次
                       
		
		int x = rand() % row + 1;//用户输入的坐标的范围就是行数列数的范围,应该是row+1才是正确 
                                   的坐标范围
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
		
			mine[x][y] = '1';
			count--;//每布置一个,雷的个数就减一;
		
	

排查雷

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 - SETCOUNT)
	
		int count_blank = 0;//空白个数,每次进入循环都要重置,如果放在循环外面依旧是上一次的值会重复叠加空白;
		printf("请输入排查雷的坐标:\\n");

		scanf_s("%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_mine = get_mine_count(mine, x, y);
				
				if (count_mine == 0 && show[x][y]=='*')//周围雷的个数为0,且没有被遍历
				
					count_blank=get_showblank(mine, show, x, y);//递归展开空白,返回空白个数
					win += count_blank;//空白的个数加到不是雷个数的总数中
				
				else if(show[x][y]=='*')//这里用else不太合适,这里控制的条件是当周围个数不是0,但是没有被遍历
				
                    show[x][y] = count_mine + '0';//不是雷,则统计周围有几个雷,放入show数组对应坐标
					win++;//他统计了周围雷的个数,但本身不是雷,加1
					
				
				
				Displayboard(show, row, col);
				
			
		
		else
		
			printf("坐标不合法,请重新输入!\\n");
		
	
	if (win== row * col - SETCOUNT)
	
		printf("恭喜你,排雷成功!\\n");
		Displayboard(show, row, col);
	

		

当排查雷时,(x,y)处不是雷且周围雷的个数不为0则需要统计周围雷的个数:

static int  get_mine_count(char mine[ROWS][COLS], int x,int y)  //static修饰函数,那这个函数 
                                                                  就只能在当前源文件里使用了

   //统计这些坐标周围有几个雷
	return mine[x][y - 1] +
		mine[x - 1][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] +
		mine[x + 1][y] - 8 * '0';  //这里返回的是数字,num+'0'='num';即一个数字加上字符0等于数字代表的字符

当(x,y)周围雷的个数为0时展开为空格,去递归遍历周围四个坐标雷的个数,并且统计空格的个数:

int get_showblank(char mine[ROWS][COLS], char show[ROWS][COLS], int x , int y)//当雷的个数为0时计算展开的空白个数

	
	int count_mine = get_mine_count(mine, x,y);
    int count_blank = 0;//初始化空白的个数
	if(count_mine == 0)
	
		show[x][y] = ' ';
		count_blank++;//只要是空白就加1;下次递归也一样

	    //判断周围四个坐标合法性,并且要满足没有被遍历,依旧是*号,以防重复遍历
		if (x - 1 >= 1 && x - 1 <= ROW && y >= 1 && y <= COL && show[x - 1][y] == '*')
		
			count_blank+=get_showblank(mine, show, x - 1, y);//每递归一次,空白个数要累加,包括了x,y的空白和周围四个坐标的空白;
			

		
		if (x >= 1 && x <= ROW && y - 1 >= 1 && y - 1 <= COL && show[x][y - 1] == '*')
		
			count_blank += get_showblank(mine, show, x, y - 1);
			
		
		if (x + 1 >= 1 && x + 1 <= ROW && y >= 1 && y <= COL && show[x + 1][y] == '*')
		
			count_blank += get_showblank(mine, show, x + 1, y);
			
		
		if (x >= 1 && x <= ROW && y + 1 >= 1 && y + 1 <= COL && show[x][y + 1] == '*')
		
			count_blank += get_showblank(mine, show, x, y + 1);
		
			
	
	return count_blank;//返回空白个数
   
	



	

游戏主体——game()函数

void game()

	char mine[ROWS][COLS] =  0 ;	//创建存放布置雷的数组
	char show[ROWS][COLS] =  0 ;	//创建存放排查雷的数组
	Initboard(mine, ROWS, COLS,'0');	//初始化布置雷的棋盘,mine表示布置雷数组的首地址
	Initboard(show, ROWS, COLS, '*');	//初始化排查雷的数组,show表示排查雷数组的首地址
	//Displayboard(mine, ROW, COL);	//打印布置雷的棋盘,这里不用打印扩展的两行两列,只需在中间的棋盘布雷,扫雷也同样
	Displayboard(show, ROW, COL);
	Setmine(mine, ROW, COL);	//布置雷
	//Displayboard(mine, ROW, COL);
	Findmine(mine,show, ROW, COL);	//排查雷

扫雷游戏主体函数则相比三子棋简单,只需要调用游戏相关函数即可,这里需要注意的是在调用这些函数进行数组传参时,要注意参数的顺序,这里创建mine和show数组都是用的ROWS和COLS,所以在实现相关函数的功能时用的依然是ROWS和COLS。


总代码实现

game.h

#pragma once
#define ROW 9
#define COL 9	
#define SETCOUNT 10

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

test.c

#include<stdio.h>
#include"game.h"
#include<stdlib.h>
#include<time.h>
void game()

	char mine[ROWS][COLS] =  0 ;	//创建存放布置雷的数组
	char show[ROWS][COLS] =  0 ;	//创建存放排查雷的数组
	Initboard(mine, ROWS, COLS,'0');	//初始化布置雷的棋盘,mine表示布置雷数组的首地址
	Initboard(show, ROWS, COLS, '*');	//初始化排查雷的数组,show表示排查雷数组的首地址
	//Displayboard(mine, ROW, COL);	//打印布置雷的棋盘,这里不用打印扩展的两行两列,只需在中间的棋盘布雷,扫雷也同样
	Displayboard(show, ROW, COL);
	Setmine(mine, ROW, COL);	//布置雷
	//Displayboard(mine, ROW, COL);
	Findmine(mine,show, ROW, COL);	//排查雷

void menu()

	printf("**********************\\n");
	printf("******* 1.play *******\\n");
	printf("******* 0.exit *******\\n");
	printf("**********************\\n");

int main()

	int input = 0;
	srand((unsigned int)time(NULL));//用于随机函数rand的调用
	do
	
		menu();
		scanf_s("%d", &input);
		switch (input)
		
		case 1:
			printf("扫雷游戏开始\\n");
			game();
			break;
		case 0:
			printf("退出游戏\\n");
			break;
		default:
			printf("输入错误,请重新选择!\\n");

		

	 while (input);
	return 0;

game.c

#include<stdio.h>
#include"game.h"
	//两个数组初始化数组的实现,char board[ROWS][COLS]接收mine数组和show数组
	//这里设置一个字符set接收mine和show数组传参过来的‘0’和‘*’
void Initboard(char board[ROWS][COLS], int rows, int cols,char set)

	int i = 0;
	int j = 0;
	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 = 0;
	int j = 0;
	printf("————扫雷游戏 ————\\n");
	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");
	
	printf("————扫雷游戏————\\n");

void Setmine(char mine[ROWS][COLS], int row, int col)

	int count = SETCOUNT;	//为了灵活变通,可以自己设置布置雷的个数,在头文件中自定义个数
	while (count)
		//直到count为0才退出循环,并且每次都是随机坐标布置雷,count是几,x和y就要随机几次
		int x = rand() % row + 1;//用户输入的坐标的范围就是行数列数的范围,应该是row+1才是正确的坐标范围
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
		
			mine[x][y] = '1';
			count--;//每布置一个,雷的个数就减一;
		
	

static int  get_mine_count(char mine[ROWS][COLS], int x,int y)  //static修饰函数,那这个函数就只能在当前源文件里使用了

   //统计这些坐标周围有几个雷
	return mine[x][y - 1] +
		mine[x - 1][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] +
		mine[x + 1][y] - 8 * '0';  //这里返回的是数字,num+'0'='num';即一个数字加上字符0等于数字代表的字符


int get_showblank(char mine[ROWS][COLS], char show[ROWS][COLS], int x , int y)//当雷的个数为0时计算展开的空白个数

	
	int count_mine = get_mine_count(mine, x,y);
    int count_blank = 0;//初始化空白的个数
	if(count_mine == 0)
	
		show[x][y] = ' ';
		count_blank++;//只要是空白就加1;下次递归也一样

	    //判断周围四个坐标合法性,并且要满足没有被遍历,依旧是*号,以防重复遍历
		if (x - 1 >= 1 && x - 1 <= ROW && y >= 1 && y <= COL && show[x - 1][y] == '*')
		
			count_blank+=get_showblank(mine, show, x - 1, y);//每递归一次,空白个数要累加,包括了x,y的空白和周围四个坐标的空白;
			

		
		if (x >= 1 && x <= ROW && y - 1 >= 1 && y - 1 <= COL && show[x][y - 1] == '*')
		
			count_blank += get_showblank(mine, show, x, y - 1);
			
		
		if (x + 1 >= 1 && x + 1 <= ROW && y >= 1 && y <= COL && show[x + 1][y] == '*')
		
			count_blank += get_showblank(mine, show, x + 1, y);
			
		
		if (x >= 1 && x <= ROW && y + 1 >= 1 && y + 1 <= COL && show[x][y + 1] == '*')
		
			count_blank += get_showblank(mine, show, x, y + 1);
		
			
	
	return count_blank;//返回空白个数
   
	



	

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 - SETCOUNT)
	
		int count_blank = 0;//空白个数,每次进入循环都要重置,如果放在循环外面依旧是上一次的值会重复叠加空白;
		printf("请输入排查雷的坐标:\\n");

		scanf_s("%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_mine = get_mine_count(mine, x, y);
				
				if (count_mine == 0 && show[x][y]=='*')//周围雷的个数为0,且没有被遍历
				
					count_blank=get_showblank(mine, show, x, y);//递归展开空白,返回空白个数
					win += count_blank;//空白的个数加到不是雷个数的总数中
				
				else if(show[x][y]=='*')//这里用else不太合适,这里控制的条件是当周围个数不是0,但是没有被遍历
				
                    show[x][y] = count_mine + '0';//不是雷,则统计周围有几个雷,放入show数组对应坐标
					win++;//他统计了周围雷的个数,但本身不是雷,加1
					
				
				
				Displayboard(show, row, col);
				
			
		
		else
		
			printf("坐标不合法,请重新输入!\\n");
		
	
	if (win== row * col - SETCOUNT)
	
		printf("恭喜你,排雷成功!\\n");
		Displayboard(show, row, col);
	

		


总结

这是扫雷优化也叫完整版的扫雷游戏,博主花了一天时间思考和修改代码,整理博客,实属不易。这让我感觉到每一个游戏的实现离不开每一个细节的把控,如果忽略一个细节,整个游戏就无法完成。扫雷游戏细节颇多,对于我们的思考能力和代码实现能力有一定考验,彻底掌握则需要我们反复去琢磨,去动手实现,只有这样我们才能变得更强。如果这篇文章能帮助到你,请给我一键三连,有了大家的鼓励和指教我才能更进一步!!谢谢大家

 

 

 

 

 

 

 

 

以上是关于扫雷游戏 c语言的主要内容,如果未能解决你的问题,请参考以下文章

C语言小游戏扫雷游戏的实现

C语言游戏玩转扫雷——简单扫雷功能的实现!

C语言实现入门级小游戏——扫雷

C语言的扫雷简化版

C语言游戏超详解扫雷游戏完整版,细节满满!!

C语言游戏超详解扫雷游戏完整版,细节满满!!