C语言扫雷详解实现

扫雷

  • 前言
  • 代码思路
  • 1.创建游戏菜单
  • 2.创建二个游戏棋盘
  • 初始化棋盘
    • 函数的实现
  • 布置雷
    • 代码实现
  • 打印棋盘测试
  • 排查雷
    • mine_count 函数的思路图解
    • 代码实现
  • 胜利条件
  • 扫雷代码()全)
    • test.c
    • game.h
    • game.c

前言

C语言扫雷详解实现_第1张图片
今天就用之前所学的知识来写一个C语言简易版扫雷游戏,主要涉及了C语言中的一些基本知识,循环、分支、函数、数组等等,如果熟练掌握以上的知识其实都不难
游戏规则:
就是在一个棋盘内点击格子,通过出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输
游戏胜利条件:找出所有非雷的格子,同时不能踩到雷

代码思路

大致思路,一步一步写出来
C语言扫雷详解实现_第2张图片

1.创建游戏菜单

先创建游戏菜单,咱们用do while循环来实现,最开始先执行一次在进行判断,switch用于分支选择,来判断玩家是否要重复进行游戏,然后就是 game()函数,就是游戏的实现了

void menu()
{
	printf("**********************\n");
	printf("****** 1. 开始 *******\n");
	printf("****** 0. 退出 *******\n");
	printf("**********************\n");
}
int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请选择:\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误\n");
			break;
		}
	} while (input);
	return 0;
}

2.创建二个游戏棋盘

咱们先创建一个源文件和一个头文件,分别放game.c (函数功能的实现)game.h (函数的声明)
然后再创建数组,这里数组不建议使用方法一,因为不方便修改,如果我们想扩大棋盘要修改数组的时候,要一个一个地方进行修改
方法二:
推荐大家都这样写
只需要在 game.h 头文件定义个全局变量就可以,方便后期修改

方法一:
void game()
{
	char mine[9][9] = { 0 };
	char show[9][9] = { 0 };
}
-------------------------------
方法二:
void game()
{
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
}

假设我们建立 9 * 9 的游戏棋盘,那我们真正就要建立 11 * 11 的棋盘,如图,绿色区域就是要扫雷的区域,在绿色区域才会有雷。之所以要建立大一圈的棋盘,是为了后面检测扫雷地址周围雷数目时不越界
C语言扫雷详解实现_第3张图片

game.h  函数声明文件
#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2

mine用以放置布置雷的信息
show用于放置排查雷的信息
这样做可以方便的显示排查地址周围雷的数量。使用define定义后期想改变棋盘大小更方便

void game()
{
	char mine[ROWS][COLS] = { 0 };  存放的是布置雷的棋盘
	char show[ROWS][COLS] = { 0 };  存放的是排查雷的棋盘
}

C语言扫雷详解实现_第4张图片
不理解,没关系,多看几遍

初始化棋盘

将mine初始化为‘0’,布置雷的棋盘
show初始化为‘*’,玩家看到的棋盘,初始化为 *,看起来更有神秘感
这样做是为了让埋雷、计算雷的数量的时候更方便

void game()
{
	char mine[ROWS][COLS] = { 0 };//存放布置雷
	char show[ROWS][COLS] = { 0 };//存放排查雷的信息
	//初始化棋盘
	//mine 数组在没有布置雷时,初始化为 - '0'
	Isitboard(mine, ROWS, COLS,'0');
	//show 数组在没有排查雷时,初始化为 - '*'
	Isitboard(show, ROWS, COLS, '*');
}

函数的实现

把全部都初始化为 str 里的元素

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

布置雷

记住雷是布置在mine数组里的,别传错了,还有就是传的是棋盘大小,不是数组大小
ROWS 和 COLS 是棋盘大小,ROW 和 COL 是棋盘大小
Mine_count是全局变量,Mine_count是雷的个数

前面已经把mine初始化为‘ 0 ’了,现在只需将要放雷的位置的内容改为‘ 1 ’就可以了。这个位置是随机产生的,这里使用了srand函数和rand函数来生成随机数。雷的放置坐标区域是[1][1]到[9][9],也就是上面的绿色区域。所以rand() % row得到0~8的数,要加上1

