扫雷-c语言实现

目录

初始化

mine数组

show数组

布置雷

排查雷

1)按到不是雷的坐标,就递归展开一片

2)结束

小Tips

完整代码如下


写在前面:棋盘大小是11*11的二维数组。雷为1,非雷为0。

初始化

11*11而非9*9的原因:

正常情况下,要数出来这个格子周围的八个格子里面有没有雷;但是边边角角的区域,可能只有5个格子、3个格子。

所以在设计的时候,设计成11*11的棋盘。

但只展示中间的9*9数组,即在打印棋盘的时候循环遍历只能从1-9。在随机生成雷的时候,循环遍历只能从1-9。

实际上要用两个棋盘,一个数组(mine)存放实际布置好的雷的信息,一个数组(show)存放排查出来的雷的信息,周围有几个雷就显示几。

mine数组

初始化为'0',布置雷为'1'

show数组

初始化为'*',排查雷后具体位置改为数字字符

布置雷

随机生成雷的x,y坐标,范围是1-9。如果这个位置上没有雷就布置雷

排查雷

这个函数有4个参数,要将排查mine的信息反馈到show数组。

1)按到不是雷的坐标,就递归展开一片

条件:1、该坐标不是雷;2、该坐标未被排查过;3、该坐标周围没有雷。

1.若该坐标没有雷,则赋值为空格。之后,判断周围八个坐标的周围是否有雷,周围没有雷的坐标同样赋值为空格,周围没有雷的坐标则继续向外展开,直到遇到周围有雷的坐标或达到了扫雷盘面的边缘,则停止递归。

2.若该坐标有雷,则直接赋值为周围雷的个数。

2)结束

1、找出全部71个非雷位置;

2、踩雷

小Tips

如何将int类型的数字num(0-9)变成字符ch的('0'-'9')

char ch = num + '0';

同理,字符转int

int num = ch - '0';

完整代码如下

//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 init_board(char board[ROWS][COLS], int rows, int cols, char set);

//打印棋盘
void display_board(char board[ROWS][COLS], int row, int col);

//布置雷
void set_mine(char mine[ROWS][COLS], int row, int col);

//排查雷
void fine_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

//计算周围8个格子是否有雷
int get_mine(char mine[ROWS][COLS], int x, int y);

//扩展空白区域
void ExpandBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int* win);
//game.c
#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"

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

void display_board(char board[ROWS][COLS], int row, int col)
{
	//列号,显示在1行
	for (int j = 0; j <= col; j++)
	{
		printf("%d ", j);
	}
	printf("\n");

	for (int i = 1; i <= row; i++)
	{
		//打印行号,显示在1列
		printf("%d ", i);
		for (int j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("\n");
}

void set_mine(char mine[ROWS][COLS], int row, int col)
{
	//布置10个雷
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;//坐标范围从1到9
		int y = rand() % row + 1;

		//检查是否已经有雷
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			//布置成功就--
			count--;
		}
		
	}
}

int get_mine(char mine[ROWS][COLS], int x, int y)
{
	//统计周围8个格子的雷的个数,char转int
	return (mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] 
		+  mine[x - 1][y] + mine[x + 1][y] 
		+  mine[x - 1][y + 1] + mine[x][y + 1] + mine[x + 1][y + 1]
		- 8 * '0');
}

void ExpandBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int* win)
{
	int count = get_mine(mine, x, y);
	if (count == 0)
	{
		show[x][y] = ' ';//没有雷的坐标赋值为空格
		(*win)++;
		//递归周围的八个格子
		if (show[x - 1][y - 1] == '*' && x - 1 > 0 && x - 1 < ROWS && y - 1 > 0 && y - 1 < COLS)
			ExpandBoard(mine, show, x - 1, y - 1, win);
		if (show[x - 1][y] == '*' && x - 1 > 0 && x - 1 < ROWS && y > 0 && y < COLS)
			ExpandBoard(mine, show, x - 1, y, win);
		if (show[x - 1][y + 1] == '*' && x - 1 > 0 && x - 1 < ROWS && y + 1 > 0 && y + 1 < COLS)
			ExpandBoard(mine, show, x - 1, y + 1, win);
		if (show[x][y - 1] == '*' && x > 0 && x < ROWS && y - 1 > 0 && y - 1 < COLS)
			ExpandBoard(mine, show, x, y - 1, win);
		if (show[x][y + 1] == '*' && x > 0 && x < ROWS && y + 1 > 0 && y + 1 < COLS)
			ExpandBoard(mine, show, x, y + 1, win);
		if (show[x + 1][y - 1] == '*' && x + 1 > 0 && x + 1 < ROWS && y - 1 > 0 && y - 1 < COLS)
			ExpandBoard(mine, show, x + 1, y - 1, win);
		if (show[x + 1][y] == '*' && x + 1 > 0 && x + 1 < ROWS && y > 0 && y < COLS)
			ExpandBoard(mine, show, x + 1, y, win);
		if (show[x + 1][y + 1] == '*' && x + 1 > 0 && x + 1 < ROWS && y + 1 > 0 && y + 1 < COLS)
			ExpandBoard(mine, show, x + 1, y + 1, win);
	}
	else
	{
		show[x][y] = count + '0';
	}
}

void fine_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;

	while (win < (row * col - EASY_COUNT))
	{
		printf("请输入排查的坐标:>(范围1-9)\n");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
		{
			if (show[x][y] == '*')
			{
				if (mine[x][y] == '1')
				{
					printf("踩雷啦!!!\n");
					display_board(mine, ROW, COL);
					break;
				}
				else
				{
					//排查到无雷区域不会展开
					//排查雷
					//int count = get_mine(mine, x, y);
					//show[x][y] = count + '0';//这样存放的就是字符数字
					//display_board(show, ROW, COL);
					没踩到雷,就是成功
					//win++;

					//排查到无雷区域可展开
					//该坐标周围没有雷
					int count = get_mine(mine, x, y);
					if (0 == count)
					{
						ExpandBoard(mine, show, x, y, &win);
						display_board(show, ROW, COL);
					}
					else
					{
						show[x][y] = count + '0';//这样存放的就是字符数字

						display_board(show, ROW, COL);
						//没踩到雷,就是成功
						win++;
					}
				}
			}
			else
			{
				printf("该坐标已经排查过了\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入!\n");
		}
	}
	//最终判断 是否成功排雷
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你!排雷成功!\n");
	}
}
//test.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()
{
	//printf("扫雷\n");
	//定义两个字符数组mine show
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
	//初始化棋盘
	//mine全'0'  show全'*'
	init_board(mine, ROWS, COLS, '0');
	init_board(show, ROWS, COLS, '*');
	//打印棋盘
	//display_board(mine, ROW, COL);//不打印雷的信息
	display_board(show, ROW, COL);

	//布置雷
	set_mine(mine, ROW, COL);
	//display_board(mine, ROW, COL);

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

int main()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏!\n");
			break;
		default:
			printf("选择错误,请重新输入!\n");
			break;
		}
	} while (input);
	return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值