扫雷(升级版)

一、实现思路

  1. 创建一个与玩家交互的菜单
  2. 利用二维数组创建两个棋盘,分别为mine(雷盘)和show盘,mine盘不可见,而show盘可见
  3. 随机在雷盘上布置雷
  4. 以输入坐标的方式扫雷
  5. 选择标记雷区
  6. 选择取消对雷的标记
  7. 判断游戏是否结束

二、实现过程

1、创建菜单

选择 1 进行游戏
选择 0 退出游戏

2、创建、初始化以及展示mine盘和show盘

用宏定义的方法定义棋盘的行和列,方便后期维护

#define ROW 9
#define COL 9

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

用二维数组的方式定义两个盘

	char mine[ROWS][COLS] = { 0 };//存放布置好的雷的信息
	char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息

利用初始化函数对两个盘进行初始化,mine盘全部初始化为 ‘0’ ,show盘全部初始化为 ‘*’

	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');

初始化函数

//初始化
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] =set;
		}
	}
}

展示

void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("----—扫雷游戏—----\n");
	for (j = 0; j <= col; j++)
	{
		printf("%d ", j);
	}
	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("----—扫雷游戏—----\n");

}

效果

3、随机布雷

用宏定义的方式设置要布置的雷数,方便随时修改

#define EASY_COUNT 10

利用rand和srand函数以及时间戳生成随机雷

	//设置随机数生成起点
	srand((unsigned int)time(NULL));
