【C语言】实现扫雷游戏

发布时间:2024年01月20日

目录

游戏的组成

1.头文件saolei.h

2.源文件1 define.c

3.源文件2 saolei.c

总结


游戏的组成

还是跟之前猜数游戏一样,需要进去需求分析。首先需要设计一个菜单界面,其次是游戏界面,相

信每个人都玩过扫雷游戏,这样我们能联想到这么些步骤,初始化棋盘、打印棋盘、设置雷的位

置、排查雷。这次设计这个扫雷游戏需要分多个文件来组成,首先需要一个头文件,其次是两个源

文件,头文件放函数的声明以及一些定义,源文件就放我们的函数定义。

1.头文件saolei.h

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

//#define Row 9 //定义行
//#define Col 9 //定义列
//
//#define Rows Row + 2 //在后续统计雷的时候,这样定义坐标就不会越界了
//#define Cols Col + 2
//
//#define Mine_count 10 //定义雷的数量

#define MaxSize 50//定义最大长度

//以下是函数声明

void menu();//菜单

void game(int Rows, int Cols, int Row, int Col, int Mine_count);//游戏

void test();//输入选择

void InitPanel(char arr[MaxSize][MaxSize], int rows, int cols, char set);//初始化棋盘

void PrintPanel(char arr[MaxSize][MaxSize], int row, int col);//打印棋盘

void setMine(char arr[MaxSize][MaxSize], int row, int col, int Mine_count);//设置雷

void checkMine(char mine[MaxSize][MaxSize], char show[MaxSize][MaxSize], int row, int col, int Mine_count);//排雷

void foldPanel(char mine[MaxSize][MaxSize], char show[MaxSize][MaxSize], int row, int col);//附近没有雷展开

?头文件的声明我写了注释,方便大家理解,如果不理解也不要着急,我们接着往下看。


2.源文件1 define.c

#include "saolei.h"

//以下是函数的定义

void InitPanel(char arr[MaxSize][MaxSize], int rows, int cols, char set)//初始化棋盘,形参接收实参传来的
{
	int i = 0;
	for (int i = 0; i < rows; i++) {
		for (int j = 0; j < cols; j++) {
			arr[i][j] = set;//set是根据实参传进来决定
		}
	}
}
 
void PrintPanel(char arr[MaxSize][MaxSize], int row, int col)//打印棋盘,形参接收实参传来的
{
	int i = 0;
	for (int i = 0; i <= col; i++) {//打印列0-9数字,方便排雷
		printf("%2d ", i);//最大宽度为2
	}
	printf("\n");
	for (int i = 1; i <= row; i++) {
		printf("%2d ", i);//打印行0-9数字,方便排雷
		for (int j = 1; j <= col; j++) {
			printf("%2c ", arr[i][j]);
		}
		printf("\n");
	}
}

void setMine(char arr[MaxSize][MaxSize], int row, int col,int Mine_count) //设置雷的位置
{	
	int count = Mine_count;//雷

	int x = 0;//设置坐标
	int y = 0;

	while (count) 
	{
		int x = rand() % row + 1;//随机坐标用来赋雷
		int y = rand() % col + 1;

		if ( arr[x][y]!='1') //判断有没有重复赋雷
		{
			arr[x][y] = '1';
			count--;
		}
	}
}

void foldPanel(char mine[MaxSize][MaxSize], char show[MaxSize][MaxSize], int x, int y) //附件没有雷展开
{
	int count = get_Mine_quantity(mine, x, y);//统计周围雷的数量
	
	if (count != 0) 
	{
		show[x][y]= count + '0';
	}
	else if(show[x][y] != ' ')//判断这个位置有没有被展开
	{
		show[x][y] = ' ';//没有的话并且周围没雷直接展开

		//通过checkMine函数,用户所输入的坐标传进来然后判断,没有雷且这个位置没有被展开,接着展开
		//通过递归的方式一直展开,直到周围有雷。
		int i, j;
		for (int i = x - 1; i < x + 1; i++) {
			for (int j = y - 1; j < y + 1; j++) {
				foldPanel(mine, show, i, j);
			}
		}
	}
	else
	{
		return;
	}
}

static int get_Mine_quantity(char arr[MaxSize][MaxSize], int x, int y)//这个设置成静态函数,只在这个文件下使用
{
	int count_AroundMine = 0;//统计周围雷的数量

	for (int i = x - 1; i < x + 1; i++) {//通过checkMine函数,用户所输入的坐标传进来然后判断
		for (int j = y - 1; j < y + 1; j++) {
			count_AroundMine += arr[i][j] - '0';//通过计算'1'和'0'的ASCII码值来统计,'1'=49、'0'=48
		}
	}
	return count_AroundMine;//返回雷的数量
}

