1.设计两个数组,设计者数组和玩家数组。
设计者数组比玩家数组大两行两列。
用来装布置的地雷数据,但只用1-(row-2)来存储,0和(row-1)什么也不放,只是为了方便扫雷时对周围8个数据的便利
2.设置生成地雷函数,采用生成随机数的方式。
3.设计两个显示函数:一个用来显示玩家下棋过程中的结果,另一个在踩到地雷后用来显示布置的所有地雷
4.难度等级:两个。简单和困难。
简单:设置(2倍数组行)个地雷;
困难:设置(5倍数组行)个地雷。
(本来还可以设置行数的多少来提升难度,但因为我的行列数用的宏定义,暂时没找到一个很好的方法通过命令行改变数组行列数)
5.设计玩家函数。玩家在屏幕上输出坐标,开始排雷。
6.设计判断是否踩雷函数。
注意:bug:用生成随机数布置地雷,可能因为生成的随机数相同,即地雷重复布置,而导致显示出的地雷数量比实际统计的地雷数量要少。
代码展示:
头文件:
game.h
#define ROW 11 //设计者数组行与列
#define COL 11
#define ROW_p (ROW - 2) //玩家数组行与列
#define COL_p (COL - 2)
#define easy_Mine 2*ROW_p //简单:地雷数量=ROW_p 通过mine可调整生成地雷数量
#define hard_Mine 5*ROW_p //困难:地雷数量=5*ROW_p
#include
#include
#include
void menu();
void game(int input);
void test();
//初始化棋盘
void IniGame(char board[ROW][COL],char board_p[ROW_p][COL_p],int row,int col);
//生成地雷
void MineGenerate(char board[ROW][COL],int row,int col,int mine_Num);
//玩家
void Player(char board[ROW][COL],char board_p[ROW_p][COL_p],int mine_Num);
//显示下棋后的结果(x y 设为空时显示空棋盘,即游戏初始界面)
void DisPlayRst(char board_p[ROW_p][COL_p],int row_p,int col_p,int x,int y);
//显示所有炸弹(游戏结束后显示)
void DisPlayerAll(char board[ROW][COL],int row,int col);
//判断是否踩雷
void JudgeMine(char board[ROW][COL],char board_p[ROW_p][COL_p],int x,int y,int mine_Num);
源文件1:用来定义各个函数
game.c
#include "game.h"
//初始化
void IniGame(char board[ROW][COL],char board_p[ROW_p][COL_p],int row,int col)
{
int i = 0,j = 0;
int row_p = row - 2,col_p = col - 2;
//程序设计者数组初始化 设计者数组比玩家数组多两行两列,
//方便结果的输出,防止地址访问溢出,同时简化算法
for(i = 0;i < row;i++)
{
for(j = 0;j < col;j++)
{
board[i][j] = ' ';
}
}
//玩家数组初始化
for(i = 0;i < row_p;i++)
{
for(j = 0;j < col_p;j++)
{
board_p[i][j] = '*';
//printf("玩家数组%d:%c\n",(i+1)*(j+1),board_p[i][j]);
}
}
}
//生成地雷
void MineGenerate(char board[ROW][COL],int row,int col,int mine_Num)
{
int x = 0,y = 0;
int i = 0,j = 0;
int count = 0;//地雷数量
srand((unsigned int)time(NULL));
do
{
x = rand()%(row-2) + 1;//row - 2 = 8,rand()%8范围是0-7,再加一范围为1—8
y = rand()%(col-2) + 1;
//printf("x,y值为:%d%d\n",x,y); //生成地雷的坐标,测试时使用,
//但是生成的地雷数可能有重复,不知道该怎么改
for(i = 1;i < (row-1);i++) //1-8
{
for(j = 1;j < (col-1);j++) //1-8
{
if(x == i && j == y)
{
board[i][j] = '+';
//棋盘的(1,1)对应的是设计者数组的(1,1),而对应玩家数组的(0,0)
count ++;
}
}
}
}while(count < mine_Num);//
printf("生成%d颗地雷\n",mine_Num); //这里有bug,如果生成地雷有重复的,这个地雷数就不准确了
//比如在(1,1)处生成三次雷,总共生成十颗雷,但实际上只能显示出8颗,因为有重复
}
//显示玩家下棋后的结果
void DisPlayRst(char board_p[ROW_p][COL_p],int row_p,int col_p,int x,int y)
{
int i = 0,j = 0;
//打印列号
printf(" ");//先空出一格来
for(i = 1;i < col_p + 1;i++)
{
printf(" %d ",i);
}
printf("\n");
for(i = 1;i < row_p + 1 ;i++)
{
//打印行号
printf(" %d ",i);
//输出第一行数据
for(j = 1;j < col_p + 1;j++)
{
if( x == i && y == j) //被改变的元素输出
{
printf(" %c ",board_p[x - 1][y -1 ]); //输出时要按玩家数组输出,所以-1
if(j < col_p)
{
printf("|");
}
}
else //未被改变的元素输出
{
printf(" %c ",board_p[i - 1][j - 1]);//note::ij循环时从1-8,但数组时0-7
if(j < col_p)
{
printf("|");
}
}
}
printf("\n");
//输出第二行分隔符
printf(" ");//行号所占一个,所以先吧行号位置空出来
for(j = 1;j < col_p + 1;j++)
{
printf("---");
if(j < col_p)
{
printf("|");
}
}
printf("\n");
}
}
//显示棋盘所有炸弹
void DisPlayerAll(char board[ROW][COL],int row,int col)
{
int i = 0,j = 0;
//打印列号
printf(" ");//先空出一格来
for(i = 1;i < col - 1;i++)
{
printf(" %d ",i);
}
printf("\n");
for(i = 1;i < row - 1;i++) //1-8
{
//打印行号
printf(" %d ",i);
//输出第一行数据
for(j = 1;j < col - 1;j++) //1-8
{
printf(" %c ",board[i][j]);
if(j < col - 2)
{
printf("|");
}
}
printf("\n");
//输出第二行分隔符
printf(" ");
for(j = 1;j < col - 1;j++)
{
printf("---");
if(j < col - 2)
{
printf("|");
}
}
printf("\n");
}
}
//玩家
void Player(char board[ROW][COL],char board_p[ROW_p][COL_p],int mine_Num)
{
int x = 0,y = 0;
while(1)
{
printf("请输入要下坐标:> (输入格式:x 空格 y)\n");
scanf_s("%d%d",&x,&y);
if(x > 0 && x < ROW -1 && y > 0 && y < COL - 1)
{
printf("输入坐标成功\n");
}
else
{
printf("输入坐标非法,请重新输入:\n");
}
JudgeMine(board,board_p,x,y,mine_Num);
if(board[x][y] == '+') //
{
//printf("炸弹引爆,游戏结束\n");
//DisPlayerAll(board,ROW,COL);
break;
}
}
}
//判断是否踩雷 或者周围有几颗雷
void JudgeMine(char board[ROW][COL],char board_p[ROW_p][COL_p],int x,int y,int mine_Num)
{
int i = 0,j = 0;
int count = 0;
//没踩中雷
if (board[x][y] != '+')
//设计者数组和玩家输入坐标刚好对应,玩家输入(1,1)就对应board[1][1]
{
int num = 0;
for(i = x - 1;i < x + 2;i++)//判断周围的炸弹数量,并显示 (x-1)--(x+1)
{
//printf("炸弹判断开始\n");
for(j = y-1;j < y + 2;j++)
{
if(board[i][j] == '+')
{
num ++;
//printf("num:%d\n",num);
//itoa(num,num_c, 10);
board_p[x - 1][y - 1] = num + '0'; //玩家输入(1,1)对应玩家数组(0,0)
//printf("%d",board_p[x - 1][y - 1]);
}
}
}
num = 0;//循环结束后将num置零
DisPlayRst(board_p,ROW_p,COL_p,x,y);
count++;
printf("%d",count);
printf("结果显示成功\n");
if(num == ROW_p*COL_p - mine_Num)
//如果扫雷次数达到总数减去布置雷的数量,剩下的全是雷,游戏胜利
//但是这里有bug就是如果生成雷有重复的,显示出的雷数就比mine_Num这个数要小,
//这个判断胜利的功能实现就不太好实现,但还不知道该怎么改
{
printf("雷已扫清,游戏胜利!!");
}
}
//踩雷了
else if(board[x][y] == '+') //
{
printf("炸弹引爆,游戏结束\n");
DisPlayerAll(board,ROW,COL);
}
}
源文件2:`
test.c
#include "game.h"
void menu()
{
printf("****************************\n");
printf("**********扫雷游戏 *********\n");
printf("**********1 . 简单**********\n");
printf("**********2 . 困难**********\n");
printf("**********3 . 退出**********\n");
printf("****************************\n");
}
void game(int input)
{
int mine_Num; //地雷数量
char board[ROW][COL] = {
0}; //设计者数组 10 10
char board_p[ROW_p][COL_p] = {
0}; //玩家数组 8 8
if(input == 1)
{
mine_Num = easy_Mine;//难度简单
}
else if(input == 2)
{
mine_Num = hard_Mine;//难度困难
}
//char board[ROW][COL] = {0};
//!!!note:定义要放在最前面,否则会报错,在数组定义前面加了if片段结果一直报错,找了老半天
//char board_p[ROW_p][COL_p] = {0};
//初始化
IniGame(board,board_p,ROW,COL);
printf("游戏初始化完成\n");
//生成地雷
MineGenerate(board,ROW,COL,mine_Num);
printf("生成地雷完成\n");
//显示所有地雷
//DisPlayerAll(board,ROW,COL); //玩家玩游戏时,不显示地雷,设计者测试时使用
//显示游戏棋盘(空)
DisPlayRst(board_p,ROW_p,COL_p,0,0);
printf("空棋盘显示完成,玩家请开始游戏\n");
//玩家玩游戏
Player(board,board_p,mine_Num);
}
void test()
{
int input = 0;
do
{
menu();
printf("请输入您的选择:> (格式:你的选择 回车)\n");
scanf_s("%d",&input);
switch(input)
{
case 1:
{
printf("扫雷游戏\n");
printf("难度:简单\n");
game(input);
break;
}
case 2:
{
printf("扫雷游戏\n");
printf("难度:困难\n");
game(input);
break;
}
case 3:
{
printf("退出游戏");
break;
}
default:
{
printf("输入有误,请重新输入\n");
break;
}
}
}while(input%3);
}
int main()
{
test();
return 0;
system("pause");
}