雷盘可拓展,我们这里以9*9做示范=)
void menu()//游戏菜单界面
{
printf("****************************************************\n");
printf("*********输入1开始游戏 输入0退出游戏************\n");
printf("****************************************************\n");
}
(这个东西写出一个后,之后再用直接cv就可=)我就是复制以前的哈哈)
行了,到这里,咱们来回想一下扫雷的游戏过程
剖析一下就是:
- 游戏先布置雷
- 我们通过点击来查找雷(我目前还不知道怎么实现点击(哭),就只能以输入坐标的形式了)
- 若是周围没雷,就会延伸出一大片(敲黑板划重点啦!!!这块是扫雷的难点)
- 如果点的地方刚好是雷,你就死翘翘啦
- 如果周围有雷,就会显示九宫格内的雷的数量(这里也要划下重点捏)
- 如何判断周围有雷呢?
- 就是以点击的该点位置为中心,判断周围8个格子
- 但是,我们如果要用代码实现的话,就是用二维数组创建雷盘,那么在所生成的雷盘边边处,它其中的某一下标已经是0了,若我们要判断周围,则会导致部分的数组越界啦!所以,聪明的人类选择在雷盘周围扩大一格,就像侵染一样,长宽各增长2格(上下和左右均扩大一格了哦)
- 总结就是,我们真正创建的数组行和列都要比实际看到的+2(我们在打印的时候还是生成9*9哈)
- 所以,我们打印时的i变量和j变量都得从1开始(这是我常用的for循环变量)
就像是这样的关系(右图是我们看到的雷的布局,左图是实际的布局)
for (i = 0; i < h; i++) {
for (j = 0; j < l; j++) {
printf("%d ", orgin[i][j]);
}
printf("\n");
}
for (i = 1; i <= hh; i++) {
for (j = 1; j <= ll; j++) {
printf("%d ", orgin[i][j]);
}
printf("\n");
}
代码中有用到我宏定义的常量
#define _CRT_SECURE_NO_WARNINGS
#define hh 9
#define ll 9
#define bomb 10
#define h hh+2
#define l ll+2
#include
#include
#include
int orgin[h][l];
char show[h][l];
void init(int m, int n);
void lay(int m, int n);
void display(int m, int n);
void seek(int m, int n);
void round(int a, int b);
void flag(int a,int b);
void init(int m, int n) {
int i = 0, j = 0;
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
show[i][j] = ' ';
orgin[i][j] = 0;
}
}
}
- 我们来分析分析扫雷的雷盘布置
- 首先用一个数组储存放雷的位置(就是那个orgin数组),如果我们直接用该数组打印,那么雷的位置就被我们看到啦,达咩
- 所以我们应该创建另一个数组专门用来展示(我把它叫做show数组)
- 因为在最开始时,雷盘上应该什么都没有,所以展示用的show数组初始化为空格
- 放雷的数组先初始化为0,每放一个雷,赋值1
- 这是我在三子棋的棋盘的基础上修改的
(改死我了),但现在看来确实不难(可恶)- 我琢磨出的小技巧就是你把实际的数代进去就行,你需要几个,for循环就设置几次,当然如果用到下标的话,还得按照实际再修改修改
void display(int m, int n) {
int i = 1, j = 0;
while (i <= ll) {
printf(" %d", i++);
}
printf("\n");
for (i = 1; i <= m-1 ; i++)//以给定的行数 重复打印
{
for (j = 0; j < n-1 ; j++)
{
if (j == 0) {
printf(" ");
}
printf("|");
if (j < n-2)
{
printf("---");
}
}//打印出分割行
printf("\n");
if (i < n-1)
{//一行的内容
for (j = 1; j <= n -1; j++)
{
if (j == 1&&i<=m-2) {
printf("%d", i);
}
printf("|");
if (j <= n-2&&i<=n-2)
printf(" %c ", show[i][j]);
/*printf(" %d ", orgin[i][j]);*/
}//打印出有数据的一行
}
printf("\n");
}
}
void lay(int m, int n) {
int x = 0, y = 0;
int count = bomb;
while (count) {
x = rand() % hh + 1;
y = rand() % ll + 1;
if (orgin[x][y] == 0) {
orgin[x][y] = 1;
count--;
}
}
}
还是熟悉的配方,还是熟悉的味道,随机数它又来啦!
这是我在五子棋那里解释过的,就不多赘述啦,感兴趣的可以去看看哦
初始化的时候我的orgin数组全为0,那么放一个雷就赋值1
我们首先要确定胜利条件
排除所有的雷我们就胜利啦,因此我们设置一个win变量来计数
void seek(int m, int n) {
printf("若您在游戏过程中想要标记某点,请您输入该游戏的雷盘行数+1,列数+1\n");
//这是我设置的如何进入标记操作
int x = 0, y = 0;
int i = 0, j = 0;
while (1) {
if (win == hh * ll - bomb) { //获胜条件写最前面,这样满足了直接就出去
printf("恭喜你获得了胜利!\n");
printf("是否要重新开始:");
break;
}
printf("\n请输入你要查找的坐标:");
scanf("%d%d", &x, &y);
int i = 0, j = 0;
if (x >= 1 && x <= hh && y >= 1 && y <= ll) { //保证输入的坐标合法
if (orgin[x][y] == 1) {
show[x][y] = '*';
display(h, l);
printf("\n很遗憾,你被炸死了");
printf("\n是否要重新开始:");
break;
}
else {
round(x, y); //没踩到就进入判断函数
display(h, l);
}
}
else {
if (x == hh + 1 && y == ll + 1) { //这里就是我设置的进入标记函数的标志
flag(h, l);
}
else {
printf("\n输入的坐标非法,请重新输入:");
}
}
}
}
踩到雷了就把该坐标标记一下然后打印雷盘,可以让你死的明明白白,视觉效果会更好
就像这样捏~
在查找的过程中我们还嵌套了不少函数,我们来一一说道说道(display函数前面讲过了哦)
void round(int a, int b) {
if (a >= 1 && a <= hh && b >= 1 && b <= ll) {
int count = find(a, b);
show[a][b] = count + '0';
win++;
if (count == 0) {
int i = 0, j = 0;
for (i = a - 1; i <= a + 1; i++) {
for (j = b - 1; j <= b + 1; j++) {
if (show[i][j] == ' ') {
round(i, j);
}
}
}
}
}
}
- 当我们排查到有一格的周围没有雷时,我们就需要继续对该格周围的八个格子排查,看是否还存在这样的情况
- 而对周围每个格子的排查过程和第一次排查的过程相同,因此我们可以写一个递归来完成该操作
- 而且要注意不能数组越界!!!这很重要!
- 并且要保证该位置没有被排查过(用if,如果它仍是初始化后的状态,则没有被排查过,因此就可以继续调用round函数,并传入新的下标参数)
int find(int a, int b) {
if(a>=1&&b>=1&&a<=hh&&b<=ll){
return orgin[a - 1][b - 1] + orgin[a - 1][b] + orgin[a - 1][b + 1] + orgin[a][b - 1] + orgin[a][b + 1] + orgin[a + 1][b - 1] + orgin[a + 1][b] + orgin[a + 1][b + 1];
}
else {
return 0;
}
}
赋值就通过return实现,用show元素来接收(管他三七二十一,就是暴力的把八个格子的数加起来就行,因为有雷的地方是1,所以和就是雷的数量)
void flag(int a, int b) {
int x = 0, y = 0;
printf("\n请输入你要标记的坐标:");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= hh && y >= 1 && y <= ll) {
show[x][y] = '?';
display(h, l);
if (orgin[x][y] == 1) {
win++;
}
}
else {
printf("\n输入的坐标非法,请重新输入:");
}
}
首先还是要保证坐标合法,标记的地方用?代替,如果标记的地方就是雷的位置,别忘了win++哦
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void menu()//游戏菜单界面
{
printf("****************************************************\n");
printf("*********输入1开始游戏 输入0退出游戏************\n");
printf("****************************************************\n");
}
void game() {
init(h, l);
lay(h, l);
//int i = 0, j = 0;
//for (i = 1; i <= hh; i++) {
// for (j = 1; j <= ll; j++) {
// printf("%d ", orgin[i][j]);
// }
// printf("\n");
//}
display(h, l);
seek(h, l);
}
void test()//游戏流程
{
srand((unsigned int)time(NULL));
int a = 0;
menu();
do
{
scanf("%d", &a);
switch (a)
{
case 1:
printf("开始我们的游戏吧!\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("请重新输入\n");
}
} while (a);
}
int main()//大框架
{
test();
return 0;
}
贴一下我的大框架,这个框架也是可以循环利用的哈哈=)
注释的地方是用来测试的,方便我看雷的情况
完结撒花啦~~~
孩子的第二篇博客终于赶出来了,今天一天就栽在扫雷上了(哭)
感谢您的观看哦~如果有什么想法和建议可以直接和我说哦,我会很感谢您的建议(鞠躬)