扫雷(超详解+全部码源)

C语言经典游戏扫雷

  • 前言
    • 一.游戏规则
    • 二.所需文件
    • 三.创建菜单
    • 四.游戏核心内容实现
      • 1.创建棋盘
      • 2.打印棋盘
      • 3.布置雷
      • 4.排查雷
      • 5.game()函数具体实现
    • 五.游戏运行实操
    • 六.全部码源

前言

😀C语言实现扫雷是对基础代码能力的考察。通过本篇文章你将学会如何制作出扫雷,坚持一段时间的复习相信你肯定能够掌握扫雷 (文末附三子棋全部代码).
👉扫雷游戏网页版 - Minesweeper
在这里插入图片描述

一.游戏规则

🚦设计游戏前先了解三子棋基本规则,以围绕规则用C语言实现
一个扫雷盘面由许多方格(cell)组成,方格中随机分布着一定数量的雷(mine),一个格子中至多只有1雷。胜利条件是打开所有安全格(非雷格,safe cell),失败条件是打开了一个雷格(踩雷)。

二.所需文件

🧐扫雷并不是一项容易的代码,需要我们进行分文件编写。
🤔什么是分文件编写?

就是把我们的程序代码划分成多个文件,这样就不会把所有的代码都放在main.c里面,采用分模块的编程思想,进行功能划分,把每个功能不一样的单独放在一个c文件里,然后写头文件把它封装成可调用的一个函数,在主函数调用这个封装好的函数,编译的时候一起编译即可

✌好处

a.功能责任划分
b.方便调试
c.主程序简洁

👀来让给我们看看具体操作如下:

头文件中创建game.h ----用来声明函数
源文件中创建game.c—函数具体实现 / test.c—主题流程
在这里插入图片描述

三.创建菜单

先创建一个菜单以展示进入退出游戏功能:

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

用do…while循环实现菜单使用,switch语句进行菜单选择

int main()
{int input = 0;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;
}

四.游戏核心内容实现

😇这里我们简化游戏,设置一个9*9的棋盘,安置10个雷。
排查过程如下:
1.如果这个位置是雷,那么游戏结束。
2.如果把不是雷的位置都找出来了,那么游戏结束。
3.如果这个位置不是雷,就计算这个位置的周围的8个格子有几个雷,并显示出雷的个数。

game()函数中实现整个游戏,先数组棋盘

1.创建棋盘

先创建数组(两个数组,为区别设置雷为1和统计雷个数为1做区分)

在这里插入图片描述 在这里插入图片描述
图一:”1“为雷(mine)
图二:”1“为雷的个数(show)

	char mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };

注:由于频繁使用在game.h中宏定义

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

在这里插入图片描述

在game.h文件中声明创建棋盘函数:

//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);

在game.c文件中实现初始化棋盘函数

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;}}
}

在test.c文件中实现调用

InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');

2.打印棋盘

在game.h中声明打印棋盘函数

//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);

在game.c中实现打印棋盘函数

