前言

先解释下扫雷的玩法,随机点一个方块(这个是有运气成分在的),显示以这个方块为中心,3x3的格子里雷的总个数,玩家通过这个个数判断雷的位置,继续点击下一个方块,直到找到所有雷的位置,才算成功,中途碰到雷游戏结束。

本教程是基础款,也就是说不会出现点一下翻出一大片(这个需要程序连续测试相邻的格子有没有雷,直到有雷了才会停止展开),也不能标记

我这里简单一点,设置了80个雷,而且展示了真实棋盘,这时候,输入唯一不是雷的坐标6,1,游戏就结束了。

*文章风格与上一篇三子棋类似,但不会那么详细(比如为什么要头文件参与声明,为什么要宏定义变量等等),有兴趣的朋友先去看看这篇 手把手教你写三子棋

一、设计思路

三、具体步骤

1、模块化编程

2、游戏开始的逻辑

展示菜单–>玩家选择–>进入相应模式

所以main函数如下,很简单的一个do while里面加个switch,不多赘述,别忘了是main()放在最下面。

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

菜单也很简单,如下:

void menu()
{printf("***********************\n");printf("******* 1.play ********\n");printf("******* 0.exit ********\n");printf("***********************\n");}

3、游戏的实现

那么game()里包含什么呢?提醒下,game()在test.c里

1)棋盘的创建以及初始化 Init_board()

正如一开始所说,首先要定义两个数组(棋盘),一个给电脑用来埋雷,一个给玩家进行不断选择排查,这里延用上次三子棋宏定义变量的创建风格,方便进行棋盘大小的修改。

其次,判断的是以你选择的方块为中心,3x3的格子内雷的个数,这里要考虑,那些边上的格子怎么办,对于数组来说,你去排查边缘外边的格子可是会发生越界访问的,那么我们为什么不一开始的就建个大一点的数组呢,可以供边缘的格子进行3x3的排查

在game.h中

#define ROW 9
#define COL 9#define ROWS ROW+2
#define COLS COL+2

game()里

 char mine[ROWS][COLS] = { 0 };//mine有布置雷的意思char show[ROWS][COLS] = { 0 };

初始化就很简单了,布雷棋盘与玩家看到的棋盘要填充不同的字符,一个要清清楚楚雷在哪,一个像是被盖住了

(1)首先确定你要确定传的参数,在game()里

 Init_board(mine, ROWS, COLS, '0');//这个是实际埋雷的棋盘Init_board(show, ROWS, COLS, '*');//这个是展示给玩家的棋盘   //          (棋盘,行,列,字符)

(2)再在game.h里声明

void Init_board(char arr[ROWS][COLS], int rows, int cols, char set);

(3)再转到game.c里定义

void Init_board(char arr[ROWS][COLS], int rows, int cols, char set)
{int i, j = 0;for (i = 0; i < rows; i++){for (j = 0; j < cols; j++){arr[i][j] = set;}}
}

2)打印棋盘 show_board()

这里注意,上面之所以要建立11x11的棋盘,是为了 排查雷这个操作不发生越界访问,但是实际打印给我们看的的时候只需要中心的9x9的棋盘,多出来的第0行和第0列可以利用下标注下几行几列,第10行和第10列,存在,而且也被填充了字符,但没有打印出来

*如下图,黑色的是实际棋盘,绿色的方框和数字是打印出来的(注意数字是打印出来,不是填充,实际上对应格子里还是‘0’和‘*’),右下角黄色框边缘方格排查雷的方式*

1)test.c中,game()

 //打印棋盘show_board(mine, ROW, COL);show_board(show, ROW, COL);

2)game.h

void show_board(char arr[ROWS][COLS], int row, int col);

3)game.h

void show_board(char arr[ROWS][COLS], int row, int col)
{int i, j = 0;printf("-------------------\n");
//第一行展示列数 0 1 2 3 4 5 6 7  8 9for (i = 0; i <= row; i++){printf("%d ", i);}printf("\n");//换行到第二行,打印中心棋盘//第二行开始从1,打印行数数for (i = 1; i <= row; i++)//注意从一开始{printf("%d ", i);//这里是打印每行的行数是几,0与第一行列数的0重合
//1
//2
//3
//。。。
//9for (j = 1; j <= col; j++)//注意是从1开始{printf("%c ",arr[i][j]);//对于设立的两个数组,一个是清晰可见的,一个是要遮盖的需要玩家排查的}printf("\n");//一行结束换下一行}printf("-------------------\n\n");}

这里结束可以先运行下,看看打印棋盘能不能运行出来

3)埋雷 set_mine()

