C语言函数(三):数组和函数实现扫雷游戏

目录

  • 1.扫雷游戏的分析和设计
    • 1.1.扫雷游戏的功能说明
    • 1.2.游戏的分析与设计
      • 1.2.1 数据结构的分析
      • 1.2.2 文件结构设计
  • 2.扫雷游戏的代码实现

1.扫雷游戏的分析和设计

1.1.扫雷游戏的功能说明

  • 使用控制台实现经典的扫雷游戏
  • 游戏可以通过菜单实现继续玩游戏或者退出游戏
  • 扫雷的棋盘是9*9的格子
  • 默认随机排布10个雷
  • 排查雷
    • 如果位置不是雷,则显示周围有几个雷
    • 如果是雷,则炸死游戏结束
    • 把除10个雷之外的所有雷都找出来,排雷成功,游戏结束

游戏界面
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

1.2.游戏的分析与设计

1.2.1 数据结构的分析

扫雷的过程中,布置的雷和排出的雷都需要被存储,因为如果将两种都放在一起,就分别不出这个位置是雷的位置还是周围8个格子的雷的总数。

因为我们需要在99的棋盘上布置雷的信息和排查雷,首先想到的是创建一个99的数组来实现棋盘。在这里插入图片描述

那如果这个位置布置雷,就存放1,没有布置雷就存放0。
当这个位置不是雷的时候,就需要统计周围8个位置的和,然后存放到当前位置。
那如果在计算边角时进行计算,就会发生数组越界的问题,为了解决这个问题,我们可以再在周围加一圈构成11*11的棋盘,这样就不会发生数组越界了。
解决了这个问题,就可以关注两个数组的问题了,因为我们的展示界面全是由 *构成的,而排查雷需要使用数字来表示,那我们可以使用数字字符来表示数值,最后将字符转化为数字就行了

1.2.2 文件结构设计

这里我们设置3个文件

1.test.c 文件中写游戏的逻辑测试
2.game.c 文件中写游戏的函数实现
3.game.h 文件中写游戏需要的数据类型和游戏声明

2.扫雷游戏的代码实现

第一步:菜单设置

test.c

void menu(void) {printf("******************\n");printf("******1.play******\n");printf("******0.exit******\n");printf("******************\n");int main() {int input = 0;//srand((unsigned int)time(NULL));//使用时间种子do {menu();printf("请选择:>");scanf("%d", &input);if (input == 1) {//printf("ready\n");game();}else if(input == 0) {printf("end\n");}else {printf("输入错误,重新输入\n");}} while (input);return 0;
}
}

这样就可输出菜单,选择1的话就可以开始游戏,选择0退出游戏,选择错误重新选择

第二步:游戏函数

test.c

void game(void) {//设置棋盘的格数,,11*11的棋盘不会出现越界问题char mine[ROWS][COLS];//11char show[ROWS][COLS];//11//初始化棋盘InitBoard(mine, ROWS, COLS,'0');InitBoard(show, ROWS, COLS,'*');}

game.h

#include<stdio.h>#define COL 9
#define ROW 9#define ROWS ROW+2
#define COLS COL+2//初始化棋盘函数
void InitBoard(char borad[ROWS][COLS], int rows, int cols,char type);

game.c

#include"game.h"
void InitBoard(char borad[ROWS][COLS], int rows, int cols,char type) {for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {borad[i][j] = type;}}
}

这个函数的作用是创建数组,初始化棋盘,分别将数据类型和函数实现写在头文件中

第三步:打印棋盘

test.c

void game(void) {//设置棋盘的格数,,11*11的棋盘不会出现越界问题char mine[ROWS][COLS];//11char show[ROWS][COLS];//11//初始化棋盘InitBoard(mine, ROWS, COLS,'0');InitBoard(show, ROWS, COLS,'*');//打印棋盘Printborad(show, ROW, COL);Printborad(mine, ROW, COL);
}

game.h


#define COL 9
#define ROW 9#define ROWS ROW+2
#define COLS COL+2
//初始化棋盘函数
void InitBoard(char borad[ROWS][COLS], int rows, int cols,char type);
//打印棋盘函数
void Printborad(char borad[ROW][COL], int row,int col);

game.c

void Printborad(char borad[ROW][COL],int row,int col) {for (int i = 0; i <= row; i++) {printf("%d ", i);}printf("\n");for (int i = 1; i <= row; i++) {printf("%d ", i);for (int j = 1; j <= col; j++) {printf("%c ",borad[i][j]);}printf("\n");}
}

