c语言-扫雷

扫雷的游戏规则:

       扫雷就是要把所有非地雷的格子揭开即胜利;踩到地雷格子就算失败

   游戏主区域由很多个方格组成。使用鼠标左键随机点击一个方格,方格即被打开并显示出方格中的数字;方格中数字则表示其周围的8个方格隐藏了几颗雷;如果点开的格子为空白格,即其周围有0颗雷,则其周围格子自动打开;如果其周围还有空白格,则会引发连锁反应;在你认为有雷的格子上,点击右键即可标记雷;如果一个已打开格子周围所有的雷已经正确标出,则可以在此格上同时点击鼠标左右键以打开其周围剩余的无雷格

数字代表所点击的上下左右及斜角合计有几颗颗雷

实现思路:

游戏使用了2个二维数组:

:二维数组boardImg[ROWS][COLS]用来存放当前位置是否有雷,如果当前位置有雷,则为1,无雷则为0;

:二维数组board[ROW][COL]用来控制显示游戏,输入位置x,y,如果当前位置没有雷则会根据boardImg[ROWS][COLS]来计算输入的这个坐标周围有多少颗雷,并显示在board[x - 1][y - 1]上。

1. 初始化两个二维数组为0

2.设置雷(在ROW*COL的随机位置上设置10个雷)

3.显示游戏面板

4.玩家输入坐标

5.判断游戏结果

游戏有board[x][y]有4个值 -2表示初始化状态,初始化将所有的值初始化为-2。且显示‘█’,如果点击的位置和board[ x + 1][ y + 1]对应为1,则表示点击的位置是雷,‘●’并显示游戏失败,如果当前坐标为数字则表示周围8个格子合计有多少个雷。

如果为0则表示当前方块周围8个格子没有雷。

//头文件sweepMine.h如下


#define ROW 9
#define COL 9

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

#define EASY_COUNT 10

void InitBoard(int board[ROW][COL], int row, int col);//初始化镜像数组
void InitBoardImg(int boardImg[ROWS][COLS], int rows, int cols);//初始化用来显示的数组
void DisplayBoard(int board[ROW][COL], int row, int col);//显示游戏面板
void SetMine(int boardImg[ROWS][COLS], int row, int col);//随机设置雷
int GetMineCount();//获得剩余雷的数量
int ClearMine(int board[ROW][COL]);//玩家输入坐标扫雷
#endif//__GAME_H__

//头文件menu.h如下


#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int showMenu()
{
	int option;
	printf("*******************************\n");
	printf("****1.开始游戏   0.退出游戏****\n");
	printf("*******************************\n");
	printf("请输入您的选择>");
	scanf("%d", &option);
	return option;
}


//以下在源文件sweepMine.c中


#include "menu.h"
#include "sweepMine.h"
int boardImg[ROWS][COLS] = { 0 };
int Count = 0;

//扩展

1. 初始化两个二维数组为0

//1

void InitBoardImg(int boardImg[ROWS][COLS], int rows, int cols)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			boardImg[i][j] = 0;
		}
	}
}
//2

void InitBoard(int board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] = -2;
		}
	}
}



2.设置雷(在ROW*COL的随机位置上设置10个雷)