埋雷是随机的,所以又要用到rand函数,不懂的可以去看下这个 详解rand函数,注意引用到的头文件有time.h, stdlib.h,初始化见一开始的main()

同样game.h里宏定义个变量MINE,埋雷,首先要保证这个位置没有雷,埋下去后雷的数量减一,循环,直到雷的数量为0.

1)game()里

 set_mine(mine, ROW, COL);

2)game.h里

#define MINE 80
void set_mine(char arr[ROWS][COLS], int row, int col);

3)game.c里

void set_mine(char arr[ROWS][COLS], int row, int col)
{int count = MINE;int x = 0;int y = 0;while (count){x = rand() % row+1 ;//从0到row+1,随机分配个数//这里之所以要加1,是因为rand随机的范围,不包括最后的数字y = rand() % col +1;if ( arr[x][y] == '0' ){arr[x][y] = '1';//在雷的地方放上‘1’count--;//不是雷的位置放一个雷,雷的数目就减一}}
}

4)排查雷 find_mine()

如果我们排查的这个格子不是雷,也就是‘0’,周围的格子有雷,放的‘1’,怎么算有几个雷呢,这里是字符,而不是数字

这里可以看下ascii码表,‘1’-‘0’=49-48=1

那么,假设你一开始的选择格子坐标是(x,y),那么周围八个的格子坐标都能表示出来,那么这八个坐标的字符相加再减去八个‘0’字符得到的数字就是雷的个数,加上‘0’,就变成对应的字符了,然后在第二张棋盘,也就是玩家看到的遮蔽的棋盘上显示出来。

那怎么才算游戏呢?我们放了80个雷,总共格子是9✖9=81个,那么不是雷的格子就1个,意味着判断一次不是雷就行

 get_around_mine(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';
}void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int x, y = 0;int win = 0;while (win<row*col-MINE)//9*9-10,就得到不是雷的有多少个格子,如果把不是雷的格子全找出来,那么游戏就胜利了{printf("请输入坐标:");scanf("%d %d", &x, &y);if (x >= 1 && x <= row&&y >= 1 && y <= col){if (mine[x][y] == '1'){printf("选择的是雷,游戏结束!");show_board(show, ROW, COL);//直接选到雷可以展示给玩家所有雷的位置break;}else{int count = 0;count = get_around_mine(mine, x, y);show[x][y] = count + '0';//数字加字符,变成字符,7+‘0’=‘7’show_board(show, ROW, COL);//每次排雷完都要给玩家打印一边棋盘win++;}}else{printf("坐标非法,请重新输入:");}if (win == row*col - MINE){printf("全部排查成功,游戏结束\n");show_board(mine, ROW, COL);//展示实际的雷图}}
}

game()里面

 //打印棋盘//show_board(mine, ROW, COL);//show_board(show, ROW, COL);
//别忘了这里把上一部分的打印注释掉//布置雷set_mine(mine, ROW, COL);//show_board(mine, ROW, COL);show_board(show, ROW, COL);//展示给玩家的棋盘find_mine(mine, show, ROW, COL);//排雷

三、全部代码

game.h

#define _CRT_SECURE_NO_WARNINGS#include <time.h>
#include <stdio.h>
#include <stdlib.h>#define ROW 9
#define COL 9#define ROWS ROW+2
#define COLS COL+2#define MINE 80void Init_board(char arr[ROWS][COLS], int rows, int cols, char set);
void show_board(char arr[ROWS][COLS], int row, int col);
void set_mine(char arr[ROWS][COLS], int row, int col);
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

test.c