这个函数用以打印棋盘,可以看出棋盘的规划是否正确,当然我们只用打印show棋盘,不用打印mine棋盘,因为mine棋盘可以看到的全是0,这里为了不多写一个函数用来分别打印’*‘和’0’,所有我们再传一个一个参数type,告诉Printboard函数应该打印什么字符。

第四步:布置雷

test.c

void game(void) {//设置棋盘的格数,,11*11的棋盘不会出现越界问题char mine[ROWS][COLS];//11char show[ROWS][COLS];//11//初始化棋盘InitBoard(mine, ROWS, COLS,'0');InitBoard(show, ROWS, COLS,'*');//打印棋盘Printborad(show, ROW, COL);	//Printborad(mine, ROW, COL);//布置雷SetMine(mine, ROW, COL);Printborad(mine, ROW, COL);//查看是否将雷布置好了
}
int main() {int input = 0;srand((unsigned int)time(NULL));//使用时间种子do {menu();printf("请选择:>");scanf("%d", &input);if (input == 1) {//printf("ready\n");game();}else if(input == 0) {printf("end\n");}else {printf("输入错误,重新输入\n");}} while (input);return 0;
}

game.h

#include<time.h>//使用时间种子
#include<stdlib.h>//使用随机数#define COUNT 10//10个雷//布置雷函数
void SetMine(char borad[ROW][COL], int row, int col);

game.c

