【c语言】扫雷

 前言:

扫雷是一款经典的单人益智游戏,它的目标是在一个方格矩阵中找出所有的地雷,而不触碰到任何一颗地雷。在计算机编程领域,扫雷也是一个非常受欢迎的项目,因为它涉及到许多重要的编程概念,如数组、循环、条件语句和函数等。

C语言是一种广泛使用的编程语言,它具有高效、灵活和可移植等特点,非常适合编写各种类型的应用程序。因此,使用C语言编写一个扫雷游戏是一个很好的学习编程的项目。

在这篇博客中,我们将介绍如何使用C语言编写一个简单的扫雷游戏。我们将从基本的编程概念开始讲解,逐步深入到更复杂的程序设计技术。我们还将提供完整的代码示例和详细的注释,以帮助读者更好地理解和掌握这个项目。

无论您是初学者还是有一定编程经验的开发者,相信通过阅读本篇博客,您都能够学到一些有用的知识和技巧。让我们一起来探索如何使用C语言编写一个令人兴奋的扫雷游戏吧!

前期准备:

先开一个test.c文件用来游戏的逻辑测试,在分别开一个game.c文件和game.h头文件用来实现游戏的逻辑

1. 主要步骤:

1.1 游戏规则:

输入1(0)开始(结束)游戏,输入一个坐标,如果该坐标不是雷则会显示该坐标周围有几个雷

1.2 打印菜单:

void menu()
{printf("----------------扫雷----------------\n");printf("|                                  |\n");printf("|              1.play              |\n");printf("|              0.exit              |\n");printf("|                                  |\n");printf("------------------------------------\n");
}
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");}} while (input);return 0;
}

1.3 打印棋盘:

写两个数组一个是用来打印给玩家看的棋盘,一个是用来放置炸弹的隐藏棋盘,等到游戏结束我们才会打印这个棋盘。然后我们给数组初始化,用*来初始化我们给玩家看的棋盘,用字符‘0’初始化隐藏棋盘。

   char mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };//初始化棋盘InitBoard(show, ROWS, COLS, '*');InitBoard(mine, ROWS, COLS, '0');//打印棋盘DisPalyBoard(show, ROW, COL);//DisPalyBoard(mine, ROW, COL);

1.4 打印行列:

因为我们是用坐标来选择排雷的,所以我们需要在棋盘的周围打印出行列才可以让玩家更好的去选择。

首先在打印棋盘for循环上方加上一个打印0~9的for循环就可以打印出棋盘的行了,然后用打印列的for循环套在打印棋盘的for循环上就可以打印出棋盘的列了。

​
void DisPalyBoard(char arr[ROWS][COLS], int row, int col)
{printf("------扫雷游戏------\n");​int i = 0;//打印行的for循环for (i = 0; i <= col; i++){printf("%d ", i);}printf("\n");//打印列的for循环for ( i = 1; i <= row; i++)  {printf("%d ", i);//打印棋盘的for循环for (int j = 1; j <= col; j++){printf("%c ", arr[i][j]);}printf("\n");}
}​

1.5 放置炸弹:

要想棋盘上随机分布十个炸弹(炸弹我们用字符‘1’定义),我们就需要生成随机数使数组的随机十个元素等于字符‘1’,而生成随机数就需要调用到前面我写猜数字游戏时讲过的rand函数、srand函数、time函数了。

