#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<Windows.h>
#include<stdbool.h>
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
#define MINENUMBER 10
void BoardInit(char board[][COLS], int row, int col, char set);
void BoardDisplay(char board[][COLS], int row, int col);
void MineSet(char board[][COLS], int row, int col);
int MineNumber(char board[][COLS], int x, int y);
void MineFind(char mine[][COLS], char show[][COLS], int row, int col);
bool MineFinish(char board[][COLS], int row, int col);
void Explode(char mine[][COLS], char show[][COLS], int x, int y);
void Flag_In(char show[][COLS]);
void Flag_Out(char show[][COLS]);
void meau()
{
printf("****************\n");
printf("*****1.Play*****\n");
printf("*****0.Exit*****\n");
printf("****************\n");
}
void game()
{
//生成时间戳
srand((unsigned int)time(NULL));
//定义存放地雷的数组,和展示结果的数组
char mineBoard[ROWS][COLS];
char showBoard[ROWS][COLS];
//对两个数组进行初始化
BoardInit(mineBoard, ROWS, COLS, '0');
BoardInit(showBoard, ROWS, COLS, '*');
//设置地雷
MineSet(mineBoard, ROW, COL);
//BoardDisplay(mineBoard, ROW, COL);
BoardDisplay(showBoard, ROW, COL);
//排查地雷
MineFind(mineBoard, showBoard, ROW, COL);
}
void BoardInit(char board[][COLS], int row, int col, char set)
{
for (int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
board[i][j] = set;
}
void BoardDisplay(char board[][COLS], int row, int col)
{
for (int i = 0; i <= col; i++)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4 | 16);
printf("%d ", i);
}
printf("\n");
for (int i = 1; i <= row; i++)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4 | 16);
printf("%d ", i);
for (int j = 1; j <= col; j++)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7 | 16);
if(board[i][j] == '$')
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 6 | 16);
printf("%c ", board[i][j]);
}
printf("\n");
}
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7 | 16);
}
void MineSet(char board[][COLS], int row, int col)
{
int count = 0;
while (count < MINENUMBER)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count++;
}
}
}
void MineFind(char mine[][COLS], char show[][COLS], int row, int col)
{
int x, y;
char ch;
while (1)
{
printf("请输入您要排查的坐标(用空格分隔):");
scanf_s("%d %d", &x, &y);
system("cls");
if (show[x][y] == '*' && x > 0 && x <= row && y > 0 && y <= col)
{
if (mine[x][y] == '1')
{
printf("很遗憾,排雷失败\n");
BoardDisplay(mine, row, col);
return;
}
else
{
Explode(mine, show, x, y);
if (MineFinish(show, row,col))
{
printf("恭喜你,排雷成功\n");
BoardDisplay(mine, row, col);
return;
}
BoardDisplay(show, row, col);
getchar();
printf("是否需要插旗(Y/N):\n");
if((ch = getchar()) == 'Y')
Flag_In(show);
getchar();
printf("是否需要取消所插的旗子(Y/N):\n");
if ((ch = getchar()) == 'Y')
Flag_Out(show);
}
}
else if (show[x][y] != '*' && x > 0 && x <= row && y > 0 && y <= col)
{
printf("该位置已经被检查,请重新输入:\n");
BoardDisplay(show, row, col);
}
else
{
printf("坐标非法,请重新输入:\n");
BoardDisplay(show, row, col);
}
}
}
int MineNumber(char board[][COLS], int x, int y)
{
return (board[x][y - 1] + board[x][y + 1]
+ board[x - 1][y] + board[x - 1][y - 1] + board[x - 1][y + 1]
+ board[x + 1][y] + board[x + 1][y - 1] + board[x + 1][y + 1]
- 8 * '0');
}
bool MineFinish(char board[][COLS], int row, int col)
{
int count = 0;
for(int i = 1; i <= row; i++)
for (int j = 1; j <= col; j++)
{
if (board[i][j] != '*')
{
count++;
if (count == row * col - MINENUMBER)
return true;
}
}
return false;
}
void Explode(char mine[][COLS], char show[][COLS], int x, int y)
{
if (show[x][y] == ' ' || x < 1 || y < 1 || x > ROW || y > COL)
return;
if (MineNumber(mine, x, y) == 0)
show[x][y] = ' ';
else
{
show[x][y] = MineNumber(mine, x, y) + '0';
return;
}
Explode(mine, show, x, y - 1);
Explode(mine, show, x, y + 1);
Explode(mine, show, x + 1, y + 1);
Explode(mine, show, x + 1, y);
Explode(mine, show, x + 1, y - 1);
Explode(mine, show, x - 1, y + 1);
Explode(mine, show, x - 1, y - 1);
Explode(mine, show, x - 1, y);
}
void Flag_In(char show[][COLS])
{
int row = 0, col = 0;
printf("您想在哪个位置插入旗子:\n");
printf("注:用空格分隔,输入0 0结束插旗\n");
while(1)
{
scanf_s("%d %d", &row, &col);
if (row == 0 && col == 0)
break;
if (row < 1 || row > ROW || col < 1 || col > COL)
{
printf("坐标非法,重新输入:");
continue;
}
else if (show[row][col] != '*')
printf("给位置不能插旗\n");
else
{
system("cls");
show[row][col] = '$';
BoardDisplay(show, ROW, COL);
}
}
}
void Flag_Out(char show[][COLS])
{
int row, col;
printf("您想取消哪个位置的旗子:\n");
printf("注:用空格分隔,输入0 0结束\n");
while (1)
{
scanf_s("%d %d", &row, &col);
if (row == 0 && col == 0)
break;
if (row < 1 || row > ROW || col < 1 || col > COL)
{
printf("坐标非法,重新输入:");
continue;
}
else if (show[row][col] != '$')
printf("该位置不是旗子\n");
else
{
system("cls");
show[row][col] = '*';
BoardDisplay(show, ROW, COL);
}
}
}
int main()
{
system("color 17");
int input;
meau();
printf("请输入您的选择:");
while (1)
{
scanf_s("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏,感谢游玩\n");
break;
default :
printf("输入错误,请重新输入:");
break;
}
meau();
printf("是否重新游玩:");
}
return 0;
}