开启掘金成长之旅!这是我参加「掘金日新计划 12 月更文应战」的第6天,点击查看活动概况


全体思路

关于上面视频所示,咱们该怎样用C语言来完成呢?这跟之前写过的那个三子棋很相像,或者说两者的本质是相同的,都是在棋盘上下棋,只是有些方法不同算了。那么,怎样详细完成呢?

首要,还是和以往一样,咱们需求一个.h的头文件来存放函数声明以及一些库函数头文件的包括。 其次,咱们需求两个.c源文件,一个用来存放函数的界说,另一个用来作为测试。这两个环节是必备的,它会使咱们的代码看起来条理愈加清晰,可读性愈加好。

然后,咱们需求棋盘,一个进行下棋的棋盘,有了棋盘,咱们还要考虑该怎样随机放雷,以及放完雷后该怎样进行扫雷,还有游戏的输赢判定。 以上就是咱们全体的思路。

扫雷小游戏————如何用C语言实现(附带所有代码)

大约结构

有了以上思路,便开端入手写代码了:

#include"game.h"
//菜单栏
void menu()
{
	printf("----------1、开端游戏-----------\n");
	printf("----------2、操作阐明-----------\n");
	printf("----------0、退出游戏-----------\n");
}
//操作阐明
void explain()
{
	printf("一共有%d个雷,请输入详细坐标来扫除,望好运!\n",MINE);
}
void game()
{
	//安置好的雷
	//初始化0,放雷的时分1
	char mine[ROWS][COLS] = { 0 };
	//排查出的雷
	//初始化为*,排查时用字符数字表明
	char show[ROWS][COLS] = { 0 };
	//初始化
	init_board(mine, ROWS, COLS,'0');
	init_board(show, ROWS, COLS,'*');
	//打印棋盘
	//dis_play(mine, ROW, COL);
	dis_play(show, ROW, COL);
	//放雷
	set_mine(mine, ROW, COL);
	//dis_play(mine, ROW, COL);
	//排查雷
	find_mine(show, mine, ROW, COL);
	dis_play(show, ROW, COL);
}
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请挑选:>\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			break;
		case 2:
			explain();
			break;
		default:
			printf("输入过错!请从头输入!\n");
			break;
		}
	} while (input);
	return 0;
}

这里为了防止咱们把代码写死,不利于以后的修正,我是在头文件#define界说棋盘以及雷的数量的,这样咱们日后修正棋盘大小以及雷的数量都比较便利。 有了上面的结构,咱们就能够在.c文件里书写界说以及在.h文件里写函数阐明了。

棋盘的界说以及初始化

扫雷小游戏————如何用C语言实现(附带所有代码)

咱们都知道,扫雷是在一个33的小格子里进行排雷,如上图所示,这是一个99的棋盘,但假设咱们利用二维数组创立一个99棋盘的话,关于边上溢出来的部分,咱们不好处理,那咱们就干脆给它加上两行两列,凑成(9+2)(9+2)的棋盘,可是,咱们只利用其中的9*9的棋盘部分,关于边上溢出来的两行两列,咱们全都初始化为非雷区域。就不必管它了。 在这里,咱们能够创立二维数组,一个用来进行初始化,放雷所用,另一个用来排雷所用,当然,咱们最终打印棋盘的时分是要把放雷的那个棋盘给屏蔽掉的,不然就公开雷的方位了。首要,进行初始化两个棋盘:

void init_board(char board[ROWS][COLS], int rows, int cols,char ret)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = ret;
		}
	}
}

扫雷小游戏————如何用C语言实现(附带所有代码)

扫雷小游戏————如何用C语言实现(附带所有代码)
在这里,咱们规则:0代表非雷,1代表雷。这样是为了便利咱们后面进行计算所用。 初始化完后便开端打印棋盘:

