扫雷的游戏规则:
扫雷就是要把所有非地雷的格子揭开即胜利;踩到地雷格子就算失败
游戏主区域由很多个方格组成。使用鼠标左键随机点击一个方格,方格即被打开并显示出方格中的数字;方格中数字则表示其周围的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];
}
}
游戏运行截图