【游戏】C语言实现扫雷游戏(超详细备注和解释)

C语言实现扫雷游戏

求个赞求个赞求个赞求个赞 谢谢🙏

先赞后看好习惯 打字不容易,这都是很用心做的,希望得到支持你 大家的点赞和支持对于我来说是一种非常重要的动力 看完之后别忘记关注我哦!️️️

思路

首先,我们需要理清楚思路,我们创建三个.c源文件
game.h用来存放游戏的函数声明和一些头文件引用和一些常量的定义
game.c用来实现游戏里面的函数
test.c用来存放游戏整体思路和main函数。
*

建议收藏后食用~

首先:
我们先编写一个选择菜单函数menu(),如果要进行游戏,选择1,退出游戏,选择0,同时,定义一个int input来接受

然后,游戏必须在一个循环里面,在循环里面,我们可以使用switch/case语句来执行我们的input,如果case 0:我们直接break,如果case1:我们进行游戏game(),default,我们重新选择。

void menu()
{
	printf("************************\n");
	printf("***********1.play*******\n");
	printf("***********0.exit*******\n");
	printf("************************\n");
}
int main()
{
	int input = 0;
	do
	{
		srand((unsigned int)time(NULL));
		menu();
		printf("please enter your input:\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("exit the game!!!!\n");
			break;
		default:
			printf("err,please input again:\n");
			break;
		}
	} while (input);
	return 0;
}

接下来,最重要的,我们要开始写我们的game()函数。

游戏函数game()函数实现详解

定义两个二维数组

在实现游戏的时候,我们必须定义两个二维数组,一个是用来存放雷的信息,一个是用来展示给玩家看的
于此同时,我们的游戏是99的,但是,我们定义二维数组的时候要定义1111的,因为我们在后面排查雷的时候,边边角角的位置的排查,找一圈,如果不定义多一行,我们为了在访问数组的时候不越界访问导致程序崩溃,我们必须定义多一行。

#define ROWS 11
#define COLS 11
#define ROW ROWS-2
#define COL COLS-2
#define MINE 10//定义雷的个数

数组的初始化

	//雷数组
	char mine[ROWS][COLS] = { 0 };
	//展示数组
	char show[ROWS][COLS] = { 0 };
	//初始化
	Initboard(mine, ROWS, COLS, '0');
	Initboard(show, ROWS, COLS, '*');

我们可以规定,在存放雷的信息的数组mine里面,我们规定,‘1’代表有雷,‘0’代表无雷
我们可以规定,在展示数组show里面,我们规定,还没排查的位置展示" * "

当然,我们使用for循环来初始化数组
头文件:

//初始化数组
void Initboard(char board[ROWS][COLS], int rows, int cols, char ch);

void Initboard(char board[ROWS][COLS], int rows, int cols, char ch)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = ch;//把ch传过来,我们就可以一个函数两用了
		}
	}
}

在传参的时候,我们,必须也把我们要初始化的字符也传过去,这样的话,我们写一个Initboard函数就可以完成两个数组的初始化了。

打印数组函数

紧接着,我们当然是需要一个函数来把我们的数组打印一下,展示给玩家看
此处注意,show数组才需要打印,mine数组是不能给玩家看的,给玩家看了还得了
但是,我们在写程序的时候可以打印出来看看,看看自己有没有写好

	//打印数组
	//Displayboard(mine, ROW, COL);
	Displayboard(show, ROW, COL);
//打印
void Displayboard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("--------game-------\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("--------game-------\n");

}

此处注意,我们不只是需要打印那些*,我们还需要行号和列号,具体请看代码,不懂的伙伴可以私信留言
打印出来是这样的:

在这里插入图片描述

布置雷函数

接下来,我们需要布置雷,我们在game.h头文件里面已经定义了雷的个数是10个(当然我们可以改)

	//布置
	Setmine(mine, ROW, COL);
	//Displayboard(mine, ROW, COL);
	     //当然,我们设置完雷,我们可以打印出来看看打印好没有

此时,我们需要rand函数,来随机生成坐标,我们rand的种子用srand函数,其中,我们把种子定义成时间,这样我们才能随机生成,而且每次打开游戏生成的位置不一样

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

注意,这个语句只需要执行一次,因此,我们放在main()函数里面,dowhile循环外面即可

//布置
void Setmine(char board[ROWS][COLS], int row, int col)
{
	int count = 0;
	while (1)
	{
		int x = rand() % row + 1;//这里的模然后加一可以控制生成x的范围控制在1<=x<=row这个范围内,有疑问的伙伴可以给我留言。
		int y = rand() % col + 1;
		if (board[x][y] == '0')//先判断这个坐标有雷没有,没有,才埋雷,如果有了,重新生成。
		{
			board[x][y] = '1';
			count++;//计算已设置雷的个数
		}
		if (count == MINE)//如果搞够十个了,就break;
			break;
	}
}

设置完雷后我们可以打印出来看一下,看完记得屏蔽代码,别让玩家看到
在这里插入图片描述

排查雷函数

接下来,玩家就要开始操作了

	//排查
	Findmine(show, mine, ROW, COL);
