扫雷
一个简单的扫雷,纯黑白界面
说说这个游戏功能吧:①用户可自定义行列大小,雷的数量
②增加可玩性,第一次踩到雷不会死,系统会将雷转移到其他位置
③如传统扫雷一般,若该位置周围无雷则显示周围区域直至周围有雷停止
现在说说程序吧
头文件CleanMine.h,定义两个宏变量ROW,COL,代表雷盘的行列大小,用户可根据自己喜好修改
#ifndef __Game_h__
#define __Game_h__
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#define ROW 5
#define COL 5
void PlayGame();
void InitInsideTable(char Table[ROW][COL], int mine_nuum);
void InitFaceTable(char Table[ROW][COL]);
void FirstNotDie(char Table[ROW][COL], int row, int col);
void UpdateInsideTable(char Table[ROW][COL]);
int Is_Die(char Table[ROW][COL], int row, int col);
int Is_Win(char NowTable[ROW][COL]);
int account_sign_num(char Table[ROW][COL],char sign, int row, int col);
#endif // !__Game_h__
然后就是功能函数的实现。Function.c
函数用来初始化玩家界面的棋盘,全部置为‘+’
void InitFaceTable(char Table[ROW][COL])//初始化玩家的桌面
{
memset(Table, '+', ROW * COL * sizeof(char));
}
这个函数用来初始化后台棋盘,生成随机雷,用‘*’代表雷。之后调用UpdateInsideTable(Table)函数,更新其他非雷位置.
void InitInsideTable(char Table[ROW][COL], int mine_num)//初始化后台桌面
{
int rand_row;
int rand_col;
srand((unsigned int)time(NULL));
while (mine_num)
{
rand_row = rand() % ROW ;
rand_col = rand() % COL ;
if (Table[rand_row][rand_col] != '*')
{
Table[rand_row][rand_col] = '*';
}
else
continue;
mine_num--;
}
UpdateInsideTable(Table);
}
之后是UpdateInsideTable(char Table[ROW][COL])函数,调用 account_sign_num(char Table[ROW]函数统计周围雷的数量,然后将雷数转换为对应字符数字赋值
void UpdateInsideTable(char Table[ROW][COL])
{
int i;
int j;
for (i = 0; i < ROW; i++)
for (j = 0; j < COL; j++)
{
if ('*' != Table[i][j])
{
Table[i][j] = account_sign_num(Table,'*', i, j) + 48;
}
}
}
之后就是上面代码所调用的account_sign_num(char Table[ROW]函数,统计周围雷的数量
int account_sign_num(char Table[ROW][COL],char sign,int row, int col)//显示周围雷的数量
{
int count = 0;
int i;
i = -1;
while (i < 2)
{
if ((row - 1 < 0) || (col + i > COL - 1 || col + i < 0))
{
i++;
continue;
}
else if (sign == Table[row - 1][col + i])
count++;
i++;
}
i = -1;
while (i < 2)
{
if ((col + i < 0) || (col + i > COL - 1))
{
i++;
continue;
}
else if (sign == Table[row][col + i])
count++;
i++;
}
i = -1;
while (i < 2)
{
if ((row + 1 > ROW) || (col + i < 0) || (col + i > COL - 1))
{
i++;
continue;
}
else if (sign == Table[row + 1][col + i])
count++;
i++;
}
return count;
}
再之后就是展示棋盘的函数,也是打印盘的功能函数
void ShowTable(char Table[ROW][COL])//打印桌面
{
int row;
int col;
int i = 0;
printf("现在为您显示棋盘...\n");
printf(" ");//雷盘第一行输出对应列标和格式
for (i = 0; i < COL; i++)
{
printf(" %d", i);
}
printf("\n");
printf("__");
for (i = 0; i < COL; i++)
{
printf("____");
}
printf("\n");
for (row = 0; row < ROW; row++)
{
printf("%d|", row);//第一列输出对应行标和格式
for (col = 0; col < COL; col++)
{
printf("%4c", Table[row][col]);
}
printf("\n");
printf(" |\n");
}
}
然后呢,是一个判断玩家是否死亡的功能函数,若为雷‘*’,则判死,否则不执行.
int Is_Die(char Table[ROW][COL],int row, int col)//判断是否死亡
{
if ('*' == Table[row][col])
{
printf("瓜娃子,你炸咧...\n");
return 1;
}
else
return 0;
}
再之后就是增加可玩性的功能函数,该位置为‘*’,则将调用上面的account_sign_num()函数统计周围雷的数量重新赋值并随机生成雷,更新后台雷盘.
void FirstNotDie(char Table[ROW][COL], int row,int col)//扩展功能:让第一次踩雷不死,并在其他位置生成雷,在220-223行
{
int mine_row;
int mine_col;
if (Table[row][col] == '*')
{
Table[row][col] = account_sign_num(Table,'*', row, col) + 48;//该位置为雷,计算周围雷的数量,重新赋值
do
{
mine_row = rand() % ROW;
mine_col = rand() % COL;
} while (Table[mine_row][mine_col] == '*');
Table[mine_row][mine_col] = '*';//将不是雷的随机位置变为雷
UpdateInsideTable(Table);
}
}
之后的ExpandAround()函数,便是判断该位置周围是否是雷,并扩展的功能函数
void ExpandAround(char BackTable[ROW][COL], char PlayerTable[ROW][COL], int row, int col)
{
int expand_time = 0;
int i;
expand_time = account_sign_num(BackTable, '0', row, col);
while (expand_time)
{
i = -1;
while (i < 2)
{
if ((row - 1 < 0) || (col + i > COL - 1 || col + i < 0))
{
i++;
continue;
}
else if ('+' == PlayerTable[row - 1][col + i])
{
if ('0' == BackTable[row - 1][col + i])
{
PlayerTable[row - 1][col + i] = BackTable[row - 1][col + i];
ExpandAround(BackTable, PlayerTable, row - 1, col + i);
}
else
{
PlayerTable[row - 1][col + i] = BackTable[row - 1][col + i];
}
}
i++;
}
i = -1;
while (i < 2)
{
if ((col + i < 0) || (col + i > COL - 1))
{
i++;
continue;
}
else if ('+' == PlayerTable[row][col + i])
{
if ('0' == BackTable[row][col + i])
{
PlayerTable[row][col + i] = BackTable[row][col + i];
ExpandAround(BackTable, PlayerTable, row , col + i);
}
else
{
PlayerTable[row][col + i] = BackTable[row][col + i];
}
}
i++;
}
i = -1;
while (i < 2)
{
if ((row + 1 > ROW) || (col + i < 0) || (col + i > COL - 1))
{
i++;
continue;
}
else if ('+' == PlayerTable[row + 1][col + i])
{
if ('0' == BackTable[row + 1][col + i])
{
PlayerTable[row + 1][col + i] = BackTable[row + 1][col + i];
ExpandAround(BackTable, PlayerTable, row + 1, col + i);
}
else
{
PlayerTable[row + 1][col + i] = BackTable[row + 1][col + i];
}
}
i++;
}
expand_time--;
}
}
Is_Win()判赢函数,很简单。遍历显示给用户的雷盘‘+’的数量,若等于雷‘*’的数量,则赢。
int Is_Win(char NowTable[ROW][COL])//判赢实现
{
int i;
int j;
int count = 0;
for(i = 0; i< ROW; i++)
for (j = 0; j < COL; j++)
{
if ('+' == NowTable[i][j])
count++;
else
continue;
}
return count;
}
最后的PlayGame()便是该文件的入口,调用多个函数实现游戏功能,用户可以在这里修改变量mine_num的来修改雷的数量.当然也可以放开第12的ShowTable(InsideTable)函数,来显示一次雷的位置.
void PlayGame()//游戏功能实现核心
{
char InsideTable[ROW][COL];
char FaceTable[ROW][COL];
int mine_num = 5;//雷的数量,建议赋值不要大于行列之积的一半的大小
int click_time = ROW*COL - mine_num;
int player_row;
int player_col;
InitInsideTable(InsideTable,mine_num);//初始化两个雷盘
InitFaceTable(FaceTable);
//ShowTable(InsideTable);
ShowTable(FaceTable);
while (Is_Win(FaceTable)!=mine_num)//判断输赢
{
printf("输入你选择的坐标...\n");
scanf("%d%d", &player_row, &player_col);
if (player_row >= 0 && player_col >= 0 && player_row < ROW && player_col < COL)
{
if (click_time == ROW*COL - mine_num)//第一次踩雷不死
{
FirstNotDie(InsideTable, player_row, player_col);
}
if (Is_Die(InsideTable, player_row, player_col))//如果当前位置是雷,展示并跳出循环
{
ShowTable(InsideTable);
break;
}
else
{
if (InsideTable[player_row][player_col] == '0')
{
ExpandAround(InsideTable, FaceTable, player_row, player_col);
ShowTable(FaceTable);
}
else
{
FaceTable[player_row][player_col] = InsideTable[player_row][player_col];
ShowTable(FaceTable);
}
click_time--;
}
}
else
printf("输入有误,请重新输入...");
}
if (Is_Win(FaceTable) == mine_num)
{
printf("恭喜你排雷成功...\n");
ShowTable(FaceTable);
}
}
第三个文件GameAchieve.c,展示玩家界面,也是整个程序的入口。switch()函数根据玩家的选择做出相应的功能实现.
#define _CRT_SECURE_NO_WARNINGS
#include"CleanMine.h"
void Start()
{
int choice = 0;
while (1)
{
printf("*************1. Play 2 .Exit**********\n");
printf("***************输入你的选择......*********\n");
scanf("%d", &choice);
switch (choice)
{
case 1: PlayGame();
break;
case 2:exit(1);
break;
default:
printf("数字输入有误,请重新选择...\n");
break;//如果default语句后面还有case则此处必须写break,若无则不可以不写
}
}
}
int main()
{
Start();
}
最后展示一个贼菜的扫雷图,当然大家不要忘记评论,点赞,给我这篇博客提意见哦