void SetMine(char borad[ROW][COL], int row, int col) {//产生随机数int count = COUNT;while (count) {int x = rand() % row + 1;int y = rand() % col + 1;if (borad[x][y] == '0') {borad[x][y] = '1';count--;}}}

这里使用随机数设置雷的位置坐标,需要包含头文件#include<time.h>和
#include<stdlib.h>,使用语句srand((unsigned int)time(NULL));确定时间种子,这样就可以将雷布置进去了,可以使用Printborad(mine, ROW, COL);打印棋盘看看雷布置的正确与否。

第五步:排查雷

test.c

void game(void) {//设置棋盘的格数,,11*11的棋盘不会出现越界问题char mine[ROWS][COLS];//11char show[ROWS][COLS];//11//初始化棋盘InitBoard(mine, ROWS, COLS,'0');InitBoard(show, ROWS, COLS,'*');//打印棋盘Printborad(show, ROW, COL);	//Printborad(mine, ROW, COL);//布置雷SetMine(mine, ROW, COL);Printborad(mine, ROW, COL);//查看是否将雷布置好了//排查雷FindMine(mine, show, ROW, COL);}

game.h

void FindMine(char mine[ROW][COL], char show[ROW][COL], int row, int col);

game.c

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

使用FindMine函数排查雷,先输入要查看的坐标,如果坐标符合规定,则看这个坐标是否是雷,如果不是则计算周围8个位置的和并输出在棋盘上,当排查完71个没有雷的位置后,游戏成功。如果该位置非法,则重新输入。

以上涉及到一个重要的知识点,那就是:如何将数字字符转化为数字
可以直接使用数字字符减去字符0,比如:
‘0’ - ‘0’ = 0
‘1’ - ‘0’ = 1
‘55’ - ‘0’ = 55
这是因为字符之间的减法是减的ASCII码值,所以ASCII值相减就可以得到数字。

完整代码:
game.h

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<time.h>//使用时间种子
#include<stdlib.h>//使用随机数#define COUNT 10//10个雷#define COL 9
#define ROW 9#define ROWS ROW+2
#define COLS COL+2
//初始化棋盘函数
void InitBoard(char borad[ROWS][COLS], int rows, int cols,char type);
//打印棋盘函数
void Printborad(char borad[ROW][COL], int row,int col);
//布置雷函数
void SetMine(char borad[ROW][COL], int row, int col);
//排查雷
void FindMine(char mine[ROW][COL], char show[ROW][COL], int row, int col);

game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void InitBoard(char borad[ROWS][COLS], int rows, int cols,char type) {for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {borad[i][j] = type;}}
}void Printborad(char borad[ROW][COL],int row,int col) {for (int i = 0; i <= row; i++) {printf("%d ", i);}printf("\n");for (int i = 1; i <= row; i++) {printf("%d ", i);for (int j = 1; j <= col; j++) {printf("%c ",borad[i][j]);}printf("\n");}
}void SetMine(char borad[ROW][COL], int row, int col) {//产生随机数int count = COUNT;while (count) {int x = rand() % row + 1;int y = rand() % col + 1;if (borad[x][y] == '0') {borad[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-1][y+1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x][y + 1] + mine[x + 1][y + 1] - 8 * '0');
}void FindMine(char mine[ROW][COL], char show[ROW][COL], int row, int col) {int x = 0;int y = 0;int win = 0;while (win < row * col- COUNT) {printf("输入要查看的坐标:>");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col) {if (mine[x][y] == '1') {printf("很遗憾,你被炸死了\n");Printborad(show, ROW, COL);break;}else {//说明此处不是雷,则统计周围8个雷int count = GetMineCount(mine, x, y);show[x][y] = count + '0';Printborad(show, ROW, COL);win++;}}else {printf("坐标非法,重新输入\n");}}if (win == row * col - COUNT) {printf("恭喜,排雷成功\n");Printborad(mine, ROW, COL);}
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu(void) {printf("******************\n");printf("******1.play******\n");printf("******0.exit******\n");printf("******************\n");
}void game(void) {//设置棋盘的格数,,11*11的棋盘不会出现越界问题char mine[ROWS][COLS];//11char show[ROWS][COLS];//11//初始化棋盘InitBoard(mine, ROWS, COLS,'0');InitBoard(show, ROWS, COLS,'*');//打印棋盘Printborad(show, ROW, COL);	//Printborad(mine, ROW, COL);//布置雷SetMine(mine, ROW, COL);Printborad(mine, ROW, COL);//查看是否将雷布置好了//排查雷FindMine(mine, show, ROW, COL);}
int main() {int input = 0;srand((unsigned int)time(NULL));//使用时间种子do {menu();printf("请选择:>");scanf("%d", &input);if (input == 1) {//printf("ready\n");game();}else if(input == 0) {printf("end\n");}else {printf("输入错误,重新输入\n");}} while (input);return 0;
}

感谢观看!

/考研势在必行/

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

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

相关文章

ssm+vue的医药垃圾分类管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的医药垃圾分类管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结…

【Linux】Linux下的基本指令

Linux下的基本指令 Linux 的操作特点&#xff1a;纯命令行ls 指令文件 pwd命令Linux的目录结构绝对路径 / 相对路径&#xff0c;我该怎么选择&#xff1f; cd指令touch指令mkdir指令&#xff08;重要&#xff09;rmdir指令rm 指令&#xff08;重要&#xff09;man指令&#xff…

RocketMQ(二):领域模型(生产者、消费者)

1 生产者&#xff08;Producer&#xff09; 本节介绍Apache RocketMQ 中生产者的定义、模型关系、内部属性、版本兼容和使用建议。 1.1 定义 生产者是Apache RocketMQ 系统中用来构建并传输消息到服务端的运行实体。 生产者通常被集成在业务系统中&#xff0c;将业务消息按照要…

【MySQL】字符串函数的学习

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-J7VN4RbrBi51ozap {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

kali最新最简单安装

之前都是用iso镜像文件的 今年好多东西都删库了&#xff0c;所有还是要主要资源的保存 去官网找下载 一般来说都是用虚拟机的 下载完会是一个压缩文件&#xff0c; 解压&#xff0c;然后操作之前需要先下载虚拟机 打开方式用虚拟机打开 kali就按装好了

Spring Boot3统一结果封装

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《spring boot实战》 &#x1f30a;山高路远&#xff0c;行路漫漫&#xff0c;终有归途。 目录 前置条件 封装目的 常用格式 定义返回结果枚举类 定义返回结果封装类 对返回结果封装 测试封装 前置条件 已…

「daily updating」k3s + openfaas serverless bench 踩坑指南持续更新中

OpenFaas从入门到实战 – 踩坑指南 &#xff5c; k3dOpenFaas | deploy your first python function https://blog.alexellis.io/first-faas-python-function/ https://docs.openfaas.com/deployment/kubernetes/ 搭建环境&#xff1a;第一种方法失败&#xff0c;第二种方法…

【SpringBootStarter】自定义全局加解密组件

【SpringBootStarter】 目的 了解SpringBoot Starter相关概念以及开发流程实现自定义SpringBoot Starter(全局加解密)了解测试流程优化 最终引用的效果&#xff1a; <dependency><groupId>com.xbhog</groupId><artifactId>globalValidation-spring…

[职场] 大厂群面的基本题型 #学习方法#其他

大厂群面的基本题型 大厂群面的基本题型 群面&#xff0c;又叫做“无领导小组面试”。历年来是企业校招时&#xff0c;进行大批量刷人的有效方法。流行于互联网、快消、银行、四大等多个行业。因为难度大、情况复杂、淘汰率高&#xff0c;又被称为“死亡面试”。 无领导小组…

CSP-202012-2-期末预测之最佳阈值

CSP-202012-2-期末预测之最佳阈值 【70分思路】 本题的难点还是时间复杂度&#xff0c;暴力枚举会导致时间超限。对于每一个可能的阈值theta&#xff0c;代码都重新计算了整个predict数组&#xff0c;统计预测正确的数目&#xff0c;因为有两个嵌套的循环&#xff0c;使得时间…

计算机网络之一

目录 1.因特网概述 1.1网络、互连网&#xff08;互联网&#xff09;和因特网 1.2.因特网发展的三个阶段 1.3基于ISP的三层架构的因特网 1.4.因特网的组成 2.三种交换方式 2.1电路交换 2.2分组交换 1.因特网概述 1.1网络、互连网&#xff08;互联网&#xff09;和因特网…

Git分支常用指令

目录 1 git branch 2 git branch xx 3 git checkout xx 4 git checkout -b xx 5 git branch -d xx 6 git branch -D xx 7 git merge xx(含快进模式和冲突解决的讲解) 注意git-log: 1 git branch 作用&#xff1a;查看分支 示例&#xff1a; 2 git branch xx 作用&a…

数据结构——5.5 树与二叉树的应用

5.5 树与二叉树的应用 概念 结点的权&#xff1a;大小可以表示结点的重要性 结点的带权路径长度&#xff1a;从树的根到该结&#xff0c;的路径长度&#xff08;经过的边数&#xff09;与该结点权的乘积 树的带权路径长度&#xff1a;树中所有叶结点的带权路径长度之和(WPL) …

蜂鸣器播放提示音音乐(天空之城)

目录 蜂鸣器播放提示音 蜂鸣器播放音乐&#xff08;天空之城&#xff09; 准备工作 主程序 中断函数 上一节讲了蜂鸣器驱动原理和乐理基础知识&#xff0c;这一节开始代码演示&#xff01; 蜂鸣器播放提示音 先创建工程&#xff1a;蜂鸣器播放提示音 把我们之前模块化的…

python 爬虫篇(3)---->Beautiful Soup 网页解析库的使用(包含实例代码)

Beautiful Soup 网页解析库的使用 文章目录 Beautiful Soup 网页解析库的使用前言一、安装Beautiful Soup 和 lxml二、Beautiful Soup基本使用方法标签选择器1 .string --获取文本内容2 .name --获取标签本身名称3 .attrs[] --通过属性拿属性的值标准选择器find_all( name , at…

Sentinel 源码分析

Sentinel源码分析 项目源码 1.Sentinel的基本概念 Sentinel实现限流、隔离、降级、熔断等功能&#xff0c;本质要做的就是两件事情&#xff1a; 统计数据&#xff1a;统计某个资源的访问数据&#xff08;QPS、RT等信息&#xff09;规则判断&#xff1a;判断限流规则、隔离规…

20240210使用剪映识别字幕的时候的GPU占比RX580-RTX4090

20240210使用剪映识别字幕的时候的GPU占比RX580-RTX4090 2024/2/10 17:54 【使用剪映识别不同的封装格式&#xff0c;不同的音视频编码&#xff0c;对GPU的占用率可能会有比较大的不同&#xff01;】 很容易发现在在WIN10下使用剪映的时候&#xff0c;X99RX550组合。 GPU部分&…

【Spring】Bean 的生命周期

一、Bean 的生命周期 Spring 其实就是一个管理 Bean 对象的工厂&#xff0c;它负责对象的创建&#xff0c;对象的销毁等 所谓的生命周期就是&#xff1a;对象从创建开始到最终销毁的整个过程 什么时候创建 Bean 对象&#xff1f;创建 Bean 对象的前后会调用什么方法&#xf…

【Go】三、Go并发编程

并发编程 我们主流的并发编程思路一般有&#xff1a;多进程、多线程 但这两种方式都需要操作系统介入&#xff0c;进入内核态&#xff0c;是十分大的时间开销 由此而来&#xff0c;一个解决该需求的技术出现了&#xff1a;用户级线程&#xff0c;也叫做 绿程、轻量级线程、协…

大厂的供应链域数据中台设计

关注我&#xff0c;紧跟本系列专栏文章&#xff0c;咱们下篇再续&#xff01; 作者简介&#xff1a;魔都技术专家兼架构&#xff0c;多家大厂后端一线研发经验&#xff0c;各大技术社区头部专家博主&#xff0c;编程严选网创始人。具有丰富的引领团队经验&#xff0c;深厚业务架…