【C语言】扫雷游戏的代码实现

本文详细介绍了使用C语言实现扫雷游戏的过程,包括文件结构设计、游戏初始界面、棋盘创建、雷的随机布置和排查雷的逻辑。通过多维数组和函数编程,逐步构建了一个基本的扫雷游戏框架。
摘要由CSDN通过智能技术生成

        扫雷游戏是一款十分经典的游戏,也是很多人童年的回忆,每次马上成功的时候结果被点到了炸弹游戏结束,只能重新开始,简直让人又爱又恨,今天我们就用C语言来实现扫雷游戏,不过肯定和电脑上的有所出入,但是也足够我们平时的消遣了。

目录

一、文件结构的设计

二、功能实现

1 游戏初始界面。

1.1 游戏初始界面。

1.2 主代码。

2 游戏实现。

2.1 棋盘的创建。

2.1.1 分析

2.1.2 代码

2.1.2.1 创建并初始化数组

2.1.2.2 初始化

2.1.2.3 打印测试

2.2 雷的布置

2.3 排查雷


一、文件结构的设计

        首先我们要先设计三个文件:分别是game.c、game.h、test.c,各个文件的功能如下:

test.c //⽂件中写游戏的测试逻辑 
game.c //⽂件中写游戏中函数的实现等
game.h //⽂件中写游戏需要的数据类型和函数声明等

二、功能实现

1 游戏初始界面。

         我们需要创建一个初始界面来进入游戏,我们完全可以通过do while循环和switch语句以及函数来实现这个目的。

        以上内容均在test.c中创建:

1.1 游戏初始界面。

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

        这是一个函数,要实现初始界面菜单选择的话我们还需要 do while循环和switch语句来进行辅助。

1.2 主代码。

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

        通过 do while循环和switch语句,我们就可以完成最基本的初始界面了,如图:

2 游戏实现。

        那么有了以上的代码,我们完成了最基本游戏初始界面,接下来我们就要开始进行游戏主体的构造了。

         扫雷游戏我们需要实现的主要是以下几种:

  •         扫雷的棋盘的创建(这里以9*9为例);
  •         雷的布置(随机布置10个雷);
  •         排查雷 ,我们需要进行以下的判断:
    1. 如果位置不是雷,就显示周围有几个雷;
    2. 如果位置是雷,就炸死游戏结束;
    3. 把除10个雷之外的所有雷都找出来,排雷成功,游戏结束;

         我们后面就要将这些分布一一实现。

2.1 棋盘的创建。

2.1.1 分析

        棋盘的话我们以9*9来举例,后面也可以根据自己的喜好来更换。棋盘的话我们可以通过多维数组来实现。那么首先我们先来创建一个9*9的棋盘。

        那如果这个位置布置雷,我们就存放1,没有布置雷就存放0。

        这么乍一看没有什么问题,但是在排查雷的时候我们就会发现一些问题。

         如果我们选择的雷在例如(8,6)位置时,如果排查周围的8个位置区域是否有雷时,会出现出界的情况。那么,为了防止这种情况的发生,我们可以制作出来一圈边界把棋盘包围起来。

        我们只需要将棋盘的大小从9*9,调整到11*11即可,这样就不会出现出借的情况了。但是新的问题又出现了,在排查雷时我们需要在排雷的位置显示周围有几颗雷,如果附近的雷的数量大于等于2的话还好,我们能够分出来,但是周围没有雷或者只有一个雷的时候显示0或1,这样的话我们就没办法分清我们时踩到雷了还是没有踩到,这个问题也好解决,我们只需要将棋盘中的数字1,改为字符‘1’即可,这样既不影响计算周围雷的数量,也不影响我们查看。

         棋盘我们创建好了,但是总不能直接就这样开始游戏吧,这样直接显示出来的话也不需要我们排雷了,直接就可以看到了,所以我们还可以根据这个创建一个展示界面,将排雷界面遮盖起来。

        如此一来,游戏的棋盘创建就分析完成了,接下来我们就需要根据这个思路用代码来实现。

2.1.2 代码
2.1.2.1 创建并初始化数组

        首先创建数组。

void game()
{
	char mine[11][11];//用来存放布置好的雷的信息
	char show[11][11];//用来存放排查出的雷的个数信息
}

        这样创建的话会有一些问题,在后面每次都要写11行11列的数组有些太麻烦了,而且在生成雷的信息的时候我们又要改成9行9列的数组,这样很麻烦而且容易出错,所以我们可以在game.h这个头文件中做出声明。

//声明
#define ROW 9 //9行
#define COL 9 //9列

#define ROWS ROW + 2 //11行
#define COLS COL + 2 //11列

        接下来,只需要将数组内的11更改一下就好了,但是切记一定要在test.c文件中包含game.h这个头文件。

void game()
{
	char mine[ROWS][COLS];//用来存放布置好的雷的信息
	char show[ROWS][COLS];//用来存放排查出的雷的个数信息
}
2.1.2.2 初始化

        初始化这里我们也可以运用函数的知识来进行,首先我们要在 game.h 进行声明。

void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set);

        接下来在test.c文件中进行函数填写。

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

        相关的函数运算则是在game.c中完成。

void InitBoard(char arr[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++)
		{
			arr[i][j] = set;
		}
	}
}

        这样初始化就完成了。

