这下玩到真正的扫雷了(超详细的C语言实现)—一扫一大片!


目录

♍️一、扫雷的简介

♎️二、C语言实现思路

        大体框架的构建

          接口的定义

 ♏️三、根据所写接口实现函数主体

         菜单的构建

         game()主体的构建

         各部分功能的实现

        🛑精华点—重点在判输赢!

♐️四、总体代码

        实现效果


♍️一、扫雷的简介

        游戏的目标是在一个矩阵布局的区域内找到所有的地雷(也称为“雷区”),而不触发任何一颗地雷。玩家会在一个数值矩阵中选择一个方块,然后从该方块开始探索,直到确定周围没有地雷为止。如果一个方块周围的八个方向都没有地雷,那么它会显示一个数字,该数字表示周围格子中有多少个地雷。玩家需要根据数字和已经探索的区域来确定地雷的位置。 如果玩家不小心选择了一个地雷,就会导致游戏失败。扫雷随着难度的增加而变得更加困难,玩家需要更加小心谨慎地选择每个方块,以避免不必要的错误。


♎️二、C语言实现思路

        大体框架的构建

1.创建一个游戏界面,并在界面上创建一个棋盘,用于显示游戏地图。

2.将雷随机分布在棋盘中,同时在每个非雷方块上计算周围雷的数量。

3.为每个方块创建一个按钮,并在按钮上显示周围雷的数量或者一个雷的图标。

4.添加点击按钮的事件处理程序,如果点击到一个未翻开的方块,则显示该方块上的内容,并根据该方块的类型进行相应的操作。

5.如果点击到雷,则游戏结束,显示游戏失败的信息,并重置游戏。

6.如果所有非雷方块都被翻开,则游戏结束,显示游戏胜利的信息,并重置游戏。

          接口的定义

        ROW和COL定义棋盘的大小,MINE来确定要随机种下的雷的数量,ROWS和COLS是实际上的棋盘大小(看不到,为了方便判断周围雷),其他接口分别为初始化棋盘、显示棋盘、获得地雷,以及判赢操作。

#define ROW 9
#define COL 9
#define MINE 10

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

void Initboard(char board[ROWS][COLS], int rows, int cols, char a);//初始化

void Showboard(char board[ROW][COL], int row, int col);//打印

void Getmine(char board[ROWS][COLS],int mine);//种地雷

void win(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);//判赢

 ♏️三、根据所写接口实现函数主体

         菜单的构建

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

                大道至简,无需多言 ! 

         game()主体的构建

        游戏大体框架构建->游戏主体->游戏主体用什么实现?->两个数组->一个显示(玩家所见)另外一个用来储存数据(存雷以及数据处理)->看玩家的选择错误与否->提示->主体需要一个循环来实现菜单以及游戏主体的显示->大体框架确认完毕。

          实现如下: 


void game()//游戏本体
{
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
	Initboard(mine, ROWS, COLS,'0');
	Initboard(show, ROWS, COLS, '*');
	Getmine(mine, MINE);
	//Showboard(mine, ROW, COL);
	printf("--------------------\n");
	Showboard(show, ROW, COL);
	win(mine, show, ROW, COL);
}

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

	} while (input);
	return 0;
}

         各部分功能的实现

        需要什么功能?->初始化->种地雷->查地雷->得到地雷数量的数据->判输赢条件。每次操作都需要判断是否踩到地雷->因此不如初始化存地雷数据的数组为‘1’和‘0’,‘1’代表雷‘0’代表没雷

        实现如下:


void Initboard(char board[ROWS][COLS],int rows,int cols,char a)//初始化数组为a
{
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			board[i][j] = a;
		}
	}
}

void Showboard(char board[ROWS][COLS], int row, int col)//打印扫雷的游戏棋盘
{
	for (int i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n ———————————————————\n");
	for (int i = 1; i <= row; i++)
	{
		printf("%d|", i);
		for (int j = 1; j <= col; j++)
		{
			if(j!=col)
			printf("%c ", board[i][j]);
			else
				printf("%c|", board[i][j]);

		}
		printf("\n");
	}
	printf(" ———————————————————\n");
}

void Getmine(char board[ROWS][COLS], int mine)//种地雷,种的数量为mine
{
	int count = 0;
	while (count < mine)
	{
		int x = rand() % 9 + 1;
		int y = rand() % 9 + 1;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count++;
		}
	}
}

int Countmine(char board[ROWS][COLS], int row, int col)//数周围的地雷数量
{
	return (board[row - 1][col] + board[row-1][col-1] + board[row][col-1] + board[row+1][col-1] + board[row+1][col] +
		board[row+1][col+1] + board[row][col+1] + board[row-1][col+1] - '0'*8 );
}

