扫雷小游戏

经典游戏扫雷,在学习C语言基础后,今天试着用C语言去实现这个经典小游戏。

1.游戏介绍

扫雷想必大家都不陌生,但是,是不是还有很多人不知道怎么扫雷呢?是不是一点就踩雷被呢?别看了,说的就是你!那么,下面就给大家介绍一下这个游戏的玩法。

注意:(改图截自扫雷游戏网页版)
图例:
左上角的数字 10–表示雷的个数(此时为8由于我已经手动标了两处旗,表明我已经排除两个雷了)
右上角的数字目前为 002–表示的是排查出雷的个数(图中的两个小旗)

 游戏规则:我们看序号 1 ,以我们画圈的哪个数字 1为中心画一个九宫格,此时九宫格内只有一个方块,而我们这个中心数字又是 1,表明以这个数字为中心的九宫格内的八个方块里有一个雷,并且,此时这个九宫格内只有一个方块还没有点开,其他地方都点开了并且显示了数字说明不是雷,因此这一个方块里一定是雷,我们插上小旗表明已经排除此处是雷。我们再来看序号 2,同样以我们画圈的那个数字 1 为中心画一个九宫格,但由于九宫格最底下那一行已经超出了游戏范围,因此在边界线上的数字为中心画九宫格只需要考虑九宫格边界线以内的情况就可以。同理,此时中心数字是 1 表明现在这个九宫格内的八个方块有一个一定是雷,由于只有一个方块没有排除,其他均已排除并显示数字表明不是雷,只有这最有一个方块没排除,因此一定是雷。    最后,如果中心数字是 2  哪以中心数字 2 为九宫格内的八个方块内一定有两个雷,其他数字同理。现在,应该没有人不会了吧。

2.扫雷代码逻辑

1.创建数组

  由上面玩游戏的过程可以体会到,我们需要两个二维素组来分别存放雷和展示雷

2.初始化素组

  我们看到,一开始点开这个游戏界面的时候,只有小方块,因此我们也需要将它进行一个初始化

3.展示(打印)数组

  存放好后的信息都已经放在了数组里,玩家进行游戏时,需要根据我们展示的信息来完成扫雷,因此我们需要将这个数组打印出来给玩家观察

4.设置雷(埋雷)

在进行扫雷之前,需要规定多大的棋盘里一共需要埋下多少颗雷来让玩家进行扫雷

5.扫雷

当上述准备过程都已经完成后,那接下来就是扫雷的过程啦,根据我们的玩法规则,结
合展示的信息完成扫雷

6.展开该坐标周围没有雷的全部方块

扫雷展开过程 效果展示

(该视频录制扫雷网页版)

 下面我们一起来观察一下这个展开效果。视频中可以观察到,前几次我点开的每一个方块都只有这一个方块没了并且显示了数字,根据我们的规则,以这个数字为中心的九宫格是有该数字个雷的,因此他的周围没有展开我的最后一步,点开了右下角的一个方块,一下子周围很多方块都消失了,这就是展开的效果,根据规则我们可以知道,展开是需要一定前提的:1.这个坐标本身不是雷2.这个坐标九宫格内的其他坐标不能是雷

7. 判断输赢

到最后,如果玩家找到了所有的雷,那么意味着排雷成功,若是中途触雷,则直接判定失败

3.详细步骤实现

1.创建数组

采取分模块写法:
1.test.c的主源文件中写主体步骤
2.game.h 中申明扫雷游戏模块相关的函数申明,自定义等
3.game.c 中实现函数定义

test.c 中代码如下:

void game()//游戏函数实现
{char mine[ROWS][COLS] = { 0 };//存放雷的数组char show_mine[ROWS][COLS] = { 0 };//存放展示扫雷的素组}void menu() //菜单函数实现
{printf("****************\n");printf("**** 1.play ****\n");printf("**** 0.exit ****\n");printf("****************\n");
}int main()
{int input = 0;srand((unsigned)time(NULL));do{menu(); //菜单printf("请选择: \n");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("即将退出游戏\n");break;default:printf("选择错误,请重新选择\n");break;}} while (input);//玩家输入的值来进行循环的判断,可达到循环玩游戏的效果return 0;
}

game.h 中代码如下:

#define ROW 9//操作的行
#define COL 9//操作的列
#define COLS COL+2//防止数组越界
#define ROWS ROW+2//防止素组越界

由于我们看到的扫雷的棋盘是一个9*9的棋盘,因此我们操作的棋盘应该就是这个大小,但是当判断内容时,我们是以一个数字为中心的九宫格,那么,在边界上的数字(如上图所示)的九宫格就会超过需要的棋盘大小,为了防止越界,我们将棋盘的行列均扩大,上下左右均需要扩大,因此行列扩大两行。

2.初始化素组

test.c 中代码如下:

void game()
{char mine[ROWS][COLS] = { 0 };//存放雷的数组char show_mine[ROWS][COLS] = { 0 };//展示扫雷的素组--给玩家观察的数组Initboard(mine, ROWS, COLS, '0');  //初始化为字符‘0’Initboard(show_mine, ROWS, COLS, '*');//初始化为字符‘*’}

game.h 中代码如下:

//初始化数组中的内容
void Initboard(char board[ROWS][COLS], int rows, int cols ,char sz);

game.c 中代码如下:

game.c 中实现函数时所涉及的头文件我们放在game.h中,可以防止重复引用

#define _CRT_SECURE_NO_WARNINGS 1#include"game.h"//用了game.h 中 ROWS COLS 等自定义的变量须应用头文件
void Initboard(char board[ROWS][COLS], int rows, int cols,char sz)
{ //**传入 sz 这个字符参数 方便我们一个函数可以解决 雷的棋盘和展示棋盘的初始化**int i = 0;int j = 0;for (i = 0; i < rows; i++){for (j = 0; j < cols; j++){board[i][j] = sz;}}
}

3.展示(打印)数组

test.c 中代码如下:

void game()
{char mine[ROWS][COLS] = { 0 };//存放雷的数组char show_mine[ROWS][COLS] = { 0 };//展示扫雷的数组--给玩家观察的数组Initboard(mine, ROWS, COLS, '0');  //初始化为字符‘0’Initboard(show_mine, ROWS, COLS, '*');//初始化为字符‘*’print_board(show_mine, ROW, COL);//展示扫雷的数组
//注意的是,我们操作的是展示的9*9的棋盘,因此我们传入的棋盘行列大小也是9*9,即ROW,COL
}

game.h 中代码如下:

#include<stdio.h>//打印初始化后的内容
void print_board(char board[ROWS][COLS], int row, int col);我们传入的是show_mine 这个数组,因此这里的【ROWS】【COLS】也应当是和
show_mine创建的时候保持一直,但我们展示的却是9*9的棋盘,因此传入的行列是
row和col

game.c 中代码如下:

void print_board(char board[ROWS][COLS], int row, int col)
{printf("--------扫雷-------\n");//上分割线int i = 0;int j = 0;//打印横坐标for (i = 0; i <= row; i++)  {if (i == 0)printf("  ");elseprintf("%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");}printf("--------扫雷-------\n");下分割线
}

效果展示:

4. 设置雷(埋雷)

test.c 中代码如下:

void game()
{char mine[ROWS][COLS] = { 0 };//存放雷的数组char show_mine[ROWS][COLS] = { 0 };//展示扫雷的数组--给玩家观察的数组Initboard(mine, ROWS, COLS, '0');  //初始化为字符‘0’Initboard(show_mine, ROWS, COLS, '*');//初始化为字符‘*’print_board(show_mine, ROW, COL);//展示扫雷的数组Set_mine(mine, ROW, COL);//埋雷的过程,只操作我们存放雷的数组//print_board(mine, ROW, COL);//可以观察设置的雷是否正确
}

game.h 中代码如下:

#define junior_mine 10//雷的数目
#include<stdlib.h>//srand,rand 的头文件
#include<time.h> //time 的头文件
//设置雷
void Set_mine(char board[ROWS][COLS], int row, int col);
同上面展示雷的数组一样,埋雷的这个数组操作的是创建的 mine这个数组
【ROWS】【COLS】需要保持一直,由于扫雷的方块是9*9大小,所以我们传
入的棋盘大小任然是row 和 col

game.c 中代码如下:

void Set_mine(char board[ROWS][COLS], int row, int col)
{int x = 0;int y = 0;int count = junior_mine;while (count) //雷的数量为0时跳出循环说明雷已经布置完了{//随机产生雷的坐标在 1~9的范围内x = rand() % row + 1;y = rand() % col + 1;if (board[x][y] == '0') //说明该坐标处没有雷并且可以设置雷{board[x][y] = '1';  //埋雷成功 用 字符 1表示count--;}}
}

5.扫雷

test.c 中代码如下:

void game()
{char mine[ROWS][COLS] = { 0 };//存放雷的数组char show_mine[ROWS][COLS] = { 0 };//展示扫雷的数组--给玩家观察的数组Initboard(mine, ROWS, COLS, '0');  //初始化为字符‘0’Initboard(show_mine, ROWS, COLS, '*');//初始化为字符‘*’print_board(show_mine, ROW, COL);//展示扫雷的数组Set_mine(mine, ROW, COL);Find_mine(mine, show_mine, ROW, COL);}

game.h 中代码如下:

//排雷
void Find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

game.c 中代码如下:

//统计该坐标周围雷的个数
int sum_mine(char board[ROWS][COLS], int x, int y)
{int sum = 0;int i = 0;int j = 0;for (i = x - 1; i <= x + 1; i++)   {//产生以该坐标为中心的九宫格内的八个坐标for (j = y - 1; j <= y + 1; j++){sum+=board[i][j] - '0'; //注意数字和字符之间的转换}}return sum;
}void Find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{printf("请输入坐标进行排查:\n");int x = 0;int y = 0;//IsWin函数用于判断是否胜利 下在一步具体实现while (IsWin(show,row,col)==0) {scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col)//判断坐标合法性{if (mine[x][y] == '1'){printf("踩雷!\n");print_board(mine, ROW, COL);//踩雷后给玩家展示踩雷在哪里//和雷的全部坐标break;}else  //没有踩雷{int count = sum_mine(mine, x, y);//先统计该做标的周围的雷show[x][y] = count + '0';//注意int类型和字符类型转换Open_Not_mine(mine, show, x, y);//展开该坐标周围没有雷的方块print_board(show, ROW, COL);//展示完以及雷的个数统计后,展示给玩家观察}}elseprintf("输入错误,请重新输入\n");}

6.展开该坐标周围没有雷的全部方块

由于展开周围坐标没有雷的方块这个函数不属于游戏模块test.c 中的game()里的函数,因此不需要写在game.h中声明

game.c 中代码如下:

void Open_Not_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{int i = 0;int j = 0;int count = 0;//判断坐标是否合法if (x >= 1 && x <= 9 && y >= 1 && y <= 9){        for (i = -1; i<= 1; i++){    //该坐标为中心的八个坐标的循环写法for (j = -1; j<= 1; j++){//如果这个坐标不是雷的情况下if (mine[x + i][y + j] == '0'){     // 注意是 [x+i]和[y+i] 是改坐标周围其他坐标//统计这个坐标周围的雷count = sum_mine(mine, x + i, y + j);if (count == 0) //坐标周围没有雷,说明可以展开{if (show[x + i][y + j] == '*'){show[x + i][y + j] = ' ';Open_Not_mine(mine, show, x + i, y + j);  //回去递归调用周围坐标判断}}else //周围有雷 则这个坐标轴为中心的九宫格将不展开{show[i + x][j + y] = count + '0'; //统计这个坐标周围有几个雷并显示在改坐标处}}}}}
}

7.判断输赢

同展开函数 Open_Not_mine 一样, 判断输赢这个函数也不需要在game.h中进行声明

game.c中代码如下:

int IsWin(char show[ROWS][COLS], int row, int col)
{int i = 0;int j = 0;int count = 0;for (i = 1; i <= row;i++){//判断坐标范围for (j = 1; j <= col; j++){if (show[i][j] == '*'){count++; //统计show数组在9*9中棋盘上一共有多少个不是雷的个数}}}               //雷的个数return count == junior_mine;//相等返回1  不想动返回0//相等时说明 没有雷的方块都已经找到了,其余的位置都为雷--胜利//不相等的时候表明,不是雷的方块还没有全部找出来--未胜利
}

经典游戏扫雷详解--你也可以写出扫雷和玩好扫雷相关推荐

  1. 转载 雨松mono Unity获取游戏对象详解(来自我的长微博)

    Unity获取游戏对象详解(来自我的长微博) 转载 自 雨松mono 本文固定链接: http://www.xuanyusong.com/archives/2768 转载请注明: 雨松MOMO 201 ...

  2. 十大经典排序算法详解(三)-堆排序,计数排序,桶排序,基数排序

    养成习惯,先赞后看!!! 你的点赞与关注真的对我非常有帮助.如果可以的话,动动手指,一键三连吧!!! 十大经典排序算法-堆排序,计数排序,桶排序,基数排序 前言 这是十大经典排序算法详解的最后一篇了. ...

  3. 《Android游戏开发详解》一1.8 控制流程第2部分——while和for循环

    本节书摘来异步社区<Android游戏开发详解>一书中的第1章,第1.8节,译者: 李强 责编: 陈冀康,更多章节内容可以访问云栖社区"异步社区"公众号查看. 1.8 ...

  4. 算法经典“钓鱼”问题详解 基于贪心算法 C语言描述

    算法经典"钓鱼"问题详解 基于贪心算法 初始条件 在一条水平路边,有 n 2 ≤ n ≤ 25个钓鱼池,从左到右编号为1.2.3.--.n.小明有H1 ≤ H ≤ 16个小时的空余 ...

  5. php井字游戏代码_JS实现井字棋游戏步骤详解

    这次给大家带来JS实现井字棋游戏步骤详解,JS实现井字棋游戏的注意事项有哪些,下面就是实战案例,一起来看一下. 最近有一门课结束了,需要做一个井字棋的游戏,我用JavaScript写了一个.首先界面应 ...

  6. 《Android游戏开发详解》——第1章,第1.6节函数(在Java中称为“方法”更好)...

    本节书摘来自异步社区<Android游戏开发详解>一书中的第1章,第1.6节函数(在Java中称为"方法"更好),作者 [美]Jonathan S. Harbour,更 ...

  7. python小游戏代码大全-20行python代码的入门级小游戏的详解

    背景: 作为一个python小白,今天从菜鸟教程上看了一些python的教程,看到了python的一些语法,对比起来(有其他语言功底),感觉还是非常有趣,就随手添了一点内容,改了一个小例程,当着练练手 ...

  8. 《Android游戏开发详解》一2.16 区分类和对象

    本节书摘来异步社区<Android游戏开发详解>一书中的第2章,第2.16节,作者: [美]Jonathan S. Harbour 译者: 李强 责编: 陈冀康,更多章节内容可以访问云栖社 ...

  9. 《Android游戏开发详解》一3.1 构造方法

    本节书摘来异步社区<Android游戏开发详解>一书中的第3章,第3.1节,作者: [美]Jonathan S. Harbour 译者: 李强 责编: 陈冀康,更多章节内容可以访问云栖社区 ...

  10. 《Android游戏开发详解》一导读

    前 言 Android游戏开发详解 作为对编程知之甚少或者毫无所知的初学者,开始学习Android游戏开发,可能会觉得就像是穿越陌生的星际的旅程.有太多的事情要尝试,太多的知识要学习,令人遗憾的是,还 ...

最新文章

  1. 【转载】 stm32之PWM
  2. 扩展筛选LightOj 1054 Efficient Pseudo Code
  3. 理解JavaScript的执行机制
  4. [mybatis]缓存_缓存有关的设置以及属性
  5. 修改Oracle最大连接数
  6. Stanford Local Programming Contest 2011
  7. 什么是内容电商?核心是“内容”
  8. 开源如何走向商业化?
  9. [转载] python-numpy总结
  10. R语言之高级数据分析「聚类分析」
  11. 10. 单例模式(singleton pattern)
  12. js去掉所有html标记
  13. javascript实现文件下载
  14. 2022-2028年中国饮用水市场投资分析及前景预测报告(全卷)
  15. 二维码扫码支付实现方案(仅供自己参考)
  16. mac mini php开发,mac mini主要用来干嘛
  17. krita源码提供了Tarball 和KDE Repository两套源码的区别
  18. Java实验3-2【在职研究生类设计实验】
  19. 自助广告插件系统 7.4版本 高颜值网站广告代码
  20. iPhone手机史上最全的扫盲帖【解锁,激活,Cydia,基带,裸机】

热门文章

  1. 免费的mysql图形化界面_免费好用的MySQL数据库客户端图形界面管理工具
  2. 基于Java毕业设计智慧后勤系统源码+系统+mysql+lw文档+部署软件
  3. 【电子技术实验理论】语音放大电路
  4. Multi-Scale Boosted Dehazing Network with Dense Feature Fusion笔记和代码
  5. Python问题:ImportError: cannot import name ‘Template‘ from ‘string‘
  6. 【教程向】如何用L298N电机驱动模块与Arduino实现PWM调速
  7. TextWatcher接口
  8. 使用Kotlin创建动态Android TextWatcher
  9. 图解 Excel 添加数据透视表
  10. plc用c语言编写程序,plc编程和c语言编程的联系