梅州网站优化公司,百科网站推广,门户网站建设工作制度建立情况,ae有么有做gif的网站目录 一、游戏设计分析二、各个步骤的代码实现1. 游戏菜单界面的实现2. 游戏初始化3. 开始扫雷 三、完整代码四、总结 一、游戏设计分析
本次设计的扫雷游戏是展示一个 9 * 9 的棋盘#xff0c;然后输入坐标进行判断#xff0c;若是雷#xff0c;则游戏结束#xff0c;否则… 目录 一、游戏设计分析二、各个步骤的代码实现1. 游戏菜单界面的实现2. 游戏初始化3. 开始扫雷 三、完整代码四、总结 一、游戏设计分析
本次设计的扫雷游戏是展示一个 9 * 9 的棋盘然后输入坐标进行判断若是雷则游戏结束否则继续判断直到排除所有雷游戏胜利。然后选择退出或者重新开始游戏。
1游戏菜单界面实现 提供开始游戏和退出游戏两个选项游戏结束后可以再次选择直到退出游戏。 2游戏初始化 开始游戏后初始化棋盘随机设置地雷然后显示棋盘。这里需要两个二维数组一个用来显示棋盘一个用来存储地雷的信息。 3开始扫雷 提示玩家输入坐标然后检查坐标是否合法最后判断位置是否为雷。若为雷则游戏结束若不为雷则计算周围地雷的个数若周围地雷的个数不为 0则显示将其显示在棋盘上若周围地雷个数为 0则使用刚才的方法继续检查周围的 8 个位置以此类推检查结束后把信息全部显示在棋盘上。然后继续下一次坐标输入直到把所有的雷找出游戏获胜。
上述需要计算输入坐标周围的的雷的个数如果在该坐标在最边上一圈那么会存在排查的坐标非法的情况。这里可以使用 11 * 11 的棋盘然后通过把雷设置为字符 ‘1’非雷设置为字符 ‘0’当计算时把周围八个坐标相加然后减去 8 个字符 ‘0’ 即可。 4游戏结束或重新开始游戏
二、各个步骤的代码实现
1. 游戏菜单界面的实现
游戏菜单界面需要提供开始游戏和退出游戏两个选项且玩完一局游戏之后可以选择再玩一局。在主函数使用一个循环来控制实现如下
1test.c 测试文件
// 头文件
#include Mine.hint main()
{// 所需变量int select;// 选择do{// 菜单menu();// 输入scanf(%d, select);// 判断switch (select){case 1:printf(扫雷游戏\n);//Minesweeper_game();break;case 0:printf(游戏结束\n);break;default:printf(输入错误请重新输入\n);break;}} while (select);return 0;
}2Mine.h 头文件
// 头文件
#include stdio.h// 函数声明
// 菜单
void menu();3Mine.c 函数实现文件
// 头文件
#include Mine.h// 函数定义
// 菜单
void menu()
{printf(*****************************************\n);printf(************* 1. play *************\n);printf(************* 0. exit *************\n);printf(*****************************************\n);
}4代码运行效果
2. 游戏初始化
游戏初始化需要显示棋盘然后随机设置雷。这里需要使用两个数组一个数组用来显示棋盘另一个数组用来存储雷的信息。为了方便计算两个数组都采用 11*11 的字符数组初始棋盘使用符号 ‘*’地雷使用字符 ‘1’非地雷使用字符 ‘0’。数组大小使用在头文件中定义的符号常量设计一个初始化函数 InitBoard() 和设置雷函数 SetMine()还有显示棋盘函数 PrintBoard()。
InitBoard() 函数可以一次性传两个数组也可以通过参数传递设置的值。SetMine() 函数需要使用随机数。PrintBoard() 函数显示的时候可以在左边和上面加上行号和列号方便玩家输入坐标。
1test.c 测试文件 添加了扫雷游戏函数 Minesweeper_game()
// 头文件
#include Mine.hint main()
{// 所需变量int select;// 选择do{// 菜单menu();// 输入scanf(%d, select);// 判断switch (select){case 1:Minesweeper_game(); // 扫雷游戏break;case 0:printf(游戏结束\n);break;default:printf(输入错误请重新输入\n);break;}} while (select);return 0;
}2Mine.h 头文件
// 头文件
#include stdio.h// 常量声明
#define ROW 9
#define COL 9#define ROWS ROW2
#define COLS COL2// 函数声明
// 菜单
void menu();// 初始化棋盘
void InitBoard(char Board[ROWS][COLS], int rows, int cols, char set);// 设置雷
void SetMine(char Board[ROWS][COLS], int row, int col);// 显示棋盘
void PrintBoard(char Board[ROWS][COLS], int row, int col);// 扫雷游戏
void Minesweeper_game();3Mine.c 函数实现文件
// 初始化棋盘
void InitBoard(char Board[ROWS][COLS], int rows, int cols, char set)
{int i;for (i 0; i rows; i){int j;for (j 0; j cols; j){Board[i][j] set;}}
}// 设置雷
void SetMine(char Board[ROWS][COLS], int row, int col)
{// 所需变量int x, y; // 雷的坐标int num MINE_COUNT; // 雷的数量// 设置雷while (num){// 随机设置坐标值x rand() % row 1; // 11 * 11 实际坐标 1 - 9y rand() % col 1;// 检查坐标是否重复if (Board[x][y] 0){Board[x][y] 1;--num;}}
}// 显示棋盘
void PrintBoard(char Board[ROWS][COLS], int row, int col)
{// 分界线printf(-----------------------扫雷----------------------\n);// 列号printf( );int j;for (j 0; j col; j){printf(%d , j 1);}printf(\n);// 棋盘int i;for (i 0; i row; i){// 列号printf(%d , i 1);for (j 0; j col; j){printf(%c , Board[i1][j1]);}// 下一行printf(\n);}// 分界线printf(-----------------------扫雷----------------------\n);
}// 扫雷游戏
void Minesweeper_game()
{// 创建两个棋盘char board[ROWS][COLS];char mine[ROWS][COLS];// 初始化棋盘InitBoard(board, ROWS, COLS, *);printf(初始化两个数组\n); // 删除PrintBoard(board, ROW, COL); // 删除InitBoard(mine, ROWS, COLS, 0);PrintBoard(mine, ROW, COL); // 删除// 设置雷SetMine(mine, ROW, COL);printf(雷的信息\n); // 删除PrintBoard(mine, ROW, COL); // 删除
}上述标记了删除的语句都是不需要的这是作者写完代码用来检测的。
4代码运行效果
3. 开始扫雷
开始扫雷设计一个函数 find()要求玩家输入坐标检查该坐标是否合法然后判断该位置是否为雷是雷则游戏结束不是雷则使用函数 calc_mine() 计算周围一圈的雷的个数。如果周围一圈没有雷则按照刚才的步骤检查周围一圈实现函数 calc_mine() 递归。然后继续扫雷直到找出所有的雷。
函数 calc_mine() 只在 find() 函数中使用可以设置为 Mine.c 函数实现文件中的静态函数。判断游戏结束也需要使用一个变量这里使用一个全局变量 REAMIN 来进行控制当 REAMIN 的值为棋子总数减去雷数时则排除所有雷游戏结束。
代码测试时可以一个一个功能进行测试一个功能完成无误后再进入下一个。作者是全部测试好了才放上来的。
1Mine.h 头文件
// ...// 找雷
void find(char Board[ROWS][COLS], int row, int col);// 扫雷游戏
void Minesweeper_game();2Mine.c 函数实现文件
// 计算周围的雷
void calc_mine(char Board[ROWS][COLS], char Mine[ROWS][COLS], int row, int col, int x, int y)
{// 坐标非法或者已经排查或该位置为雷则退出if (x 1 || x 9 || y 1 || y 9 || Board[x][y] ! * || Mine[x][y] ! 0)return;// 所需变量int num 0;int i;for (i x - 1; i x 1; i){int j;for (j y - 1; j y 1; j){num Mine[i][j];}}// 加的是字符 0 所以要减去num num - 9 * 0;// 排雷 1REMAIN;if (num){Board[x][y] num 0;}else{Board[x][y] ;// 如果该坐标周围没雷则对其周围八个坐标进行检查形成递归for (i x - 1; i x 1; i){int j;for (j y - 1; j y 1; j){calc_mine(Board, Mine, row, col, i, j);}}}
}// 找雷
int find(char Board[ROWS][COLS], char Mine[ROWS][COLS], int row, int col)
{// 所需变量int x, y;// 输入排查坐标while (1){printf(请输入排雷坐标);scanf(%d %d, x, y);// 判断坐标是否合法if (Board[x][y] ! *){printf(该坐标已被排查\n);continue;}if (x 1 x row y 1 y col){if (Mine[x][y] 1){printf(很遗憾你被炸死了\n);printf(以下是本局雷的信息\n);return 0;}else{calc_mine(Board, Mine, row, col, x, y);return 1;}}}
}// 扫雷游戏
void Minesweeper_game()
{// 重置REMAIN 0;// 创建两个棋盘char board[ROWS][COLS];char mine[ROWS][COLS];// 初始化棋盘InitBoard(board, ROWS, COLS, *);InitBoard(mine, ROWS, COLS, 0);// 设置雷SetMine(mine, ROW, COL);int ret 0;while (REMAIN ! ROW * COL - MINE_COUNT){// 显示棋盘PrintBoard(board, ROW, COL);// 排雷ret find(board, mine, ROW, COL);// 如果是雷则显示雷的信息游戏结束if (!ret){PrintBoard(mine, ROW, COL);break;}}// 判断if (REMAIN ROW * COL - MINE_COUNT)\{printf(恭喜你排雷成功游戏结束!\n);printf(以下是本局雷的信息\n);PrintBoard(mine, ROW, COL);}
}3代码运行效果 下图是完整代码运行效果一整局游戏的运行图
三、完整代码
完整代码分为三个文件头文件 Mine.h测试文件 test.c函数实现文件 Mine.c
头文件 Mine.h
#pragma once// 头文件
#include stdio.h
#include stdlib.h// 常量声明
#define ROW 9
#define COL 9#define ROWS ROW2
#define COLS COL2#define MINE_COUNT 10// 函数声明
// 菜单
void menu();// 初始化棋盘
void InitBoard(char Board[ROWS][COLS], int rows, int cols, char set);// 设置雷
void SetMine(char Board[ROWS][COLS], int row, int col);// 显示棋盘
void PrintBoard(char Board[ROWS][COLS], int row, int col);// 找雷
int find(char Board[ROWS][COLS],char Mine[ROWS][COLS], int row, int col);// 扫雷游戏
void Minesweeper_game();测试文件 test.c
// 头文件
#include Mine.h
#include time.hint main()
{// 设置随机数种子srand((unsigned)time(0));// 所需变量int select;// 选择do{// 菜单menu();// 输入scanf(%d, select);// 判断switch (select){case 1:Minesweeper_game(); // 扫雷游戏break;case 0:printf(游戏结束\n);break;default:printf(输入错误请重新输入\n);break;}} while (select);return 0;
}函数实现文件 Mine.c
// 头文件
#include Mine.h// 全局静态变量
static REMAIN 0;// 函数定义
// 菜单
void menu()
{printf(*****************************************\n);printf(************* 1. play *************\n);printf(************* 0. exit *************\n);printf(*****************************************\n);
}// 初始化棋盘
void InitBoard(char Board[ROWS][COLS], int rows, int cols, char set)
{int i;for (i 0; i rows; i){int j;for (j 0; j cols; j){Board[i][j] set;}}
}// 设置雷
void SetMine(char Board[ROWS][COLS], int row, int col)
{// 所需变量int x, y; // 雷的坐标int num MINE_COUNT; // 雷的数量// 设置雷while (num){// 随机设置坐标值x rand() % row 1; // 11 * 11 实际坐标 1 - 9y rand() % col 1;// 检查坐标是否重复if (Board[x][y] 0){Board[x][y] 1;--num;}}
}// 显示棋盘
void PrintBoard(char Board[ROWS][COLS], int row, int col)
{// 分界线printf(-----------------------扫雷----------------------\n);// 列号printf( );int j;for (j 0; j col; j){printf(%d , j 1);}printf(\n);// 棋盘int i;for (i 0; i row; i){// 列号printf(%d , i 1);for (j 0; j col; j){printf(%c , Board[i1][j1]);}// 下一行printf(\n);}// 分界线printf(-----------------------扫雷----------------------\n);
}// 计算周围的雷
void calc_mine(char Board[ROWS][COLS], char Mine[ROWS][COLS], int row, int col, int x, int y)
{// 坐标非法或者已经排查或该位置为雷则退出if (x 1 || x 9 || y 1 || y 9 || Board[x][y] ! * || Mine[x][y] ! 0)return;// 所需变量int num 0;int i;for (i x - 1; i x 1; i){int j;for (j y - 1; j y 1; j){num Mine[i][j];}}// 加的是字符 0 所以要减去num num - 9 * 0;// 排雷 1REMAIN;if (num){Board[x][y] num 0;}else{Board[x][y] ;// 如果该坐标周围没雷则对其周围八个坐标进行检查形成递归for (i x - 1; i x 1; i){int j;for (j y - 1; j y 1; j){calc_mine(Board, Mine, row, col, i, j);}}}
}// 找雷
int find(char Board[ROWS][COLS], char Mine[ROWS][COLS], int row, int col)
{// 所需变量int x, y;// 输入排查坐标while (1){printf(请输入排雷坐标);scanf(%d %d, x, y);// 判断坐标是否合法if (Board[x][y] ! *){printf(该坐标已被排查\n);continue;}if (x 1 x row y 1 y col){if (Mine[x][y] 1){printf(很遗憾你被炸死了\n);printf(以下是本局雷的信息\n);return 0;}else{calc_mine(Board, Mine, row, col, x, y);return 1;}}}
}// 扫雷游戏
void Minesweeper_game()
{// 重置REMAIN 0;// 创建两个棋盘char board[ROWS][COLS];char mine[ROWS][COLS];// 初始化棋盘InitBoard(board, ROWS, COLS, *);InitBoard(mine, ROWS, COLS, 0);// 设置雷SetMine(mine, ROW, COL);int ret 0;while (REMAIN ! ROW * COL - MINE_COUNT){// 显示棋盘PrintBoard(board, ROW, COL);// 排雷ret find(board, mine, ROW, COL);// 如果是雷则显示雷的信息游戏结束if (!ret){PrintBoard(mine, ROW, COL);break;}}// 判断if (REMAIN ROW * COL - MINE_COUNT)\{printf(恭喜你排雷成功游戏结束!\n);printf(以下是本局雷的信息\n);PrintBoard(mine, ROW, COL);}
}四、总结
本次扫雷游戏的代码实现总体来说还比较可以。基本功能均实现游戏也能正常进行。本游戏还有许多可以提升的地方比如代码的优化雷的标记难度的选择等等。
本代码稍微难一点的地方在于排查坐标周围地雷数的函数 calc_mine() 的递归需要明确何时需要递归和递归的结束条件。
复习一下递归需要满足两个条件 1需要结束条件 2每次递归都更加靠近这个结束条件