代码实现

随机放置雷,雷表示字符 ‘1’

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

打印棋盘测试

打印棋盘是和上面布置雷一样传的是棋盘大小(ROW和COL),先把棋盘的全部元素,在一步一步加上行号和列号,别忘了要函数的声明
C语言扫雷详解实现_第5张图片
这样就完成了大半了,就剩下排查雷了

C语言扫雷详解实现_第6张图片
C语言扫雷详解实现_第7张图片

//打印棋盘测试
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 FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;
	while ()
	{
		printf("请输入排雷坐标:\n");
		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
			{   //计算周围 8 个格子雷的数量
				int count = mine_count(mine, x, y); 
				show[x][y] = count+'0';
				DisplayBoard(show, ROW, COL);
			}
		}
		else
			printf("坐标非法,重新输入\n");
	}
}

mine_count 函数的思路图解

C语言扫雷详解实现_第8张图片
雷个数的计算方式就是把坐标周围8个字符加起来再减去8个字符‘0’,得到的就是雷的个数,再加上‘0’字符的形式打印
为什么要减去8个字符‘ 0’
因为字符0是以ASCll码值存储的,字符0的ASCLL值是48,字符‘1’的ASCLL值是49,而周围有8个坐标,加起来在减去8个字符‘ 0’,相减就得出雷的个数
这么写是为了区分开来数字0和字符0

代码实现

int 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';
}

胜利条件

row*col 是计算数组的个数
-Mine_count 是减去雷的数量

//胜利条件
	if (win == row * col - Mine_count)
	{
		printf("排雷成功\n");
		DisplayBoard(show, ROW, COL);

	}

扫雷代码()全)

test.c

#include"game.h"

void menu()
{
	printf("**********************\n");
	printf("****** 1. 开始 *******\n");
	printf("****** 0. 退出 *******\n");
	printf("**********************\n");
}

void game()
{
	char mine[ROWS][COLS] = { 0 };// 存放的是布置雷的棋盘
	char show[ROWS][COLS] = { 0 };//存放的是排查雷的棋盘

	//初始化棋盘
	//mine 数组在没有布置雷时,初始化为 - '0'
	Isitboard(mine, ROWS, COLS,'0');
	//show 数组在没有排查雷时,初始化为 - '*'
	Isitboard(show, ROWS, COLS, '*');

	//布置雷
	SetMine(mine, ROW, COL);

	//打印数组测试
	//布置雷棋盘
	//DisplayBoard(mine, ROW, COL);

	//存放排雷棋盘
	DisplayBoard(show, ROW, COL);

	// 排查雷
	FindMine(mine, show, ROW, COL);
}
int main()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();
		printf("请选择:\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误\n");
			break;
		}
	} while (input);
	return 0;
}

game.h

//棋盘的大小
#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2

//雷的数量
#define Mine_count 10

#include
#include
#include

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

//布置雷
void SetMine(char mine[ROWS][COLS], int row,int col);

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

//排雷
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col);

game.c

#include"game.h"

//初始化棋盘
void Isitboard(char board[ROWS][COLS], int rows, int cols, char str)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = str;
		}
	}
}

//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col)
{	
	int count = Mine_count;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}

//打印棋盘测试
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");

}

//排查周围雷的数量
int 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 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-Mine_count)
	{
		printf("请输入排雷坐标:\n");
		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
			{
				//统计mine数组中 x 和 y坐标周围有几个雷
				win++;
				int count = mine_count(mine, x, y);
				show[x][y] = count +'0';
				DisplayBoard(show, ROW, COL);
			}
		}
		else
			printf("坐标非法,重新输入\n");
	}
	//胜利条件
	if (win == row * col - Mine_count)
	{
		printf("排雷成功\n");
		DisplayBoard(show, ROW, COL);

	}
}

扫雷今天就写完啦,下次在见!!
觉得有用,就点个赞!!
C语言扫雷详解实现_第9张图片

你可能感兴趣的:(练习小程序,c语言,开发语言)