我们把这个游戏分成了三个文件来写,分别一个文件是头文件两个.c文件,而两个.c文件一个是扫雷的主函数,另一个是扫雷的功能实现。我们这次用的9*9的棋盘并且设置了10个雷。这个游戏我们分成四个步骤来写,第一步是建立游戏菜单,第二步建立棋盘,第三步布置雷,第四步排雷。
1.建立游戏菜单
void menu()
{
printf("****************************\n");
printf("******* 1.play ********\n");
printf("******* 0.exit ********\n");
printf("****************************\n");
}
int main()
{
srand((unsigned int)time(NULL));//这是生成随机数的函数。
int input = 0;
do
{
menu();
printf("请输入>:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("游戏结束,退出游戏\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
这个大概就是扫雷这个游戏的基本框架,通过switch这个分支语句可以进入到不同界面。
2.建立棋盘
我们建立了两个棋盘,一个棋盘存储我们的数据,一个棋盘展示给用户们。采用的是字符数组来建立我们的棋盘而不是整型数组,可以在对这个棋盘的操作方面给了便捷。并且我们设置的不是9*9的方格而是11*11的方格,因为在统计雷的个数时,在排边沿雷的时候就会缺少一些雷的个数。
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;
}
}
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("******************************************\n");
for (i = 1; 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");
}
我们使用InitBoard()函数来初始化数组,我们将统计数据的数组定义为mine数组我们给mine数组全部初始化为字符0,将展示给用户的数组定义成show数组并全部初始化为字符*。当我想到两个数组都要初始化时,调用两次就有点慢了,在主函数中
InitBoard(mine, ROWS, COLS,'0');
InitBoard(show, ROWS, COLS,'*');我分别传一个字符0一个字符*,然后我用一个set变量来接收就行了这样效率就高了。我还创建了一个DisplayBoard()函数来打印show数组。
3.布置雷
我先定义了10个雷#define EASY_COUNT 10,然后创建了一个布置雷的函数SetMine()来实现布雷,我们用rand()来随机生成10个雷但在使用rand()函数我们要调用srand((unsigned int)time(NULL));这个函数。
void SetMmine(char mine[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
4.排雷
排雷的过程有三种情况:
第一种是排到雷了那么很遗憾你被炸死了游戏结束了。
第二种是没排到雷,这样的话你就要计算以你没排到雷的为中心周围8个坐标雷的个数并统计传到show数组中去。
第三种就是你把所有雷都排出来了,那么你就成功了。
排雷我建立 GetMineCount()函数来实现。
int GetMineCount(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';
}
void FindBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;
while (win<row*col-EASY_COUNT)
{
printf("请输入坐标\n");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了\n");
DisplayBoard(mine, ROW, COL);
break;
}
else
{
int sum = GetMineCount(mine, x, y);
show[x][y] = sum + '0';
win++;
DisplayBoard(show, ROW, COL);
}
}
else
{
printf("坐标非法,请重新输入\n");
}
}
if (win == row * col - EASY_COUNT)
{
DisplayBoard(show, ROW, COL);
printf("恭喜你,成功通过游戏\n");
}
}
在统计周围8个坐标雷的个数时我们采用将以排雷的那个为中心的周围8个坐标的雷加起来了,但不能直接加起来因为我们采用的时字符数组,因为字符0-字符0=0;字符1-字符0=1这是根据ASCII值来计算的,这样的话我们只要把8个坐标加起来减去8*字符0得到就是雷的个数。但在传给show数组时得加上字符0.
5.头文件以及函数的声明和定义的常量
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 10
//为什么int rows和int cols用小写;
//对数组初始化
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set);
//打印数组
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//布雷
void SetMmine(char mine[ROWS][COLS], int row, int col);
//排雷
void FindBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);