C语言实现扫雷游戏
目录
整体思路
游戏菜单
符号定义
游戏逻辑
棋盘初始化
棋盘展示
布置雷
排查雷
分文件代码
整体思路
1.真正的扫雷游戏,应该是 点击的当前位置如果没有雷,直接展开周围的一片区域情况,而我们实现的扫雷游戏稍微简化一点:如果当前位置没有雷,就显示当前各自周围一圈(八个格子)的雷数量
2.我们依然用二维数组表示整个扫雷界面,我们开始是需要布置雷的,用 '1'代表有雷,用 '0'代表没有雷,当玩家玩的过程中,点击了一个没有雷的格子时,需要显示周围雷的个数,因此每个位置是需要用到两个信息的,二维数组的每一个元素需要是一个结构体,但为了方便理解,我们拆分成两个二维数组,分别是 mine(布置雷) 数组和 show(展示给用户)数组
3.统计当前格子周围一圈有多少个雷很简答,但在某些位置还要单独判断可能出现越界的情况,比较麻烦,因此我们可以在原二维数组周围加一圈,可以完美处理越界的情况,但实际使用时(比如布置雷和排查雷)我们依旧使用的是原二维数组的范围
4.开始时一个雷都没有,我们用 字符'*' 表示,不能用整数0/字符0,因为 show棋盘要显示某个位置周围雷的个数,会混淆,因此我们的二维数组元素都是字符类型的!
游戏菜单
void menu()
{printf("##########################################\n");printf("############### 1.play ###################\n");printf("############### 0.exit ###################\n");printf("##########################################\n");
}int main()
{int input = 0;srand((unsigned int)time(NULL));do{menu();printf("请选择:->");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误, 请重新选择:\n");break;}} while (input);return 0;
}
符号定义
#define ROW 9 //原先行
#define COL 9 //原先列
#define ROWS ROW+2 //加一圈之后的行
#define COLS COL+2 //加一圈之后的列
#define EASY_COUNT 10 //布置雷的个数
游戏逻辑
void game()
{char mine[ROWS][COLS] = { 0 }; //实际布置雷(0表示没有雷 / 1表示有雷)char show[ROWS][COLS] = { 0 }; //给用户展示, 无雷要展示周围雷的个数InitBoard(mine, ROWS, COLS, '0'); InitBoard(show, ROWS, COLS, '*');DisplayBoard(show, ROW, COL); //展示棋盘SetMine(mine, ROW, COL); //布置雷//DisplayBoard(mine, ROW, COL);FindMine(mine, show, ROW, COL); //排查雷
}
棋盘初始化
1.我们只需要给 InitBoard 加一个额外的参数,便可以将初始化两个棋盘的逻辑封装到一个函数里
2.注意, 棋盘的初始化包含我们额外加的一圈
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");for (int j = 0; j <= col; j++)printf("%d ", j);printf("\n");for (int i = 1; i <= row; i++){printf("%d ", i);for (int j = 1; j <= col; j++) {printf("%c ", board[i][j]);}printf("\n");}
}

布置雷
void SetMine(char mine[ROWS][COLS], int row, int col)
{int count = EASY_COUNT;while (count){int x = rand() % row + 1, y = rand() % col + 1;if (mine[x][y] == '0'){mine[x][y] = '1';count--;}}
}
排查雷
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{return mine[x - 1][y - 1] +mine[x - 1][y] + mine[x - 1][y + 1] +mine[x][y - 1] + mine[x][y + 1] +mine[x + 1][y - 1] + mine[x + 1][y]+ mine[x + 1][y + 1] - 8 * '0';
}//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int win = 0;while(win < row * col - EASY_COUNT){printf("请输入排查雷的坐标:->");int x, y; scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (show[x][y] == '*'){if (mine[x][y] == '1'){printf("很遗憾, 你被炸死了!\n");break;}else{int count = GetMineCount(mine, x, y);show[x][y] = count + '0';DisplayBoard(show, row, col);win++;}}else{printf("该位置已经排查, 请重新输入\n");}}else{printf("坐标输入非法, 请重新输入\n");}}if (win == row * col - EASY_COUNT)printf("恭喜你, 已经排查完了所有的雷\n");
}
分文件代码
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"void menu()
{printf("##########################################\n");printf("############### 1.play ###################\n");printf("############### 0.exit ###################\n");printf("##########################################\n");
}void game()
{char mine[ROWS][COLS] = { 0 }; //实际布置雷(0表示没有雷 / 1表示有雷)char show[ROWS][COLS] = { 0 }; //给用户展示, 无雷要展示周围雷的个数InitBoard(mine, ROWS, COLS, '0'); InitBoard(show, ROWS, COLS, '*');DisplayBoard(show, ROW, COL); //展示棋盘SetMine(mine, ROW, COL); //布置雷//DisplayBoard(mine, ROW, COL);FindMine(mine, show, ROW, COL); //排查雷
}int main()
{int input = 0;srand((unsigned int)time(NULL));do{menu();printf("请选择:->");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误, 请重新选择:\n");break;}} while (input);return 0;
}
game.h
#pragma once#define ROW 9 //原先行
#define COL 9 //原先列
#define ROWS ROW+2 //加一圈之后的行
#define COLS COL+2 //加一圈之后的列
#define EASY_COUNT 10 //布置雷的个数#include <stdio.h>
#include <stdlib.h>
#include <time.h>//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col);//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"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");for (int j = 0; j <= col; j++)printf("%d ", j);printf("\n");for (int i = 1; i <= row; i++){printf("%d ", i);for (int j = 1; j <= col; j++) {printf("%c ", board[i][j]);}printf("\n");}
}//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col)
{int count = EASY_COUNT;while (count){int x = rand() % row + 1, y = rand() % col + 1;if (mine[x][y] == '0'){mine[x][y] = '1';count--;}}
}int GetMineCount(char mine[ROWS][COLS], int x, int y)
{return mine[x - 1][y - 1] +mine[x - 1][y] + mine[x - 1][y + 1] +mine[x][y - 1] + mine[x][y + 1] +mine[x + 1][y - 1] + mine[x + 1][y]+ mine[x + 1][y + 1] - 8 * '0';
}//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int win = 0;while(win < row * col - EASY_COUNT){printf("请输入排查雷的坐标:->");int x, y; scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (show[x][y] == '*'){if (mine[x][y] == '1'){printf("很遗憾, 你被炸死了!\n");break;}else{int count = GetMineCount(mine, x, y);show[x][y] = count + '0';DisplayBoard(show, row, col);win++;}}else{printf("该位置已经排查, 请重新输入\n");}}else{printf("坐标输入非法, 请重新输入\n");}}if (win == row * col - EASY_COUNT)printf("恭喜你, 已经排查完了所有的雷\n");
}