//打印棋盘
void dis_play(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	int m = 0;
	for (m = 0; m <=col; m++)
	{
		printf("%d ", m);
	}
	printf("\n");
	//printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}

扫雷小游戏————如何用C语言实现(附带所有代码)
在这里,这两步是为了打印出棋盘的坐标,便利玩家根据坐标进行扫雷,需求留意的是,这个时分咱们是打印出来咱们的9*9的棋盘的:咱们看一下传的参数:
扫雷小游戏————如何用C语言实现(附带所有代码)
在头文件#define界说常量里,ROW与COL别离对应9行9列:
扫雷小游戏————如何用C语言实现(附带所有代码)
这里打印出来就是如图所示:

扫雷小游戏————如何用C语言实现(附带所有代码)
一个9*9的棋盘,咱们能够看到,一切数据满是0,接下来咱们便开端放雷了。

放雷环节

void set_mine(char mine[ROWS][COLS], int row, int col)
{
	int cont = MINE;
	while (cont)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			cont--;
		}
	}
}

咱们在mine棋盘进行放雷,这里用到了rand函数,以及时刻戳

srand((unsigned int)time(NULL));

这是用来生成随机数所用,需求包括头文件#include<stdlib.h>以及#include<time.h>, rand()%一个数再加上,表明的就是随机生成1-这个数。 这里咱们屏蔽掉show棋盘,来看一下咱们的mine棋盘:

扫雷小游戏————如何用C语言实现(附带所有代码)
能够看到,现已在棋盘里随机生成了15个1,即15个雷。

扫雷环节(Death or Survive)

接下来就是触目惊心的扫雷环节了,在这里,往往伴随着逝世与生计。

//排查雷
int get_mine(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 find_mine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;
	while (win<ROW*COL-MINE)
	{
		printf("请输入排查雷的坐标(行 列):>");
		scanf("%d %d", &x,&y);
		system("cls");
		if (show[x][y] == '*')
		{
			//踩中雷
			if (mine[x][y] == '1')
			{
				printf("很惋惜,你被炸死了!\n");
				dis_play(mine, ROW, COL);
				printf("上方为详细雷的方位,死个明白吧。\n");
				printf("\n");
				break;
			}
			//持续排雷
			else
			{
				if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
				{
					int cont = get_mine(mine, x, y);
					show[x][y] = cont + '0';
					dis_play(show, ROW, COL);
					win++;
				}
				else
				{
					printf("已出界\n");
					dis_play(show, ROW, COL);
				}
			}
		}
		else
		{
			printf("该方位已被排查过!\n");
			dis_play(show, ROW, COL);
		}
	}
	if (win == ROW * COL - MINE)
	{
		printf("NB!游戏通关!!!");
		dis_play(mine, ROW, COL);
	}
}

首要,咱们是在show棋盘上对mine的99棋盘里的雷进行扫除,所以这里传送的是4个参数

扫雷小游戏————如何用C语言实现(附带所有代码)
然后在show棋盘上进行扫雷,有一个条件,就是这个棋盘是空的,即还没有被扫,所以加了一个大的条件:if (show[x][y] == ‘‘),不然就阐明这里现已排查过了, 然后扫雷途中有可能会被炸死,也有可能持续扫下去,可是扫的条件是在棋盘内,总不能跑棋盘外面去扫, 持续扫雷的话,咱们知道,它是在一个3*3的范围内计算邻近的雷,就好象这样:
扫雷小游戏————如何用C语言实现(附带所有代码)

这里的1,就表明以它为中心,周围8个里面只有一个雷,相同,在咱们的棋盘里,也需求这样进行计算,那么怎样进行计算呢?

这就提到了前面为何要把0设置成非雷,把1设置成雷了,咱们仔细想一下,假设咱们要扫的当地显示出一个2,就代表周围一圈8个有两个雷,而咱们这里规则,0代表非雷,1代表雷,把他们八个加起来,不就是2了吗,这个2就是咱们所排查的当地!