void flower(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int* count)//递归查询周围地雷实现地雷游戏的遍地开花
{
	if (row > 0 && row < ROWS && col>0 && col < COLS)//使数组不越距
	{
		if (show[row][col] == '*')//递归结束条件
		{
			if (Countmine(mine, row, col)  == 0)//周围都空遍地开花
			{
				show[row][col] = ' ';//使其显示为空格
				(*count)--;
				flower(mine, show, row - 1, col, count);
				flower(mine, show, row - 1, col - 1, count);
				flower(mine, show, row, col - 1, count);
				flower(mine, show, row + 1, col - 1, count);
				flower(mine, show, row + 1, col, count);
				flower(mine, show, row + 1, col + 1, count);
				flower(mine, show, row, col + 1, count);
				flower(mine, show, row - 1, col + 1, count);
			}
			else//周围不是全空则标出周围地雷数量
			{
				show[row][col] = Countmine(mine, row, col) + '0';
				(*count)--;
			}
		}
	}
	
}

void change(char mine[ROWS][COLS], int row, int col)//就是为了好看点^_^用来游戏结尾显示地雷
{
	for (int i = 1; i <= row; i++)
	{
		for (int j = 1; j <= col; j++)
		{
			if (mine[i][j] == '1')
				mine[i][j] = '$';
		}
	}
}

void win(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//判断输赢
{
	int a = 0, b = 0;
	int move = 81 - MINE;
	while (move != 0)
	{
		printf("输入扫雷位置(空格隔开):");
		scanf("%d %d", &a, &b);
		if (a >= 1 && a <= row && b >= 1 && b <= col&&show[a][b]=='*')//使数组不越距并且防止选同样的位置
		{
			if (mine[a][b] == '1')
			{
				system("cls");//清屏为了好看
				change(mine, ROW, COL);
				printf("你被炸4了!\n");
				Showboard(mine, row, col);
				break;
			}
			else
			{
					flower(mine, show, a, b, &move);
					system("cls");
					Showboard(show, row, col);
			}
		}
		else
		{
			printf("输入错误!请重新输入! ");
		}
	}
	if (move == 0)
	{
		system("cls");
		printf("恭喜你!扫完了全部雷!\n");
		change(mine, ROW, COL);
		Showboard(mine, row, col);
	}

}

        🛑精华点—重点在判输赢!

        怎么算赢?主要在于玩家扫完所有雷,因此需要定义一个变量move来实现计数,move一开始的数量为9X9-地雷数量,玩家每动一步便-1直到为0跳出循环。重点在于遍地开花(选中的坐标包括周围共8个空位没有地雷)每找到一个就让他为空格,这也算是玩家动作也需让move-1;每多出来一个空以及标明附近地雷数量都要让move-1。

        遍历递归函数

void flower(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int* count)//递归查询周围地雷实现地雷游戏的遍地开花
{
	if (row > 0 && row < ROWS && col>0 && col < COLS)//使数组不越距
	{
		if (show[row][col] == '*')//递归结束条件
		{
			if (Countmine(mine, row, col)  == 0)//周围都空遍地开花
			{
				show[row][col] = ' ';//使其显示为空格
				(*count)--;
				flower(mine, show, row - 1, col, count);
				flower(mine, show, row - 1, col - 1, count);
				flower(mine, show, row, col - 1, count);
				flower(mine, show, row + 1, col - 1, count);
				flower(mine, show, row + 1, col, count);
				flower(mine, show, row + 1, col + 1, count);
				flower(mine, show, row, col + 1, count);
				flower(mine, show, row - 1, col + 1, count);
			}
			else//周围不是全空则标出周围地雷数量
			{
				show[row][col] = Countmine(mine, row, col) + '0';
				(*count)--;
			}
		}
	}
	
}

        判赢函数

void win(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//判断输赢
{
	int a = 0, b = 0;
	int move = 81 - MINE;
	while (move != 0)
	{
		printf("输入扫雷位置(空格隔开):");
		scanf("%d %d", &a, &b);
		if (a >= 1 && a <= row && b >= 1 && b <= col&&show[a][b]=='*')//使数组不越距并且防止选同样的位置
		{
			if (mine[a][b] == '1')
			{
				system("cls");//清屏为了好看
				change(mine, ROW, COL);
				printf("你被炸4了!\n");
				Showboard(mine, row, col);
				break;
			}
			else
			{
					flower(mine, show, a, b, &move);
					system("cls");
					Showboard(show, row, col);
			}
		}
		else
		{
			printf("输入错误!请重新输入! ");
		}
	}
	if (move == 0)
	{
		system("cls");
		printf("恭喜你!扫完了全部雷!\n");
		change(mine, ROW, COL);
		Showboard(mine, row, col);
	}

}


♐️四、总体代码

        game.h

#pragma once

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

#define ROW 9
#define COL 9
#define MINE 10

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

void Initboard(char board[ROWS][COLS], int rows, int cols, char a);//初始化

void Showboard(char board[ROW][COL], int row, int col);//打印

void Getmine(char board[ROWS][COLS],int mine);//种地雷

void win(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);//判赢

        game.c

#define _CRT_SECURE_NO_WARNINGS 01

#include"game.h"


void Initboard(char board[ROWS][COLS],int rows,int cols,char a)//初始化数组为a
{
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			board[i][j] = a;
		}
	}
}

