C语言小游戏——简易版扫雷

前言

本文主要介绍了C语言学习初级阶段的一个综合小游戏——简单版扫雷。
作者感觉学会这个游戏能够对初级阶段C语言的知识有一个比较牢靠的巩 固和复习!大家可以参考。
作者将游戏封装为了:game.h、game.c、test.c三个文件进行实现
game.h包含所需要的头文件、定义的数组长度的宏和实现游戏过程函数的函数声明!

一、游戏组成

我们可以用几个函数分别实现每个游戏功能步骤的实现。
我是这样划分的:
1、游戏菜单
2、游戏测试
3、布置棋盘和初始化棋盘
4、根据我们的需求初始化雷的个数
5、打印棋盘
6、玩家开始排雷
7、根据每个函数进行玩游戏的game函数
8、game.h的头文件展示
9、游戏成品展示


二、每个函数的具体实现

1.菜单函数

代码如下:

`void menu()
{
    
    
	printf("*****************************************\n");
	printf("**************   1、play!   *************\n");
	printf("**************   0、exit!   *************\n");
	printf("*****************************************\n");
}`
菜单就用printf函数打印出对应选项就可以实现

2.游戏测试

代码如下(示例):

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");

		}
	} while (input);
	return 0;
}

根据我们的菜单栏有几个选项,利用switch语句进行选择实现,放在循环中可以保证在每次玩完游戏后继续供我们进行选择
srand((unsigned int)time(NULL));调用这个函数可以保证我们在生成随机数时每次生成的不同!


3.布置棋盘和初始化棋盘

我们在布置棋盘时可以选择多种棋盘,作者在这里选择的是99的棋盘格。
我们想要将棋盘格初始化为什么样子,就传入什么字符
因为作者在展示棋盘初始化的是’
',所以将棋盘的二维数组定义为了字符类型
代码如下:

void InitBoard(char Mine[Rows][Cols], int rows, int cols,char ch)
{
    
    //字符ch是我们想要将棋盘格初始化为什么样子,就传入什么字符
	int i = 0, j = 0;
	for (i = 0; i < rows; i++)
	{
    
    
		for (j = 0; j < cols; j++)
		{
    
    
			Mine[i][j] = ch;
		}
	}
}

数组长度用了我们在game.h头文件中定义的常宏量来表示,这样在以后维护和更新游戏时非常方便,只需要修改定义宏的地方,减小了工作量。


4.根据我们的需求初始化雷的个数

因为扫雷游戏每排一个雷后会展示它周围八个位置的雷数总和,所以我们在定义棋盘的时候就应该定义两个,一个用来布置雷,一个用来展示每次排雷后棋盘的情况,又因为在判断当前位置周围八个位置雷数量的时候需要访问周围八个元素,由于棋盘边界的位置在访问时会出现数组小标越界的情况,所以我们需要将99的棋盘定义成1111的,上下分别多出一行格子,左右分别多出一列格子,多的这些我们只对它进行初始化,防止雷时不会给这些位置放置,这样我们在访问每个位置9*9棋盘的每个位置周围的八个位置时就不会出现数组下标越界的情况,也不会影响我们对周围雷数量的判断
代码展示:

void ArrBoard(char Mine[Rows][Cols], int rows, int cols)
{
    
    
	int count = Easy_Count;
	while (count)
	{
    
    
		int x = rand() % 9 + 1;
		int y = rand() % 9 + 1;
		if (Mine[x][y] != '1')
		{
    
    
			Mine[x][y] = '1';
			count--;
		}
	}
}

调用rand函数配合srand((unsigned int)time(NULL));函数的调用生成1-9的随机数,我们用’1’表示雷


5.打印棋盘

打印棋盘时只需要打印我们所需要的9*9行列,所以我们只需要传入我们打印为9的那个宏量
代码展示:

void DisBoard(char Mine[Rows][Cols], int rows, int cols)
{
    
    
	printf("---------扫雷---------\n");
	int i = 0, j = 0;
	for (i = 0; i <= rows; i++)
	{
    
    
		printf("%d ", i);//把列的序号也打印出来
	}
	printf("\n");
	for (i = 1; i <=rows; i++)
	{
    
    
		printf("%d ", i);//每行打印前先把行号打印了
		for (j = 1; j <=cols; j++)
		{
    
    
			printf("%c ", Mine[i][j]);
		}
		printf("\n");
	}
	printf("---------扫雷---------\n");
}

