C语言制作扫雷游戏

1.先制作一个菜单,要求循环可玩。第一次进入就需要选择,所以用do while语句(进入游戏的函数先放着)

void menu()
{
	printf("**************************\n");
	printf("**********1.play**********\n");
	printf("**********0.exit**********\n");
	printf("**************************\n");
}

int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请输入数字:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			break;
		default:
			printf("请输入正确的值!!!\n");
			break;
		}
	} while (input);
	return 0;
}

2.写出游戏函数里的内容

先定下来有多少行和列以及地雷个数,#define定义固定

需要注意的是:1.我们要创造两个空间,一个是藏地雷的数组,另一个是战场具体情况的数组 2.

#define ROW 9
#define COL 9
#define ROWS (ROW+2)
#define COLS (COL+2)
#define MINE 10

2.1得到两个数组,一个是雷区,一个是战场

char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };

2.2给两个数组赋值,给一个函数,实现出雷区(0);战场(*)【因为雷区跟战场是全赋值,所以就把他们需要赋值成的数也传入函数内部方便设计】

get_board(mine, ROWS, COLS, '0');
get_board(show, ROWS, COLS, '*');
void get_board(char board[ROWS][COLS], int row, int col, char p)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < row; j++)
		{
			board[i][j] = p;
		}
	}
}

