编程环境:【Visual Studio 2019】
标题传送门
扫雷怎么玩
编程思路
创建地图即初始化
打印地图
埋雷
玩家排雷
全部代码(传送门)
演示效果
扫雷怎么玩
扫雷是一款经典的小游戏。当地图上随机点击一个格子,如果不是则雷,检查以该格子为中心的8个坐标有多少个雷。如果附近8个坐标都不是雷,则展开一片不是雷的区域。当玩家排查完所有地雷,则玩家胜利。如果玩家踩雷,则游戏失败。
编程思路 创建地图即初始化首先创建两个字符类型的二维数组(mine,show),一个是存放雷的数组,另一个给玩家看的排雷信息数组。如果当玩家输入了处于边缘的坐标,当程序检查附近的雷时导致数组越界,所以两个数组大小应该是地图大小N+2。
假设表示雷为1,非雷为0,给存放雷的数组全部初始化字符0。排雷信息数组全部初始化为星号。
#define ROW 9 #define COL 9 #define ROWS 9+2 #define COLS 9+2 char mine[ROWS][COLS] = { 0 }; //存放排雷信息的数组 char show[ROWS][COLS] = { 0 }; InitBoard(mine, ROWS, COLS,'0'); InitBoard(show, ROWS, COLS, '*'); //初始化 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; for (i = 0;i <= col;i++) { printf("%d ", i);//行 } printf("n"); for (i = 1;i <= row;i++) { printf("%d ", i);//列 for (j = 1;j <= col;j++) { printf("%c ", board[i][j]); } printf("n"); } }埋雷
需要传的是存放雷的数组和地图大小的长和宽。因为需要随机埋雷,需要用到时间戳函数生成随机值。要注意,因为数组大小是9+2×9+2的,而地图则是9×9的,地图边缘不能埋雷,所以在生成随机值时,不能将雷埋在地图外的坐标。当埋的雷满足个数程序结束。
//设置雷个数 #define EASILY_MINE 10 SetMine(mine, ROW, COL); void SetMine(char mine[ROWS][COLS], int row, int col) { //计数 int count = EASILY_MINE; while (count) { int x = rand() % row + 1; int y = rand() % col + 1; if (mine[x][y] == '0') { mine[x][y] = '1'; count--; } } }玩家排雷
将雷埋好之后,就要开始玩家排雷了,排雷需要用到存放数组和排雷信息数组,让玩家输入排雷坐标。接着判断该坐标的合法性,若坐标非法则让玩家重新输入,若坐标合法,则判断该坐标是不是地雷,如果是雷,game over,不是就以该坐标为中心,计算周围的8个坐标有多少个雷,如果附近8个坐标都不是雷,则向外递归展开一片都不是雷的区域。而main函数内并没有调用过这个展开函数和检查雷函数,它们只是为了支持我们的排雷函数存在的,所以在函数前加一个static让函数失去外部链接属性,只能在这个工程内调用。在头文件也不再需要函数声明了。
//检查雷个数 static int get_mine_count(char mine[ROWS][COLS], int x, int y) { //返回坐标周围的八个坐标 return mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] + mine[x][y - 1] + mine[x][y + 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] - 8 * '0'; } //展开函数 static void ExcludeMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) { int count = get_mine_count(mine, x, y); if (count != 0) { //当周围8个坐标有雷,计算雷个数 show[x][y] = count + '0'; } else { //当周围8个坐标没有雷 show[x][y] = ' '; if ('*' == show[x - 1][y - 1]) ExcludeMine(mine, show, x - 1, y - 1); if ('*' == show[x - 1][y]) ExcludeMine(mine, show, x - 1, y); if ('*' == show[x - 1][y + 1]) ExcludeMine(mine, show, x - 1, y + 1); if ('*' == show[x][y - 1]) ExcludeMine(mine, show, x, y - 1); if ('*' == show[x][y + 1]) ExcludeMine(mine, show, x - 1, y + 1); if ('*' == show[x + 1][y - 1]) ExcludeMine(mine, show, x + 1, y - 1); if ('*' == show[x + 1][y]) ExcludeMine(mine, show, x - 1, y + 1); if ('*' == show[x + 1][y + 1]) ExcludeMine(mine, show, x - 1, y + 1); } } //玩家排雷 void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col) { int x = 0; int y = 0; int win = 0; while (1) { //外挂(方便测试) //DisplayBoard(mine, row, col); printf("请输入排雷坐标:"); scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col && show[x][y] == '*') { //坐标是雷 if (mine[x][y] == '1') { system("cls"); printf("Peng!!!GAME OVER!n"); break; } //不是雷 else { system("cls"); ExcludeMine(mine, show, x, y); DisplayBoard(show, row, col); //DisplayBoard(mine, row, col); win = CheckShow(show, row, col); win = CheckShow(show, row, col); if (win == EASILY_MINE)//当只剩雷的个数,排雷成功 { system("cls"); break; } } } else { printf("坐标非法,请重新输入n"); } } if (win == EASILY_MINE) printf("恭喜你排雷成功!n"); //查看所有雷的位置 DisplayBoard(mine, row, col); system("pause"); system("cls"); }
当玩家排雷解决后就要解决如何判定玩家是否胜利,玩家的结束条件有踩雷和排雷成功。踩雷已经解决完毕,接下来就是如何判断玩家的输赢。我的方法是用循环判断还有多少个未排坐标,然后返回一个变量,用变量来和雷的个数比较,如果雷的个数等于未排个数说明排雷成功。当游戏结束后给玩家打印雷的位置,让玩家看看怎么赢或输的。
//判赢 static char CheckShow(char show[ROWS][COLS], int row, int col) { int x = 0; int y = 0; int win = 0; for (x = 1;x <= row;x++) { for (y = 1;y <= col;y++) { if (show[x][y] == '*') { //计算还有几个未排坐标 win++; } } } return win; }全部代码(传送门)
#pragma once #include演示效果#include #include #include #define ROW 9 #define COL 9 #define ROWS 9+2 #define COLS 9+2 //设置雷个数 #define EASILY_MINE 10 //初始化 void InitBoard(char board[ROWS][COLS], int rows, int cols, char set); //打印 void DisplayBoard(char board[ROWS][COLS], int row, int col); //埋雷 void SetMine(char mine[ROWS][COLS], int row, int col); //排雷 void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col); 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; for (i = 0;i <= col;i++) { printf("%d ", i);//行 } printf("n"); for (i = 1;i <= row;i++) { printf("%d ", i);//列 for (j = 1;j <= col;j++) { printf("%c ", board[i][j]); } printf("n"); } } void SetMine(char mine[ROWS][COLS], int row, int col) { int count = EASILY_MINE; while (count) { int x = rand() % row + 1; int y = rand() % col + 1; if (mine[x][y] == '0') { mine[x][y] = '1'; count--; } } } //检查雷个数 static int get_mine_count(char mine[ROWS][COLS], int x, int y) { //返回坐标周围的八个坐标 return mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] + mine[x][y - 1] + mine[x][y + 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] - 8 * '0'; } static void ExcludeMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) { int count = get_mine_count(mine, x, y); if (count != 0) { //当周围8个坐标有雷,计算雷个数 show[x][y] = count + '0'; } else { //当周围8个坐标没有雷 show[x][y] = ' '; if ('*' == show[x - 1][y - 1]) ExcludeMine(mine, show, x - 1, y - 1); if ('*' == show[x - 1][y]) ExcludeMine(mine, show, x - 1, y); if ('*' == show[x - 1][y + 1]) ExcludeMine(mine, show, x - 1, y + 1); if ('*' == show[x][y - 1]) ExcludeMine(mine, show, x, y - 1); if ('*' == show[x][y + 1]) ExcludeMine(mine, show, x - 1, y + 1); if ('*' == show[x + 1][y - 1]) ExcludeMine(mine, show, x + 1, y - 1); if ('*' == show[x + 1][y]) ExcludeMine(mine, show, x - 1, y + 1); if ('*' == show[x + 1][y + 1]) ExcludeMine(mine, show, x - 1, y + 1); } } //判赢 static char CheckShow(char show[ROWS][COLS], int row, int col) { int x = 0; int y = 0; int win = 0; for (x = 1;x <= row;x++) { for (y = 1;y <= col;y++) { if (show[x][y] == '*') { //计算还有几个未排坐标 win++; } } } return win; } //玩家排雷 void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col) { int x = 0; int y = 0; int win = 0; while (1) { //外挂(方便测试) //DisplayBoard(mine, row, col); printf("请输入排雷坐标:"); scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col && show[x][y] == '*') { //坐标是雷 if (mine[x][y] == '1') { system("cls"); printf("Peng!!!GAME OVER!n"); break; } //不是雷 else { system("cls"); ExcludeMine(mine, show, x, y); DisplayBoard(show, row, col); //DisplayBoard(mine, row, col); win = CheckShow(show, row, col); win = CheckShow(show, row, col); if (win == EASILY_MINE)//当只剩雷的个数,排雷成功 { system("cls"); break; } } } else { printf("坐标非法,请重新输入n"); } } if (win == EASILY_MINE) printf("恭喜你排雷成功!n"); //查看所有雷的位置 DisplayBoard(mine, row, col); system("pause"); system("cls"); } #include"game.h" void menu() { printf("***********************n"); printf("***** 1. play *****n"); printf("***** 0. exit *****n"); printf("***********************n"); } void game() { //存放雷信息的数组 char mine[ROWS][COLS] = { 0 }; //存放排雷信息的数组 char show[ROWS][COLS] = { 0 }; InitBoard(mine, ROWS, COLS,'0'); InitBoard(show, ROWS, COLS, '*'); //观察两个数组 //DisplayBoard(show, ROW, COL); //DisplayBoard(mine, ROW, COL); //埋雷 SetMine(mine, ROW, COL); //DisplayBoard(mine, ROW, COL); system("cls");//清空屏幕 DisplayBoard(show, ROW, COL); //排雷 FindMine(mine, show, ROW, COL); } void test() { int input = 0; //时间戳 srand((unsigned int)time(NULL)); do { menu(); printf("请输入你的选择:"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏n"); break; default: printf("输入错误,请重新输入n"); } } while (input); } int main() { test(); return 0; }
因为是测试运行效果,所以用外挂来辅助测试~~
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)