今天看了b站鹏哥做的扫雷,其中有几点鹏哥没有进行优化,第一个就是没有在进行游戏前不布置雷,在选择第一个方块的时候再布置雷,还有就是如何像原版扫雷一样,点到一个周围为0的方块再检测其周围的方块的取值,鹏哥也暗示了可以用递归的方法,最后一点就是像原版一样进行标记选择,最后一点其实挺容易实现的,所以我这里的代码就没有交代了,大致思想就是,给与输入一个选择1和2,当为1的时候是输入扫雷的位置,当为2的时候是标注,然后要注意标注的地点必须是需要扫雷的地方就好,这点都是很通常的思想,本文就鹏哥前两个问题展开自己的扫雷代码思想。具体代码分别如下:
test.c文件
#include "game.h"
void game()
{
srand((unsigned int)time(NULL));
char show[ROWS][COLS] = { 0 };
char mine[ROWS][COLS] = { 0 };
//禁忌搜索数组
int tabu[ROWS][COLS] = { 0 };
//初始化棋盘
initialBoard(show, ROWS, COLS, '*');
initialBoard(mine, ROWS, COLS, '0');
system("cls");
//展示棋盘
Display(show, ROW, COL);
//第一次点击;
int x;
int y;
printf("要下哪儿呢?\n演示一下如果要下第一行第三列输入1 3就好\n");
scanf("%d%d", &x, &y);
system("cls");
//埋雷
Setmine(mine,ROW, COL,EASY,x,y);
//排查第一次雷
Detect(show,mine,ROW,COL,x,y,tabu);
Display(show, ROW, COL);
//排雷
Play(mine, show, ROW, COL,x,y,tabu);
}
int main()
{
int input ;
do {
menu();
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
break;
default:
printf("你在输入些什么?\n");
}
} while (input);
}
game.c文件
#include "game.h"
void menu()
{
printf("*********** 扫雷 ***********\n");
printf("*********** 1.play ***********\n");
printf("*********** 0.exit ***********\n");
printf("**********************************\n");
}
void initialBoard(char Board[ROWS][COLS], int row, int col, char set)
{
int i;
int j;
for (i=0;i<row;i++)
for (j = 0; j < col; j++)
{
Board[i][j] = set;
}
return 0;
}
void Display(char Board[ROWS][COLS], int row, int col)
{
int i;
int j;
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i );
for (j = 1; j <= col; j++)
{
printf("%c ", Board[i][j]);
}
printf("\n");
}
}
void Setmine(char Board[ROWS][COLS], int row, int col, int Difficult,int first_x,int first_y)
{
int a;
int b;
int i = 0;
for (i = 0; i < Difficult; i++)
{
flag:
a = (rand()%row)+1;
b = (rand()%col)+1;
if ((Board[a][b] == '0')&&((a != first_x)||(b != first_y)))
{
Board[a][b] = '1';
}
else
{
goto flag;
}
}
}
void Detect(char Boardshow[ROWS][COLS], char Boardmine[ROWS][COLS], int row, int col, int Detect_x, int Detect_y,int tabu[ROWS][COLS])
{
if ((Detect_x >= 1) && (Detect_x <= row) && (Detect_y >= 1) && (Detect_y <= col)&&tabu[Detect_x][Detect_y]==0)
{
Boardshow[Detect_x][Detect_y] = Boardmine[Detect_x - 1][Detect_y + 1] + Boardmine[Detect_x][Detect_y + 1]
+ Boardmine[Detect_x + 1][Detect_y + 1] + Boardmine[Detect_x - 1][Detect_y]
+ Boardmine[Detect_x - 1][Detect_y - 1] + Boardmine[Detect_x + 1][Detect_y]
+ Boardmine[Detect_x][Detect_y - 1] + Boardmine[Detect_x + 1][Detect_y - 1] - 7 * '0';
tabu[Detect_x][Detect_y] = 1;
if ((Boardshow[Detect_x][Detect_y] == '0'))
{
Detect(Boardshow, Boardmine, row, col, Detect_x - 1, Detect_y + 1, tabu);
Detect(Boardshow, Boardmine, row, col, Detect_x , Detect_y + 1, tabu);
Detect(Boardshow, Boardmine, row, col, Detect_x + 1, Detect_y + 1, tabu);
Detect(Boardshow, Boardmine, row, col, Detect_x - 1, Detect_y , tabu);
Detect(Boardshow, Boardmine, row, col, Detect_x + 1, Detect_y , tabu);
Detect(Boardshow, Boardmine, row, col, Detect_x - 1, Detect_y - 1, tabu);
Detect(Boardshow, Boardmine, row, col, Detect_x , Detect_y - 1, tabu);
Detect(Boardshow, Boardmine, row, col, Detect_x + 1, Detect_y - 1, tabu);
}
}
}
void Play(char Boardmine[ROWS][COLS], char Boardshow[ROWS][COLS], int row, int col, int a, int b, int tabu[ROWS][COLS])
{
int x1= 0;
int x2= 0;
int i = 0;
int j = 0;
while (1)
{
while (1)
{
printf("请输入:");
scanf("%d%d", &x1, &x2);
if ((x1 <= row && x1 >= 1) && (x1 <= col && x2 >= 1) && (Boardshow[x1][x2] == '*'))
{
break;
}
else
printf("请输入没有下过的位置\n");
}
if (Boardmine[x1][x2] == '1')
{
printf("BOOM!\n");
break;
}
else
{
Detect(Boardshow, Boardmine, row, col, x1, x2,tabu);
}
system("cls");
Display(Boardshow, ROW, COL);
int count = 0;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if (Boardshow[i][j] == '*')
{
count += 1;
if (count > EASY)
{
goto flag;
}
}
}
}
if (count == EASY)
{
printf("恭喜胜利\n");
break;
}
flag:
;
}
}
game.h文件
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <windows.h>
#define ROWS 11
#define COLS 11
#define ROW ROWS-2
#define COL COLS-2
#define EASY ((ROWS-1)*(COLS-1))/10
#include <time.h>
#include <stdlib.h>
void menu();
void initialBoard(char Board[ROWS][COLS], int row, int col,char set );
void Display(char Board[ROWS][COLS], int row, int col);
void Setmine(char Board[ROWS][COLS], int row, int col, int Difficult ,int first_x,int first_y);
void Detect(char Boardshow[ROWS][COLS], char Boardmine[ROWS][COLS], int row, int col, int Detect_x, int Detect_y, int tabu[ROWS][COLS]);
void Play(char Boardmine[ROWS][COLS], char Boardshow[ROWS][COLS],int row, int col ,int a,int b, int tabu[ROWS][COLS]);
运行代码如下
输入1后
如下棋盘1 3的位置
可以看到与鹏哥不同的点在于像原版扫雷一样遍历出来了很多区域
说一下我的思路,遍历查找的思想,利用递归的方式就好,但是呢这里要防止他反复递归,就是有些递归过的点要让他不参与递归,所以在主函数一开始我用到了一个tabu的禁忌递归矩阵,就是如果里面有坐标递归过了,令其里面等于1,如果没有那就还是初始值0,按照这个思想就可以完成扫雷区域的扩充。
其次就是如何实现第一次点击不会点到炸弹,只需要再游戏没进入play循环前,提前输入一次就好,然后再设置地雷的时候,不让那个坐标参与设置就行,如这行代码的条件
这里的xy就是排除上面输入的坐标设置的参数,具体可以在函数里看到
其他的代码和鹏哥的思路大差不差。
标签:ROWS,int,void,printf,COLS,C语言,char,扫雷,原版 From: https://blog.csdn.net/azurehan01/article/details/136635167