电子信息 工科男
一点一点努力!

文章目录

  • 前言
  • 一、游戏介绍
  • 二、游戏设计思路
  • 二、具体步骤
    • 1.创建test.c和game.c源文件以及 game.h头文件
    • 2.创建菜单
    • 3.创建雷盘
    • 4.初始化雷盘
    • 5.打印雷盘
    • 6.布雷
    • 7.排雷
  • 三、程序源码

前言

本文使用C语言实现扫雷游戏

一、游戏介绍

扫雷游戏大家都不陌生,玩家翻开一个格子,如果是雷则直接游戏结束,如果不是雷则显示周围8格包含雷的个数,通过玩家逐渐推理出所有非雷的位置,最终取得胜利

二、游戏设计思路

我们定义两个数组,一个数组(mine)用来存放布置好的雷的信息,一个数组(show)用来存放排查出类雷的信息(用于和玩家交互),通过修改show的信息达到排雷的目的。

如上图可知:在计算边界1周围雷数时,数组会越界,所以为了防止这个现象,我们可以在周围多留一圈,例如如果我们要玩9x9的,那就定义11x11大小的数组

二、具体步骤

1.创建test.c和game.c源文件以及 game.h头文件

注:各文件作用解释如下
1:test.c代码为整个程序的主题实现逻辑
2:game.c代码为游戏函数的定义
3:game.h代码为游戏函数的声明

2.创建菜单

在test.c文件中创建菜单函数。
代码如下(示例):

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

注:玩家选择1进入游戏,0退出游戏

3.创建雷盘

mine数组雷盘示例如下:

show数组雷盘示例如下:

代码如下:

#define ROW 9
#define COL 9#define ROWS ROW+2
#define COLS COL+2//1:雷盘创建,mine数组用来存放雷,show数组用来显示排雷
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };

4.初始化雷盘

两个数组的初始化
mine数组初始化为’0’,布置雷的时候,改成’1’
show数组初始化为‘*’,排除雷后,具体位置改成数字字符

代码如下:

雷盘初始化。初始化是参数要为11*11,防止数组越界,打印只需要9*9的就行了
void init_board(char board[ROWS][COLS], int rows, int cols, char set)
{int i = 0;for (i = 0; i < rows; i++){int j = 0;for (j = 0; j < cols; j++){board[i][j] = set;}}
}

5.打印雷盘

由上图雷盘示例可见,为了便于玩家输入排雷坐标,需要在打印雷盘信息前打印行号和列号,同时只需要打印9x9的雷盘大小即可。

代码如下:

//打印9*9的就行了
void display_board(char board[ROWS][COLS], int row, int col)
{int i = 0;int j = 0;//打印列号for (j = 0; j <= col; j++){printf("%d ", j);}printf("\n");for (i = 1; i <= row; i++){printf("%d ", i);  //打印行号for (j = 1; j <= col; j++){printf("%c ", board[i][j]);}printf("\n");}
}

6.布雷

布雷需要考虑三个因素
1:随机生成两个数,横坐标x,纵坐标y
2:该坐标是否布过雷
3:由于布雷是在11x11(0-10)数组中间9x9(1-9)的格子上布置的,故调用rand()函数对行和列取余生成的是0-10的数字,故还需加一才能时期布置在目标的位置

代码如下:

//布雷
//1:要随机生成两个数,横坐标x,纵坐标y
//2:该位置是否被布过雷
void set_mine(char board[ROWS][COLS], int row, int col)
{int count = EASY_COUNT;while (count){int x = rand() % row + 1;  //取余生成的数是0-row-1的int y = rand() % col + 1;  //取余生成的数是0-row-1的if (board[x][y] == '0'){board[x][y] = '1';count--;}}
}

注:生成随机数需要用到rand()函数,但是多次运行代码会发现rand()函数会生成的随机数一样。故需要在使用前调用前采用如下代码,同时需要引用头文件#include <stdlib.h>和#include <time.h>

7.排雷

排雷需要考虑五个问题:
1:输入坐标是否合法
2:输入坐标是否排过雷
3:如果输入坐标四周都不是雷,且周围的格子四周也没有雷怎么办
4:如何显示雷的数量
5:排雷结束标志,全部排完,或者踩雷

对于问题三:
我们采用递归思想,如果输入坐标(x,y)周围没有雷,那么就将其改成空格,然后再用同样的方法向四周扩散(x从x-1 ~ x+1)(y从y-1~y+1),看其周围的8个位置附近有雷,没有雷同样也改为空格,有雷则显示周围雷的数量。

递归的两个必要条件
1:存在限制条件,当满足这个条件的时候,递归将不在继续,本处递归的限制条件是:只对*进行递归,防止死循环即if (show[i][j] == '')才进行递归
2:每次递归调用以后越来越接近这个限制条件,本处由于向四周扩散,故最后一定会碰到show[i][j] != '
'的地方

对于问题四:
我们需要一个函数获(x,y)周围雷的数量,由于雷的数字为1,但是如果单纯的将周围数字加起来确实整形十进制数字,而数组中存放的是字符型,故需要将其转换。
根据ASCII表可知,字符数字1和数子0的十进制相差1,即’1’ - ‘0’=1,故如果想要得到字符’1’,则是十进制相减的结果加上字符0即可


代码如下:

//获取雷数
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 expand(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int* win)
{if (x >= 1 && x <= ROW && y >= 1 && y <=  COL){int count = get_mine_count(mine, x, y);if (count == 0){//如果(x,y)坐标四周没有雷,将其改为空格,并且向四周扩散show[x][y] = ' ';int i = 0;for (i = x - 1; i <= x + 1; i++){int j = 0;for (j = y - 1; j <= y + 1; j++){//只对*进行递归,防止死循环if (show[i][j] == '*'){expand(mine, show, i, j,win);}}}}else  //四周有雷显示雷数{show[x][y] = count + '0';}(*win)++;}
}//排雷
//1:输入坐标是否合法
//2:输入坐标是否排过雷//3:排雷结束标志,全部排完,或者踩雷
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int x = 0;int y = 0;int win = 0;while (win < row * col - EASY_COUNT){printf("------------------------------\n");printf("请输入要排雷的坐标:>");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){//判断是否排过雷if (show[x][y] == '*'){//踩雷了if (mine[x][y] == '1'){printf("很遗憾,你被雷裤衩子都炸没了\n");//Sleep(1000);//system("cls");display_board(mine, ROW, COL);break;}else{//int count = get_mine_count(mine, x, y);//show[x][y] = count + '0';expand(mine, show, x, y, &win);display_board(show, ROW, COL);//win++;}}else{printf("该位置已经排过雷了,请重新输入\n");}}else{printf("坐标非法,请重新输入\n");}}if (win == row * col - EASY_COUNT){printf("恭喜你排雷成功\n");display_board(mine, ROW, COL);}
}

三、程序源码

test.c中代码

#include "game.h"void menu()
{printf("****************************\n");printf("*********1. play ***********\n");printf("*********0. play ***********\n");printf("****************************\n");
}void game()
{//1:雷盘创建,mine数组用来存放雷,show数组用来显示排雷char mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };//2:雷盘初始化//mine数组初始化为0其中1为雷//show数组初始化为*init_board(mine, ROWS, COLS, '0');init_board(show, ROWS, COLS, '*');//3:雷盘打印display_board(mine, ROW, COL);display_board(show, ROW, COL);//4:布雷,雷要布在9*9的格子里set_mine(mine, ROW, COL);//display_board(mine, ROW, COL);//排雷find_mine(mine, show, ROW, COL);}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;
}

game.c中代码

#define _CRT_SECURE_NO_WARNINGS 1#include "game.h"雷盘初始化。初始化是参数要为11*11,防止数组越界,打印只需要9*9的就行了
void init_board(char board[ROWS][COLS], int rows, int cols, char set)
{int i = 0;for (i = 0; i < rows; i++){int j = 0;for (j = 0; j < cols; j++){board[i][j] = set;}}
}//打印9*9的就行了
void display_board(char board[ROWS][COLS], int row, int col)
{int i = 0;int j = 0;//打印列号for (j = 0; j <= col; j++){printf("%d ", j);}printf("\n");for (i = 1; i <= row; i++){printf("%d ", i);  //打印行号for (j = 1; j <= col; j++){printf("%c ", board[i][j]);}printf("\n");}
}//布雷
//1:要随机生成两个数,横坐标x,纵坐标y
//2:该位置是否被布过雷
void set_mine(char board[ROWS][COLS], int row, int col)
{int count = EASY_COUNT;while (count){int x = rand() % row + 1;  //取余生成的数是0-row-1的int y = rand() % col + 1;  //取余生成的数是0-row-1的if (board[x][y] == '0'){board[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 expand(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int* win)
{if (x >= 1 && x <= ROW && y >= 1 && y <=  COL){int count = get_mine_count(mine, x, y);if (count == 0){//如果(x,y)坐标四周没有雷,将其改为空格,并且向四周扩散show[x][y] = ' ';int i = 0;for (i = x - 1; i <= x + 1; i++){int j = 0;for (j = y - 1; j <= y + 1; j++){//只对*进行递归,防止死循环if (show[i][j] == '*'){expand(mine, show, i, j,win);}}}}else  //四周有雷显示雷数{show[x][y] = count + '0';}(*win)++;}
}//排雷
//1:输入坐标是否合法
//2:输入坐标是否排过雷//3:排雷结束标志,全部排完,或者踩雷
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int x = 0;int y = 0;int win = 0;while (win < row * col - EASY_COUNT){printf("------------------------------\n");printf("请输入要排雷的坐标:>");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){//判断是否排过雷if (show[x][y] == '*'){//踩雷了if (mine[x][y] == '1'){printf("很遗憾,你被雷裤衩子都炸没了\n");//Sleep(1000);//system("cls");display_board(mine, ROW, COL);break;}else{//int count = get_mine_count(mine, x, y);//show[x][y] = count + '0';expand(mine, show, x, y, &win);display_board(show, ROW, COL);//win++;}}else{printf("该位置已经排过雷了,请重新输入\n");}}else{printf("坐标非法,请重新输入\n");}}if (win == row * col - EASY_COUNT){printf("恭喜你排雷成功\n");display_board(mine, ROW, COL);}
}

game.h中代码

#define _CRT_SECURE_NO_WARNINGS 1#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>#define ROW 9
#define COL 9#define ROWS ROW+2
#define COLS COL+2#define EASY_COUNT 10//雷盘初始化,初始化是参数要为11*11,防止数组越界,打印只需要9*9的就行了
void init_board(char board[ROWS][COLS], int rows, int cols, char set);//打印雷盘
void display_board(char board[ROWS][COLS], int row, int col);//布雷
void set_mine(char board[ROWS][COLS], int row, int col);//排雷
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

以上就是本游戏的全部代码,程序是在VS2019环境下实现

C语言实现扫雷游戏(超详细讲解+全部源码)相关推荐

  1. C语言实现扫雷【超详细讲解】

    目录 一.实现扫雷的基本思路 二.代码实现的具体步骤 三.完整代码 1.saolei.h部分 2.saolei.c部分 3.test.c部分 扫雷和三子棋有很多相似的地方,相信大家认真学习完三子棋再将 ...

  2. 【HTML | CSS】纯CSS居然能做出这种效果,一款宝藏网页分享(超详细讲解 | 附源码)

  3. 超详细!ArrayList源码图文解析

    不诗意的女程序媛不是好厨师~ 转载请注明出处,From李诗雨-[https://blog.csdn.net/cjm2484836553/article/details/104329665] <超 ...

  4. C语言青蛙过河游戏超详细教程【附源码】

    今天给大家带来一个青蛙过河小游戏代码,先看看效果吧! 开始界面: 游戏界面 : 游戏中界面:  胜利界面: 死亡界面: 代码我们分了几个模块来写,这样不容易写乱,也方便后续修改 木板模块: #incl ...

  5. 用Android Studio做一个超好玩的拼图游戏,附送超详细注释的源码

    文章目录 一.项目概述 二.开发环境 三.需求分析 四.实现过程 1.拼图游戏布局绘制 2.拼图游戏时间计时 3.拼图游戏打乱显示 4.拼图游戏碎片位置切换 5.拼图游戏成功的条件 6.拼图游戏重新开 ...

  6. 用Python做一个超好玩的拼图游戏,0基础也能包你学会,附送超详细注释的源码~

    导语 你所认为的python........                                                              python & bor ...

  7. C语言实现扫雷(含展开,附源码)

    我相信在做的各位都是玩过扫雷的,游戏玩法就不赘述了. 直接进入主题:先思考后敲代码!! 首先,我将扫雷分为两个棋盘,一个放雷,另一个为玩家猜测盘. 这就有同学问了,设置一个棋盘不就完了,这样不就搞复杂 ...

  8. c语言2048代码linux,C语言2048小游戏课设(附源码).doc

    PAGE PAGE 1 C语言2048小游戏课设 项目说明 本系统基于C语言开发,适用于刚入门的C语言新手项目课设,开发软件采用VC++6.0开发,VS,DEV C++等均可运行.(书生) 项目运行截 ...

  9. python k-means聚类算法 物流分配预测实战(超详细,附源码)

    数据集和地图可以点赞关注收藏后评论区留下QQ邮箱或者私信博主要 聚类是一类机器学习基础算法的总称. 聚类的核心计算过程是将数据对象集合按相似程度划分成多个类,划分得到的每个类称为聚类的簇 聚类不等于分 ...

最新文章

  1. 创业基础(第四章: 创业风险及识别与管理) 来自高校:全国大学生创新创业实践联盟 分类:创新创业 学习规则:按序学习
  2. 解决fstream不能打开带有中文路径文件的问题
  3. 让FX1.1的NotifyIcon支持BalloonTip(2)
  4. 无盘服务器怎么修改ip,怎么进入无盘服务器修改IP地址呢
  5. c语言如何设置c99标准,新的C语言: C99标准介绍
  6. SIGIR 2019 开源论文 | 基于图神经网络的协同过滤算法
  7. AI体验馆上线!集成业界领先NLP场景深度迁移学习框架EasyTransfer
  8. SAP CRM和Cloud for Customer的UI界面皮肤更改
  9. 说说 Spring 的事务同步管理器
  10. bzoj 1084 DP
  11. 我们真正需要的目标(原名:制定目标你会吗?)
  12. win10浏览器加载很慢_win10系统打开网页速度慢的排除原因及解决方法
  13. 老九学堂C++实现小游戏之小公主养成记
  14. 路径算法:遗传算法 (Genetic Algorithm, GA)
  15. 为什么企业微信只能群发一次?如何增加群发次数?
  16. 儿童剧剧本话剧舞台剧戏剧情景剧红色课本剧英语剧音乐小品剧视频
  17. 思科ACS5.8最新搭建教程-亲测可用
  18. python百度贴吧图片下载脚本实例
  19. [免费专栏] Android安全之Android奇淫run-as命令,调用系统受UID限制的API
  20. 计算机硬盘如何做移动硬盘,移动硬盘怎么做电脑系统盘使用?

热门文章

  1. 富阳银湖云栖著_【首页】富阳绿城云栖桃花源杭州售楼处——绿城雲栖桃花源——售楼...
  2. 成都编程python培训
  3. 理解二重积分极坐标算法
  4. 亚信科技两方案入围工信部“数字技术融合创新解决方案”评选
  5. ClickHouse拆解
  6. Android traceView使用
  7. python自动化[poco篇]
  8. Java el ognl 正则,struts2中ognl表达式 各种合集_struts2 ognl 正则表达式_struts2 ognl表达式...
  9. 关于近期更新导致RDP远程桌面无法访问之10.0.19041.2673
  10. avr 运行 linux,如何在8位AVR单片机上运行Linux?