(C语言)扫雷 您所在的位置:网站首页 扫雷是怎么判断雷的位置的 (C语言)扫雷

(C语言)扫雷

2024-07-07 00:06| 来源: 网络整理| 查看: 265

电影《地雷区》

扫雷 1.新建源文件2.建立主函数3.game函数设计思路4.函数定义 源码分析4.1 `初始化函数 Init`4.2 `打印函数 Displayboard`4.3 `设置地雷函数 SetMine`4.4 `排查地雷函数FindMine`4.4.1 防止第一步踩雷4.4.2 展开 5.函数声明 game.h 源码6.main函数 test.h 源码7 函数定义 game.c 源码8.实际游玩效果

1.新建源文件

在这里插入图片描述

test.c中存放主函数; game.h中存放使用的函数的声明; game.c中存放使用的函数的定义; 2.建立主函数

需求:

1.玩家选择是否进行游戏; 2.要有反复游玩的功能;

主函数代码如下:

int main() { int input; 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\n"); break; } } while (input); return 0; }

生成的游戏菜单 在这里插入图片描述

玩家输入1,进入game函数,进行游戏; 玩家输入0,结束游戏; 玩家输入其他字符,提示输入错误,重新输入;

3.game函数设计思路

思路:定义界面->初始化->打印->埋雷->找雷

1.游戏界面

扫雷游戏的界面是一个方盘 在这里插入图片描述 我们很容易联想到建立一个二维数组来作为游戏界面,其中需要存放地雷的位置信息,同时玩家面对的二维数组则是一片未知区域,只有点下某一点位时才出现周围雷区的信息。于是我们建立两个二维数组,mine数组存放地雷信息,show数组则是面对玩家实际操作。 首先利用宏定义行数与列数

#define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2 char mine[ROWS][COLS],show[ROWS][COLS];

这里不得不提到一点:因为需要统计坐标周围8个位置雷的个数,假如要统计边界坐标周围雷的个数,那么就会造成数组越界,如果单独讨论就十分繁琐。如果我们定义了9* 9的边界,也就要定义11*11的数组元素,最外边一圈元素我们不要打印出来,如下图 在这里插入图片描述 地雷存放在橙色区域中,以及玩家面对的游戏界面也为橙色区域。行的范围1~ROW,列的范围1 ~ COL。 —————————————————————————

2.初始化 Init

既然数组已经定义好了,我们就要初始化这两个二维数组。 我们规定地雷用字符'1'表示,安全区域用字符'0'表示,而玩家的show数组则全部初始化为字符'*'。 初始化函数声明:

void Init(char board[ROWS][COLS], int rows, int cols, char sign);

—————————————————————————

3.打印函数 Displayboard

验证是否初始化成功; 以及每次玩家点击某个坐标后,我们都要将结果打印出来。 打印函数声明:

void Displayboard(char board[ROWS][COLS], int row, int col)

—————————————————————————

4.设置雷的位置 SetMine

首先利用宏定义雷的数量

#define bomb 10

然后利用函数rand随机在上述橙色区域中布置地雷。 设置地雷函数声明:

void SetMine(char board[ROWS][COLS], int row, int col);

—————————————————————————

5.排查雷 FindMine

需求: 1.防止第一步踩雷 2.如果踩到雷,提示玩家踩中地雷,该轮游戏结束。 3.如果没有踩雷,则在坐标中标记周围地雷数,如果标记为0,那么展开。 4.找出所有地雷,提示玩家排雷成功,该轮游戏结束。 排查雷函数声明:

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col); 4.函数定义 源码分析

初始化,打印和设置地雷函数都比较简单,直接上源码。扫雷的核心在于排查地雷。

