【C语言入门】扫雷游戏

本文介绍了如何使用C语言实现一个简单的扫雷游戏,通过模块化设计,包括main函数、菜单、游戏主体、棋盘初始化、雷布置、打印棋盘和查找雷等功能,展示了代码组织和优化的重要原则。
摘要由CSDN通过智能技术生成

引言:

        本篇文章来介绍学习C语言中的一个小项目“扫雷游戏”,该项目代码量在200行左右,同时该篇文章也是专题<C语言小游戏>中的一篇,接下来就请跟着笔者的思路来一步一步完成这个项目。

正文:

项目躯干:

        首先,一个程序的诞生一定有main函数,所以我们要先写出一个main函数

int main()
{

return 0;
}

而其他代码一定是在main函数中被调用或运行的。

        有了main函数,我们就要思考这个项目分为哪几部分?可以想到它需要一个菜单,我们接着向下写

void Menu()//打印菜单
{
	printf("* * * * * * * * * * * * *\n");
	printf("* * * 1 开 始 游 戏 * * *\n");
	printf("* * * 0 结 束 游 戏 * * *\n");
	printf("* * * * * * * * * * * * *\n");
}

这时我们给出了菜单,就要用户进行选择了,同时对用户做出的选择作出相应反应

void Test()
{
	int choose = 0;
	do
	{
		Menu();
		printf("请输入你的选择==>");
		scanf("%d", &choose);
		system("cls");
		switch (choose)
		{
		case 1:
			Game();
			break;
		case 0:
			printf("正在退出游戏\n");
			break;
		default:
			printf("识别错误,请重新输入\n");
		}
	} while (choose);
}

为了使用户玩的更加方便,这里笔者加上了一个do-while循环,同时还有一个清屏指令(system("cls");),该指令存在于<Windows.h>中,可以使页面使用时更加人性化。这是可以看到笔者还卖了一个坑:Game();这就是项目的核心,也可以说是灵魂。

项目灵魂:

接下来就是重磅的Game();函数,首先就要创建一个Game();函数

void Game()//游戏主体
{
}

当然有了它我们还要往里面填充东西,这时就要想到,扫雷一定要有棋盘吧,这是我们就要创建两个棋盘,一个给用户展示,另一个存放雷,用来判断用户排查的是不是雷

char Mine[ROW][COL] = { 0 };//放雷数组
char Show[ROW][COL] = { 0 };//展示数组

这里用到了ROW,COL两个常量,这两个常量是笔者事先定义好的不止这两个如下

#define row 9//行
#define col 9//列
#define ROW row+2
#define COL col+2
#define Easy 10//雷数

这些常量在下文都会用到,继续上文问题,有了棋盘还要做相应的初始化,通常我们会进行一个数组一个数组的进行初始化,可这样在无形中就增大了项目的代码量,所以这里笔者将其单独写成一个函数进行调用

void Init(char arr[ROW][COL], int Row, int Col, char c)//初始化数组
{

	for (int i = 0; i < Row; i++)
	{
		for (int j = 0; j < Col; j++)
		{
			arr[i][j] = c;
		}
	}
}

这时调用语句就应写成这样

Init(Mine, ROW, COL, '0');//数组初始化
Init(Show, ROW, COL, '*');

虽然棋盘被初始化了但是我们还是没有将雷布置进去,所以接下来就是布置雷

void MineDep(char arr[ROW][COL], int Row, int Col)//布置雷
{
	srand((unsigned int)time(NULL));
	int count = Easy;
	while (count)
	{
		int x = rand() % Row + 1;
		int y = rand() % Row + 1;
		if (arr[x][y] == '0')
		{
			arr[x][y] = '1';
			count--;
		}
	}
}

这里就是用了srand对rand进行了处理保证了数字的随机性,而count作为while函数的条件也保证了雷的个数,同时if函数使雷的位置不会重复。

我们布置好了雷,下一步就是让用户开始扫雷,而扫雷就要给用户提供一个棋盘供其参考,因为雷要一点点扫,所以棋盘也不止一次被打印,所以这里还是将其写成一个函数

void Print(char arr[ROW][COL], int Row, int Col)//打印棋盘
{
	printf("- - - 扫 雷 游 戏 - - -\n");
	for (int i = 0; i <= Col; i++)
	{
		printf("%2d", i);
	}
	printf("\n");
	for (int i = 1; i <= Row; i++)
	{
		printf("%2d", i);
		for (int j = 1; j <= Col; j++)
		{
			printf("%2c", arr[i][j]);
		}
		printf("\n");
	}
	printf("- - - - - - - - - - - -\n");

}

当然该函数中笔者对棋盘做了一点美化,有了这个函数之后就是让用户一次又一次的去排查雷,直到棋盘上只剩下雷,或踩到雷时结束游戏

void Find(char arr1[ROW][COL], char arr2[ROW][COL], int Row, int Col)//寻找雷
{
	int x = 0, y = 0;
	int temp = 0;
	while (1) {
		Print(arr2, row, col);
		printf("输入要排查的坐标==>");
		scanf("%d %d", &x, &y);
		system("cls");
		if ((x > 0 && x < 10) && (y > 0 && y < 10))
		{
			if (arr1[x][y] == '1')
			{
				printf("你踩到地雷了!!!\n地雷排布图\n");
				Print(arr1, row, col);
				break;
			}
			else
			{
				int sum = 0;
				for (int i = x - 1; i <= x + 1; i++)
				{
					for (int j = y - 1; j <= y + 1; j++)
					{
						sum += arr1[i][j] - '0';
					}
				}
				arr2[x][y] = '0' + sum;
				temp++;
			}
		}
		else
		{
			printf("坐标不存在,请重新输入\n");
		}
		if (temp == row * col - Easy)
		{
			printf("扫雷成功!!!\n");
			break;
		}
	}
}

