目录
一、设计思路
1.棋盘设计
扫雷棋盘是由9x9个方块组成的棋盘,所以我们需要使用二维数组来表示他的棋盘,但由于查找雷的过程需要对其周围八个方块都要检索会造成数组指针越界的问题,于是我们不能使用9x9的二维数组,我们需要定义成11x11的方便操作。
为了实现扫雷我们需要两个棋盘:
一个用来存放地雷和安全区域 //1表示有雷 2表示无雷
一个用来显示#让玩家进行排查 //#表示未排查 数字表示周围雷数
2.工程设计
我们需要三个工程文件来实现扫雷游戏
1.game.h //用来引入库函数和声明游戏函数
2.game.c //对游戏函数的定义的实现
3.test.c //对函数的测试
二、设置棋盘及其初始化
#define Row 9
#define Col 9
#define Rows Row+2
#define Cols Col+2
//设置棋盘
char mine[Rows][Cols] = { 0 };
char show[Rows][Cols] = { 0 };
//初始化棋盘
init_board(mine, Rows, Cols,'0');
init_board(show, Rows, Cols, '*');
在mine数组中‘0’表示无雷区域 ‘1’表示有雷
在show数组中用'✳'表示未排查区域 翻开后数字表示周围雷数
void init_board(char arr[Rows][Cols], int rows, int cols, char set) {
for (int i = 0; i < Rows; i++) {
for (int j = 0; j < Cols; j++) {
arr[i][j] = set;
}
}
}
用函数 init_board 来初始化两个数组 一个置‘0’ 一个置'✳'
三、打印棋盘
void show_board(char arr[Rows][Cols], int row, int col);
用遍历数组的方式打印二维字符数组
void show_board(char arr[Rows][Cols], int row, int col) {
for (int i = 0; i <= row; i++) {
printf("%d ", i);
}
printf("\n");
for (int i = 1; i <= row; i++) {
printf("%d ", i);
for (int j =1; j <= col; j++) {
printf("%c ", arr[i][j]);
}
printf("\n");
}
}
效果展示:
打印出来的棋盘是这样子的之后可以根据行列坐标去排雷
四、埋雷
在mine数组中我们用1表示有雷0表示无雷,我们使用srand()和rand()函数生成随机数,对随机数取模9就可以获得一个0~9的数,在加上1就得到1~10的数,然后可以利用下标随机脉雷.
void set_mine(char mine[Rows][Cols], int row, int col) {
int count = ease_count;
int x, y = 0;
while (count) {
x = rand()% row + 1;
y = rand()% col + 1;
if (mine[x][y] == '0') {
mine[x][y] = '1';
count--;
}
}
}
五、扫雷
void find_mine(char mine[Rows][Cols], char show[Rows][Cols],int row,int col);
思想:我们运用函数将数组mine和数组show 传入
我们通过坐标来筛查mine数组当前位置是否为‘1’ 是则踩雷游戏结束
为‘0’通过查找该区域周围区域雷数之和显示在show数组当前位置
直到翻开所有无雷区域 胜利
void find_mine(char mine[Rows][Cols], char show[Rows][Cols], int row, int col) {
int x, y = 0;
int win = 0;
while (win<Row*Col-ease_count) {
printf("你要排查的坐标\n");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col) {
if (mine[x][y] == '1') {
printf("很遗憾,游戏结束\n");
show_board(mine, Row, Col);
break;
}
else {
int count = get_mine_count(mine,x, y);
show[x][y] = count + '0';
show_board(show, Row, Col);
win++;
}
}
else {
printf("坐标非法,请重新输入\n");
}
}
if (win == Row * Col - ease_count) {
printf("恭喜你,排雷成功\n");
show_board(mine, Row, Col);
}
}
小tips:‘9’-‘0’=9(字符变为数字) 与ASCII码有关
同理:9+‘0’=‘9’
//计算周围雷数
int get_mine_count(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] -
'0' * 8;
}
只要将该区域周围八个区域的所存字符(不是‘1’就是‘0’)相加减去八个字符‘0’的结果就是周围雷数 (有多少个字符‘1’)
六、完整代码
game.h
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define Row 9
#define Col 9
#define Rows Row+2
#define Cols Col+2
#define ease_count 10
//初始化棋盘
void init_board(char arr[Rows][Cols], int rows, int cols, char set);
//打印棋盘
void show_board(char arr[Rows][Cols], int row, int col);
//布置雷
void set_mine(char arr[Rows][Cols], int row, int col);
//查找雷
void find_mine(char mine[Rows][Cols], char show[Rows][Cols],int row,int col);
//计算周围雷数
int get_mine_count(char mine[Rows][Cols],int x, int y);
game.c
#include "game.h"
//初始化棋盘
void init_board(char arr[Rows][Cols], int rows, int cols, char set) {
for (int i = 0; i < Rows; i++) {
for (int j = 0; j < Cols; j++) {
arr[i][j] = set;
}
}
}
//显示棋盘
void show_board(char arr[Rows][Cols], int row, int col) {
for (int i = 0; i <= row; i++) {
printf("%d ", i);
}
printf("\n");
for (int i = 1; i <= row; i++) {
printf("%d ", i);
for (int j =1; j <= col; j++) {
printf("%c ", arr[i][j]);
}
printf("\n");
}
}
//布置雷
void set_mine(char mine[Rows][Cols], int row, int col) {
int count = ease_count;
int x, y = 0;
while (count) {
x = rand()% row + 1;
y = rand()% col + 1;
if (mine[x][y] == '0') {
mine[x][y] = '1';
count--;
}
}
}
//计算周围雷数
int get_mine_count(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] -
'0' * 8;
}
//查找雷
void find_mine(char mine[Rows][Cols], char show[Rows][Cols], int row, int col) {
int x, y = 0;
int win = 0;
while (win<Row*Col-ease_count) {
printf("你要排查的坐标\n");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col) {
if (mine[x][y] == '1') {
printf("很遗憾,游戏结束\n");
show_board(mine, Row, Col);
break;
}
else {
int count = get_mine_count(mine,x, y);
show[x][y] = count + '0';
show_board(show, Row, Col);
win++;
}
}
else {
printf("坐标非法,请重新输入\n");
}
}
if (win == Row * Col - ease_count) {
printf("恭喜你,排雷成功\n");
show_board(mine, Row, Col);
}
}
test.c
#include "game.h"
void meau() {
printf(" ********************** \n");
printf(" *******扫雷游戏******* \n");
printf(" ********1.play******** \n");
printf(" ********0.exit******** \n");
printf(" ********************** \n");
}
void game() {
//设置棋盘
char mine[Rows][Cols] = { 0 };
char show[Rows][Cols] = { 0 };
//初始化棋盘
init_board(mine, Rows, Cols,'0');
init_board(show, Rows, Cols, '*');
//打印棋盘
/* show_board(mine, Row, Col);
show_board(show, Row, Col);*/
//布置雷
set_mine(mine, Row, Col);
show_board(show, Row, Col);
find_mine(mine,show,Row,Col);
}
int main() {
int input;
srand((unsigned)time(NULL));
do {
meau();
printf("请输入选择: \n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
default:
printf("请重新输入\n ");
break;
}
} while (input);
return 0;
}