博文目的

相信不少人都学习了c语言的函数,循环,分支那我们就可以写一个控制台的扫雷小游戏来检验自己学得如何。

在做一件事之前我们都要先考虑我们学要做哪些。同样要实现一个扫雷小游戏,我们首先要思考学要做什么。

实现思路

实现思路可以参考以下步骤:

  • 判断玩家进行游戏还是退出。

  • 将扫雷的棋盘确定。

  • 地图初始化。

  • 埋雷 。

  • 玩家扫雷的实现。

  • 对玩家扫的是不是雷判断,周围几颗雷判断

项目创建

在所有开始之前我们先建项目。
​​​​控制台扫雷(C语言实现)-LMLPHP

文件解释

对文件的解释如下:

  • 创一个头文件game.h里面放都要用到的头文件和参数。

  • 在game.c中实现我们的游戏逻辑。

  • 在扫雷.c中把游戏串起来。

具体实现

具体实现可以参考如下思路:

判断玩家进行游戏还是退出

使用一个menu函数将作为菜单打印。
在主函数中使用do-while循环来判断用户是玩还是退出。

void menu()
{
	printf("------------------------------\n");
	printf("----------1.play--------------\n");
	printf("----------0.exit--------------\n");
	printf("------------------------------\n");
}
int main()
{
	int a;
	do
	{
		menu();
		scanf("%d",&a);
	} while(a);
	return 0;
}

扫雷棋盘的确定

首先会先想到创建一个9 * 9的数组来表示棋盘。
控制台扫雷(C语言实现)-LMLPHP
但是我们就要考虑到判断周围雷个数时的判断,只创建9*9的棋盘,那在边界上的雷就不好判断周围有几颗雷,要判断就需要在写其他的判断方法不能与中间的判断方法统一了。

所以扩大一圈创建11 * 11的地图。
控制台扫雷(C语言实现)-LMLPHP

在头文件中使用宏定义出地图的长度和能访问的长度。

#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2

地图初始化

我们将代表地图的数组有雷的设为1,无雷的设为0。

想到这我们又会考虑到 什么代表雷呢,我们就以字符0代表没雷1代表有雷;
难道我们在控制台输出0 1吗,那还玩个屁啊。
因此我们应该还要创建一个地图来输出。

在扫雷.c文件中定义出两个数组,在game.c文件中写数组初始化函数。

//扫雷.c中封装函数
void game()
{
	char map1[ROWS][COLS];
	char map2[ROWS][COLS];
	init(map1, '0');
	init(map2, '*');
}
//game.c中初始化棋盘函数
void init(char a[ROWS][COLS], char ch)
{
	for (int i = 0; i < ROWS; i++)
	{
		for (int j = 0; j < COLS; j++)
		{
			a[i][j] = ch;
		}
	}
}

埋雷

我们要埋雷而且还要是随机的,那我们就要用到随机数生成函数,
如果我们像这样布置雷,随机数生成后会不会相等,让同一位置布置多个雷了?
所以我们要判断生成的是否已经埋雷。

//埋雷函数
void LayMine(char map1[ROWS][COLS])
{
	int count = MINE_NUMBER;
	srand((unsigned int)time(NULL));
	while(count)
	{ 
		int x = rand() % ROW + 1;
		int y = rand() % COL + 1;
		if (map1[x][y] == '0')
		{
			map1[x][y] = '1';
			count--;
		}
	}
}

玩家扫雷的实现

玩家在控制台上扫雷是通过坐标来输入,那我们打印棋盘时就去提供每个坐标,不然输入时要玩家自己一个一个数坐标,本来就玩的不爽,就更不爽了。