//设置雷
void SetMine(int boardImg[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int i = 0;
	int count = EASY_COUNT;//雷的数量
	while(count)
	{
		x = rand() % row;//只能是1到9
		++x;
		y = rand() % col;
		++y;
		if (boardImg[x][y] == 0)
		{
			boardImg[x][y] = 1;
			--count;
		}
	}
}



3.显示游戏面板


//显示游戏面板
void DisplayBoard(int board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("  ");
	for (i = 0; i < row; i++)
	{
		printf("%d ",i+1);
	}
	printf("\n");
	for (i = 0; i < row; i++)
	{
		printf("%d ", i + 1);
		for (j = 0; j < col; j++)
		{
			if(board[i][j] == -2)//表示初始化状态
				printf("█");
			else if (board[i][j] == -1)//碰到雷的状态
				printf("●");
			else
				printf("%d ",board[i][j]);//显示有几颗类
		}
		printf("\n");
	}
}



4.玩家输入坐标:当游戏开始为第一次输入时,如果点击的坐标为雷则将这个坐标置为0,然后再随机在一个不是雷的位置产生一个雷


//玩家输入坐标扫雷
int ClearMine(int board[ROW][COL])
{
	int Player_x;
	int Player_y;
	int x;
	int y;
	while (1)
	{
		printf("请输入坐标(x , y)\n");
		scanf("%d%d", &Player_x, &Player_y);
		x = Player_x - 1;
		y = Player_y - 1;
		if (board[x][y] == -2)
			break;
		printf("输入坐标非法!\n");

	}
	if (Count == 0)
	{
		if (boardImg[Player_x][Player_y] == 1)
		{
			boardImg[Player_x][Player_y] = 0;
			Count = 1;
			board[x][y] =
				(boardImg[Player_x][Player_y - 1] + boardImg[Player_x - 1][Player_y - 1] +
					boardImg[Player_x - 1][Player_y] + boardImg[Player_x - 1][Player_y + 1] +
					boardImg[Player_x][Player_y + 1] + boardImg[Player_x + 1][Player_y + 1] +
					boardImg[Player_x + 1][Player_y] + boardImg[Player_x + 1][Player_y - 1]);
			if (board[x][y] == 0)
			{
				click_Expand(board, boardImg, Player_x, Player_y);
			}
			
			while (1)
			{
				x = rand() % ROW;//只能是1到9
				++x;
				y = rand() % COL;
				++y;
				if (boardImg[x][y] != 1)
				{
					boardImg[x][y] = 1;
					break;
				}
			}
		}
		else
		{
			Count = 1;
			//未碰到雷显示周围雷的个数
			board[x][y] =
				(boardImg[Player_x][Player_y - 1] + boardImg[Player_x - 1][Player_y - 1] +
					boardImg[Player_x - 1][Player_y] + boardImg[Player_x - 1][Player_y + 1] +
					boardImg[Player_x][Player_y + 1] + boardImg[Player_x + 1][Player_y + 1] +
					boardImg[Player_x + 1][Player_y] + boardImg[Player_x + 1][Player_y - 1]);
			if (board[x][y] == 0)
			{
				click_Expand(board, boardImg, Player_x, Player_y);
			}
		}
	}
	else 
	{
		if (boardImg[Player_x][Player_y] == 1)
		{
			//表示碰到雷
			board[x][y] = -1;
			//游戏结束
			return 0;
		}
		else
		{
			++Count;
			//未碰到雷显示周围雷的个数
			board[x][y] =
					(boardImg[Player_x][Player_y - 1] + boardImg[Player_x - 1][Player_y - 1] +
					boardImg[Player_x - 1][Player_y] + boardImg[Player_x - 1][Player_y + 1] +
					boardImg[Player_x][Player_y + 1] + boardImg[Player_x + 1][Player_y + 1] +
					boardImg[Player_x + 1][Player_y] + boardImg[Player_x + 1][Player_y - 1]);
			if (board[x][y] == 0)
			{
				click_Expand(board, boardImg, Player_x, Player_y);
			}
		}
	}
	return 1;
}


5.判断游戏结果:EASY_COUNT表示游戏难度,10表示有10个雷,30表示有30个雷,Count为全局变量表示输入坐标的次数,返回0表示游戏胜利,返回1表示游戏继续。


//判断游戏胜利
int GetMineCount()
{
	if (Count == ROW*COL - EASY_COUNT)
	{
		return 0;
	}
	else
		return 1;
}



//实现点击扩展的函数:扩展思路,使用深度优先搜索算法,但是没能实现,目前只能扩展当前坐标最近的8个块块
//扩展
void click_Expand(int board[ROW][COL], int boardImg[ROWS][COLS], int player_x, int player_y)
{
	int i = 0;
	int j = 0;
	int boardToGetCount[ROW][COL] = { 0 };
	for (i = 1; i <= ROW; i++)
	{
		for (j = 1; j <= COL; j++)
		{
			boardToGetCount[i - 1][j - 1] =
				(boardImg[i][j - 1] + boardImg[i - 1][j - 1] +
					boardImg[i - 1][j] + boardImg[i - 1][j + 1] +
					boardImg[i][j + 1] + boardImg[i + 1][j + 1] +
					boardImg[i + 1][j] + boardImg[i + 1][j - 1]);
		}
	}
	for (i = 0; i < ROW; i++)
	{
		for (j = 0; j < COL; j++)
		{
			printf("%d ", boardToGetCount[i][j]);
		}
		printf("\n");
	}

	if (boardToGetCount[player_x + 1][player_y + 1] == 0)
	{
		if(player_x - 1 + 1< COL && player_y - 1 + 1 < ROW)
			board[player_x - 1 + 1][player_y - 1 + 1] = 0;
	}
	else
	{
		if (player_x - 1 + 1< COL && player_y - 1 + 1 < ROW)
			board[player_x - 1 + 1][player_y - 1 + 1] = boardToGetCount[player_x + 1][player_y + 1];
	}

	if (boardToGetCount[player_x - 1][player_y - 1 + 1] == 0)
	{
		if (player_x - 1< COL && player_y - 1 + 1 < ROW)
			board[player_x - 1][player_y - 1 + 1] = 0;
	}
	else
	{
		if (player_x - 1< COL && player_y - 1 + 1 < ROW)
			board[player_x - 1][player_y - 1 + 1] = boardToGetCount[player_x - 1][player_y - 1 + 1];
	}

	if (boardToGetCount[player_x - 1 + 1][player_y - 1] == 0)
	{
		if (player_x - 1 + 1< COL && player_y - 1< ROW)
			board[player_x - 1 + 1][player_y - 1] = 0;
	}
	else
	{
		if (player_x - 1 + 1< COL && player_y - 1< ROW)
			board[player_x - 1 + 1][player_y - 1] = boardToGetCount[player_x - 1 + 1][player_y - 1];
	}

	if (boardToGetCount[player_x - 1 - 1][player_y - 1 - 1] == 0)
	{
		if (player_x - 1 - 1 >= 0 && player_y - 1 - 1 >= 0)
			board[player_x - 1 - 1][player_y - 1 - 1] = 0;
	}
	else
	{
		if (player_x - 1 - 1 >= 0 && player_y - 1 - 1 >= 0)
			board[player_x - 1 - 1][player_y - 1 - 1] = boardToGetCount[player_x - 1 - 1][player_y - 1 - 1];
	}

	if (boardToGetCount[player_x - 1 - 1][player_y - 1] == 0)
	{
		if (player_x - 1 - 1 >= 0 && player_y - 1 + 1 < ROW)
			board[player_x - 1 - 1][player_y - 1] = 0;
	}
	else
	{
		if (player_x - 1 - 1 >= 0 && player_y - 1 + 1 < ROW)
			board[player_x - 1 - 1][player_y - 1] = boardToGetCount[player_x - 1 - 1][player_y - 1];
	}

	if (boardToGetCount[player_x - 1][player_y - 1 - 1] == 0)
	{
		if (player_x - 1 + 1< COL && player_y - 1 - 1 >= 0)
			board[player_x - 1][player_y - 1 - 1] = 0;
	}
	else
	{
		if (player_x - 1 + 1< COL && player_y - 1 - 1 >= 0)
			board[player_x - 1][player_y - 1 - 1] = boardToGetCount[player_x - 1][player_y - 1 - 1];
	}

	if (boardToGetCount[player_x - 1 + 1][player_y - 1 - 1] == 0)
	{
		if (player_x - 1 + 1< COL && player_y - 1 - 1 >= 0)
			board[player_x - 1 + 1][player_y - 1 - 1] = 0;
	}
	else
	{
		if (player_x - 1 + 1< COL && player_y - 1 - 1 >= 0)
			board[player_x - 1 + 1][player_y - 1 - 1] = boardToGetCount[player_x - 1 + 1][player_y - 1 - 1];
	}

	if (boardToGetCount[player_x - 1 - 1][player_y - 1 + 1] == 0)
	{
		if (player_x - 1 - 1 >= 0 && player_y - 1 + 1 < ROW)
			board[player_x - 1 - 1][player_y - 1 + 1] = 0;
	}
	else
	{
		if (player_x - 1 - 1 >= 0 && player_y - 1 + 1 < ROW)
			board[player_x - 1 - 1][player_y - 1 + 1] = boardToGetCount[player_x - 1 - 1][player_y - 1 + 1];
	}
}


游戏运行截图


















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值