void SetMine(char arr[ROWS][COLS], int row, int col)
{int count = EsayCount;while (count){int x = rand() % row + 1;int y = rand() % col + 1;if (arr[x][y] == '0')//防止生成相同随机数时,使多个炸弹放置在同一位置{arr[x][y] = '1';count--;}}
}

1.6 排查炸弹:

当我们输入一个坐标后如果时炸弹结束游戏,如果不是炸弹则需要显示炸弹的数量。

判断是否是炸弹只需写一个if语句判断该坐标中数组所对应的元素是否等于‘1’就行了。

显示周围有几个雷,我们就需要将所选坐标的周围的数加起来就可以了,这些加起来的数的和替换所选坐标的元素就可以了。

int GetMineCount(char mine[ROWS][COLS],int x,int y)
{return (mine[x - 1][y] + mine[x - 1][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] + mine[x][y + 1] - 8 * '0');
}

也可以用for循环统计

int GetMineCount(char mine[ROWS][COLS], int x, int y)
{int a = 0;for (int i = x - 1; i <= x + 1; i++){for (int j = y - 1; j <= y + 1; j++){a += mine[i][j];}}return a - '0' * 9;
}

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int x = 0, y = 0;int win = 0;while (win < row*col - EsayCount){printf("请输入要排查的坐标:>");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (mine[x][y] == '1'){printf("很遗憾,你被炸死了\n");DisPalyBoard(mine, ROW, COL);break;}else{//该坐标不是雷,就得统计该坐标的周围有几个雷int count = GetMineCount(mine, x, y);show[x][y] = count + '0';DisPalyBoard(show, ROW, COL);win++;}}else{printf("坐标非法,请重新输入\n");}}if (win == row * col - EsayCount){printf("恭喜你,排雷成功\n");DisPalyBoard(mine, ROW, COL);}
}

1.7 周围没有雷就展开一片

首先需要判断所选坐标的周围是否有雷,即判断count是否等于0,如果所选坐标周围没有雷的话,就将此坐标的周围的坐标都调用显示雷的数量的函数。当然还需要判断一下坐标是否为‘*’,如果没有这个判断它就会重复的调用函数,从而进入了死循环。

void arr(char mine[ROWS][COLS], char show[ROWS][COLS], int x,int y)
{if (show[x][y] == '*'){int count = GetMineCount(mine, x, y);show[x][y] = count + '0';if (x >= 1 && x <= ROW && y >= 1 && y <= ROW){if (count == 0){arr(mine, show, x - 1, y);arr(mine, show, x - 1, y - 1);arr(mine, show, x - 1, y + 1);arr(mine, show, x, y - 1);arr(mine, show, x, y + 1);arr(mine, show, x + 1, y - 1);arr(mine, show, x + 1, y + 1);arr(mine, show, x + 1, y);}}}
}

1.8 计算游戏时间

time函数可以返回一个时间戳,我们可以利用这个函数计算游戏的时间。

int y = time(NULL);
while (1)
{system("cls");int x = time(NULL) - y;printf("%d", x);Sleep(1000);
}

1.9 游戏可改性

因为在写这个程序时需要输入很多的数字,如果我们想修改这些数时就要一个一个改,这样非常的麻烦。为了避免这些麻烦我们只需要在头文件定义某字符等于某个数字就可以了,这样我们想改游戏参数的时候在头文件game.h改就行了。

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

比如当我们想改行和列改为16炸弹数量改为40的时候,我们只需要在头文件将ROW 与 COL定义为16就可以了。

#define ROW 16
#define COL 16#define ROWS ROW+2
#define COLS COL+2
#define EsayCount 40

 

 1.10 控制台颜色的修改

使用system("color attr");函数可以修改控制台颜色,这个函数需要使用#include<windonws.h>调用。颜色可以参考下面这张图:

  例:
 

2. 完整代码

2.1 game.h头文件

#pragma once
#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 EsayCount 10//声明函数
void InitBoard(char arr[ROWS][COLS], int rows, int cols, char test);
//
void DisPalyBoard(char arr[ROW][COL], int row, int col, int o);
//布置雷的信息
void SetMine(char arr[ROWS][COLS], int row, int col, int o);
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int o);

 2.2 game.c文件

#include"game.h"
void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set)
{int i = 0;for (i = 0; i < rows; i++){for (int j = 0; j < cols; j++){arr[i][j] = set;}}
}
void DisPalyBoard(char arr[ROWS][COLS], int row, int col,int o)
{//清屏system("cls");printf("-----------扫雷游戏----------\n");//计算时间printf("已用时间:%ds\n", time(NULL) - o);int i = 0;for (i = 0; i <= col; i++){printf("%2d ", i);}printf("\n");for (i = 1; i <= row; i++){printf("%2d ", i);for (int j = 1; j <= col; j++){printf("%2c ", arr[i][j]);}printf("\n");}
}void SetMine(char arr[ROWS][COLS], int row, int col)
{int count = EsayCount;while (count){int x = rand() % row + 1;int y = rand() % col + 1;if (arr[x][y] == '0'){arr[x][y] = '1';count--;}}
}int GetMineCount(char mine[ROWS][COLS], int x, int y)
{//return (mine[x - 1][y] + mine[x - 1][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] + mine[x][y + 1] - 8 * '0');int a = 0;for (int i = x - 1; i <= x + 1; i++){for (int j = y - 1; j <= y + 1; j++){a += mine[i][j];}}return a - '0' * 9;
}int win = 0;
void arr(char mine[ROWS][COLS], char show[ROWS][COLS], int x,int y)
{if (show[x][y] == '*'&& x >= 1 && x <= ROW && y >= 1 && y <= ROW){int count = GetMineCount(mine, x, y);show[x][y] = count + '0';win++;if (count == 0){arr(mine, show, x - 1, y);arr(mine, show, x - 1, y - 1);arr(mine, show, x - 1, y + 1);arr(mine, show, x, y - 1);arr(mine, show, x, y + 1);arr(mine, show, x + 1, y - 1);arr(mine, show, x + 1, y + 1);arr(mine, show, x + 1, y);}}
}void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int o)
{int x = 0, y = 0;while (win < row * col - EsayCount){printf("请输入要排查的坐标(0 0重开):>");scanf("%d %d", &y, &x);if (x >= 1 && x <= row && y >= 1 && y <= col){if (mine[x][y] == '1'){DisPalyBoard(mine, ROW, COL, o);printf("你被炸死了!!!\n");break;}else{//该坐标不是雷,就得统计该坐标的周围有几个雷arr(mine, show, x, y);DisPalyBoard(show, ROW, COL, o);}}else if (x == 0 && y == 0){printf("重新开始游戏。\n");break;}else{printf("坐标非法,请重新输入\a\n");}}if (win == row * col - EsayCount){DisPalyBoard(mine, ROW, COL, o);printf("恭喜你,排雷成功\n");}
}

2.3 test.c文件

#include"game.h"void menu()
{printf("----------------扫雷----------------\n");printf("|                                  |\n");printf("|              1.play              |\n");printf("|              0.exit              |\n");printf("|                                  |\n");printf("------------------------------------\n");
}void game()
{int o = time(NULL);//存放布置好雷的信息char mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };InitBoard(show, ROWS, COLS, '*');InitBoard(mine, ROWS, COLS, '0');//随机布置10个雷SetMine(mine, ROW, COL, o);//打印棋盘/*DisPalyBoard(mine, ROW, COL,o);*/DisPalyBoard(show, ROW, COL, o);//排查雷FindMine(mine, show, ROW, COL, o);
}
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("输入错误请重新输入\a\n");}} while (input);return 0;
}