这里还有一个小块就是对于排查后的坐标显示其周围雷的个数

int sum = 0;
for (int i = x - 1; i <= x + 1; i++)
{
				for (int j = y - 1; j <= y + 1; j++)
				{
					sum += arr1[i][j] - '0';
				}
}
arr2[x][y] = '0' + sum;

这时整个项目能用到的代码大多都在这了,可是可以发现这些代码都是一块一块的,并不连贯,就像一块块灵魂碎片,接下来还有一份工作就是将这些碎片拼接起来

整理拼接:

<Game.h>

首先可以看我们定义了多个常量、函数、同时也要调用多个头文件,所以这里笔者就自己定义了一个头文件来存放这些东西命名为Game.h

#define row 9
#define col 9
#define ROW row+2
#define COL col+2
#define Easy 10

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


void Menu();//菜单
void Test();
void Game();
void Init(char arr[ROW][COL], int Row, int Col, char c);//棋盘初始化
void MineDep(char arr[ROW][COL], int Row, int Col);//布置雷
void Print(char arr[ROW][COL], int Row, int Col);//打印棋盘
void Find(char arr1[ROW][COL], char arr2[ROW][COL], int Row, int Col);//寻找雷

<main.c>

        这个函数就没存放多少东西

#include"Game.h"

int  main()
{
	
	Test();
	return 0;
}

void Test()
{
	int choose = 0;
	do
	{
		Menu();
		printf("请输入你的选择==>");
		scanf("%d", &choose);
		system("cls");
		switch (choose)
		{
		case 1:
			Game();
			break;
		case 0:
			printf("正在退出游戏\n");
			break;
		default:
			printf("识别错误,请重新输入\n");
		}
	} while (choose);
}

<game.c>

        这个文件是重量级的包含大量函数

#include"Game.h"

void Menu()//打印菜单
{
	printf("* * * * * * * * * * * * *\n");
	printf("* * * 1 开 始 游 戏 * * *\n");
	printf("* * * 0 结 束 游 戏 * * *\n");
	printf("* * * * * * * * * * * * *\n");
}

void Game()//游戏主体
{
	char Mine[ROW][COL] = { 0 };//创建数组
	char Show[ROW][COL] = { 0 };

	Init(Mine, ROW, COL, '0');//数组初始化
	Init(Show, ROW, COL, '*');

	MineDep(Mine, row, col);//布置雷

	Find(Mine, Show, ROW, COL);//寻找雷


}

void Init(char arr[ROW][COL], int Row, int Col, char c)//初始化数组
{

	for (int i = 0; i < Row; i++)
	{
		for (int j = 0; j < Col; j++)
		{
			arr[i][j] = c;
		}
	}
}

void MineDep(char arr[ROW][COL], int Row, int Col)//布置雷
{
	srand((unsigned int)time(NULL));
	int count = Easy;
	while (count)
	{
		int x = rand() % Row + 1;
		int y = rand() % Row + 1;
		if (arr[x][y] == '0')
		{
			arr[x][y] = '1';
			count--;
		}
	}
}

void Print(char arr[ROW][COL], int Row, int Col)//打印棋盘
{
	printf("- - - 扫 雷 游 戏 - - -\n");
	for (int i = 0; i <= Col; i++)
	{
		printf("%2d", i);
	}
	printf("\n");
	for (int i = 1; i <= Row; i++)
	{
		printf("%2d", i);
		for (int j = 1; j <= Col; j++)
		{
			printf("%2c", arr[i][j]);
		}
		printf("\n");
	}
	printf("- - - - - - - - - - - -\n");

}

void Find(char arr1[ROW][COL], char arr2[ROW][COL], int Row, int Col)//寻找雷
{
	int x = 0, y = 0;
	int temp = 0;
	while (1) {
		Print(arr2, row, col);
		printf("输入要排查的坐标==>");
		scanf("%d %d", &x, &y);
		system("cls");
		if ((x > 0 && x < 10) && (y > 0 && y < 10))
		{
			if (arr1[x][y] == '1')
			{
				printf("你踩到地雷了!!!\n地雷排布图\n");
				Print(arr1, row, col);
				break;
			}
			else
			{
				int sum = 0;
				for (int i = x - 1; i <= x + 1; i++)
				{
					for (int j = y - 1; j <= y + 1; j++)
					{
						sum += arr1[i][j] - '0';
					}
				}
				arr2[x][y] = '0' + sum;
				temp++;
			}
		}
		else
		{
			printf("坐标不存在,请重新输入\n");
		}
		if (temp == row * col - Easy)
		{
			printf("扫雷成功!!!\n");
			break;
		}
	}
}

至此代码的整合拼接就结束了,同时正文也告一段落

演示:

扫雷演示

总结: 

        为什么要写那么多的函数呢?因为代码要讲求高内聚,底耦合;同时减少代码量,减轻自己负担,提高代码质量,同时也提高代码的可读性。

        最后,该项目就到此告一段落,如果各位读者对文章有什么看法,或问题欢迎留言。

        

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

衫裤_跑路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值