/打印棋盘
void Print(char map[ROWS][COLS])
{
	printf("=====扫雷===========\n");
	for (int i = 0; i <= COL; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (int i = 1; i <= ROW; i++)
	{
		printf("%d ", i);
		for (int j = 1; j <= COL; j++)
		{
			printf("%c ", map[i][j]);
		}
		printf("\n");
	}
}

雷判断函数

对玩家扫的是不是雷判断,周围几颗雷判断 。

void FindMine(char map1[ROWS][COLS], char map2[ROWS][COLS])
{
	int count = 0;//记扫了几个雷
	while (count < MINE_NUMBER)
	{
		int x = 0, y = 0;
		printf("请输入需要排查的坐标 ");
		scanf("%d%d", & x, & y);
		if ((x >= 1 && x <= ROW) && (y >= 1 && y <= COL))//确保用户输入正确坐标
		{
			if (map1[x][y] == '1')
			{
				printf("踩雷结束\n");
				Print(map1);
				break;
			}
			else
			{
				count--;
				int num = 0;
				for (int i = x - 1; i <= x + 1; i++)
				{
					for (int j = y - 1; j <= y + 1; j++)
					{
						if (map1[i][j] == '1')
						{
							num++;
						}
					}
				}
				map2[x][y] = num + '0';
				Print(map2);
			}

		}
		else
		{
			printf("错误输入\n");
		}
	}
	if (count == MINE_NUMBER)
	{
		printf("过关牛逼\n");
	}
}

源码

源码呈上:

game.c

game.c文件下的代码

# define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"

//初始化棋盘函数
void init(char a[ROWS][COLS], char ch)
{
	for (int i = 0; i < ROWS; i++)
	{
		for (int j = 0; j < COLS; j++)
		{
			a[i][j] = ch;
		}
	}
}

//埋雷函数
void LayMine(char map1[ROWS][COLS])
{
	int count = MINE_NUMBER;
	srand((unsigned int)time(NULL));
	while(count)
	{ 
		int x = rand() % ROW + 1;
		int y = rand() % COL + 1;
		if (map1[x][y] == '0')
		{
			map1[x][y] = '1';
			count--;
		}
	}
}

//打印棋盘
void Print(char map[ROWS][COLS])
{
	printf("=====扫雷===========\n");
	for (int i = 0; i <= COL; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (int i = 1; i <= ROW; i++)
	{
		printf("%d ", i);
		for (int j = 1; j <= COL; j++)
		{
			printf("%c ", map[i][j]);
		}
		printf("\n");
	}
}
void FindMine(char map1[ROWS][COLS], char map2[ROWS][COLS])
{
	int count = 0;//记扫了几个雷
	while (count < MINE_NUMBER)
	{
		int x = 0, y = 0;
		printf("请输入需要排查的坐标 ");
		scanf("%d%d", & x, & y);
		if ((x >= 1 && x <= ROW) && (y >= 1 && y <= COL))//确保用户输入正确坐标
		{
			if (map1[x][y] == '1')
			{
				printf("踩雷结束\n");
				Print(map1);
				break;
			}
			else
			{
				count--;
				int num = 0;
				for (int i = x - 1; i <= x + 1; i++)
				{
					for (int j = y - 1; j <= y + 1; j++)
					{
						if (map1[i][j] == '1')
						{
							num++;
						}
					}
				}
				map2[x][y] = num + '0';
				Print(map2);
			}

		}
		else
		{
			printf("错误输入\n");
		}
	}
	if (count == MINE_NUMBER)
	{
		printf("过关牛逼\n");
	}
}

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 MINE_NUMBER 10

void init(char a[ROWS][COLS], char ch);
void LayMine(char map1[ROWS][COLS]);
void Print(char map[ROWS][COLS]);
void FindMine(char map1[ROWS][COLS], char map2[ROWS][COLS]);

扫雷.c

扫雷.c文件下的代码:

# define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
	printf("------------------------------\n");
	printf("----------1.play--------------\n");
	printf("----------0.exit--------------\n");
	printf("------------------------------\n");
}

void game()
{
	char map1[ROWS][COLS];
	char map2[ROWS][COLS];
	init(map1, '0');
	init(map2, '*');
	LayMine(map1);
	//Print(map1);
	Print(map2);
	FindMine(map1, map2);
}
int main()
{
	int a;

	do
	{
		menu();
		scanf("%d", &a);
		switch (a)
		{
			case 1:
				game();
				break;
			case 0:
				printf("exit\n");
				break;
			default:
				printf("错误输入\n");
				break;
		}
	} while (a);

	return 0;
}
07-01 19:04