所以,咱们调用了一个get_mine(mine, x, y)函数,用来计算mine棋盘里有多少个雷,再把成果给cont,cont再从咱们的show棋盘里显示出来:

					int cont = get_mine(mine, x, y);
					show[x][y] = cont + '0';
					dis_play(show, ROW, COL);

相同,扫雷是一个循环往复的进程,不是说一会儿就中止,所以咱们把这一整个全都用while进行循环

判定条件咱们能够给一个变量win,来计算排查的个数,当win == 一切格子-雷的个数,即win == 一切非雷方位时,就代表咱们现已扫除结束,不然一向循环,每扫除一个,win++,直到一切排完。 最终咱们能够在这里加一个system函数,整理屏幕,有一个无缺的体会感。

扫雷小游戏————如何用C语言实现(附带所有代码)

完整代码

头文件
#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
#define MINE 15
//初始化棋盘
void init_board(char board[ROWS][COLS], int rows,int cols,char ret);
//打印棋盘
void dis_play(char board[ROWS][COLS], int row, int col);
//放雷
void set_mine(char mine[ROWS][COLS], int row, int col);
//排查雷
void find_mine(char show[ROWS][COLS],char mine[ROWS][COLS], int row,int col);
game.c源文件
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//棋盘初始化
void init_board(char board[ROWS][COLS], int rows, int cols,char ret)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = ret;
		}
	}
}
//打印棋盘
void dis_play(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	int m = 0;
	for (m = 0; m <=col; m++)
	{
		printf("%d ", m);
	}
	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 set_mine(char mine[ROWS][COLS], int row, int col)
{
	int cont = MINE;
	while (cont)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			cont--;
		}
	}
}
//排查雷
int get_mine(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 find_mine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;
	while (win<ROW*COL-MINE)
	{
		printf("请输入排查雷的坐标(行 列):>");
		scanf("%d %d", &x,&y);
		system("cls");
		if (show[x][y] == '*')
		{
			//踩中雷
			if (mine[x][y] == '1')
			{
				printf("很惋惜,你被炸死了!\n");
				dis_play(mine, ROW, COL);
				printf("上方为详细雷的方位,死个明白吧。\n");
				printf("\n");
				break;
			}
			//持续排雷
			else
			{
				if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
				{
					int cont = get_mine(mine, x, y);
					show[x][y] = cont + '0';
					dis_play(show, ROW, COL);
					win++;
				}
				else
				{
					printf("已出界\n");
					dis_play(show, ROW, COL);
				}
			}
		}
		else
		{
			printf("该方位已被排查过!\n");
			dis_play(show, ROW, COL);
		}
	}
	if (win == ROW * COL - MINE)
	{
		printf("NB!游戏通关!!!");
		dis_play(mine, ROW, COL);
	}
}
测试源文件
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//菜单栏
void menu()
{
	printf("----------1、开端游戏-----------\n");
	printf("----------2、操作阐明-----------\n");
	printf("----------0、退出游戏-----------\n");
}
//操作阐明
void explain()
{
	printf("一共有%d个雷,请输入详细坐标来扫除,望好运!\n",MINE);
}
void game()
{
	//安置好的雷
	//初始化0,放雷的时分1
	char mine[ROWS][COLS] = { 0 };
	//排查出的雷
	//初始化为*,排查时用字符数字表明
	char show[ROWS][COLS] = { 0 };
	//初始化
	init_board(mine, ROWS, COLS,'0');
	init_board(show, ROWS, COLS,'*');
	//打印棋盘
	//dis_play(mine, ROW, COL);
	printf("\n");
	dis_play(show, ROW, COL);
	//放雷
	set_mine(mine, ROW, COL);
	//dis_play(mine, ROW, COL);
	//
	////排查雷
	find_mine(show, mine, ROW, COL);
	dis_play(show, ROW, COL);
}
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请挑选:>\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			break;
		case 2:
			explain();
			break;
		default:
			printf("输入过错!请从头输入!\n");
			break;
		}
	} while (input);
	return 0;
}