#define _CRT_SECURE_NO_WARNINGS#include "game.h"//思考内容:
//1.标记可能的雷
//2.展开一片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 };//初始化棋盘Init_board(mine, ROWS, COLS, '0');//这个是实际埋雷的棋盘Init_board(show, ROWS, COLS, '*');//这个是展示给玩家的棋盘//打印棋盘//show_board(mine, ROW, COL);//show_board(show, ROW, COL);
//别忘了这里把上一部分的打印注释掉//布置雷set_mine(mine, ROW, COL);//show_board(mine, ROW, COL);show_board(show, ROW, COL);//展示给玩家的棋盘find_mine(mine, show, ROW, COL);//排雷
}
int main()
{int input = 0;srand((unsigned int)time(NULL));//初始化随机数发生器//time是时钟函数,是获取时间,这边要强制转化下数据类型//本来应该是先定义一个time_t类型的t变量,然后time(&t)//但也可以直接传入一个空指针,因为程序不需要经过参数而去获得的数据do{menu();printf("请选择:");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误,请重新选择\n");break;}} while (input);return 0;
}

game.c

#define _CRT_SECURE_NO_WARNINGS#include "game.h"//初始化棋盘
void Init_board(char arr[ROWS][COLS], int rows, int cols, char set)
{int i, j = 0;for (i = 0; i < rows; i++){for (j = 0; j < cols; j++){arr[i][j] = set;}}
}//打印棋盘,只打印9x9的实际棋盘,可以再标注下行和列
//注意这里打印出来,第11行和第11列是不展示的,但是它存在,而且都是实际上放的是设置的“set"
void show_board(char arr[ROWS][COLS], int row, int col)
{int i, j = 0;printf("-------------------\n");for (i = 0; i <= row; i++){printf("%d ", i);}printf("\n");//这里是打印第一行所展示的行数for (i = 1; i <= row; i++){printf("%d ", i);//这里是打印每行的列数是几,0与第一行行数的0重合for (j = 1; j <= col; j++){printf("%c ",arr[i][j]);//对于设立的两个数组,一个是清晰可见的,一个是要遮盖的需要玩家排查的}printf("\n");}printf("-------------------\n\n");}//布置雷
void set_mine(char arr[ROWS][COLS], int row, int col)
{int count = MINE;int x = 0;int y = 0;while (count){x = rand() % row+1 ;//从0到row+1,随机分配个数//这里之所以要加1,是因为rand随机的范围,不包括最后的数字y = rand() % col +1;if ( arr[x][y] == '0' ){arr[x][y] = '1';count--;//不是雷的位置放一个雷,雷的数目就减一}}
}get_around_mine(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';//在ASCII码表中,‘1’-’0‘,就是相应的数字49-48,也就是1//按照选择位置周围八个字符加起来减去8个字符0.那么就得到周围有x个雷,这个数字加上字符’0‘,在棋盘上就是显示的x//因为一开始这个数组类型就是char,不加’0‘显示的是x在ASCII中对应的符号,或者直接是个方块
}void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int x, y = 0;int win = 0;while (win<row*col-MINE)//9*9-10,就得到不是雷的有多少个格子,如果把不是雷的格子全找出来,那么游戏就胜利了{printf("请输入坐标:");scanf("%d %d", &x, &y);if (x >= 1 && x <= row&&y >= 1 && y <= col){if (mine[x][y] == '1'){printf("选择的是雷,游戏结束!");show_board(show, ROW, COL);break;//直接选到雷可以展示给玩家所有雷的位置}else{int count = 0;count = get_around_mine(mine, x, y);show[x][y] = count + '0';show_board(show, ROW, COL);win++;}}else{printf("坐标非法,请重新输入:");}if (win == row*col - MINE){printf("全部排查成功,游戏结束\n");show_board(mine, ROW, COL);}}
}

四、 总结

这次写明显得心应手很多了,果然自己写,和教别人写是完全不同的感觉,思考,纠正,清晰。
教别人也是在教自己,希望和朋友们共勉,如果有什么错误或者建议,欢迎指出!

手把手教你作出扫雷小游戏相关推荐

  1. python手机版做小游戏代码大全-Python大牛手把手教你做一个小游戏,萌新福利!...

    原标题:Python大牛手把手教你做一个小游戏,萌新福利! 引言 最近python语言大火,除了在科学计算领域python有用武之地之外,在游戏.后台等方面,python也大放异彩,本篇博文将按照正规 ...

  2. matlab 手把手教你制作五子棋小游戏

    想把以前写过的小游戏出一款详细教程呀 这两天发现五子棋有个简单的写法 虽然说有点弊端但这个程序真的很简单呀 一共只有70多行 相信大家就算没有基础多查多看也能学会吧嗯哒 第一步:界面设置 axis e ...

  3. python实现2048小游戏_python—手把手教你实现2048小游戏

    相信2048这个游戏对大家来说一定不陌生,下面这篇文章就主要给大家介绍了怎么用Python实现2048小游戏,文中通过注释与示例代码介绍的很详细,相信对大家的理解和学习具有一定的参考借鉴价值,有需要的 ...

  4. C++ · 手把手教你写一个扫雷小游戏

    Hello,大家好,我是余同学.这两个月真是太忙了,无暇给大家更新文章- 暑假不是写了个扫雷小游戏吗(Link)?考虑到很多同学对代码没有透彻的理解,那么,这篇文章,我们来详细分析一下代码. 我们分为 ...

  5. 【java游戏开发】教你用java做出扫雷小游戏

    扫雷是一款大众类的益智小游戏.根据点击格子出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输. 本课程详细讲解一个扫雷游戏的开发过程.只要90分钟就可以完成一个你自己亲手开发出来的Java ...

  6. 小心踩雷!手把手教你制作扫雷游戏简单版本

    扫雷游戏----C语言必写游戏之一 扫雷游戏 背景 起源与玩法 基本实现思路 涉及语言的主要内容 具体实现步骤 1.基本框架 2.菜单页面的实现 3.初始化棋盘 4.在屏幕中显示棋盘 5.布置好棋盘中 ...

  7. 如何利用C#开发“扫雷”小游戏

    本文详细说明了利用C#语言开发"扫雷"小游戏的开发过程.

  8. 用C语言实现扫雷小游戏(附上思路+项目展示+源代码)

    文章目录 前言 一.扫雷小游戏整体思路讲解. 二.game.c各游戏功能函数的讲解 1.InitBoard 初始化数组函数讲解 2.DisplayBoard 打印格子函数讲解 3.Setmine 电脑 ...

  9. C语言编写扫雷小游戏

    该博文为原创文章,未经博主同意不得转载,如同意转载请注明博文出处 本文章博客地址:https://cplusplus.blog.csdn.net/article/details/104992377 扫 ...

最新文章

  1. mysql的count(*)的优化,获取千万级数据表的总行数
  2. 【自动驾驶】相机标定 疑问总结
  3. C语言函数调用过程的汇编分析(停更)
  4. LeetCode Combination Sum
  5. 三维重建6:绑架问题/SensorFusion/IMU+CV-小尺度SLAM
  6. #Plugin 中国省市选择插件
  7. JavaScript覆盖率统计实现
  8. java数组有跨类建立对象_Java性能优化的45个细节(珍藏版)
  9. 使用sqoop从Oracle或mysql抽取数据到HDFS遇到的报错及解决
  10. 美团技术:交易平台建设实践(视频+胶片)
  11. Ansible-playbook 学习
  12. Google将推中文信息流产品,今日头条们请注意~
  13. Jenkins定时构建与轮询SCM
  14. Directshow播放框架详解
  15. Blast2GO使用方法详解(命令界面
  16. 嵌入式学习代码总结(二)
  17. C++智能指针与类型转换
  18. Unified Functional Testing(UFT)15.0.2入门保姆级教程(二),图文详解。QTP
  19. 源码:批量修改喜马拉雅下载节目的文件名
  20. android蓝牙连接取消后怎么重新连上,重新启动后接收蓝牙连接更改

热门文章

  1. 桌面计算机右击选项里没有管理员,电脑右击文件没有以管理员身份运行选项如何解决...
  2. 微信小程序学习笔记-自定义组件
  3. 内部RAID 0:OCZ将推廉价高速固态硬盘
  4. 【墨染】找特有姿态!基于【灵茶山艾府】题解的补充图解
  5. 支付宝数字证书对FIREFOX4的支持
  6. 蓝桥杯知识点汇总:基础知识和常用算法
  7. 强大的网段掩码计算处理工具netmask
  8. Java开发了解这些自然无惧面试,文末有彩蛋
  9. Java中时间格式 yyyyMMdd和yyyy-MM-dd相互转换
  10. 护肤:食盐美容4招 控油除痘去黑头 - 生活至上,美容至尚!