void DisplayBoard(char board[ROWS][COLS], int row, int col)
{int i = 0;int j = 0;printf("------------扫雷------------\n");for (i = 0; i <= row; 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");}printf("------------扫雷------------\n");
}

3.布置雷

在game.h中声明布置雷函数

//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col);

在game.c文件中实现布置雷函数,设置随机雷数EASY_COUNT,进入while循环每设置一个雷,EASY_COUNT减一,直到雷设置完毕跳出循环。为保证雷的随机性需生成随机坐标,判断设置雷是否重复,未重复设置雷”1“。

void SetMine(char board[ROWS][COLS], int row, int col)
{int count = EASY_COUNT;while (count){int x = rand() % row + 1;//x坐标为1-9int y = rand() % col + 1;//y坐标为1-9if (board[x][y] == '0'){board[x][y] = '1';}count--;}
}

随机数在game.h中进行宏定义

#define EASY_COUNT 10

调用rand()需要srand()

srand((unsigned int)time(NULL));

注:包含头文件

#include<stdlib.h>—>srand
#include<time.h>----->time

4.排查雷

在game.h文件中声明排查雷函数

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

在game.c中实现排查雷函数,输入坐标↔️确保坐标在棋盘范围内否则重新输入,判断棋盘范围内坐标是否重复输入,未重复输入判断是否踩雷,.若踩雷”很遗憾炸死“,若没有统计周围雷个数(用GetMineCount函数)。放入while循环,若雷没有排查完持续循环,若被炸死跳出循环。若所有雷被排查出则排雷成功

void FindMine(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("请输入排查坐标>");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (show[x][y] != '*'){printf("输入坐标重复,请重新输入\n");}else if (mine[x][y] == '1'){printf("很遗憾,你被炸死了\n");DisplayBoard(mine, ROW, COL);break;}else{//不是雷,就统计x,y坐标周围有几个雷int c = GetMineCount(mine, x, y);show[x][y] = c + '0';DisplayBoard(show, ROW, COL);win++;}}else{printf("输入坐标错误,请重新输入\n");}}if (win == row * col - EASY_COUNT){printf("排雷成功\n");DisplayBoard(mine, ROW, COL);}
}

在game.c文件中实现统计雷个数函数,因为在排查雷函数内部,不需在game.h文件中声明。因为坐标内输入的是字符‘0’,所以统计出个坐标数‘1’之和减去‘0’及为周围雷数

int GetMineCount(char mine[ROWS][COLS], int x, int y)
{return mine[x + 1][y] + mine[x - 1][y] +mine[x][y + 1] + mine[x][y - 1] +mine[x + 1][y + 1] + mine[x - 1][y + 1] +mine[x - 1][y - 1] + mine[x + 1][y - 1] - 8 * '0';
}

5.game()函数具体实现

1实现棋盘初始化,2打印棋盘,3设置棋盘雷数,4排查雷

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);SetMine(mine, ROW, COL);FindMine(mine, show, ROW, COL);
}

五.游戏运行实操

出现菜单进行选择
在这里插入图片描述
选1进入游戏
在这里插入图片描述
输入坐标开始游戏
在这里插入图片描述
坐标重复,重新输入
在这里插入图片描述
越界重新输入
在这里插入图片描述
踩雷炸死
在这里插入图片描述
选择0退出游戏
在这里插入图片描述

六.全部码源

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#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);SetMine(mine, ROW, COL);FindMine(mine, show, ROW, COL);
}
int main()
{srand((unsigned int)time(NULL));int input = 0;do{menu();printf("请输入选项>");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏");break;default:printf("输入错误,请重新输入");break;}} while (input);return 0;
}

game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"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;printf("------------扫雷------------\n");for (i = 0; i <= row; 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");}printf("------------扫雷------------\n");
}void SetMine(char board[ROWS][COLS], int row, int col)
{int count = EASY_COUNT;while (count){int x = rand() % row + 1;int y = rand() % col + 1;if (board[x][y] == '0'){board[x][y] = '1';}count--;}
}int GetMineCount(char mine[ROWS][COLS], int x, int y)
{return mine[x + 1][y] + mine[x - 1][y] +mine[x][y + 1] + mine[x][y - 1] +mine[x + 1][y + 1] + mine[x - 1][y + 1] +mine[x - 1][y - 1] + mine[x + 1][y - 1] - 8 * '0';
}void FindMine(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("请输入排查坐标>");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (show[x][y] != '*'){printf("输入坐标重复,请重新输入\n");}else if (mine[x][y] == '1'){printf("很遗憾,你被炸死了\n");DisplayBoard(mine, ROW, COL);break;}else{//不是雷,就统计x,y坐标周围有几个雷int c = GetMineCount(mine, x, y);show[x][y] = c + '0';DisplayBoard(show, ROW, COL);win++;}}else{printf("输入坐标错误,请重新输入\n");}}if (win == row * col - EASY_COUNT){printf("排雷成功\n");DisplayBoard(mine, ROW, COL);}
}

game.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>#define ROW 9
#define COL 9#define ROWS ROW + 2
#define COLS COL + 2#define EASY_COUNT 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);

💘本次扫雷学习告一段落,扫雷详解+完整代码,反复阅读,坚持打码,相信你在不久的将来就会拿下扫雷,以扩展更高级代码。期待下次作品与大家见面!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/83191.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

centos linux 安装RDMA Soft-RoCE|虚拟机安装Soft-RoCE

什么是Soft-RoCE softRoCE的目标是在所有支持以太网的设备上都可以部署RDMA传输&#xff0c;可以使不具备RoCE能力的硬件和支持RoCE的硬件间进行基于IB语义的交流。 大白话就是模拟RDMA的软件栈&#xff0c;使得在没有RDMA网卡的环境上&#xff0c;也可以运行基于RDMA写的传输…

Java-数据类型

数据类型 数据类型基本数据类型整形浮点字符型布尔类字节 引用数据类型类型转换显式转换隐式转换注意事项 整型提升 作为学习Java的入门知识,在刚开始面试的几场,表现不太好的时候,就有几个面试官会问这个问题,估计此时此刻我在他们的心目中也就是这个问题的层次了吧…当然,当时…

Leetcode-每日一题【剑指 Offer 15. 二进制中1的个数】

题目 编写一个函数&#xff0c;输入是一个无符号整数&#xff08;以二进制串的形式&#xff09;&#xff0c;返回其二进制表达式中数字位数为 1 的个数&#xff08;也被称为 汉明重量).&#xff09;。 提示&#xff1a; 请注意&#xff0c;在某些语言&#xff08;如 Java&…

postgresql|数据库|角色(用户)管理工作---授权和去权以及usage和select两种权限的区别

前言&#xff1a; postgresql做为一个比较复杂的关系型的重型数据库&#xff0c;不管是安装部署&#xff0c;还是后期的运行维护&#xff0c;都还是有比较多的细节问题需要引起关注。 例如&#xff0c;用户权限的合理分配&#xff0c;那么&#xff0c;什么是权限的合理分配呢…

详解推送Git分支时发生的 cannot lock ref 错误

在码云上建了一个项目仓库,分支模型使用 git-flow ,并在本地新建了一个功能分支 feature/feature-poll。后来在推送时发生错误,提示 cannot lock ref ...... 这样的错误信息。下面复盘一下具体过程和解决办法,以供参考。 在码云中建立仓库时,考虑到想按照 GitFlow 的模式…

Python数据分析实战-格式化字符串的两种方法(附源码和实现效果)

实现功能 格式化字符串的两种方法 实现代码 # 方法一&#xff1a;format方法 query SELECT customer_id, COUNT(*) as num_ordersFROM ordersWHERE date > {start_date} AND date < {end_date} GROUP BY customer_idHAVING num_orders > {min_orders} start_da…

软件安全测试包含哪些内容和方法?安全测试报告的必要性

软件安全测试是一种通过模拟真实攻击的方式&#xff0c;对软件系统进行全面的安全性评估和测试&#xff0c;以发现潜在的安全漏洞和弱点&#xff0c;是确保软件系统安全性的重要措施。在进行软件安全测试时&#xff0c;我们需要了解测试的内容和方法&#xff0c;以及为什么进行…

echarts 图表设置 滚动条

效果图&#xff1a; 代码实现&#xff1a; 第一种方式&#xff1a; 通过 dataZoom 属性缩放进行配置滚动条。 //给x轴设置滚动条 dataZoom: [{start:0,//默认为0end: 100-1500/31,//默认为100type: slider,show: true,xAxisIndex: [0],handleSize: 0,//滑动条的 左右2个滑…

Mysql的instr()函数用法详解

最近接手了一个大型老项目&#xff0c;用到的jfinal技术&#xff0c;后端大部分都是拼写的sql&#xff0c;对一些sql函数不太理解的我算是一个挑战&#xff0c;也是一个进步的很大空间。 今天来说下instr这个函数 首先看下我们的表数据 我们先执行&#xff1a; SELECT * fro…

《Linux运维实战:Docker基础总结》

一、简介 1、docker的基本结构是什么&#xff0c;包含哪些组件&#xff1f; docker的基本机构是c/s模式&#xff0c;即客户端/服务端模式。 由docker客户端和docker守护进程组成。docker客户端通过命令行或其它工具使用docker sdk与docker守护进程通信&#xff0c;发送容器管理…

Qt 6. 其他类调用Ui中的控件

1. 把主类指针this传给其他类&#xff0c;tcpClientSocket new TcpClient(this); //ex2.cpp #include "ex2.h" #include "ui_ex2.h"Ex2::Ex2(QWidget *parent): QDialog(parent), ui(new Ui::Ex2) {ui->setupUi(this);tcpClientSocket new TcpClient…

Redis过期键删除策略

如果一个键过期了&#xff0c;那么它什么时候会被删除呢? 这个问题有三种可能的答案&#xff0c;它们分别代表了三种不同的删除策略&#xff1a; 1.定时删除&#xff1a;在设置键的过期时间的同时&#xff0c;创建一个定时器(timer)&#xff0c;让定时器在键的过期时间来临时…

Spring 创建和使用

文章目录 创建 Spring 项目1. 创建一个Maven项目2. 添加 Spring 框架支持3. 添加启动类 存储 Bean 对象创建一个 Bean将 Bean 注册到容器 获取并使用 Bean 对象创建 Spring 上下文获取指定的 Bean 对象使用 Bean 对象 getBean() 的用法总结 创建 Spring 项目 1. 创建一个Maven…

数据结构----结构--线性结构--链式存储--链表

数据结构----结构–线性结构–链式存储–链表 1.链表的特点 空间可以不连续&#xff0c;长度不固定&#xff0c;相对于数组灵活自由 搜索&#xff1a; 时间复杂度O(n) 增删: 头增头删时间复杂度O(1) 其他时间复杂度为O(n) 扩展&#xff1a;单向循环链表的特性 从任意节…

zookeeper+kafka分布式消息队列集群的部署

目录 一、zookeeper 1.Zookeeper 定义 2.Zookeeper 工作机制 3.Zookeeper 特点 4.Zookeeper 数据结构 5.Zookeeper 应用场景 &#xff08;1&#xff09;统一命名服务 &#xff08;2&#xff09;统一配置管理 &#xff08;3&#xff09;统一集群管理 &#xff08;4&…

C语言有关文件的操作

打开文件与关闭文件 在编写代码时&#xff0c;我有一个习惯是“保证一一对应”。 写下代码fopen()之后&#xff0c;还没有写对文件进行增删查改等操作的代码&#xff0c;先立刻写上fclose()&#xff0c;避免忘记关闭FILE* fd的情况。 不关闭fd&#xff0c;在fopen()次数较少的…

SAP度量单位转换功能

针对今天N2项目提出业务痛点&#xff1a;物料30011110的基本单位是KG&#xff0c;在XXX的BOM里单位是G&#xff0c;由于物料没配单位转换关系&#xff0c;但系统又能正常进行转换&#xff0c;开发需要技术支持。 经专项调查&#xff0c;G和KG的转换是SAP相同量纲转换标准功能&…

限流式保护器在高校宿舍电气防火的应用

安科瑞 华楠 引言 14日早晨6时10分左右&#xff0c;上海商学院徐汇校区学生宿舍楼发生火灾&#xff0c;4名女生从六楼宿合阳台跳下逃生当场死亡&#xff0c;酿成近年来惨烈的校园事故。宿舍火灾初步判断缘起于寝室里使用热得快导致电器故障并将周围可燃物引燃。 任何条生命都是…

Kafka与Zookeeper版本对应关系

文章目录 了解版本对应Kafka安装包Kafka源码包 了解 比如&#xff1a; kafka_2.11-1.1.1.jar包 其中2.11表示的是Scala的版本&#xff0c;因为Kafka服务器端代码完全由Scala语音编写。”-“后面的1.1.1表示的kafka的版本信息。遵循一个基本原则&#xff0c;Kafka客户端版本和服…

DC-8靶机

DC-8官网地址 信息收集 靶机MAC&#xff1a; 00:0C:29:3A:46:A1 主机发现 nmap -sP 192.168.80.0/24端口扫描 nmap -A -p- 192.168.80.142访问80端口 点击页面能点击的地方&#xff0c;发现每点击一个链接&#xff0c;地址栏的?nid后面的数字就会变 尝试在数字后面加个 引…