//排查
static int get_mine(char mine[ROWS][COLS], int x, int y)
{
	return mine[x][y - 1] + mine[x][y + 1] + 
		mine[x - 1][y - 1] + mine[x - 1][y] + 
		mine[x - 1][y + 1] + mine[x + 1][y] + 
		mine[x + 1][y - 1] + mine[x + 1][y + 1] - 8 * '0';//字符转整型
}
void Findmine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int count = 0;

	while (count<row*col-MINE)
	{
		printf("please input the location you want to search:\n");
		scanf_s("%d %d", &x,&y);
		//判断坐标合法性
		if (x >= 1 && x <= 9 && y <= 9 && y >= 1)
		{
			if (mine[x][y]=='1')
			{
				Displayboard(mine, row, col);
				printf("Your LOSE the GAME!!\n");
				//输掉的时候,打印一下雷的数组给玩家看看
				break;
			}
		    else
		    {
			    int ret = get_mine(mine, x, y);//把坐标传过去,计算附近到底有多少个雷
			    //如果没有被炸死,计算附近雷的个数,并打印出来
			    show[x][y] = ret + '0';//整型转字符
				Displayboard(show, row, col);//打印排查信息给玩家看
			    count++;//计算已排查坐标个数
		    }
		}
		else//如果玩家输入了不在范围内的坐标,重新输入
		{
			printf("err,please input again\n");
		}


	}
	if (count == row * col - MINE)//判断是否赢,赢了才打印,输的情况跳出来是不用打印的
	{
		printf("YOU WIN!!!\n");
		Displayboard(mine, row, col);
	}
}

实现以下函数,用来计算玩家输入坐标xy附近的雷个数

static int get_mine(char mine[ROWS][COLS], int x, int y)

整体代码展示

test.c

#define _CRT_SECURE_NO_WARNINGS 1 

#include<stdio.h>
#include"game.h"
#include<time.h>
void game()
{
	//雷数组
	char mine[ROWS][COLS] = { 0 };
	//展示数组
	char show[ROWS][COLS] = { 0 };
	//初始化
	Initboard(mine, ROWS, COLS, '0');
	Initboard(show, ROWS, COLS, '*');

	//打印数组
	//Displayboard(mine, ROW, COL);
	Displayboard(show, ROW, COL);

	//布置
	Setmine(mine, ROW, COL);
	//Displayboard(mine, ROW, COL);

	//排查
	Findmine(show, mine, ROW, COL);

}
void menu()
{
	printf("*****************************\n");
	printf("***********1.play************\n");
	printf("***********0.exit************\n");
	printf("*****************************\n");
}
int main()
{
	int input = 0;
	do
	{
		srand((unsigned int)time(NULL));
		menu();
		printf("please enter your input:\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("exit the game!!!!\n");
			break;
		default:
			printf("err,please input again:\n");
			break;
		}
	} while (input);
	return 0;
}

game.h

#pragma once
#define ROWS 11
#define COLS 11
#define ROW ROWS-2
#define COL COLS-2
#define MINE 10
//初始化数组
void Initboard(char board[ROWS][COLS], int rows, int cols, char ch);
//打印
void Displayboard(char board[ROWS][COLS], int row, int col);
//布置
void Setmine(char board[ROWS][COLS], int row, int col);
//排查
void Findmine(char show[ROWS][COLS], char mine[ROWS][COLS], int rows, int cols);

game.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"
#include<stdio.h>
//初始化棋盘
void Initboard(char board[ROWS][COLS], int rows, int cols, char ch)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = ch;//把ch传过来,我们就可以一个函数两用了
		}
	}
}
//打印函数
void Displayboard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("--------game-------\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("--------game-------\n");

}
//布置雷函数
void Setmine(char board[ROWS][COLS], int row, int col)
{
	int count = 0;
	while (1)
	{
		int x = rand() % row + 1;//这里的模然后加一可以控制生成x的范围控制在1<=x<=row这个范围内,有疑问的伙伴可以给我留言。
		int y = rand() % col + 1;
		if (board[x][y] == '0')//先判断这个坐标有雷没有,没有,才埋雷,如果有了,重新生成。
		{
			board[x][y] = '1';
			count++;//计算已设置雷的个数
		}
		if (count == MINE)//如果搞够十个了,就break;
			break;
	}
}
//排查雷函数
static int get_mine(char mine[ROWS][COLS], int x, int y)//计算(x,y)坐标附近雷的总数
{
	return mine[x][y - 1] + mine[x][y + 1] +
		mine[x - 1][y - 1] + mine[x - 1][y] +
		mine[x - 1][y + 1] + mine[x + 1][y] +
		mine[x + 1][y - 1] + mine[x + 1][y + 1] - 8 * '0';//字符转整型
}
void Findmine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int count = 0;

	while (count < row * col - MINE)
	{
		printf("please input the location you want to search:\n");
		scanf_s("%d %d", &x, &y);
		//判断坐标合法性
		if (x >= 1 && x <= 9 && y <= 9 && y >= 1)
		{
			if (mine[x][y] == '1')
			{
				Displayboard(mine, row, col);
				printf("Your LOSE the GAME!!\n");
				//输掉的时候,打印一下雷的数组给玩家看看
				break;
			}
			else
			{
				int ret = get_mine(mine, x, y);
				//如果没有被炸死,计算附近雷的个数,并打印出来
				show[x][y] = ret + '0';//整型转字符
				Displayboard(show, row, col);//打印排查信息给玩家看
				count++;//计算已排查坐标个数
			}
		}
		else//如果玩家输入了不在范围内的坐标,重新输入
		{
			printf("err,please input again\n");
		}


	}
	if (count == row * col - MINE)//赢了才打印you win,否则不打印
	{
		printf("YOU WIN!!!\n");
		Displayboard(mine, row, col);
	}
}

尾声

以上就是本期博客的全部内容了,谢谢各位的耐心观看,如果对这个小游戏还有什么问题的话,可以在评论区留言哦!在划走之前点个赞支持下吧!!

posted @ 2021-10-17 10:34  背包Yu  阅读(26)  评论(0编辑  收藏  举报  来源