2.3打印雷区和战场方便下一步调试,所以做一个打印的函数:需要从1开始到设定的行列结束,并且为了方便别人看,我们还需要写出对应坐标(前面用//注释是为了方便看)

//print_board(mine, ROW, COL);
//print_board(show, ROW, COL);
void print_board(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("-------------------\n");
	for (i = 0; j <= row; j++)
	{
		printf("%d ", j);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		for (j = 1; j <= row; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("-------------------\n");
}

2.4随机生成炸弹,需要用到rand()函数对9取模,得到0~8,然后加一范围向上一位,并且写给打印函数,以观察是不是生成正确

get_mine(mine, ROW, COL);
//print_board(mine, ROW, COL);
void get_mine(char board[ROWS][COLS], int row, int col)
{
	int count = 1;
	while (count <= MINE)
	{
		int i = rand() % ROW + 1;
		int j = rand() % COL + 1;
		if (board[i][j] == '0')
		{
			board[i][j] = '1';
		}
		else
			continue;
		count++;
	}
}

需要在main函数里加入srand函数

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

2.5.做个循环,判断游戏进行状况(需要做到一个标记,一个选择地址,判断输赢)

2.5.1外面一层循环做标记,区域判断和输赢判断先不写

void choice()
{
	printf("**********1.排  雷**********\n");
	printf("**********2.标记雷**********\n");
}
while (1)
	{
		int ret = 0;
		print_board(show, ROW, COL);
		choice();
		int cho = 1;
		scanf("%d", &cho);
		while (cho == 1)
		{
            //
			//选择区域判断有没有炸弹的模块	
            //
		}
		while (cho == 2)
		{
			//标记雷函数guess_mine()
			guess_mine(show, ROW, COL);
			print_board(show, ROW, COL);
			choice();
			cho = 0;
			scanf("%d", &cho);
		}
		if (/*输赢的条件*/)
		{
			break;
		}
	}
void guess_mine(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("请输入坐标\n");
	scanf("%d %d", &i, &j);
	if (board[i][j] == '*')
	{
		board[i][j] = '#';
	}
	else if (board[i][j] == '#')
	{
		board[i][j] = '*';
	}
}

 2.5.2区域判断和跳出区域判断的循环

while (cho == 1)
	{
		print_board(show, ROW, COL);
		int i = 0; int j = 0;
		printf("请输入坐标\n");
		scanf("%d %d", &i, &j);
		//坐标在范围内的
		if (i >= 1 && i <= 9 && j >= 1 && j <= 9)
		{
			//1.不是地雷且没探索过的
			if (mine[i][j] == '0' && show[i][j] == '*')
			{
				//1)下面是点开的格子周围地雷分布
				get_blank(mine, show, i, j);
				//2.做给函数判断是否赢了
				num = if_win(show, ROW, COL);
				if (num == MINE)
				{
					printf("你赢了\n");
					print_board(show, ROW, COL);
					ret = 1;
					break;
				}
			}
			//1.2.不是地雷但是重复探索的
			else if (mine[i][j] == '0' && show[i][j] != '*')
			{
				printf("这个坐标你已经探索过了,请重新输入其他未探索目标!\n");
			}
			//1.3.踩到地雷的
			else
			{
				printf("你踩到地雷了...\n");
				printf("以下是地雷的分布图\n");
				print_board(mine, ROW, COL);
				ret = 1;
				break;
			}
		}
		//2.在范围外的
		else
		{
			printf("请输入正确的坐标!\n");
		}
		print_board(show, ROW, COL);
		choice();
		cho = 0;
		scanf("%d", &cho);
	}

以下是开辟空格,以及如果选择的区域没有雷,向四周扩散的函数 

void get_blank(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	//1.最重要的一步就是获取格子周围的地雷数目
	show[x][y] = mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] + mine[x][y - 1] +
		mine[x][y + 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] - 8 * '0' + '0';
	//2.扩散空白部分
	if ((show[x][y] == '0') && (x - 1 >= 1) && (mine[x - 1][y] != 1) && show[x - 1][y] == '*')
	{
		get_blank(mine, show, x - 1, y);
	}
	if ((show[x][y] == '0') && (x + 1 <= ROW) && (mine[x + 1][y] != 1) && show[x + 1][y] == '*')
	{
		get_blank(mine, show, x + 1, y);
	}
	if ((show[x][y] == '0') && (y - 1 >= 1) && (mine[x][y - 1] != 1) && show[x][y - 1] == '*')
	{
		get_blank(mine, show, x, y - 1);
	}
	if ((show[x][y] == '0') && (y + 1 <= COL) && (mine[x - 1][y] != 1) && show[x][y + 1] == '*')
	{
		get_blank(mine, show, x, y + 1);
	}
}

再是判断输赢的函数,赢的条件就是剩下的*跟雷的个数一致

int if_win(char show[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	int count = 0;
	for (i = 1; i <= row; i++)
	{
		for (j = 1; j <= col; j++)
		{
			if (show[i][j] == '*')
			{
				count++;
			}
		}
	}
	return count;
}

 最后整体的实现是这样的

while (1)
	{
		int ret = 0;
		print_board(show, ROW, COL);
		choice();
		int cho = 1;
		scanf("%d", &cho);
		while (cho == 1)
		{
			print_board(show, ROW, COL);
			int i = 0; int j = 0;
			printf("请输入坐标\n");
			scanf("%d %d", &i, &j);
			//5.1.坐标在范围内的
			if (i >= 1 && i <= 9 && j >= 1 && j <= 9)
			{
				//5.1.1.不是地雷且没探索过的
				if (mine[i][j] == '0' && show[i][j] == '*')
				{
					//1)下面是点开的格子周围地雷分布
					get_blank(mine, show, i, j);
					//2).做给函数判断是否赢了
					num = if_win(show, ROW, COL);
					if (num == MINE)
					{
						printf("你赢了\n");
						print_board(show, ROW, COL);
						ret = 1;
						break;
					}
				}
				//5.1.2.不是地雷但是重复探索的
				else if (mine[i][j] == '0' && show[i][j] != '*')
				{
					printf("这个坐标你已经探索过了,请重新输入其他未探索目标!\n");
				}
				//5.1.3.踩到地雷的
				else
				{
					printf("你踩到地雷了...\n");
					printf("以下是地雷的分布图\n");
					print_board(mine, ROW, COL);
					ret = 1;
					break;
				}
			}
			//5.2.在范围外的
			else
			{
				printf("请输入正确的坐标!\n");
			}
			print_board(show, ROW, COL);
			choice();
			cho = 0;
			scanf("%d", &cho);
			
		}
		while (cho == 2)
		{
			//标记雷函数guess_mine()
			guess_mine(show, ROW, COL);
			print_board(show, ROW, COL);
			choice();
			cho = 0;
			scanf("%d", &cho);
		}
		if (ret == 1)
		{
			break;
		}
	}

最后是我写的代码,其实还有挺多漏洞跟赘余的,不过我有好多想法有点难实现,以后再试试

test.c文件
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"

void menu()
{
	printf("**************************\n");
	printf("**********1.play**********\n");
	printf("**********0.exit**********\n");
	printf("**************************\n");
}
//6.标记雷
void choice()
{
	printf("**********1.排  雷**********\n");
	printf("**********2.标记雷**********\n");
}

void game()
{
	//1.得到两个数组,一个是雷区,一个是战场
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
	//2.给两个数组赋值,雷区(0);战场(*)
	get_board(mine, ROWS, COLS, '0');
	get_board(show, ROWS, COLS, '*');
	//3.打印雷区和战场方便下一步调试
	//print_board(mine, ROW, COL);
	//print_board(show, ROW, COL);
	//4.随机生成炸弹;
	get_mine(mine, ROW, COL);
	//print_board(mine, ROW, COL);
	//5.做个循环,判断游戏进行状况
	int num = ROW * COL;
	while (1)
	{
		int ret = 0;
		print_board(show, ROW, COL);
		choice();
		int cho = 1;
		scanf("%d", &cho);
		while (cho == 1)
		{
			print_board(show, ROW, COL);
			int i = 0; int j = 0;
			printf("请输入坐标\n");
			scanf("%d %d", &i, &j);
			//5.1.坐标在范围内的
			if (i >= 1 && i <= 9 && j >= 1 && j <= 9)
			{
				//5.1.1.不是地雷且没探索过的
				if (mine[i][j] == '0' && show[i][j] == '*')
				{
					//1)下面是点开的格子周围地雷分布
					get_blank(mine, show, i, j);
					//2).做给函数判断是否赢了
					num = if_win(show, ROW, COL);
					if (num == MINE)
					{
						printf("你赢了\n");
						print_board(show, ROW, COL);
						ret = 1;
						break;
					}
				}
				//5.1.2.不是地雷但是重复探索的
				else if (mine[i][j] == '0' && show[i][j] != '*')
				{
					printf("这个坐标你已经探索过了,请重新输入其他未探索目标!\n");
				}
				//5.1.3.踩到地雷的
				else
				{
					printf("你踩到地雷了...\n");
					printf("以下是地雷的分布图\n");
					print_board(mine, ROW, COL);
					ret = 1;
					break;
				}
			}
			//5.2.在范围外的
			else
			{
				printf("请输入正确的坐标!\n");
			}
			print_board(show, ROW, COL);
			choice();
			cho = 0;
			scanf("%d", &cho);
			
		}
		while (cho == 2)
		{
			//标记雷函数guess_mine()
			guess_mine(show, ROW, COL);
			print_board(show, ROW, COL);
			choice();
			cho = 0;
			scanf("%d", &cho);
		}
		if (ret == 1)
		{
			break;
		}
	}

}

int main()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();
		printf("请输入数字:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			break;
		default:
			printf("请输入正确的值!!!\n");
			break;
		}
	} while (input);
	return 0;
}
game.c文件
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"

void get_board(char board[ROWS][COLS], int row, int col, char p)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < row; j++)
		{
			board[i][j] = p;
		}
	}
}

