复杂的逻辑,都是可以通过简单的尝试轻松实现的!
扫雷游戏的想法:
(1)我们想要一个9*9的数组,其中存放了每个格子是否有雷(1代表有雷,0代表没有雷)
(2)为了防止冲突,我们还想要一个9*9的数组,其中放置提示雷数量的相关信息
(3)不知道周围雷的数目时,我们标记格子为*,保留神秘感
(4)为了使得格子中既能放置数字也可以放置字符,我们选择两个char类型的数组
(5)将mine数组中均标记为1,将show数组中均标记为*
(6)show每个格子的计算规则是统计在mine中的对应格子周围的8个格子中0的个数(注意判断是否越界!!)
(7)为了放置越界问题的产生,不妨将mine数组自动改成11*11大一号的数组
(8)为了两个数组之间抓换的麻烦,将show数组也改为11*11的数组
(9)以do while结构放置函数主体,一旦input为0则停止游戏,一旦input为1则开始扫雷游戏,其他输入提示输入错误
(10)需要menu函数提示你的输入
(11)在game函数中实现具体的扫雷游戏的过程
(12)分别创建mine和show两个数组分别表示布置好的雷的数组和排查出的雷的信息
(13)InitBoard函数用来创建初始化的数组,同时为了满足既能初始化mine也能初始化show数组,可以传递一个set参数来区分初始化的数组对象,传递的参数还有ROWS和COLS
(14)把棋盘打印出来看一下初始化的结果,用DisplayBoard函数,但是注意传递参数是ROW和COL。虽然传递的参数是ROW,但是由于原数组的ROWS行数,所以函数体中还是ROWS
(15)打印时为了清楚,标记上具体的行号和列号
(16)SetMine函数用以在show数组中随机放入10个雷,为了使每一次放置的雷的数目不尽相同,用当前时间作为随机数的产生根写在主函数中
(17)get_mine_count函数用以提示如果你寻找的位置不是雷,则提供给你在该位置附近有几个雷的有用信息,方式是通过计算8个格子中雷的数目并加和。注意其中的0和1存储的是字符,如果要进行加减法的运算要记得转换成数字0和1
(18)如果碰到雷,就被炸死了,并展示show数组中全部的10个雷的位置
(19)胜利条件是除了标记有雷的10个方格之外其他方格均被访问过一遍
(20)避免被排查过的坐标再次被排查
#include
#include
#include
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 10
void menu()
{
printf("***************************\n");
printf("****** 1. play **\n");
printf("****** 0. exit **\n");
printf("***************************\n");
printf("***************************\n");
}
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)
{
return (board[x-1][y-1]+
board[x-1][y]+
board[x-1][y+1]+
board[x][y-1]+
board[x][y+1]+
board[x+1][y-1]+
board[x+1][y]+
board[x+1][y+1] - 8 * '0');
}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;//找到非雷的个数
while(win < col * row - EASY_COUNT)
{
while(1)
{
printf("请输入要排查的坐标:>");
scanf("%d%d", &x, &y);
if(x >= 1 && x <= row && y >= 1 && y <= row)
{
if(show[x][y] != '*')
printf("该坐标被排查过了,不能重复排查\n");
else
{
//如果是雷
if(mine[x][y] == '1')
{
printf("很遗憾,你被炸死了\n");
DisplayBoard(mine,ROW,COL);
break;
}
//如果不是雷
else
{
win++;
//统计mine数组中x,y坐标周围有几个雷
int count = get_mine_count(mine,x,y);
show[x][y] = count + '0';//转换成数字字符
DisplayBoard(show,ROW,COL);
}
}
}
else
{
printf("输入的坐标非法,请重新输入:>");
}
}
}
if(win < col * row - EASY_COUNT)
{
printf("恭喜你,排雷成功\n");
DisplayBoard(mine,ROW,COL);
}
}
void game()
{
char mine[ROWS][COLS] = {0};//存放布置好的雷的信息
char show[ROWS][COLS] = {0};//存放排查出的雷的信息
//初始化数组的内容为指定的内容
//mine数组在没有布置雷时,都是0
InitBoard(mine,ROWS,COLS,'0');
//show数组在没有排查雷时,都是'*'
InitBoard(show,ROWS,COLS,'*');
// DisplayBoard(mine,ROW,COL);
//设置雷
SetMine(mine,ROW,COL);
// DisplayBoard(mine,ROW,COL);
DisplayBoard(show,ROW,COL);
FindMine(mine,show,ROW,COL);
}
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;
}
但是该代码只完成了基础功能,欢迎大家在评论区讲这个基础代码进行改进:
其中可改进的功能包括但不限于:
(1)可标记功能——已知某个位置有雷,可以标记一下以方便记忆
(2)展开一片功能:该坐标不是雷,该坐标周围没有雷且该坐标没有被排查过(可以用递归算法分别检查其周围的8个坐标是否满足这三个条件)——这些坐标不用显示数字,可以直接放置空格
不仅可以用C语言程序进行编写,也推荐大家尝试C++和Python等语言尝试实现一些较大的程序的功能,我们一起努力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)