2.4 效果图:

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

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

相关文章

Sketch怎么增加组件?

Sketch怎么增加组件&#xff1f;Sketch组件库经常使用&#xff0c;想要添加一些新的组件&#xff0c;该怎么添加呢&#xff1f;下面我们就来看看Sketch组件库添加新组建的技巧&#xff0c;详细请看下文介绍 打开电脑&#xff0c;找到sketch软件的图标&#xff0c;点击进入 新建…

计算机工作原理解析和解剖(基础版)

我们会从软件⼯程师的⻆度解释计算机是如何⼯作的&#xff0c;我们的主要⽬标既不是期待 ⼤家可以造出⾃⼰的计算机&#xff0c;也不是介绍如何编程&#xff0c;⽽是希望让⼤家了解计算机的核⼼⼯作机制后&#xff0c;打破计算机的神秘感&#xff0c;并且有利于理解我们平时编程…

【大数据】Flink 中的数据传输

Flink 中的数据传输 1.基于信用值的流量控制2.任务链接 在运行过程中&#xff0c;应用的任务会持续进行数据交换。TaskManager 负责将数据从发送任务传输至接收任务。它的网络模块在记录传输前会先将它们收集到 缓冲区 中。换言之&#xff0c;记录并非逐个发送的&#xff0c;而…

Stream实战-统计求和

Stream实战-统计 stream在开发中经常使用场景就是统计&#xff0c;再次记录一下实际开发中用的到统计&#xff0c;使用模拟数据。 需求如下&#xff1a; 代码如下: /*** map集合统计*/ public class StreamDemo4 {/*** 实体类*/DataAllArgsConstructorNoArgsConstructorclas…

Python模块与包:扩展功能、提高效率的利器

文章目录 一、引言1.1 模块与包对于Python开发的重要性1.2 Python作为拥有丰富生态系统的编程语言 二、为什么学习模块与包2.1 复用代码&#xff1a;利用现有模块与包加速开发过程2.2 扩展功能&#xff1a;通过模块与包提供的功能增强应用的能力 三、模块的使用3.1 导入模块&am…

UDF学习(二)数据访问宏

数据访问宏一 网格节点相关宏** NODE_X (v) 节点v的x方向的坐标 &#xff08;Node *v&#xff09; NODE_Y (v) 节点v的y方向的坐标 &#xff08;Node *v&#xff09; NODE_Z (v) 节点v的z方向的坐标 &#xff08;Node *v&#xff09; F_NODE (f,t,n) 获取节点 (face_t f, Thre…

Java基础进阶03-注解和单元测试

目录 一、注解 1.概述 2.作用 3.自定义注解 &#xff08;1&#xff09;格式 &#xff08;2&#xff09;使用 &#xff08;3&#xff09;练习 4.元注解 &#xff08;1&#xff09;概述 &#xff08;2&#xff09;常见元注解 &#xff08;3&#xff09;Target &#x…

vue3预览pdf文件的几种方法

vue3预览pdf集中方法 方法一&#xff1a; iframe&#xff1a;这种方法显示有点丑 <iframesrc"E:\\1.pdf"frameborder"0"style"width: 80%; height: 100vh; margin: auto; display: block"></iframe>方法二&#xff1a; 展示效果&…

