这次是写一个扫雷的小游戏,可实现周围没雷时展开和第一次排雷不被炸死(防止欧皇直接暴毙!)。
首先我们先梳理代码思路:
1、既然要展示和布雷,所以我们需要2个二维数组,一个用来展示给观众,一个显示雷利于我们编程,我们将雷数组初始化为 0 ,将展示的数组初始化为 * ,保持神秘~ 2、我们需要将雷布置到雷数组中去,当然是随机布置; 3、我们还需要一个安全函数,就是当第一次排雷的时候不被炸死;(就是如果第一次排的是雷,就将此位置的雷转移) 4、排雷的过程,包括了如何展开,还有表明旁边有几颗雷;
1、初始化数组(mine和show),而且为了边上的坐标也能排雷,所以需要建的数组要比棋盘多两行两列。然后就是初始化数组(mine初始化为字符0,show初始化为 *)
void InitBoard(char board
[ROWS
][COLS
], int rows
, int cols
, char set
)
{
int i
= 0;
int j
= 0;
for (i
= 0; i
< rows
; i
++)
{
for (j
= 0; j
< cols
; j
++)
{
board
[i
][j
] = set
;
}
}
}
2、打印数组,当然要都打印出来以便我们测试(为了排雷方便,我们给数组加上了序号)
void DisplayBoard(char board
[ROWS
][COLS
], int row
, int col
)
{
int i
= 0;
int j
= 0;
printf("----------------------------------\n");
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");
}
printf("----------------------------------\n");
}
3、将雷布置到 mine数组中去,这里我们需要用到随机数,我们用的是rand()这个函数来产生随机数,当然范围要控制在数组范围中
void SetMine(char mine
[ROWS
][COLS
], int row
, int col
)
{
int x
= 0;
int y
= 0;
int count
= EASY_COUNT
;
while (count
)
{
x
= rand() % row
+ 1;
y
= rand() % col
+ 1;
if (mine
[x
][y
] == '0')
{
mine
[x
][y
] = '1';
count
--;
}
}
}
4、安全函数,这个函数的作用是保证我们第一次排雷不被炸死…
void SafeMine(char mine
[ROWS
][COLS
],char show
[ROWS
][COLS
],int row
, int col
)
{
int ret
= 1;
int x
= 0;
int y
= 0;
int count
= 0;
printf("请输入你要排查的坐标:");
scanf("%d%d", &x
,&y
);
if (mine
[x
][y
] == '1')
{
mine
[x
][y
] = '0';
count
= GetMine(mine
, x
, y
);
show
[x
][y
] = count
+ '0';
while (ret
)
{
if (mine
[x
][y
] == '1')
{
int m
= rand() % 9 + 1;
int n
= rand() % 9 + 1;
mine
[x
][y
] = '0';
mine
[m
][n
] = '1';
}
ret
--;
}
}
OpenMine(mine
, show
, row
, col
,x
,y
);
DisplayBoard(show
, row
, col
);
}
5、最后就是排雷的过程了,展开函数也在里面(展开函数是用递归来完成的)
void FindMine(char mine
[ROWS
][COLS
], char show
[ROWS
][COLS
], int row
, int col
)
{
int x
= 0;
int y
= 0;
int win
= 0;
int count
= 0;
while (1)
{
printf("请输入要排查的坐标:");
scanf("%d%d", &x
, &y
);
if (x
>= 0 && x
<= row
&& y
>= 0 && y
<= col
)
{
if (mine
[x
][y
] == '1')
{
printf("很遗憾,你被炸死了!\n");
DisplayBoard(mine
, row
, col
);
break;
}
else
{
count
= GetMine(mine
, x
, y
);
show
[x
][y
] = count
+'0';
OpenMine(mine
, show
, row
, col
, x
, y
);
DisplayBoard(show
, row
, col
);
if (MyWin(show
,row
,col
) == EASY_COUNT
)
{
break;
}
}
}
else
{
printf("坐标非法,请重新输入!\n");
}
}
if (MyWin(show
, row
, col
) == EASY_COUNT
)
{
printf("恭喜你排雷成功!\n");
DisplayBoard(mine
, row
, col
);
}
}
void OpenMine(char mine
[ROWS
][COLS
], char show
[ROWS
][COLS
], int row
, int col
, int x
, int y
)
{
int ret
= 0;
ret
= GetMine(mine
, x
, y
);
if (ret
== 0) {
show
[x
][y
] = ' ';
if (x
- 1>0 && y
>0 && show
[x
- 1][y
] == '*')
OpenMine(mine
, show
, row
, col
, x
- 1, y
);
if (x
- 1>0 && y
+ 1 <= col
&& show
[x
- 1][y
+ 1] == '*')
OpenMine(mine
, show
, row
, col
, x
- 1, y
+ 1);
if (x
>0 && y
+ 1 <= col
&& show
[x
][y
+ 1] == '*')
OpenMine(mine
, show
, row
, col
, x
, y
+ 1);
if (x
+ 1 <= row
&& y
+ 1 <= col
&& show
[x
+ 1][y
+ 1] == '*')
OpenMine(mine
, show
, row
, col
, x
+ 1, y
+ 1);
if (x
+ 1 <= row
&& y
>0 && show
[x
+ 1][y
] == '*')
OpenMine(mine
, show
, row
, col
, x
+ 1, y
);
if (x
+ 1 <= row
&& y
- 1>0 && show
[x
+ 1][y
- 1] == '*')
OpenMine(mine
, show
, row
, col
, x
+ 1, y
- 1);
if (x
>0 && y
- 1>0 && show
[x
][y
- 1] == '*')
OpenMine(mine
, show
, row
, col
, x
, y
- 1);
if (x
- 1>0 && y
- 1>0 && show
[x
- 1][y
- 1] == '*')
OpenMine(mine
, show
, row
, col
, x
- 1, y
- 1);
}
else
{
show
[x
][y
] = GetMine(mine
, x
, y
) + '0';
}
}
6、其中有一个GetMine函数是用来统计周围有多少雷,这个函数写的很巧妙,这也是我们为什么非要设计0和1作为雷数组
int GetMine(char mine
[ROWS
][COLS
], int x
, int y
)
{ return mine
[x
- 1][y
] +
mine
[x
- 1][y
- 1] + mine
[x
][y
- 1]
+ mine
[x
+ 1][y
- 1] + mine
[x
+ 1][y
] +
+ mine
[x
+ 1][y
+ 1] + mine
[x
][y
+ 1] +
+ mine
[x
- 1][y
+ 1] - 8 * '0';
}
总结:这个游戏总体来说不是很难,难点就在于展开的那里,是用递归来进行完成的,总体设计和三子棋的界面一样,我们需要注意的就是雷的布置和雷的统计还有雷的展开。