初级版扫雷(功能无阉割)
- 1. 扫雷整体思路分析
- 2. 初始化数据与雷的放置
- 3. 打印游戏信息
- 4. 排查雷与标记雷
- 5. 排查后附近格子的自动展开
- 6. 判断输赢
- 7. 细节优化
- 8. 各个文件中的原码
1. 扫雷整体思路分析
- 扫雷算是一个代码量比较大的程序,需要用到大量我们自定义的函数,故需要不同的文件去声明与实现函数。
- 设置两个二维数组,一个用来储存雷的信息,另一个打印出游戏的信息。
- 各种函数来实现功能。
文件 |
功能 |
test.c |
程序main函数的运行文件 |
game.c |
实现函数的功能 |
game.h |
声明函数和引用各种头文件 |
2. 初始化数据与雷的放置
- 数组stormir存放雷
- 数组showmir展示游戏信息
- 根据游戏功能,后面排查雷时需要遍历其周围的八个格子,故将数组大小扩大到行:11、列:11。(实际操作数组还是行9列9)
- 用rand()函数随机布置雷
#define ROWS 11
#define COLS 11
#define ROW 9
#define COL 9
char stormir[ROWS][COLS] = {
0 };
char showmir[ROWS][COLS] = {
0 };
initboard(stormir,ROWS,COLS,' ');
initboard(showmir, ROWS,COLS,' ');
setmire(stormir, ROW, COL);
void initboard(char stormir[][COLS], int rows, int cols, char ch)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
stormir[i][j] = ch;
}
}
}
void setmire(char stormir[ROWS][COLS], int row, int col)
{
int count = 0;
int i = 0, j = 0;
while (count !=10)
{
i = rand() % row + 1;
j = rand() % col + 1;
if (stormir[i][j] != '*')
{
stormir[i][j] = '*';
count++;
}
}
}
3. 打印游戏信息
void disaplayboard(char showmir[][COLS], int row, int col)
{
int i = 0, j = 0;
printf("\n");
for (i = 1; i <= row; i++)
{
if (i == 1)
{
printf(" ");
for (j = 0; j < col; j++)
{
printf(" %d ", j + 1);
printf(" ");
}
printf("\n");
}
printf(" %2d ", i);
for (j = 1; j <= col; j++)
{
printf(" %c ", showmir[i][j]);
if (j != col)
{
printf("|");
}
}
printf("\n");
for (j = 0; j < col; j++)
{
if (j == 0)
printf(" ");
printf("---");
if (j != col - 1)
{
printf("|");
}
}
printf("\n");
}
}
- 存放雷的数组的打印
- 游戏信息的打印
4. 排查雷与标记雷
- 排查当前格子附近八个格子雷的个数,并把数目赋值给该格子
- 标记符号用“?”来标记。
printf("请输入排查雷的坐标:>\n");
printf("行:"); scanf("%d", &i);
printf("\n");
printf("列:"); scanf("%d", &j);
if (i > 0 && i<ROW+1 && j>0 && j < COL+1)
{
if (stormir[i][j] == '*')
{
Sleep(1000);
printf("很遗憾,你被炸死了\n");
disaplayboard(stormir, ROW, COL);
break;
}
else
{
countmir(stormir, showmir, i, j);
disaplayboard(showmir, ROW, COL);
}
void countmir(char stormir[][COLS], char showmir[][COLS], int x, int y)
{
int count = 0;
count = stormir[x - 1][y - 1] % 32 + stormir[x][y - 1] % 32 + stormir[x + 1][y - 1] % 32 + stormir[x - 1][y] % 32 + stormir[x + 1][y] % 32 + stormir[x - 1][y + 1] % 32 + stormir[x][y + 1] % 32 + stormir[x + 1][y + 1] % 32;
showmir[x][y] = count / 10 + 48;
}
printf("请选择标记雷的位置:>\n");
printf("行:"); scanf("%d", &x);
printf("\n");
printf("列:"); scanf("%d", &y);
if (x > 0 && x<ROW+1 && y>0 && y < COL+1&&showmir[x][y]==' ')
{
markmir(showmir,ROW,COL,x,y);
disaplayboard(showmir, ROW, COL);
}
else
{
printf("输入非法,请重新输入:>");
}
void markmir(char showmir[][COLS], int row, int col, int x, int y)
{
showmir[x][y] = '?';
}
- 排查雷
- 标记雷
5. 排查后附近格子的自动展开
- 一个一个排查太麻烦,根据游戏功能,可以实现自动展开
- 八个方向展开,碰到0则继续展开,碰到不为0的则停止
- 注意不越界
void if_extern(char stormir[][COLS], char showmir[][COLS], int x, int y)
{
if (countmir(stormir,showmir,x,y) == '0')
{
if (x - 1 > 0&&showmir[x-1][y]==' ')
if_extern(stormir, showmir, x - 1, y);
if (x + 1 <= ROW&&showmir[x+1][y]==' ')
if_extern(stormir, showmir, x + 1, y);
if (y-1>0&&showmir[x][y-1]==' ')
if_extern(stormir, showmir, x , y-1);
if (y+1<=COL&&showmir[x][y+1]==' ')
if_extern(stormir, showmir, x, y+1);
if (x-1>0&&y-1>0&&showmir[x-1][y-1]==' ')
if_extern(stormir, showmir, x - 1, y-1);
if (x-1>0&&y+1<=COL&&showmir[x-1][y+1]==' ')
if_extern(stormir, showmir, x - 1, y+1);
if(x+1<=ROW&&y-1>0&&showmir[x+1][y-1]==' ')
if_extern(stormir, showmir, x + 1, y-1);
if (x+1<=ROW&&y+1<=COL&&showmir[x+1][y+1]==' ')
if_extern(stormir, showmir, x + 1, y+1);
}
}
6. 判断输赢
当showmir数组中出现了71个数字时,即剩下10个格子全为雷。
int if_win(char showmir[][COLS], int row, int col)
{
int i = 0, j = 0;
int count = 0;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if (showmir[i][j] != ' '||showmir[i][j]!='?')
count++;
}
}
return count;
}
7. 细节优化
- 添加选择项,是排雷还是标记雷
- 当要显示雷的信息时,添加exchangmir函数来交换雷的信息(当被炸死时可以只用showmir显示游戏信息与雷的信息)
- 进入游戏界面时,采用do while循环保证进入while循环一次,而后根据玩家所选择再判断while循环是否继续
- 游戏菜单与界面优化
void exchangmire(char stormir[][COLS], char showmir[][COLS], int row, int col)
{
char tmp = ' ';
int i = 1, j = 1;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if (stormir[i][j] == '*'&&showmir[i][j]==' ')
{
tmp = stormir[i][j];
showmir[i][j] = tmp;
}
}
}
}
void selct_menu()
{
printf("|————————————————————————————————|\n");
printf("| |\n");
printf("| 1.查雷 2.标记雷 |\n");
printf("| |\n");
printf("|————————————————————————————————|\n");
}
void game_menu()
{
printf("|————————————————————————————————|\n");
printf("| |\n");
printf("| 1.paly 0.exit |\n");
printf("| |\n");
printf("|————————————————————————————————|\n");
}
int input = 0;
do
{
game_menu();
printf("请选择:>\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
default:
break;
}
} while (input);
}
8. 各个文件中的原码
#include
#include
#include
#include
#define ROWS 11
#define COLS 11
#define ROW 9
#define COL 9
void initboard(char stormir[][COLS],int rows,int cols, char ch);
void setmire(char stormir[][COLS], int row, int col);
void disaplayboard(char showmir[][COLS], int row, int col);
char countmir(char stormir[][COLS], char showmir[][COLS], int x, int y);
void exchangmire(char stormir[][COLS],char showmir[][COLS],int row,int col);
void if_extern(char stormir[][COLS], char showmir[][COLS], int x, int y);
int if_win(char showmir[][COLS], int row, int col);
void selct_menu();
void markmir(char showmir[][COLS], int row, int col, int x, int y);
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void game()
{
char stormir[ROWS][COLS] = {
0 };
char showmir[ROWS][COLS] = {
0 };
initboard(stormir,ROWS,COLS,' ');
initboard(showmir, ROWS,COLS,' ');
setmire(stormir, ROW, COL);
disaplayboard(showmir,ROW,COL);
while (1)
{
int i = 0, j = 0, k = 0, x = 0, y = 0;
char count = '0';
selct_menu();
printf("请选择要执行的选项:>\n");
scanf("%d", &k);
if (k == 1)
{
printf("请输入排查雷的坐标:>\n");
printf("行:"); scanf("%d", &i);
printf("\n");
printf("列:"); scanf("%d", &j);
if (i > 0 && i<ROW+1 && j>0 && j < COL+1)
{
if (stormir[i][j] == '*')
{
Sleep(1000);
printf("很遗憾,你被炸死了\n");
exchangmire(stormir, showmir, ROW, COL);
Sleep(1000);
disaplayboard(showmir, ROW, COL);
break;
}
else
{
countmir(stormir, showmir, i, j);
if_extern(stormir, showmir, i, j);
disaplayboard(showmir, ROW, COL);
if (if_win(showmir, ROW, COL) == ROW*COL - 10)
{
Sleep(1000);
printf("恭喜你,排雷成功!\n");
exchangmire(stormir, showmir, ROW, COL);
disaplayboard(showmir, ROW, COL);
break;
}
}
}
else
{
printf("输入非法,请重新输入:>");
}
}
else if (k == 2)
{
printf("请选择标记雷的位置:>\n");
printf("行:"); scanf("%d", &x);
printf("\n");
printf("列:"); scanf("%d", &y);
if (x > 0 && x<ROW+1 && y>0 && y < COL+1&&showmir[x][y]==' ')
{
markmir(showmir,ROW,COL,x,y);
disaplayboard(showmir, ROW, COL);
}
else
{
printf("输入非法,请重新输入:>");
}
}
else
{
printf("选择错误,请重新选择:>\n");
}
}
}
void game_menu()
{
printf("|————————————————————————————————|\n");
printf("| |\n");
printf("| 1.paly 0.exit |\n");
printf("| |\n");
printf("|————————————————————————————————|\n");
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
game_menu();
printf("请选择:>\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
default:
break;
}
} while (input);
return 0;
}
game.c中只作为函数功能的实现,上述已经将函数功能实现的原码贴出,故不再贴game.c的原码。