void checkMine(char mine[MaxSize][MaxSize], char show[MaxSize][MaxSize], int row, int col, int Mine_count) //排雷
{
	int x = 0;//设置坐标
	int y = 0;

	int click = 0;//设置排雷的次数

	while (click < row * col - Mine_count) //当排雷排完了循环就结束
	{
		printf("请输入你要排查的位置: ");
		scanf("%d %d", &x, &y);//输入要排雷的坐标
		printf("\n");

		if (x >= 1 && y >= 1 && x <= row && y <= col) //判断有没有越界
		{
			if (mine[x][y] == '0')//根据mine棋盘判断
			{
				if ((show[x][y] >= '0' && show[x][y] <= '9') || (show[x][y] == ' '))
				{
					printf("该坐标已经排查过,请重新输入:\n");
				}
				else 
				{
					/*int amoun_Mine = get_Mine_quantity(mine, x, y);//没踩到雷,统计周围雷的数量

					show[x][y] = amoun_Mine + '0';//根据传回来雷的数量加上字符0,转化为字符形式*/

					foldPanel(mine, show, x, y);//展开

					PrintPanel(show, row, col);//然后打印出周围有多少雷的数量

					click++;
				}

			}
			if (mine[x][y] == '1')
			{
				printf("小可爱,你踩到雷了呢!\n ");
				printf("\n");
				PrintPanel(mine, row, col);//打印出所有位置的面板
				printf("\n");
				break;
			}
		}
		else
		{
			printf("请输入有效的坐标!\n ");
			printf("\n");
			PrintPanel(show, row, col);
		}

		if (click == row * col - Mine_count)//当排雷排完了游戏就结束
		{
			printf(" 恭喜挑战成功!\n");
			PrintPanel(mine, row, col);//查完成后打印出来
			break;
		}
	}

}

这里的函数分别是初始化棋盘、打印棋盘、设置雷、获取周围雷的数量、展开、排查雷。


3.源文件2 saolei.c

#include "saolei.h"

void menu()//菜单界面
{
	printf("***********************\n");
	printf("*****  1:大学生难度 *****\n");
	printf("*****  2:初中生难度 *****\n");
	printf("*****  3:高中生难度 *****\n");
	printf("*****  0:你走吧     *****\n");
	printf("***********************\n");
}

void test()
{
	int input = 0;//初始化用户输入
	do {
		menu();
		printf(" 请输入: ");
		scanf("%d", &input);//用户输入
		printf("\n");

		switch (input) 
		{
		case 0:
			printf(" 拜了个拜了您嘞! \n");
			break;
		case 1:
			printf("******  扫雷游戏  ******\n");
			game(11, 11, 9, 9, 10);
			break;
		case 2:
			printf("******  扫雷游戏  ******\n");
			game(18, 18, 16, 16, 40);
			break;
		case 3:
			printf("******  扫雷游戏  ******\n");
			game(18, 32, 16, 30, 99);
			break;
		default:
			printf(" 请输入有效数字 \n");
			break;
		}
	} while (input);

}

void game(int Rows, int Cols, int Row, int Col,int Mine_count)//游戏
{
	char mine[MaxSize][MaxSize] = { 0 };//初始化数组,一个用来存放雷的信息
	char show[MaxSize][MaxSize] = { 0 };//初始化数组,一个用来存放排雷的信息

	InitPanel(mine, Rows, Cols, '0');初始化雷的棋盘,实参传给形参,就是这里的括号里面的东西传到函数括号里的东西
	InitPanel(show, Rows, Cols, '*');//初始化玩的棋盘

	setMine(mine, Row, Col, Mine_count);//设置雷

	//PrintPanel(mine, Row, Col);
	PrintPanel(show, Row, Col);//设置完成后打印出来
	

	checkMine(mine, show, Row, Col,Mine_count);//查雷,需要两个棋盘配合起来
		
}

int main()
{ 
	srand((unsigned int)time(NULL));
	test();
	return 0;
}

这里的函数分别是菜单、入口、游戏。


总结

这次的扫雷游戏比上次写的猜数游戏难度大了许多,但是也提升了不少,通过实现这个扫雷游戏能

让你对数组、循环、分支以及函数的理解再往前一步,我也是敲了两遍才慢慢理解,但还是有所欠

缺。如果你们有兴趣的话可以自己动手试试喔。

文章来源:https://blog.csdn.net/N_0050/article/details/135701279
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。