2.1.2.3 打印测试

        为了防止在代码全部完成后出现很多错误,我们最好每完成一部进行一次测试,这样便于我们发现问题,并解决问题,既然棋盘我们已经初始化好了,那么我们就打印一下,进行测试。

        依旧是先进行声明。

void DisplayBoard(char arr[ROWS][COLS], int row, int col);

        然后函数创建。

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

        最后函数的运算。

void DisplayBoard(char arr[ROWS][COLS], int row, int col)
{
	int i = 0;//行
	for (i = 1; i <= row; i++)
	{
		int j = 0;//列
		for (j = 1; j <= col; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
}

        结果证明,两个棋盘都初始化完成。但是呢,我们会发现棋盘打印出来不方便我们进行观看,如果加上行列号的话会好很多。

        这样的话我们的代码如何实现呢?只要将刚才打印的代码进行一些小修改就可以了。

void DisplayBoard(char arr[ROWS][COLS], int row, int col)
{
	int i = 0;//行
	//先打印列号
	for (i = 0; i <= row; i++)
	{
		printf("%d ", i);
	}
	printf("\n");

	for (i = 1; i <= row; i++)
	{
		int j = 0;//列
		//打印行号
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
}

        我们也可以进行如下的一些小装饰,当然不喜欢的也可以不用,或者说换成自己喜欢的样子。 

void DisplayBoard(char arr[ROWS][COLS], int row, int col)
{
	int i = 0;//行
	printf("******* 扫雷 ******\n");
	//先打印列号
	for (i = 0; i <= row; i++)
	{
		printf("%d ", i);
	}
	printf("\n");

	for (i = 1; i <= row; i++)
	{
		int j = 0;//列
		//打印行号
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
	printf("******* 扫雷 ******\n");
}

2.2 雷的布置

        棋盘已经初始化好了,接下来我们就要开始布置雷了。布置雷其实还是比较简单的,我们这里还会用到随机数的知识点了。

        首先我们要先创建随机数,在test.c 的 main函数中我们要先初始化随机数。

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

        这里我们就需要添加两个库函数的头文件来保证这串代码能够运行,依旧放在game.h中。

#include <stdlib.h>
#include <time.h>

        接下来创建布置雷的函数放到test.c的game()的函数中。

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

        接下来就是在game.h中命名了 。

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

        最后代码编写在game.c中。

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

	}
}

         通过测试我们可以看到10个雷全部布置完成了。

2.3 排查雷

        排查雷 ,我们需要进行以下的判断:如果位置不是雷,就显示周围有几个雷;如果位置是雷,就炸死游戏结束;把除10个雷之外的所有雷都找出来,排雷成功,游戏结束。

        那么接下来就是代码的实现:

        首先就是在test.c中进行函数创建。

//排查雷
FindMine(mine, show, ROW, COL);

        在game.h进行声明。

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

        最后在game.c中进行函数代码编写。

static int Getmine(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 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 - EASY_COUNT)
	{
		printf("请输入要排查的坐标:");
		scanf("%d %d", &x, &y);

		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,你被炸死了,游戏结束。");
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else
			{
				//不是雷统计周围的雷的数量
				int n = Getmine(mine, x, y);
				show[x][y] = n + '0';
				DisplayBoard(show, ROW, COL);
				win++;
			}
		}
		else
		{
			printf("未找到该坐标,请重新输入。");
		}
	}
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功!");
	}
}

  

3 总代码

3.1 game.h

#define _CRT_SECURE_NO_WARNINGS
//库函数
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//数组声明
#define EASY_COUNT 10
#define ROW 9 //9行
#define COL 9 //9列

#define ROWS ROW + 2 //11行
#define COLS COL + 2 //11列

//函数声明
//初始化
void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set);
//打印
void DisplayBoard(char arr[ROWS][COLS], int row, int col);
//布置雷
void SetMine(char arr[ROWS][COLS], int row, int col);
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

3.2 test.c

#define _CRT_SECURE_NO_WARNINGS
#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');//'0'
	InitBoard(show, ROWS, COLS, '*');//'*'

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

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

	//排查雷
	FindMine(mine, show, ROW, COL);
}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择: > ");
		scanf("%d", &input);
		switch(input)
		{
		case 1:
			printf("开始游戏\n");
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择。\n");
			break;
		}
	} while (input);
	
	return 0;
}

 3.3 game.c

#define _CRT_SECURE_NO_WARNINGS
#include "game.h"

void InitBoard(char arr[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++)
		{
			arr[i][j] = set;
		}
	}
}

void DisplayBoard(char arr[ROWS][COLS], int row, int col)
{
	int i = 0;//行
	printf("******* 扫雷 ******\n");
	//先打印列号
	for (i = 0; i <= row; i++)
	{
		printf("%d ", i);
	}
	printf("\n");

	for (i = 1; i <= row; i++)
	{
		int j = 0;//列
		//打印行号
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
	printf("******* 扫雷 ******\n");
}

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

	}
}

static int Getmine(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 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 - EASY_COUNT)
	{
		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 n = Getmine(mine, x, y);
				show[x][y] = n + '0';
				DisplayBoard(show, ROW, COL);
				win++;
			}
		}
		else
		{
			printf("未找到该坐标,请重新输入。");
		}
	}
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功!\n");

	}
}

        就这样一个最基本扫雷游戏代码就完成了,后续胖达还会为大家带来扫雷游戏的进阶版,敬请期待!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值