void print_board(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("-------------------\n");
	for (i = 0; j <= row; j++)
	{
		printf("%d ", j);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		for (j = 1; j <= row; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("-------------------\n");
}

void get_mine(char board[ROWS][COLS], int row, int col)
{
	int count = 1;
	while (count <= MINE)
	{
		int i = rand() % ROW + 1;
		int j = rand() % COL + 1;
		if (board[i][j] == '0')
		{
			board[i][j] = '1';
		}
		else
			continue;
		count++;
	}
}

void get_blank(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	//1.最重要的一步就是获取格子周围的地雷数目
	show[x][y] = mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] + mine[x][y - 1] +
		mine[x][y + 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] - 8 * '0' + '0';
	//2.扩散空白部分
	if ((show[x][y] == '0') && (x - 1 >= 1) && (mine[x - 1][y] != 1) && show[x - 1][y] == '*')
	{
		get_blank(mine, show, x - 1, y);
	}
	if ((show[x][y] == '0') && (x + 1 <= ROW) && (mine[x + 1][y] != 1) && show[x + 1][y] == '*')
	{
		get_blank(mine, show, x + 1, y);
	}
	if ((show[x][y] == '0') && (y - 1 >= 1) && (mine[x][y - 1] != 1) && show[x][y - 1] == '*')
	{
		get_blank(mine, show, x, y - 1);
	}
	if ((show[x][y] == '0') && (y + 1 <= COL) && (mine[x - 1][y] != 1) && show[x][y + 1] == '*')
	{
		get_blank(mine, show, x, y + 1);
	}
}

int if_win(char show[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	int count = 0;
	for (i = 1; i <= row; i++)
	{
		for (j = 1; j <= col; j++)
		{
			if (show[i][j] == '*')
			{
				count++;
			}
		}
	}
	return count;
}

void guess_mine(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("请输入坐标\n");
	scanf("%d %d", &i, &j);
	if (board[i][j] == '*')
	{
		board[i][j] = '#';
	}
	else if (board[i][j] == '#')
	{
		board[i][j] = '*';
	}
}
game.h文件
#pragma once
#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 10

void get_board(char board[ROWS][COLS], int row, int col, char p);
void print_board(char board[ROWS][COLS], int row, int col);
void get_mine(char board[ROWS][COLS], int row, int col);
void get_blank(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);
int if_win(char show[ROWS][COLS], int row, int col);
void guess_mine(char board[ROWS][COLS], int row, int col);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

灼榆

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

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

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

打赏作者

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

抵扣说明:

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

余额充值