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,一经查实,立即删除!

相关文章

C 练习实例68-数组循环移动m次

题目&#xff1a;有 n 个整数&#xff0c;使其前面各数顺序向后移 m 个位置&#xff0c;最后m个数变成最前面的 m 个数。 思路&#xff1a; 先保存数组最后面的一个数把最后那个数前面的所有数向后移动一位最后&#xff0c;套入循环语句&#xff0c;循环m次&#xff0c;即移动…

【算法题】100. 相同的树

题目 给你两棵二叉树的根节点 p 和 q &#xff0c;编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同&#xff0c;并且节点具有相同的值&#xff0c;则认为它们是相同的。 示例 1&#xff1a; 输入&#xff1a;p [1,2,3], q [1,2,3] 输出&#xff1a;true 示例…

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…

物联网中基于WIFI的室内温度检测系统设计

标题:物联网中基于WIFI的室内温度检测系统设计 摘要 随着物联网技术的快速发展,智能家居环境监测系统成为研究热点之一。本论文旨在设计并实现一个基于Wi-Fi的室内温度检测系统,用于实时监控和调节家庭或办公环境中的温度条件。该系统利用Wi-Fi信号的特性进行温度感知,不…

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

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

代码随想录算法训练营第四十三天| 1049. 最后一块石头的重量 II、494. 目标和、474.一和零

1049. 最后一块石头的重量 II 题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 解题思路&#xff1a;尽量让石头分成重量相同的两堆&#xff0c;相撞之后剩下的石头最小&#xff0c;这样就化解成01背包问题了。 java&#xff1…

【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;终有归途。 目录 前置条件 封装目的 常用格式 定义返回结果枚举类 定义返回结果封装类 对返回结果封装 测试封装 前置条件 已…

C++ static 修饰全局变量时的作用探究

C static 修饰全局变量时的作用探究 作为一个c开发者&#xff0c;我们面试时经常被问到 static 变量的作用&#xff0c;其中有一个问题是&#xff0c;static 修饰全局变量时起什么作用。 通常我们会回答&#xff0c;“static 修饰全局变量时代表限制这个变量为此源文件可见&a…

「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;第二种方法…

git初始化一个远程空仓库

目录 1. 仅做简单初始化2. 推送现有的非仓库文件夹3. 推送现有的仓库 git初始化一个远程空仓库主要有以下三种途径&#xff1a; 仅做简单初始化&#xff0c;例如添加 README.md 和 .gitignore。将现有的文件夹&#xff08;非仓库&#xff09;推送到远程仓库。将现有的仓库推送…

【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;和因特网…

2024 新年快乐!

亲爱的朋友们 新年快乐&#xff01;在这个辞旧迎新的时刻&#xff0c;我想先感谢大家一直以来的支持和鼓励。作为一个刚刚踏入博客写作领域的新人&#xff0c;我深感自己的渺小和不足&#xff0c;但更感激你们一直以来的陪伴。 虽然开通 CSDN 的时间很久&#xff0c;但是主要…

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…

docker进阶 问题1

如何使用Docker的容器调试和故障排查工具&#xff1f; Docker提供了一系列强大的工具来帮助开发者调试和排查容器中的问题。以下是一些关键步骤和工具的使用方法&#xff1a; 查看容器日志&#xff1a;使用docker logs [容器ID或名称]命令可以轻松查看容器的标准输出和错误。…