4.1 初始化函数 Init void Init(char board[ROWS][COLS], int rows, int cols, char sign) { int i, j; for (i = 0; i board[i][j] = sign; } } } 4.2 打印函数 Displayboard void Displayboard(char board[ROWS][COLS], int row, int col) { int i, j; printf("------------------------------------------\n"); for (i = 0; i printf("%d ", i); for (j = 1; j int i=bomb; while(i) { int x = rand() % row + 1; int y = rand() % col + 1; if (board[x][y] != '1') { board[x][y] = '1'; i--; } } } 4.4 排查地雷函数FindMine

排查雷一定是一个循环的过程,直到出结果才能终止循环。我们可以声明变量win为安全地区的数量,当win==ROW*COL-bomb时,则排完所有地雷。 而且要求输入的坐标必须在上述的橙色区域内,否则要求玩家重新输入。 那我们就有了一个基本的框架:

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x, y; int win=0;//win为排雷数 while (1) { printf("输入坐标:>"); scanf("%d%d", &x, &y); if (x >= 1 && x = 1 && y printf("越界 重新输入\n"); } } } 4.4.1 防止第一步踩雷

好的,现在我们假设输入的坐标正确,终于能玩游戏了,但是有些时候很倒霉,一上来就踩中了地雷,那我们如何避免呢? 这里就要先设计一个函数,避免你的霉运——Prevent_jinx 将你第一步脚下的地雷挪到没雷的位置去。

//防止第一步就踩中地雷 void Prevent_jinx(char mine[ROWS][COLS],int x,int y) { int m, n; while (1) { m = rand() % ROW + 1; n = rand() % COL + 1; if (mine[m][n] != '1') { mine[m][n] = '1'; mine[x][y] = '0'; break; } } }

那我们怎么触发这个函数呢? 一定是在第一步的时候——即此刻排查出的安全区的数量win==0,而且你选择的坐标正好下面埋着一颗雷——mine[x][y] == '1'

于是我们的框架得到了更新: void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x, y; int win = 0;//win为安全数 如果win=总数-地雷数 则成功 while (1) { printf("输入坐标:>"); scanf("%d%d", &x, &y); if (x >= 1 && x = 1 && y Prevent_jinx(mine, x, y); } //正式进入排雷....... } else { printf("越界 重新输入\n"); } } }

趟过了第一步便正式进入了排雷,下面我们将判断之后的每一步是否踩中了地雷。 假设踩中了地雷,那么我们就需要提示玩家踩中地雷,而且需要打印实际地雷位置信息,好让玩家‘死’个明白,然后退出概该轮游戏。

于是我们的框架得到了更新: void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x, y; int win = 0;//win为安全地区数 如果win=总数-地雷数 则成功 while (1) { printf("输入坐标:>"); scanf("%d%d", &x, &y); if (x >= 1 && x = 1 && y Prevent_jinx(mine, x, y); } if (mine[x][y] == '1' ) //踩中雷 { printf("踩到雷啦!\n"); Displayboard(mine, ROW, COL); break; } else //未踩中雷 { ..... } } else { printf("越界 重新输入\n"); } } } 4.4.2 展开

如果没有踩中地雷,那么我们需要在show[x][y] 处标记周围八个方向的地雷个数,如果个数为0则需要展开。

展开:如果(x,y)处为0,则周围8个点依次向外找雷,如果周围找到了地雷则标记个数,否则继续向外找雷。 实现定义找周围的雷数函数——Getbombcount:

int Getbombcount(char mine[ROWS][COLS], int x, int y) { int i, j,count=0; for (i = x - 1; i if (mine[i][j] == '1') count++; } } return count; }

我们定义递归函数OpenMine来执行**展开**操作:

void OpenMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) { if (x >= 1 && x = 1 && y show[x][y] = '0'; int i, j; //依次遍历周围八个点 for (i = x - 1; i if (show[i][j] != '*') continue; //如果已被标记过则不用进入递归,避免重复查找 OpenMine(mine, show, i, j); } } } else //count不为0 停止扩展找雷 { show[x][y] = count + '0'; } } else return; }

这样的依次展开就可以排查掉许多安全区域

现在我们需要一个函数Countshow来统计以下安全区域的数量

int Countshow(char board[ROWS][COLS], int row, int col, char sign) { int count = 0,i,j; for (i = 1; i if (board[i][j] == sign) count++; } } return count; }

于是我们的FindMine函数就完全写出来了:

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x, y; int win = 0;//win为排雷数 如果win=总数-地雷数 则成功 while (1) { printf("输入坐标:>"); scanf("%d%d", &x, &y); if (x >= 1 && x = 1 && y Prevent_jinx(mine, x, y); } if (mine[x][y] == '1' ) { printf("踩到雷啦!\n"); Displayboard(mine, ROW, COL); break; } else //未踩中雷 { OpenMine(mine, show, x, y); win = ROW*COL-Countshow(show, ROW, COL, '*'); if (Countshow(show, ROW, COL, '*')== bomb) { Displayboard(show, ROW, COL); printf("排雷成功\n"); break; } Displayboard(show, ROW, COL); } } else { printf("越界 重新输入\n"); } } } 5.函数声明 game.h 源码 #include #include #include //定义宏 #define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2 #define bomb 3 //初始化 void Init(char board[ROWS][COLS], int rows, int cols, char sign); //打印游戏界面 void Displayboard(char board[ROWS][COLS], int row, int col); //布置地雷 void SetMine(char board[ROWS][COLS], int row, int col); //排查雷 void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col); 6.main函数 test.h 源码 #include "game.h" void menu() { printf("*******************\n"); printf("***0.exit 1.play***\n"); printf("*******************\n"); } void game() { //定义存放地雷的数组 和 玩家游玩的数组 char mine[ROWS][COLS],show[ROWS][COLS]; //初始化数组 Init(mine,ROWS,COLS,'0'); Init(show, ROWS, COLS, '*'); //打印 //Displayboard(mine,ROW,COL); //Displayboard(show, ROW, COL); //布置地雷 SetMine(mine,ROW,COL); Displayboard(mine, ROW, COL); Displayboard(show, ROW, COL); //排查雷 FindMine(mine,show,ROW,COL); } int main() { int input; 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\n"); break; } } while (input); return 0; } 7 函数定义 game.c 源码 #include "game.h" //初始化 void Init(char board[ROWS][COLS], int rows, int cols, char sign) { int i, j; for (i = 0; i board[i][j] = sign; } } } //打印游戏界面 void Displayboard(char board[ROWS][COLS], int row, int col) { int i, j; printf("------------------------------------------\n"); for (i = 0; i printf("%d ", i); for (j = 1; j int i=bomb; while(i) { int x = rand() % row + 1; int y = rand() % col + 1; if (board[x][y] != '1') { board[x][y] = '1'; i--; } } } //获取坐标周围地雷数目 int Getbombcount(char mine[ROWS][COLS], int x, int y) { int i, j,count=0; for (i = x - 1; i if (mine[i][j] == '1') count++; } } return count; } //防止第一步就踩中地雷 void Prevent_jinx(char mine[ROWS][COLS],int x,int y) { int m, n; while (1) { m = rand() % ROW + 1; n = rand() % COL + 1; if (mine[m][n] != '1') { mine[m][n] = '1'; mine[x][y] = '0'; break; } } } void OpenMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) { if (x >= 1 && x = 1 && y show[x][y] = '0'; int i, j; for (i = x - 1; i if (show[i][j] != '*') continue; //如果已被排雷过则不用递归 OpenMine(mine, show, i, j); } } } else //count不为0 停止扩展 { show[x][y] = count + '0'; } } else return; } int Countshow(char board[ROWS][COLS], int row, int col, char sign) { int count = 0,i,j; for (i = 1; i if (board[i][j] == sign) count++; } } return count; } //排查雷 void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x, y; int win = 0;//win为排雷数 如果win=总数-地雷数 则成功 while (1) { printf("输入坐标:>"); scanf("%d%d", &x, &y); if (x >= 1 && x = 1 && y Prevent_jinx(mine, x, y); } if (mine[x][y] == '1' ) { printf("踩到雷啦!\n"); Displayboard(mine, ROW, COL); break; } else //未踩中雷 { OpenMine(mine, show, x, y); win = ROW*COL-Countshow(show, ROW, COL, '*'); if (Countshow(show, ROW, COL, '*')== bomb) { Displayboard(show, ROW, COL); printf("排雷成功\n"); break; } Displayboard(show, ROW, COL); } } else { printf("越界 重新输入\n"); } } } 8.实际游玩效果

第一把 :设置bomb为2 在这里插入图片描述 在这里插入图片描述 第二把:设置bomb为4 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有