C语言 ——— 在控制台实现扫雷游戏(一次展开一片,递归实现)
前言
两个数组,一个用来显示在控制台上,一个用来存放雷
两个数组的实际大小为11 * 11 ,而为了方便排查雷的个数,实际使用范围是9 * 9
test.c
#include"mine_sweeping.h"void game()
{// 存放雷char mine[ROWS][COLS];// 展示char show[ROWS][COLS];// 初始化棋盘InitBoard(mine, ROWS, COLS, '0');InitBoard(show, ROWS, COLS, '*');// 打印棋盘DisplayBoard(show, ROW, COL);// 布置雷SetMine(mine, ROW, COL);// 排查雷FindMine(mine, show, ROW, COL);
}int main()
{int input = 0;// 随机数生成器srand((unsigned int)time(NULL));do{menu();printf("请输入:");scanf("%d", &input);if (input == 1){game();}else if (input == 0){printf("退出游戏\n");}else{printf("输入错误,请重新输入\n");}} while (input);return 0;
}
game.h
#include<stdio.h>
#include<stdlib.h>
#include<time.h>#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
#define MINE ((ROW + COL) / 2)// 打印菜单
void menu();// 初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char str);// 打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);// 布置雷
void SetMine(char board[ROWS][COLS], int row, int col);// 排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
game.c
#include"mine_sweeping.h"// 打印菜单
void menu()
{printf("*******************************************\n");printf("***** 1.play 0.next *****\n");printf("*******************************************\n");
}// 初始化棋盘
void InitBoard(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 DisplayBoard(char board[ROWS][COLS], int row, int col)
{printf("\n");//printf("--------------mine game--------------\n");// 打印横坐标for (int i = 1; i <= row; i++){printf(" %d ", i);printf(" ");}printf("\n");for (int i = 1; i <= row; i++){for (int j = 1; j <= col; j++){// 打印每一行printf(" %c ", board[i][j]);if (j < row){printf("|");}}// 打印纵坐标printf(" %d\n", i);// 打印分割线if (i < col){for (int k = 0; k < row; k++){printf("---");if (k < row - 1){printf("|");}}printf("\n");}}printf("\n");
}// 布置雷
void SetMine(char board[ROWS][COLS], int row, int col)
{// 雷的个数int mine = MINE;while (mine){int x = rand() % row + 1;int y = rand() % col + 1;if (board[x][y] == '0'){board[x][y] = '1';mine--;}}
}// 统计雷的个数
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
// return (mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] +
// mine[x + 1][y] + mine[x + 1][y + 1] + mine[x][y + 1] + mine[x - 1][y + 1] - 8 * '0');int count = 0;if (mine[x - 1][y] == '1')count++;if (mine[x - 1][y - 1] == '1')count++;if (mine[x][y - 1] == '1')count++;if (mine[x + 1][y - 1] == '1')count++;if (mine[x + 1][y] == '1')count++;if (mine[x + 1][y + 1] == '1')count++;if (mine[x][y + 1] == '1')count++;if (mine[x - 1][y + 1] == '1')count++;return count;
}// 一次展开一片
void UnfoldSlice(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{if (x >= 1 && x <= ROW && y >= 1 && y <= COL){int count = GetMineCount(mine, x, y);if (count == 0 && mine[x][y] != '*'){show[x][y] = count + '0';mine[x][y] = '*';UnfoldSlice(mine, show, x - 1, y);UnfoldSlice(mine, show, x - 1, y - 1);UnfoldSlice(mine, show, x, y - 1);UnfoldSlice(mine, show, x + 1, y - 1);UnfoldSlice(mine, show, x + 1, y);UnfoldSlice(mine, show, x + 1, y + 1);UnfoldSlice(mine, show, x, y + 1);UnfoldSlice(mine, show, x - 1, y + 1);}if (count != 0){show[x][y] = count + '0';return;}}else{return;}}int IsWin(char show[ROWS][COLS], int row, int col)
{int count = 0;for (int i = 1; i <= row; i++){for (int j = 1; j <= col; j++){if (show[i][j] == '*')count++;}}return count;}// 排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int x = 0;int y = 0;int MineCount = MINE;while (IsWin(show, row, col) > MineCount){printf("请输入要排查雷的坐标(用空格隔开):");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (mine[x][y] == '1'){printf("很遗憾,你被炸死了,游戏结束\n");DisplayBoard(mine, ROW, COL);break;}else{// 一次展开一片UnfoldSlice(mine, show, x, y);DisplayBoard(show, ROW, COL);}}else{printf("坐标非法,请重新输入\n");}}if (IsWin(show, row, col) == MINE){printf("恭喜你,排雷成功\n");DisplayBoard(mine, ROW, COL);}
}