玩家思路:
扫雷游戏该怎么玩呢,我们想到最简单的是先选择游戏开始,然后选择难度,一般分为简单,中等难度,高等难度,选择完毕后就可以开始玩了,出现一个像棋盘的界面,然后会提示输入坐标,如果有雷就会被炸死(提高游戏趣味,第一次输入坐标遇到雷,则把雷悄悄移走),无雷会显示此坐标周围八个坐标中雷的个数。然后就一步步玩下去,如果成功把所有的雷找出,那么恭喜你成功了,或者你在玩时触碰到雷就会游戏失败。
代码思路:
那么代码中该如何实现游戏呢? 首先游戏界面经思考可得,一个数组即存放雷有显示某坐标周围雷的个数,且还要不断打印游戏界面,显然不好实现,因此应该定义2个数组,数组1中应该布雷,数组2中显示雷的个数,且不断打印数组2游戏界面,在游戏失败或者游戏成功时,打印数组1界面,需要让玩家看到所有雷的布局。
其次的是两个数组的大小问题,否则在计算最边上的坐标周围雷个数时将很难计算,所有我们可以设置2个不同的行和列,并使两个行数和列数都相差2,这样在定义不同函数时,传递不同的行列参数,可以很省精力,比如最开始两个数组和计算坐标周围雷个数时需要设置成大的行列,而布雷,排雷和打印时需要设置成小行列。
最后两个数组中应该放什么,显然应该放字符,这样打印时可避免很多问题,所以数组1中初始化为字符0,数组2中初始化为’*’,然后布雷时把雷设置成字符1,这样在计算某坐标周围雷个数时会变的很容易,最后把某坐标周围雷个数也设置成字符1,2,3,4,5,6,7,8,某坐标雷个数最多为8个。最后就是各个函数的实现了,代码分了三个文件test.h ,test.c ,game.c ,具体实现如下:
test.h----头文件
#ifndef __TEST_H__
#define __TEST_H__
#define _CRT_SECURE_NO_WARNINGS 1 //编译环境不同,主要解决scanf函数报错问题
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <time.h>
#define ROW 9 //小行数
#define COL 9 //小列数
#define EASY_COUNT 10 //难度,雷数量
#define MIND_COUNT 30
#define HARD_COUNT 50
#define ROWS ROW+2 //大行数
#define COLS COL+2 //大列数
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,int COUNT); //布雷函数声明
void FindMine (char ArrBoard[ROWS][COLS],char ShowBoard[ROWS][COLS],int row,int col,int COUNT); //排雷函数声明
int GetMineCount (char Arr[ROWS][COLS],int x,int y); //计算坐标周围雷个数函数声明
#endif __TEST_H__
test.c----文件
#include "test.h"
1.先定义菜单函数
2.在自定义游戏函数
3.主函数
void menu () // 菜单函数
{
printf ("***********************\n");
printf ("****** 1.开始 *********\n");
printf ("****** 0.退出 *********\n");
printf ("****** 2.简单 *********\n");
printf ("****** 3.中等难度 ****\n");
printf ("****** 4.高等难度 ****\n");
printf ("***********************\n");
}
void game () //游戏函数
{ int count=0;
int word;
char arr[ROWS][COLS]={0}; //定义布雷的数组,
char show[ROWS][COLS]={0}; //定义向玩家展示的数组
again:
printf ("请选择难度: "); //难度选择,三个等级
scanf ("%d",&word);
switch (word)
{
case 2 :
count=EASY_COUNT;
break;
case 3 :
count= MIND_COUNT ;
break;
case 4 :
count= HARD_COUNT ;
break;
default :
printf ("输入错误,请重新选择难度\n");
goto again;
}
InitBoard (arr,ROWS,COLS,'0'); //调用初始化函数,使布雷数组为'0'
InitBoard (show,ROWS,COLS,'*'); //调用初始化函数,使先玩家展示数组初始化为'*'
SetMine(arr,ROW,COL,count); //调用布雷函数,并传递雷的个数
DisplayBoard(show,ROW,COL); //调用打印数组函数,打印向玩家展示数组
//DisplayBoard (arr,ROW,COL); //调用打印数组函数,方便测试
FindMine (arr,show,ROW,COL,count); //调用排雷函数,并传递雷个数
}
int main ()
{
int input=0;
srand((unsigned int) time(NULL)); //这个是种子函数 为rand函数提供不同的种子 每次运行程序产生不同的随机数
do
{
menu ();
printf ("请选择游戏开始或退出: ");
scanf ("%d",&input);
switch (input)
{
case 1 :
game ();
break;
case 0 :
printf ("退出游戏\n");
break;
default :
printf ("输入错误,请重新输入\n");
break;
}
}
while (input);
system ("pause"); //系统函数,防止运行结果快闪
return 0;
}
运行界面如图:
a.选择成功时
b.选择失败时
game.c—游戏函数定义文件
#include "test.h"
1.数组初始化函数,利用memset函数给数组赋值
void InitBoard (char board[ROWS][COLS],int rows,int cols,char set)
{
memset (&board[0][0],set,rows*cols*sizeof (board[0][0])); //从二维数组的首地址开始进行赋值,把set赋给char board[ROWS][COLS]
}
}
2.打印游戏界面(打印数组函数),主要利用for循环
void DisplayBoard (char board[ROWS][COLS],int row,int col)
{
int i=0;
int j=0;
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.布雷函数,主要数组坐标随机布雷
void SetMine(char board[ROWS][COLS],int row,int col,int COUNT)
{
while (COUNT)
{
int x=rand()%row+1;
int y=rand()%col+1; //生成随机坐标
if (board[x][y]=='0') //判断此处是否有雷
{
board[x][y]='1'; //把字符1作为雷置入空坐标
COUNT--;
}
}
}
4.计算坐标周围雷个数函数,返回雷的个数
int GetMineCount (char Arr[ROWS][COLS],int x,int y)
{
return (Arr[x+1][y]+Arr[x+1][y+1]+
Arr[x+1][y-1]+Arr[x-1][y]+Arr[x-1][y+1]+
Arr[x-1][y-1]+Arr[x][y-1]+Arr[x][y+1]-8*'0'); //返回雷个数
}
5.排雷函数 (包含第一步不被炸死)
void FindMine (char ArrBoard[ROWS][COLS],char ShowBoard[ROWS][COLS],int row,int col,int COUNT)
{
int x=0;
int y=0;
int win=0;
int count=0;
int p=1;
while (win<row*col-COUNT) //判断是否排完雷
{
printf ("请重新输入坐标: "); //玩家输入坐标
scanf ("%d%d",&x,&y);
if (x>=1 && x<=row && y>=1 && y<=col) //判断坐标是否合理
{
if (ArrBoard[x][y]=='1') //判断是否遇到雷
{
if (p==1) //判断是否是第一次输入坐标遇雷
{
p++;
ArrBoard[x][y]='0'; //把雷移走
SetMine(ArrBoard, row, col,1); //重新布1颗雷
count=GetMineCount(ArrBoard,x,y); //计算坐标周围雷个数
ShowBoard[x][y]=count+'0'; //把雷个数放入向玩家展示数组的坐标中
DisplayBoard (ShowBoard,row,col); //打印游戏界面
// DisplayBoard (ArrBoard,row,col); //打印布雷界面,方便测试
}
else
{
printf ("游戏失败\n"); //不是第一次输入坐标遇到雷,则提示游戏失败
DisplayBoard (ArrBoard,row,col); //打印布雷界面,让玩家知道为何游戏失败
break;
}
}
else
{ //输入坐标无雷
p++;
count=GetMineCount(ArrBoard,x,y);
ShowBoard[x][y]=count+'0';
DisplayBoard (ShowBoard,row,col); //打印游戏游戏界面
win++;
}
}
else //坐标不合理
{
printf ("坐标错误,请重新输\n"); //则提示重新输入坐标
}
}
if(win==row*col-COUNT) //判断雷排完
{
printf ("恭喜你成功\n"); //则提示游戏成功
DisplayBoard (ArrBoard,ROW,COL); //打印布雷数组,使玩家知道有布雷界面
}
}
游戏运行界面:
a.高等难度成功游戏界面:(把雷调成row*col-1个,方便测试)
此图片表明第一次输入坐标遇到雷时不死
b.简单游戏失败界面:(玩家玩时游戏界面)