打印时为了便于我们确定每个位置的坐标,我们可以顺带打印出每行每列的标号,这样也刚好在数组中我们棋盘的第一行的数组下标就成为:1,第一列就成为:1,更加方便玩家的定位


6.玩家开始排雷

代码展示:

int NumThunder(char Mine[Rows][Cols],int x,int y)
{
    
    //我们可以将判断一个位置周围八个位置的雷数总和的代码单独封装成一个函数
	return Mine[x - 1][y] + Mine[x][y - 1] + 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 + 1][y + 1] - 8 * 48;
	//字符'0'的Acall值是48,所以这里-8*48是进行字符和整型的转化
}


void RemMine(char Mine[Rows][Cols], char Dis[Rows][Cols], int rows, int cols)
{
    
    
	int win = 0;
	while (win<rows*cols- Easy_Count)//循环确保排雷结束后游戏才结束
	{
    
    
		int x = 0, y = 0;
		printf("请输入你想要排雷的坐标>\n");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= rows && y >= 1 && y <= cols)
		{
    
    
			if (Mine[x][y] == '1')//踩到雷,游戏直接结束
			{
    
    
				printf("踩到地雷了,结束失败!\n");
				DisBoard(Mine, Row, Col);//失败后展示雷的分布
				break;
			}
			else 
			{
    
    
				//不是雷,则计算坐标x,y周围有几个雷
				int res = NumThunder(Mine, x, y) + 48;
				Dis[x][y] = res;
				DisBoard(Dis, Row, Col);//展示本次排雷后的棋盘以供继续排雷
				win++;//每排雷一次,排雷的次数加1
			}
		}
		else//输入坐标必须在1-9范围内,否则重新输入
		{
    
    
			printf("输入坐标有误,重新输入!\n");
		}
	}
	if (win == rows * cols - Easy_Count)//排雷次数与非雷数量相等且一直没有踩到雷时游戏胜利
	{
    
    
		printf("恭喜你,排雷成功!\n");
		DisBoard(Mine, Row, Col);//成功后展示雷的分布
	}
}


7.根据每个函数进行玩游戏的game函数

我们利用一个game函数就游戏实现过程的函数进行一定顺序的组合,就完成了游戏的全过程
代码展示:

void game()
{
    
    
	char MineBoard[Rows][Cols] = {
    
     0 };//布置雷盘
	char ShowBoard[Rows][Cols] = {
    
     0 };//展示的棋盘
	InitBoard(MineBoard, Rows, Cols,'0');//初始化时将多的那两行两列也算上,因为后面统计周围雷数量时要用
	InitBoard(ShowBoard, Rows, Cols, '*');
	//DisBoard(MineBoard, Row, Col);//打印时就只穿想要打印的数量,顺便就从下标1开始打印了,因为0下标的元素刚好不用展示出来
    ArrBoard(MineBoard, Row, Col);//随机放置地雷
	//DisBoard(MineBoard, Row, Col);
	DisBoard(ShowBoard, Row, Col);
	//DisBoard(MineBoard, Row, Col);
	RemMine(MineBoard,ShowBoard, Row, Col);
}

8.game.h的头文件展示

下面展示一个game.h头文件中所所定义的常宏量和所用到的库函数的头文件
代码展示:

#pragma once
#include<stdio.h>
#include<time.h>
#include<stdlib.h>

# define Row 9
# define Col 9
# define Rows Row+2
# define Cols Col+2
#define Easy_Count 10//设置的雷数


//初始化棋盘
void InitBoard(char Mine[Rows][Cols], int rows, int cols,char ch);

//打印棋盘
void DisBoard(char Mine[Rows][Cols], int rows, int cols);

//布雷
void ArrBoard(char Mine[Rows][Cols], int rows, int cols);

//排雷
void RemMine(char Mine[Rows][Cols], char Dis[Rows][Cols], int rows, int cols);

9.游戏成品展示

选择
选择1,开始游戏
在这里插入图片描述
选择自己想要排雷的坐标开始排雷,每次排雷成功后继续展示最新棋盘继续排雷
在这里插入图片描述
踩到雷后游戏失败,给玩家展示雷的分布

总结

希望我对这个扫雷游戏的理解可以帮助到大家,也请大佬们不吝指正可以优化之处,谢谢大家观看,后续一直会分享自己的编程学习过程!!!

猜你喜欢

转载自blog.csdn.net/m0_71214261/article/details/131959914