void SetMine(char board[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;//1——9
		int y = rand() % col + 1;//1——9

		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}

3、 玩家排雷


玩家选择扫雷,通过输入坐标进行排雷

4、统计所选位置周围八个位置中雷的个数,并打印在show盘上

//获取四周的雷数
int get_mine_count(char board[ROWS][COLS], int x, int y)
{
//法一
	/*
	return board[x - 1][y] +
	   board[x - 1][y - 1] +
	   board[x][y - 1] +
	   board[x + 1][y - 1] +
	   board[x + 1][y] +
	   board[x + 1][y + 1] + 
	   board[x][y + 1] + 
	   board[x - 1][y + 1] - 8 * '0';
	*/
	//法2
	int count = 0;
	for (int i = -1; i <= 1; i++)
	{
		for (int j = -1; j <= 1; j++)
		{
			if (board[x + i][y + j] == '1')
			{
				count++;
			}
		}
	}
	return count ;
}

5、用递归的方法拓展周围不是雷的区域

用递归的方法拓展排雷

void broad(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	//判断坐标是否越界
	if (x == 0 || y == 0 || x == ROWS - 1 || y == COLS - 1)
		return;
	//判断是否已经排查
	if (show[x][y] != '*')
		return;
	int count = get_mine_count(mine, x, y);
	if (count > 0)
	{
		show[x][y] = count + '0';
		return;
	}
	//拓展
	if (count == 0)
	{
		show[x][y] = '0';
		broad(mine, show, x - 1, y);
		broad(mine, show, x - 1, y - 1);
		broad(mine, show, x, y - 1);
		broad(mine, show, x + 1, y - 1);
		broad(mine, show, x + 1, y);
		broad(mine, show, x + 1, y + 1);
		broad(mine, show, x, y + 1);
		broad(mine, show, x - 1, y + 1);
	}
}

6、对认为是雷的位置用 !进行标记

int Flagmine(char show[ROWS][COLS], int row, int col,int flag_count)
{
	int x = 0;
	int y = 0;

	if (flag_count == EASY_COUNT)
	{
		printf("标记的雷数与实际雷数相等,无法再标记\n");
		return;
	}
	printf("请输入你要标记的位置:\n");
	scanf_s("%d %d", &x, &y);
	if (x > 0 && x <= row && y > 0 && y <= col)
	{
		//判断该位置是否被排除
		if (show[x][y] == '*')
		{
			show[x][y] = '!';
			flag_count++;
		}
		else
		{
			printf("该位置已经排除,无法再标记\n");
		}
	}
	else
	{
		printf("输入坐标非法,请重新输入:\n");

	}
	return flag_count;

}

7、取消标记

int CancelFlag(char show[ROWS][COLS], int row, int col, int flag_count)
{
	int x = 0;
	int y = 0;
	printf("请输入你要取消标记的位置:\n");
	scanf_s("%d %d", &x, &y);
	if (x > 0 && x <= row && y > 0 && y <= col)
	{
		//判断该位置是否被标记
		if (show[x][y] == '!')
		{
			show[x][y] = '*';
			flag_count--;
		}
		else
		{
			printf("该位置未被标记过,无法取消标记!\n");
		}
	}
	else
	{
		printf("输入坐标非法,请重新输入:\n");

	}
	return flag_count;

}

8、判断游戏是否结束

  1. 若踩雷,则游戏失败,游戏结束

  2. 排除所有的雷,获得胜利,游戏结束

遍历棋盘,如果show盘中剩下的 ‘*’ 和 ‘!’ 数量的和加起来对于雷的数量,则排雷成功

//遍历雷盘
int TravelBoard(char show[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	int win = 0;
	for (i = 1; i <= row; i++)
	{
		for (j = 1; j <= col; j++)
		{
			if (show[i][j] == '*' || show[i][j] == '!')
			{
				win++;
			}
		}
	}
	return win;
}
	if (win == EASY_COUNT)
	{
		printf("恭喜你,排雷成功!\n");
		DisplayBoard(mine, ROW, COL);

	}

三、代码展示

1、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 EASY_COUNT 10
//初始化
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//展示
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//设置雷
void SetMine(char board[ROWS][COLS], int row, int col);
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
//拓展周围不是雷的区域
void broad(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);
//标记
int Flagmine(char show[ROWS][COLS], int row, int col, int flag_count);
//取消标记
int CancelFlag(char show[ROWS][COLS], int row, int col, int flag_count);


2、game.c

#include"game.h"

//菜单2
void menu2()
{
	printf("**************************\n");
	printf("*******	1.扫    雷 *******\n");
	printf("*******	2.标    记 *******\n");
	printf("*******	3.取消标记 *******\n");
	printf("**************************\n");
}
//初始化
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] =set;
		}
	}
}
//展示
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("----—扫雷游戏—----\n");
	for (j = 0; j <= col; j++)
	{
		printf("%d ", j);
	}
	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("----—扫雷游戏—----\n");

}
//设置雷的位置
void SetMine(char board[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;//1——9
		int y = rand() % col + 1;//1——9

		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}

//遍历雷盘
int TravelBoard(char show[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	int win = 0;
	for (i = 1; i <= row; i++)
	{
		for (j = 1; j <= col; j++)
		{
			if (show[i][j] == '*' || show[i][j] == '!')
			{
				win++;
			}
		}
	}
	return win;
}

//获取四周的雷数
int get_mine_count(char board[ROWS][COLS], int x, int y)
{
	//return board[x - 1][y] +
	//	   board[x - 1][y - 1] +
	//	   board[x][y - 1] +
	//	   board[x + 1][y - 1] +
	//	   board[x + 1][y] +
	//	   board[x + 1][y + 1] + 
	//	   board[x][y + 1] + 
	//	   board[x - 1][y + 1] - 8 * '0';
	int count = 0;
	for (int i = -1; i <= 1; i++)
	{
		for (int j = -1; j <= 1; j++)
		{
			if (board[x + i][y + j] == '1')
			{
				count++;
			}
		}
	}
	return count ;
}

//拓展周围不是雷的区域
void broad(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	//判断坐标是否越界
	if (x == 0 || y == 0 || x == ROWS - 1 || y == COLS - 1)
		return;
	//判断是否已经排查
	if (show[x][y] != '*')
		return;
	int count = get_mine_count(mine, x, y);
	if (count > 0)
	{
		show[x][y] = count + '0';
		return;
	}
	//拓展
	if (count == 0)
	{
		show[x][y] = '0';
		broad(mine, show, x - 1, y);
		broad(mine, show, x - 1, y - 1);
		broad(mine, show, x, y - 1);
		broad(mine, show, x + 1, y - 1);
		broad(mine, show, x + 1, y);
		broad(mine, show, x + 1, y + 1);
		broad(mine, show, x, y + 1);
		broad(mine, show, x - 1, y + 1);
	}
}

//标记
int Flagmine(char show[ROWS][COLS], int row, int col,int flag_count)
{
	int x = 0;
	int y = 0;

	if (flag_count == EASY_COUNT)
	{
		printf("标记的雷数与实际雷数相等,无法再标记\n");
		return;
	}
	printf("请输入你要标记的位置:\n");
	scanf_s("%d %d", &x, &y);
	if (x > 0 && x <= row && y > 0 && y <= col)
	{
		//判断该位置是否被排除
		if (show[x][y] == '*')
		{
			show[x][y] = '!';
			flag_count++;
		}
		else
		{
			printf("该位置已经排除,无法再标记\n");
		}
	}
	else
	{
		printf("输入坐标非法,请重新输入:\n");

	}
	return flag_count;

}

//取消标记
int CancelFlag(char show[ROWS][COLS], int row, int col, int flag_count)
{
	int x = 0;
	int y = 0;
	printf("请输入你要取消标记的位置:\n");
	scanf_s("%d %d", &x, &y);
	if (x > 0 && x <= row && y > 0 && y <= col)
	{
		//判断该位置是否被标记
		if (show[x][y] == '!')
		{
			show[x][y] = '*';
			flag_count--;
		}
		else
		{
			printf("该位置未被标记过,无法取消标记!\n");
		}
	}
	else
	{
		printf("输入坐标非法,请重新输入:\n");

	}
	return flag_count;

}
//扫雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int choice = 0;//选择
	int flag_count = 0;//标记雷的个数
	int win = 0;//判断是否赢
	while (1)
	{
		menu2();
		scanf_s("%d", &choice);
		if (choice == 1)
		{
			int x = 0;
			int y = 0;
			printf("请输入要排查的坐标:\n");
			scanf_s("%d %d", &x, &y);
			if (x >= 1 && x <= row && y >= 1 && y <= col)
			{
				if (show[x][y] != '*')
				{
					printf("改坐标已经被排查过了,不能重复排查!\n");
					system("pause");

				}
				else
				{
					//如果是雷
					if (mine[x][y] == '1')
					{
						printf("很遗憾,你被炸死了!!!\n");
						DisplayBoard(mine, ROW, COL);
						break;
					}
					else//如果不是雷
					{
						broad(mine, show, x, y);
						//统计mine数组中(x,y) 周围有几个雷
						DisplayBoard(show, ROW, COL);
					}
				}
			}
			else
			{
				printf("输入坐标非法,请重新输入\n");
			}
		}
		else if (choice == 2)
		{
			printf("请标记雷:\n");
			flag_count = Flagmine(show, ROW, COL,flag_count);
			DisplayBoard(show, ROW, COL);
		}
		else if (choice == 3)
		{
			flag_count = CancelFlag(show, ROW, COL, flag_count);
			DisplayBoard(show, ROW, COL);
		}
		else
		{
			printf("输入错误,请重新输入!\n");
		}
		win = TravelBoard(show, ROW, COL);
		if (win == EASY_COUNT)
		{
			break;
		}
	}

	if (win == EASY_COUNT)
	{
		printf("恭喜你,排雷成功!\n");
		DisplayBoard(mine, ROW, COL);

	}

}


3、test.c

#include"game.h"

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

void game()
{
	char mine[ROWS][COLS] = { 0 };//存放布置好的雷的信息
	char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息
	//初始化数组内容为指定的内容
	//mine 数组在没有布置雷的时候,都是'0'
	InitBoard(mine, ROWS, COLS, '0');
	//show 数组在没有排查雷的时候, 都是'*'
	InitBoard(show, ROWS, COLS, '*');
	DisplayBoard(show, ROW, COL);

	//DisplayBoard(mine, ROW, COL);
	
	//设置雷
	SetMine(mine, ROW, COL);
	//DisplayBoard(mine, ROW, COL);

	//排查雷
	FindMine(mine, show, ROW, COL);

}

int main()
{
	//设置随机数生成起点
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf_s("%d", &input);
		switch (input)
		{
		case 1:
			//printf("扫雷\n");
			system("cls");

			game();

			system("pause");
			system("cls");
			break;
		case 0:
			system("cls");

			printf("退出游戏\n");
			system("pause");
			break;
		default:
			printf("输入错误,请重新输入:\n");
			system("pause");
			system("cls");
			break;
		}
	} while (input);

	return 0;
}


  • 18
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

求知.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值