扫雷游戏是一个很经典的电脑小游戏了,相信大家在童年的时候都有玩过,是绞尽脑汁然后通关,还是每次都被炸弹杀死,不管怎样,相信这个游戏都给大家留下了深刻的印象,那么接下来我将介绍如何来写一个9*9的基本扫雷游戏回忆我们的童年。
1.扫雷游戏的分析和设计
1.1扫雷游戏的简单说明
1.9*9的图上随机布置了10个雷
2.排查雷:
a.如果排查的位置不是雷,就显示周围的九宫格内有几个雷
b.如果排查的位置是雷,那么就被炸死了,游戏结束
c.如果找到了所有的雷,则扫雷成功
1.2游戏的分析和设计
1.2.1
我们在进行扫雷游戏的过程中,布置的雷和排查的雷都需要地方储存。
因为我们要写的是一个9*9的扫雷游戏,所以需要在9*9的棋盘上布置雷的信息和排查雷,这样我们最先想到的就是创建一个9*9的二维数组来存放信息。空棋盘如图所示:
如果某个位置上有雷,我们就在此处存放1,若没有雷,就存放0。
这是一个随机布置了雷的棋盘:
这个时候我们就要开始设想如何来排查雷了,当我们想排查(2,5)时,我们需要访问周围的8个格子,来统计雷的个数。
但是当我们想排查(8,6)这个坐标时,就会发现访问周围的8个格子时下面的3个就会越界,不在我们的数组范围内,为了防止这种情况的发生,我们可以将数组扩大一圈,变为11*11的数组,雷仍然放在中间9*9的格子中。所以我们最后需要的是一个11*11的数组。
让我们继续分析,现在我们已经在棋盘上布置好了雷,也存储了对应的信息即雷(1),非雷(0),现在让我们开始进行排查。我们排查了一个位置,发现这个地方不是雷,但是它的周围有一个雷,那么我们就需要将雷的数量记录并存储下来,并且打印在棋盘上,作为我们接下来排雷的重要参考信息。但是我们会发现,如果将这个信息存入布置雷的数组中就可能会产生混淆,这种方法显然是行不通的。
那么我们为什么不将它们分开储存呢?
我们让一个棋盘(数组lei)来存放布置好的雷的信息,再让另一个棋盘(数组show)存放排查的信息。这样我们就得到了两个互不干扰的数组,将雷布置在lei数组,并且在lei数组中对雷进行排查,再将排查出的数据放入show数组,并将show数组打印出来。
这样我们就可以将show数组初始化为字符‘*’,为了方便打印,我们将两个数组的类型保持一致,lei数组的初始化也使用字符‘1’来表示雷,字符‘0’来表示非雷。
两个数组的初始化情况如下图所示:
char lei[11][11] = {0};//⽤来存放布置好的雷的信息 char show[11][11] = {0};//⽤来存放排查出的雷的个数信息
1.2.2
为了方便文件的管理,以及实践多文件形式下的函数声明和定义,我们设计三个文件来满足需要:
test.c // ⽂件中写游戏的测试逻辑game.c // ⽂件中写游戏中函数的实现等game.h // ⽂件中写游戏需 要的数据类型和函数声明等
2.扫雷游戏的代码实现
game.h
#pragma once//写游戏需要的数据类型和函数声明等 #include <stdio.h> #include <stdlib.h> #include <time.h> #define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2 #define EASY 10 void initboard(char arr[ROWS][COLS],int rows ,int cols ,char set);//初始化 void printboard(char arr[ROWS][COLS],int rows ,int cols );//打印棋盘 void setlei(char arr[ROWS][COLS], int row, int col);//布置雷 //排查雷 void findlei(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int rows, int cols);
game.c
#define _CRT_SECURE_NO_WARNINGS 1//游戏中函数的实现等 #include "game.h" void initboard(char arr[ROWS][COLS], int rows, int cols,char set) { int a = 0; for (a = 0; a < rows; a++) { int b = 0; for (b = 0; b < cols; b++) { int x = 1; arr[a][b] = set; } } } void printboard(char arr[ROWS][COLS], int rows, int cols) { int a = 0; for (a = 0; a < rows - 1; a++) { printf("%d ", a); } printf("\n"); for (a = 1; a < rows-1; a++) { printf("%d ", a); int b = 0; for (b = 1; b < cols - 1; b++) { printf("%c ", arr[a][b]); } printf("\n"); } } void setlei(char arr[ROWS][COLS], int row, int col) { int sum = EASY;//布置十个雷 while (sum) { int x = rand() % 9 + 1; int y = rand() % 9 + 1;//控制随机数的范围在1-9 if (arr[x][y] == '0') { arr[x][y] = '1'; sum--; } } } int getleinum(char arr[ROWS][COLS], int x, int y) { return arr[x - 1][y - 1] + arr[x - 1][y] + arr[x - 1][y + 1] + arr[x][y - 1] + arr[x][y + 1] + arr[x + 1][y - 1] + arr[x + 1][y] + arr[x + 1][y + 1] - 8 * '0';//从字符转换为数字‘n’-'0'=n } void findlei(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int rows, int cols) { int x = 0; int y = 0; int win = 0; while (win < ROW * COL - EASY) { printf("请输入要排查的坐标:"); scanf("%d %d", &x, &y); if (x >= 1 && x <= rows && y >= 1 && y <= cols) { if (arr1[x][y] == '1') { printf("很遗憾,你被炸死了"); printboard(arr1, ROWS, COLS); break; } else { int n = getleinum(arr1, x, y);//找周围有几个雷 arr2[x][y] = n + '0';//数字转换为对应的字符n+'0'='n' printboard(arr2, ROWS, COLS); win++; } } else { printf("坐标错误,请重新输入坐标"); } } if (win == ROW * COL - EASY) { printf("恭喜你,游戏成功"); printboard(arr1, ROWS, COLS); } }
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 lei[ROWS][COLS]; char show[ROWS][COLS]; //初始化棋盘 initboard(lei,ROWS,COLS,'0');//'0' initboard(show,ROWS,COLS,'*');//'*' //布置雷 setlei(lei, ROW, COL); //打印棋盘,我们不需要将11*11全部打印,只需要中间的9*9 printboard(show, ROWS, COLS); //排查雷 findlei(lei, show, ROW ,COL); } int main() { srand((unsigned int)time(NULL));//产生随机数 int i = 0; do { menu(); printf("请输入你的选择:"); scanf("%d", &i); switch (i) { case 1: printf("扫雷开始\n"); game(); break; case 0: printf("退出游戏\n"); break; default: printf("输入错误,请重新选择!!!\n"); break; } printf("\n"); } while (i); return 0; }
注:代码中使用了rand()函数等,对此不了解的可以看我的这篇文章,里面有对这几种函数的基本介绍http://t.csdnimg.cn/a9h8v
如果对代码有什么疑问欢迎在评论区留言,我看到后会尽可能解答。
代码的写法不止一种,如果有什么好的想法也欢迎在评论区提出。