【RA6M3 HMI Board线下培训笔记】 RT Thread实现物联网应用 ETH+MQTT+LVGL+RTOS 实现温湿度监测

【RA6M3 HMI Board线下培训笔记】 RT Thread实现物联网应用 ETHMQTTLVGLRTOS 实现温湿度监测 1. 序言 随着物联网技术的飞速发展&#xff0c;越来越多的生活场景变得越来越智能&#xff0c;网联化、智能化越来越成为主旋律。 值此之际&#xff0c;RT-Thread 和 瑞萨电子共同…

光耦驱动继电器电路图大全

光耦驱动继电器电路图&#xff08;一&#xff09; 注&#xff1a; 1U1-1脚可接12V&#xff0c;也可接5V&#xff0c;1U1导通&#xff0c;1Q1导通&#xff0c;1Q1-30V&#xff0c;线圈两端电压为11.7V. 1U1-1脚不接或接地&#xff0c;1U1不通&#xff0c;1Q1截止&#xff0c;1…

蓝桥OJ3694肖恩的投球游戏plus

二维差分 #include<bits/stdc.h> using namespace std;const int N 1e3 5; int a[N][N],d[N][N];int main() {int n, m, q;cin >> n >> m >> q;for (int i 1 ; i < n; i){for (int j 1; j < m; j){cin >> a[i][j];d[i][j] a[i][j] a…

webug存在的越权漏洞-水平越权以及垂直越权的漏洞复现(超详解)

越权漏洞-webug、 1.登录 账号&#xff1a;admin 密码&#xff1a;admin 2.进入逻辑漏洞 3.进入越权修改密码靶场 &#xff08;1&#xff09;输入账号密码 进入进去会发现没有权限进入 方法一&#xff1a; 这里我们只需要将 127.0.0.1:8080/control/a/auth_cross/cross_a…

pytorch实战-图像生成与对抗

1 概述 what&#xff1a;给定一句话&#xff0c;或一些要求&#xff0c;按要求生成需要的图像。 本篇总结主要包含反卷积和GAN&#xff08;generative adversial network, GAN&#xff09; 2 反卷积与图像生成 what&#xff1a;反卷积可以看成卷积的反操作&#xff0c;但不…

紫光展锐T760_芯片性能介绍_展锐T760安卓核心板定制

展锐T760核心板是一款基于国产5G芯片的智能模块&#xff0c;采用紫光展锐T760制程工艺为台积电6nm工艺&#xff0c;支持工艺具有出色的能效表现。其采用主流的44架构的八核设计&#xff0c;包括4颗2.2GHz A76核心和4颗A55核心设计&#xff0c;内存单元板载可达8GB Ram256GB ROM…

uniapp vuecli项目融合[小记]:将多个项目融合,打包成一个小程序/App,拆分多个H5应用

前言&#xff1a; 目前两个uniapp vuecli开发的项目【A、B】&#xff0c;新规划的项目C&#xff1a;需要融合项目B 80%的功能模块&#xff0c;同时也需要涵盖项目A的所有功能模块。 应用需求&#xff1a; 1、新项目C【小程序】可支持切换到应用A/C界面【内部通过初始化、路由跳…

0125-1-vue3初体验

vue3尝鲜体验 初始化 安装vue/clinext&#xff1a; yarn global add vue/clinext # OR npm install -g vue/clinext然后在 Vue 项目运行&#xff1a; vue upgrade --next项目目录 vue3-template ├── index.html // html模板 ├── mock // mock数据 │ └── user.…

qt学习:QListWidget控件+自定义条目项+双击删除+单击获取

目录 图片 头函数 接口 显示案例 方法1 方法2 方法3 方法4 自定义 方法5 在方法4上实现 图片 头函数 #include <QListWidgetItem> 接口 //不怎么常用void addItem(const QString &label)void addItems(const QStringList &labels) //自定义条目项…

Redis客户端之Redisson(二)Redisson分布式锁

一、原理&#xff1a; Redisson并没有通过setNx命令来实现加锁&#xff0c;而是基于 Redis 看⻔狗机制&#xff0c;自己实现了一套分布式锁逻辑。 1、加锁机制&#xff1a; 二、使用方法&#xff1a;

EasyExcel实现下载模板

实体类&#xff1a; package com.aicut.monitor.domain;import com.alibaba.excel.annotation.ExcelIgnore; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.write.s…

YOLOv8全网独家首发:Powerful-IoU更好、更快的收敛IoU | 2024年最新IoU

💡💡💡本文独家改进:Powerful-IoU更好、更快的收敛IoU,是一种结合了目标尺寸自适应惩罚因子和基于锚框质量的梯度调节函数的损失函数 💡💡💡MS COCO和PASCAL VOC数据集实现涨点 收录 YOLOv8原创自研 https://blog.csdn.net/m0_63774211/category_12511737.htm…