要求实现的功能如下:
1.初始化两个棋盘,一个用来设置有雷与无雷即为‘1’和‘0’,另一个先全部初始化为*。
注意:初始化棋盘为11行×11列;显示只需9行×9列。
2.只需向玩家展示是*的棋盘。
3.游戏一开始就要布置雷阵,随机产生雷。
4.玩家排雷,其中第一步不能为雷;
若是雷,重新设置雷;
若第一步不是雷,要计算周围雷数并且展开计算直到边界一圈都为雷数。
5.判断输赢。若玩家在没有被炸死的情况下还有十个未排除即为雷数,游戏胜利。
以下是代码实现:
头文件:
#define COLS COL+2
#define EASY_COUNT 10
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<stdlib.h>
void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set);
void DisplayBoard(char arr[ROWS][COLS], int row, int col);
void SetMine(char arr[ROWS][COLS], int row, int col);
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col);
int FindMineCount(char mine[ROWS][COLS], int x, int y);
int IsWin(char show[ROWS][COLS],int row,int col);
void SafeFirst(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
void ExtendBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
#endif //__GAME_H_
源文件game.c`
#include"game.h"
void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set){
memset(&arr[0][0], set, rows*cols*sizeof(arr[0][0]));
}
void DisplayBoard(char arr[ROWS][COLS], int row, int col){
int i = 0;
int j = 0;
//打印列号
for (i = 0; i <= row; i++){
printf("%d ", i);
}
printf("\n");
//打印棋盘
for (i = 1; i <= row; i++){
printf("%d ", i);// 行号
for (j = 1; j <= col; j++){
printf("%c ", arr[i][j]);
}
printf("\n");
}
printf("\n");
}
//设雷
void SetMine(char arr[ROWS][COLS], int row, int col){
int x = 0;
int y = 0;
int count = EASY_COUNT;
while (count){
x = rand() % 9 + 1;
y = rand() % 9 + 1;
if (arr[x][y] == '0'){
arr[x][y] = '1';
count--;
}
}
}
//排雷
//排雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col){
int x = 0;
int y = 0;
int count = 0; //排查到的雷数
int ret = 0; //排查次数
while (IsWin(show, ROW, COL)!=EASY_COUNT){
printf("请输入要排查的坐标->\n");
scanf("%d,%d", &x, &y);
if (x >= 1 && x <= 9 && y >= 1 && y <= 9){ //坐标要合法
if (mine[x][y] == '1'){
//若第一次排到雷,将其坐标变为‘0’
if (ret == 0){
SafeFirst(mine, show, ROW, COL); //再找到一个‘0’的地方将其设为雷
ExtendBoard(mine, show, ROW, COL, x, y); //展开棋盘
DisplayBoard(show, ROW, COL);
ret++;
break;
}
//若不是第一次,则游戏失败
else{
printf("很遗憾,你被炸死了\n");
printf("一共排查了%d次\n", ret);
break;
}
}
//若第一步不是雷
else{ //排查周围雷的个数
ExtendBoard(mine, show, ROW, COL, x, y);
DisplayBoard(show, ROW, COL);
ret++;
}
}
else{
printf("输入坐标不合法,请重新输入\n");
break;
}
}
if (IsWin(show, ROW, COL) == EASY_COUNT){
printf("恭喜你!排雷成功!\n");
DisplayBoard(show, ROW, COL);
printf("一共排查了%d次\n",ret);
}
}
//排查周围雷的个数
//排查输入位置的周围八个有没有雷,前提将雷设为‘1’,数其之和为多少,注意字符和数字的转换
int FindMineCount(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';
}
//判断输赢,在玩家没有被炸死的情况下如果排查完所有的坐标还剩下十个雷即为雷的个数,排雷成功
int IsWin(char show[ROWS][COLS], int row, int col){
int i = 0;
int j = 0;
int count = 0;
for (i = 0; i < row; i++){
for (j = 0; j < col; j++){
if (show[i][j] == '*')
count++;
}
}
return count;
}
//第一步若是雷,修改坐标,在没有雷的地方布雷
void SafeFirst(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col){
int x = 0;
int y = 0;
int count = 0;
int empty = 1;
if (mine[x][y] == '1'){
mine[x][y] = '0';
count = FindMineCount(mine, x, y);
show[x][y] = count + '0';
}
while (empty){
x = rand() % 9 + 1;
y = rand() % 9 + 1;
if (mine[x][y] == '0'){
mine[x][y] = '1';
empty--;
}
}
}
//一次要展开一片没有雷的地方,排查到的雷数作为边界
void ExtendBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col,int x,int y){
int count = FindMineCount(mine, x, y);
if (count == 0){
show[x][y] = ' ';
if ((x - 1 > 0) && (y > 0) && (show[x - 1][y] == '*'))
ExtendBoard(mine, show, ROW, COL, x - 1, y);
if ((x - 1 > 0) && (y - 1 > 0) && (show[x - 1][y - 1] == '*'))
ExtendBoard(mine, show, ROW, COL, x - 1, y - 1);
if ((x > 0) && (y - 1 > 0) && (show[x][y - 1] == '*'))
ExtendBoard(mine, show, ROW, COL, x, y - 1);
if ((x + 1 > 0) && (y + 1 > 0) && (show[x + 1][y + 1] == '*'))
ExtendBoard(mine, show, ROW, COL, x + 1, y + 1);
if ((x + 1 > 0) && (y > 0) && (show[x + 1][y] == '*'))
ExtendBoard(mine, show, ROW, COL, x + 1, y);
if ((x + 1 > 0) && (y + 1 > 0) && (show[x + 1][y + 1] == '*'))
ExtendBoard(mine, show, ROW, COL, x + 1, y + 1);
if ((x > 0) && (y + 1 > 0) && (show[x][y + 1] == '*'))
ExtendBoard(mine, show, ROW, COL, x, y + 1);
if ((x - 1 > 0) && (y + 1 > 0) && (show[x - 1][y + 1] == '*'))
ExtendBoard(mine, show, ROW, COL, x - 1, y + 1);
}
else
show[x][y] = count + '0';
}
源文件test.c
#include "game.h"
void menu(){
printf("************ 扫雷小游戏 *************\n");
printf("************1. 开始游戏 *************\n");
printf("************0. 退出游戏 *************\n");
printf("***************************************\n");
}
void game(){
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
SetMine(mine, ROW, COL);
//DisplayBoard(mine, ROW, COL);
DisplayBoard(show, ROW, COL);
FindMine(mine,show, ROW, COL);
}
int main(){
int input = 0;
srand((unsigned int)time(NULL));
do{
menu();
printf("请输入选择-> \n");
scanf("%d", &input);
char ch;
while(((ch=getchar()!='\n')&&(ch!=EOF)){
;
} //避免输入坐标不合法时程序出现死循环
switch (input){
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}