void Showboard(char board[ROWS][COLS], int row, int col)//打印扫雷的游戏棋盘
{
	for (int i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n ———————————————————\n");
	for (int i = 1; i <= row; i++)
	{
		printf("%d|", i);
		for (int j = 1; j <= col; j++)
		{
			if(j!=col)
			printf("%c ", board[i][j]);
			else
				printf("%c|", board[i][j]);

		}
		printf("\n");
	}
	printf(" ———————————————————\n");
}

void Getmine(char board[ROWS][COLS], int mine)//种地雷,种的数量为mine
{
	int count = 0;
	while (count < mine)
	{
		int x = rand() % 9 + 1;
		int y = rand() % 9 + 1;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count++;
		}
	}
}

int Countmine(char board[ROWS][COLS], int row, int col)//数周围的地雷数量
{
	return (board[row - 1][col] + board[row-1][col-1] + board[row][col-1] + board[row+1][col-1] + board[row+1][col] +
		board[row+1][col+1] + board[row][col+1] + board[row-1][col+1] - '0'*8 );
}

void flower(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int* count)//递归查询周围地雷实现地雷游戏的遍地开花
{
	if (row > 0 && row < ROWS && col>0 && col < COLS)//使数组不越距
	{
		if (show[row][col] == '*')//递归结束条件
		{
			if (Countmine(mine, row, col)  == 0)//周围都空遍地开花
			{
				show[row][col] = ' ';//使其显示为空格
				(*count)--;
				flower(mine, show, row - 1, col, count);
				flower(mine, show, row - 1, col - 1, count);
				flower(mine, show, row, col - 1, count);
				flower(mine, show, row + 1, col - 1, count);
				flower(mine, show, row + 1, col, count);
				flower(mine, show, row + 1, col + 1, count);
				flower(mine, show, row, col + 1, count);
				flower(mine, show, row - 1, col + 1, count);
			}
			else//周围不是全空则标出周围地雷数量
			{
				show[row][col] = Countmine(mine, row, col) + '0';
				(*count)--;
			}
		}
	}
	
}

void change(char mine[ROWS][COLS], int row, int col)//就是为了好看点^_^用来游戏结尾显示地雷
{
	for (int i = 1; i <= row; i++)
	{
		for (int j = 1; j <= col; j++)
		{
			if (mine[i][j] == '1')
				mine[i][j] = '$';
		}
	}
}

void win(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//判断输赢
{
	int a = 0, b = 0;
	int move = 81 - MINE;
	while (move != 0)
	{
		printf("输入扫雷位置(空格隔开):");
		scanf("%d %d", &a, &b);
		if (a >= 1 && a <= row && b >= 1 && b <= col&&show[a][b]=='*')//使数组不越距并且防止选同样的位置
		{
			if (mine[a][b] == '1')
			{
				system("cls");//清屏为了好看
				change(mine, ROW, COL);
				printf("你被炸4了!\n");
				Showboard(mine, row, col);
				break;
			}
			else
			{
					flower(mine, show, a, b, &move);
					system("cls");
					Showboard(show, row, col);
			}
		}
		else
		{
			printf("输入错误!请重新输入! ");
		}
	}
	if (move == 0)
	{
		system("cls");
		printf("恭喜你!扫完了全部雷!\n");
		change(mine, ROW, COL);
		Showboard(mine, row, col);
	}

}

        text.c

#define _CRT_SECURE_NO_WARNINGS 01

#include"game.h"

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

void game()//游戏本体
{
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
	Initboard(mine, ROWS, COLS,'0');
	Initboard(show, ROWS, COLS, '*');
	Getmine(mine, MINE);
	//Showboard(mine, ROW, COL);
	printf("--------------------\n");
	Showboard(show, ROW, COL);
	win(mine, show, ROW, COL);
}

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

	} while (input);
	return 0;
}

        实现效果

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值