亚马逊网站做外贸,阿里巴巴网络营销方式,成都专门做网络推广的公司,网站模板中文乱码文章目录 1. 游戏分析和设计1.1扫雷游戏的功能说明1.2数据结构的分析与设计 2.代码实现2.1基本框架2.2初始化棋盘2.3打印棋盘2.4布置雷2.4统计周围雷的个数2.5排查雷2.6展开一片 3.完成代码3.1game.h3.2 game.c3.3test.c 学习完了函数和数组#xff0c;让我们做个扫雷小游戏巩… 文章目录 1. 游戏分析和设计1.1扫雷游戏的功能说明1.2数据结构的分析与设计 2.代码实现2.1基本框架2.2初始化棋盘2.3打印棋盘2.4布置雷2.4统计周围雷的个数2.5排查雷2.6展开一片 3.完成代码3.1game.h3.2 game.c3.3test.c 学习完了函数和数组让我们做个扫雷小游戏巩固一下所学的知识把 1. 游戏分析和设计
1.1扫雷游戏的功能说明
使用控制台操作通过菜单实现选择棋盘为9×9默认随机布置10个雷排查雷 如果排查的位置不是雷就显示周围有几个雷排查位置是雷游戏结束玩家失败把10个雷全部排除游戏结束玩家成功
1.2数据结构的分析与设计
扫雷的过程中布置的雷和排查出的雷的信息都需要存储所以我们需要⼀定的数据结构来存储这些信息。因为我们是9×9的棋盘所以我们可以用一个9×9的数组来存放数据,如下图如果这个位置是雷就存放1不是雷就存放0. 假设我们现在要排查(66)这个位置是否有雷可以实现。但是如果我们排查(11)这个位置是否有雷的话那么数组就会越界。 为了避免数组越界我们可以把这个数组扩大一圈这样就不会出现越界问题了。 再继续分析我们在棋盘上布置了雷有雷的位置为1非雷的位置为0如果我们排查了一个位置并且这个位置周围有一个雷那么这个位置应该显示为1。那么问题来了该位置显示的1是雷呢还是周围有1个雷呢
所以为了避免混淆我采取下面的方式 我们用两个棋盘⼀个棋盘对应⼀个数组mine存放布置好的雷的信息再给另外⼀个棋盘对应另外⼀个数组show存放排查出的雷的信息。这样就互不⼲扰了把雷布置到mine数组在mine数组中排查雷排查出的数据存放在show数组并且打印show数组的信息给后期排查参考。 同时为了保持神秘show数组开始时初始化为字符 ‘*’为了保持两个数组的类型⼀致可以使⽤同⼀套函数处理mine数组最开始也初始化为字符’0’布置雷改成’1’
对应的数组为 char mine[ROWS][COLS]; //用来存放布置雷的信息char show[ROWS][COLS]; //用来存放排查雷的信息话不多说直接上代码。
2.代码实现
2.1基本框架
void menu()
{printf(*******************************\n);printf(********* 1.play *********\n);printf(********* 0.exit *********\n);printf(*******************************\n);
}
void game()
{//实现游戏的各种操作对数组
}int main()
{int input 0;//打印菜单do{menu();printf(请选择);scanf(%d, input);switch (input){case 1:printf(玩游戏\n);game();break;case 0:printf(退出游戏\n);break;default:printf(选择错误请重新选择!\n);break;}} while (input);return 0;
}2.2初始化棋盘
为了使一个函数能实现两种符号的打印我们让他把需要打印的符号传过来 调用 InitBoard(mine, ROWS, COLS ,0);InitBoard(show, ROWS, COLS, *);void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{int i 0;for (i 0; i rows; i){int j 0;for (j 0; j cols; j){board[i][j] set;}}
}2.3打印棋盘
为了看的更清楚我们也打印上一些分割线
void DisPlay(char board[ROWS][COLS], int row, int col)
{printf(-------------扫雷-------------\n);int i 0;//打印行号for (i 0; i row; i){printf(%d , i);if (i 0){printf(|);}}printf(\n);//打印行分割线for (i 0; i row; i){printf(--);if (i 0){printf(|);}}printf(\n);for (i 1; i row;i){//打印列分割线printf(%d |, i);int j 0;//打印列号for (j 1; j col; j){printf(%c , board[i][j]);}printf(\n);}printf(-------------扫雷-------------\n);
}效果如下
2.4布置雷
采用rand()随机生成10个坐标
判断该坐标是不是雷 不是雷将该坐标设置为雷是雷重新生成坐标
void SetMine(char board[ROWS][COLS])
{//需要布置几个雷Count_mine 10int count Count_mine;while (count){//对9取余余0-8 加1正好为1-9int x rand() % 9 1;int y rand() % 9 1;if (board[x][y] 0){board[x][y] 1;count--;}}
}2.4统计周围雷的个数
统计周围八个坐标是雷的个数其实就是遍历一个二维数组如下图
int Around_Mine(char board[ROWS][COLS], int x, int y)
{int count 0;int i 0;for (i x - 1; i x 1; i){int j 0;for (j y - 1; j y 1; j){if (board[i][j] 1){count;}}}return count;
}2.5排查雷
玩家输入坐标
判断该坐标是否合法 合法 判断该坐标位置是不是雷 是雷游戏结束玩家输不是雷统计周围雷的个数显示在该坐标上继续排查 直到所有非雷位置被排查完毕游戏结束玩家赢 不合法 重新输入坐标
void FindMine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{int x 0;int y 0;int win_count 0;while (win_count row * col - Count_mine){printf(请输入要排查的坐标);scanf(%d %d, x, y);if (x 1 x 9 y 1 y 9){if (mine[x][y] 1){printf(很遗憾你踩到雷了游戏结束\n下面为雷阵图\n);DisPlay(mine, row, col);break;}else{//该位置不是雷统计周围有几个雷int count Around_Mine(mine ,x, y);show[x][y] count - 0;win_count;}}else{printf(坐标错误请重新输入\n);}}if (win_count row * col - Count_mine){printf(恭喜你所有的雷都被你排除了\n);}
}为了方便测试代码我将雷的数量设置为78个测试效果如下 这样其实已经可以玩了吧但是又好像不是那么的完美真正的扫雷好像是你一点展开一大片呀如下图
2.6展开一片
如图所示我点击的是15这个位置周围的是依据什么展开的呢 仔细观察你会发现如果我们选的格子(x,y)不是雷那么就依次对它周围八个格子进行同样的查雷操作因此我们需要写出一个展开函数OpenBoard在对我们选择的格子进行查完之后再依次对它周围的格子进行查雷如此反复调用该函数。 但是存在一个问题当我们点击x,y后会对他周围的八个坐标进行查找也就是到了x1y1该坐标不是雷又会对它周围的八个坐标查找这就又到了x,y位置此时函数就走不出来了那怎么办呢 我们可以将两个棋盘都利用起来具体思路如下
对x,y周围八个坐标进行查找
周围坐标都没有雷将该坐标置为空 排查该坐标周围的八个坐标 将周围坐标的周围八个坐标都不是雷的坐标置为空 如此递归下去一定要读懂周围坐标的周围八个坐标有雷该坐标就显示周围雷的个数 周围有雷则该坐标显示周围雷的个数 如图所示我点击的(x,y)坐标该坐标不是雷且周围八个不是雷我就将该坐标置为空依次检查周围的八个坐标周围。检查到1号坐标该坐标周围也没有雷就将1号坐标置为空在检查1号坐标周围的8个坐标检查到2号坐标发现二号坐标周围有雷那么二号坐标就不能置为空应该显示该坐标周围雷的个数递归停止。 每个位置都按照上述步骤一次判断就可展开一片。
void OpenBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{int count 0;int i 0;int j 0;for (i x - 1; i x 1; i){for (j y - 1; j y 1; j){//该坐标周围雷的个数if (mine[i][j] 1){count;}}}if (count 0){show[x][y] ;win_count;}else{show[x][y] count 0;win_count;}if (show[x][y] ){for (i x - 1; i x 1; i){for (j y - 1; j y 1; j){//该坐标不是雷并且没有被排查过下标也不能越界if (mine[i][i] ! 1 show[i][j] * (i 1 i ROW) (j 1 j COL)){OpenBoard(mine, show, i, j);}}}}
}3.完成代码
3.1game.h
各种头文件
#pragma once
#includestdio.h
#includetime.h
#includestdlib.h//可操作的数组大小
#define ROW 9
#define COL 9//实际大小
#define ROWS ROW2
#define COLS COL2
//雷的数量
#define Count_mine 3
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//打印棋盘
void DisPlay(char board[ROWS][COLS], int row, int col);
//布雷
void SetMine(char board[ROWS][COLS]);
//计算周围有多少雷
int Around_Mine(char board[ROWS][COLS], int x, int y);
//排查雷
void FindMine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col);
//展开周围
void OpenBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);3.2 game.c
各种功能的实现
#define _CRT_SECURE_NO_WARNINGS 1
#includegame.hvoid InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{int i 0;for (i 0; i rows; i){int j 0;for (j 0; j cols; j){board[i][j] set;}}
}void DisPlay(char board[ROWS][COLS], int row, int col)
{printf(----------扫雷----------\n);int i 0;//打印行号for (i 0; i row; i){printf(%d , i);if (i 0){printf(|);}}printf(\n);//打印行分割线for (i 0; i row; i){printf(--);if (i 0){printf(|);}}printf(\n);for (i 1; i row;i){//打印列分割线printf(%d |, i);int j 0;//打印列号for (j 1; j col; j){printf(%c , board[i][j]);}printf(\n);}printf(----------扫雷----------\n);printf(\n);
}void SetMine(char board[ROWS][COLS])
{//需要布置几个雷Count_mine 10int count Count_mine;while (count){//对9取余余0-8 加1正好为1-9int x rand() % 9 1;int y rand() % 9 1;if (board[x][y] 0){board[x][y] 1;count--;}}
}int Around_Mine(char board[ROWS][COLS], int x, int y)
{int count 0;int i 0;for (i x - 1; i x 1; i){int j 0;for (j y - 1; j y 1; j){if (board[i][j] 1){count;}}}return count;
}
//排查完的个数
int win_count 0;void OpenBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{int count 0;int i 0;int j 0;for (i x - 1; i x 1; i){for (j y - 1; j y 1; j){//该坐标周围雷的个数if (mine[i][j] 1){count;}}}if (count 0){show[x][y] ;win_count;}else{show[x][y] count 0;win_count;}if (show[x][y] ){for (i x - 1; i x 1; i){for (j y - 1; j y 1; j){//该坐标不是雷并且没有被排查过下标也不能越界if (mine[i][i] ! 1 show[i][j] * (i 1 i ROW) (j 1 j COL)){OpenBoard(mine, show, i, j);}}}}
}
void FindMine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{int x 0;int y 0;while (win_count row * col - Count_mine){printf(请输入要排查的坐标);scanf(%d %d, x, y);if (x 1 x 9 y 1 y 9){if (mine[x][y] 1){printf(很遗憾你踩到雷了游戏结束\n下面为雷阵图\n);DisPlay(mine, row, col);break;}else{该位置不是雷统计周围有几个雷//int count Around_Mine(mine ,x, y);//show[x][y] count 0;//win_count;OpenBoard(mine, show, x, y);DisPlay(show, ROW, COL);}}else{printf(坐标错误请重新输入\n);}}if (win_count row * col - Count_mine){printf(恭喜你所有的雷都被你排除了\n);}
}3.3test.c
main函数
#define _CRT_SECURE_NO_WARNINGS 1#includegame.hvoid menu()
{printf(*******************************\n);printf(********* 1.play *********\n);printf(********* 0.exit *********\n);printf(*******************************\n);
}
void game()
{char mine[ROWS][COLS]; //用来存放布置雷的信息char show[ROWS][COLS]; //用来存放排查雷的信息//初始化两个棋盘InitBoard(mine, ROWS, COLS ,0);InitBoard(show, ROWS, COLS, *);//打印棋盘//DisPlay(mine, ROW, COL);DisPlay(show, ROW, COL);//布雷SetMine(mine);//DisPlay(mine, ROW, COL);//排查雷FindMine(show, mine, ROW, COL);
}int main()
{srand((unsigned int)time(NULL));int input 0;//打印菜单do{menu();printf(请选择);scanf(%d, input);switch (input){case 1:printf(玩游戏\n);game();break;case 0:printf(退出游戏\n);break;default:printf(选择错误请重新选择!\n);break;}} while (input);return 0;
}