win10过后大家的电脑想必都没用了扫雷小游戏了吧。今天我们用C语言基础的数组,循环,条件语句等基础知识挑战写出扫雷游戏。
1、扫雷的规则
简单介绍一下扫雷的规则,我们首先在棋盘随机点开一个格子,然后格子会显示以他为中心附近3×3的格子中包含的雷数,我们根据雷数判断雷的位置
2、编写扫雷程序前的准备工作
对于一个比较复杂的程序实现,我们需要把它工程化,细分化,分为不同的模块,这样有利于我们思路的建立和程序的编写
这里我们分为三个文件,头文件game.h用来存放各种头文件,test.c是用来实现用户进入游戏以及调用游戏函数,game.c包含了游戏中各个函数的分块实现。
3、初步构想
我们现在想写的是一个9×9的最初级的扫雷版本,我们需要两个棋盘,一个实玩家能看见的显示雷数和格子的,一个是埋雷(内置的,便于开发者初始化棋盘)。然后我们大概需要有显示棋盘的函数,玩家下棋的函数,显示周围雷数的函数,以及判断输赢的函数。这里,我想说明一点,为了方便统计棋盘边上的那些格子,我们采用11*11的二维数组,并且多余的那两行两列我们不初始化,已就相当于便于我们编写函数的操作了。
4、函数的实现,主体部分的完成
(一)首先,我们完成用户进入游戏的过程test.c并引出game.c的代码部分
见下代码,详细讲解在注释中
#include "game.h"
void menu()
{
printf("*******************************\n");
printf("******1、 play *****\n");
printf("******0、 exit *****\n");
printf("*******************************\n");
}
void game()
{
char mine[ROWS][COLS] = { 0 };//存放布置好雷的信息,0表示没有雷,1表示有雷
char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息,先显示*,后显示周围雷的个数
//初始化数组内容为指定的内容
//mine数组在没有布置雷的时候,都是'0'
InitBoard(mine, ROWS, COLS,'0');
//show数组在没有排查雷的时候,都是'*'
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)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
printf("扫雷\n");
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
(二)我们根据test.c中构想的函数,把他们写到game.h头文件中,以便写好后调用
见下为game.h中的内容
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS ROW+2
#include<stdio.h>
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set);
void DisplayBoard(char board[ROWS][COLS],int row,int col);
void SetMine(char board[ROWS][COLS], int row, int col);
#define EASY_COUNT 2//雷数
#include<time.h>
#include<stdlib.h>
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col);
void remove_NoMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y,int win);
int Is_win(char show[ROWS][COLS], int row, int col);
(三)到这里我们就要着重开始写最主要的函数部分了,我们根据所构想的函数一一拆分然后一一实现各个部分,详解如下
#include"game.h"
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(j=0;j<=col;j++)
{
printf("%d ", j);
}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");
}
void SetMine(char board[ROWS][COLS], int row, int col)//布置雷
{
int count = EASY_COUNT;
while(count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if(board[x][y]=='0')
{
board[x][y] = '1';
count--;
}
}
}
int get_mine_count(char board[ROWS][COLS], int x, int y)//输出附近3×3的雷数
{
return (board[x - 1][y] +
board[x - 1][y - 1] +
board[x][y - 1] +
board[x + 1][y - 1] +
board[x + 1][y] +
board[x + 1][y + 1] +
board[x][y + 1] +
board[x - 1][y + 1] - 8 * '0');
}
void remove_NoMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)//附近都无雷,把棋盘扩展开来知道遇到雷
{
if (x >= 1 && x <= ROW && y >= 1 && y <= COL)//判断坐标是否合法
{
int i = 0;
int j = 0;
show[x][y] = get_mine_count(mine, x, y) + '0';//将展示的数组里坐标更改为周围雷的个数
if (show[x][y] == '0')
{
show[x][y] = ' ';//如果周围雷的个数为0,则设置此坐标为“空格”
//判断此坐标周围坐标是否还有可设为空格的坐标
for (i = -1; i <= 1; i++)
{
for (j = -1; j <= 1; j++)
{
if (show[x + i][y + j] == '*')
remove_NoMine(mine, show, x + i, y + j);//递归
}
}
}
}
}
Is_win(char show[ROWS][COLS], int row, int col)//判断输赢
{
int win = 0;
int i = 0;
int j = 0;
for(i=1;i<=row;i++)
{
for (j = 1; j <= col; j++)
if (show[i][j] == '*')
win++;
}
if (win == EASY_COUNT)
return 1;
else
return 0;
}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//玩家输入坐标,玩游戏的部分
{
int x = 0;
int y = 0;
int win = 0;//找到非雷的个数
int ret = 0;
while(ret!=1)
{
printf("请输入要排查的坐标:>");
scanf("%d%d", &x, &y);
if(x>=1&&x<=row&&y>=1&&y<=col)
{if(show[x][y]!='*')
{
printf("该坐标排查过了,不能重复排查\n");
}
else{
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了\n");
DisplayBoard(mine, ROW, COL);
break;
}
else//如果不是雷
{//统计mine数组中x,y坐标周围有几个雷
remove_NoMine(mine,show, x, y);//显示周围雷的个数
ret=Is_win(show, ROW, COL);
DisplayBoard(show, ROW, COL);
}
}
}
else
{
printf("输入坐标非法,请重新输入\n");
}
}
if (ret == 1)
printf("你赢了\n");
}
最后的运行结果如下
快自己尝试一下吧,祝你学业有成。