C语言小游戏——扫雷

前言

结合前边我们所学的C语言知识,本期我们将使用C语言实现一个简单的小游戏——扫雷


 

目录

前言

总体框架设计

多文件分装程序

各功能模块化实现

初始化棋盘

 棋盘打印

埋雷

 判赢与排雷

游戏逻辑安排

总结


总体框架设计

和三子棋相同,游戏开始时不需要任何判断与操作直接进入游戏(符合我们所学的do…while结构),然后再根据菜单选择,开始游戏和退出游戏,这部分的操作与三子棋较为类似,这里不再详细讲解(详请看三子棋那期博客)。

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do {
		menu();
		printf("请选择>:\n");
		scanf("%d", &input);
		switch (input) {
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏!\n");
			break;
		default:
			printf("输入错误请重新输入>:\n");
			break;
		}
	} while (input);
	return 0;
}

 菜单打印部分也是相同

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

多文件分装程序

当然根据之前的方法,我将程序分装到多文件,.h文件用于声明函数,test.c文件用于程序设计,game.c文件用于函数定义

注意:函数的定义和声明是不同的(详细请看函数那期内容)

函数声明(在.h文件中)

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

 函数定义(在函数实现.c文件中)

void InitBoard(char board[ROWS][COLS], char set)
{
}

各功能模块化实现

接下来是最重要的部分,game()游戏部分的实现。游戏开始首先我们需要布置棋盘,设置雷的个数,和三子棋有所不同,这里我们最好是创建两个二维数组来存放我们的棋盘信息,一个棋盘用于玩家下棋棋盘,另外一个用于存放雷的信息。

初始化棋盘

    InitBoard(mine,'0');//埋雷棋盘
	InitBoard(show,'*');//玩家棋盘

 棋盘初始化和二维数组初始化相同

void InitBoard(char board[ROWS][COLS], char set)//字符型变量用于接收传入的字符
{
	for (int i = 0; i < ROWS; i++) {//为了便于更改棋盘大小这里需要定义字符型常量
		for (int j = 0; j < COLS; j++) {
			board[i][j] = set;
		}
	}
}

 棋盘打印

棋盘的打印没有三子棋那么难,如果想要美化棋盘也是可以使用与三子棋结合的棋盘。

效果图如下:

 这里我们采用上图的效果进行讲解

void DisPlaybroad(char board[ROWS][COLS])
{
	printf("------------------扫雷游戏------------------\n");//棋盘分割线
	printf("  ");                                           //与行打印对齐
	for (int i = 1; i <=COL; i++) {                         //打印列数序号1~9
		printf(" %d  ", i);
	}
	printf("\n");         //打印完一行及时换行
	printf("  -----------------------------------");//列与棋盘分割线
	printf("\n");
	for (int i = 1; i <= ROW; i++) {             //打印行数序号
		printf("%d ",i);
		for (int j = 1; j <= COL; j++) {        //与三子棋打印一样" %c |"为一次循环进行打印
			printf(" %c ", board[i][j]);
			if (j < COL) {                      
				printf("|");
			}
		}
		printf("\n");
		if (i < ROW) {
			for (int i = 1; i <=ROW; i++) {
				if (i ==1) {
					printf("  ");          //空出第一列用于打印序列号
			}
				printf("---");
				if (i < ROW) {           //---|---|---为一个整体(一次循环)循环打印
					printf("|");
				}
			}
			printf("\n");
		}
	}
}

埋雷

首先我们需要了解扫雷的规则,玩家选择一个坐标,然后检测该坐标附近8个坐标是否有雷,然后在玩家棋盘中显示附近雷的个数,简单的9*9的棋盘在边缘检测时比较复杂,那么我们就可以采用11*11的棋盘去初始化,埋雷的位置限制在9*9的棋盘中,这样就可以避免许多没必要的判断。

void SetMine(char board[ROWS][COLS]) {
	int count = N;//雷的个数
	while (count) {
		int x = rand() % ROW + 1;//使用随机数来进行埋雷,与srand配合使用来实现真正的随机。
		int y = rand() % COL + 1;//COL,ROW等于9,随机数与9求余范围是0~8,加一范围就变成了1~9
		if (board[x][y] == '0') {//确保雷的位置不重复布置
			board[x][y] = '1';//用1来表示雷
			count--;//布置之后雷的数量减一
		}
	}
}

 字符型常量定于如下:

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

 判赢与排雷

这部分特别需要注意的是两个棋盘之间的联系。判断雷的数量在埋雷的棋盘中进行,打印输出雷的信息在show这个数组展现。

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS]) {
	int x = 0;
	int y = 0;
	int win = 0;
	while (win<COL*ROW-N) //判赢
	{
		printf("请输入要排查的位置>:\n");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= 9 && y >= 1 && y <= 9) {
			if (mine[x][y] == '1') {
				printf("很遗憾,你踩到了雷,游戏结束!\n");
				DisPlaybroad(mine);            //游戏结束打印埋雷棋盘
				break;
			}
			else {
				show[x][y] = Get_Mine(mine, x, y) + '0';//扫雷部分函数返回值是一个数字,而打印时是以字符的形式打印数字,所以加上‘0’转变为对应的ascll值,注意这里将埋雷棋盘的排雷信息通过函数返回给show棋盘。
				DisPlaybroad(show);//没有踩到雷继续打印棋盘
				win++;//计数
			}
		}
		else {
			printf("坐标非法,请重新输入!\n");
		}
	}
	if (win == ROW * COL - N) {//9*9的棋盘埋10个雷,那需要走71步才能将雷扫完。
		printf("恭喜你排雷成功!\n");
		DisPlaybroad(mine);
	}
}
int Get_Mine(char mine[ROWS][COLS], int x, int y)//排雷
{//在ascll表中数字都有对应的ascll值,且是10个连续的,对应0~9,数字字符
	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');
}//判断附近8个位置中雷的个数,1是字符不是数字有对应的ascll值,-8*‘0’减去8个字符0的ascll值

 以上便是游戏各模块的实现。

游戏逻辑安排

游戏的各个模块我们已经基本实现,接下来我们需要将各个模块进行组装,使游戏顺利运行。

void game()
{
	char mine[ROWS][COLS];
	char show[ROWS][COLS];
	//初始化棋盘
	InitBoard(mine,'0');
	InitBoard(show,'*');
	//埋雷
	SetMine(mine);
	//打印棋盘
	DisPlaybroad(show);
	//排雷+判赢
	FindMine(mine,show);
}

 首先我们创建了两个二维数组,游戏开始需要先初始化棋盘,游戏开始前我们需要先进行埋雷操作,然后才是打印棋盘,最后就是判赢。这就是游戏大概整体逻辑。

以下便是整体代码的呈现:

用于声明的头文件(.h文件)

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define N 10
//初始化棋盘
void InitBoard(char board[ROWS][COLS], char set);
//打印棋盘
void DisPlaybroad(char board[ROWS][COLS]);
//埋雷
void SetMine(char board[ROWS][COLS]);
//排雷
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS]);

 函数定义文件(.c文件)

#include"game1.h"
void InitBoard(char board[ROWS][COLS], char set)
{
	for (int i = 0; i < ROWS; i++) {
		for (int j = 0; j < COLS; j++) {
			board[i][j] = set;
		}
	}
}
void DisPlaybroad(char board[ROWS][COLS])
{
	printf("------------------扫雷游戏------------------\n");
	printf("  ");
	for (int i = 1; i <=COL; i++) {
		printf(" %d  ", i);
	}
	printf("\n");
	printf("  -----------------------------------");
	printf("\n");
	for (int i = 1; i <= ROW; i++) {
		printf("%d ",i);
		for (int j = 1; j <= COL; j++) {
			printf(" %c ", board[i][j]);
			if (j < COL) {
				printf("|");
			}
		}
		printf("\n");
		if (i < ROW) {
			for (int i = 1; i <=ROW; i++) {
				if (i ==1) {
					printf("  ");
			}
				printf("---");
				if (i < ROW) {
					printf("|");
				}
			}
			printf("\n");
		}
	}
}
void SetMine(char board[ROWS][COLS]) {
	int count = N;
	while (count) {
		int x = rand() % ROW + 1;
		int y = rand() % COL + 1;
		if (board[x][y] == '0') {
			board[x][y] = '1';
			count--;
		}
	}
}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS]) {
	int x = 0;
	int y = 0;
	int win = 0;
	while (win<COL*ROW-N) //判赢
	{
		printf("请输入要排查的位置>:\n");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= 9 && y >= 1 && y <= 9) {
			if (mine[x][y] == '1') {
				printf("很遗憾,你踩到了雷,游戏结束!\n");
				DisPlaybroad(mine);
				break;
			}
			else {
				show[x][y] = Get_Mine(mine, x, y) + '0';
				DisPlaybroad(show);
				win++;
			}
		}
		else {
			printf("坐标非法,请重新输入!\n");
		}
	}
	if (win == ROW * COL - N) {
		printf("恭喜你排雷成功!\n");
		DisPlaybroad(mine);
	}
}
int Get_Mine(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');
}

 游戏主体(.c文件)

#include"game1.h"
void menu()
{
	printf("******************************\n");
	printf("*********   1.play   *********\n");
	printf("*********   0.exit   *********\n");
	printf("******************************\n");
}
void game()
{
	char mine[ROWS][COLS];
	char show[ROWS][COLS];
	//初始化棋盘
	InitBoard(mine,'0');
	InitBoard(show,'*');
	//埋雷
	SetMine(mine);
	//打印棋盘
	DisPlaybroad(show);
	//排雷+判赢
	FindMine(mine,show);
}
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do {
		menu();
		printf("请选择>:\n");
		scanf("%d", &input);
		switch (input) {
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏!\n");
			break;
		default:
			printf("输入错误请重新输入>:\n");
			break;
		}
	} while (input);
	return 0;
}

 


 

总结


      以上就是今天要讲的内容,本文仅仅使用简单的C语言基础语法来实现的扫雷小游戏,希望可以对你有所帮助,感谢阅读!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux安装MySQL后无法通过IP地址访问处理方法

本文主要总结Linux安装Mysql后&#xff0c;其他主机访问不了MySQL数据库的原因和解决方法 环境说明&#xff1a; MySQL 5.7.30CentOS Linux release 7.6.1810 (Core) 创建完Mysql数据库后可以查看mysql 日志获取root 用户登录密码 [rootlocalhost mysql-5.7.30]# cat /var/l…

spring源码学习

1.xmlBeanFactory对defaultListableBeanFactory类进行扩展&#xff0c;主要用于从XML文档中获取BeanDefinition&#xff0c;对于注册及获取bean都是使用从父类DefaultListableBeanFactory继承的方法去实现。 xmlBeanFactory 主要是使用reader属性对资源文件进行读取和注册。 2.…

Maven属性与版本管理

文章目录 1 属性1.1 问题分析1.2 解决步骤步骤1:父工程中定义属性步骤2:修改依赖的version 2 配置文件加载属性步骤1:父工程定义属性步骤2:jdbc.properties文件中引用属性步骤3:设置maven过滤文件范围步骤4:测试是否生效 3 版本管理 在这一章节内容中&#xff0c;我们将学习两个…

cpp11实现线程池(一)——项目介绍

项目介绍 线程池是库的形式提供给用户&#xff0c;是必须放到代码中&#xff0c;不能单独运行&#xff0c;亦称为基础组件 第一版线程池任务对象使用继承技术&#xff0c;提供一个抽象基类Task&#xff0c;里面有一个纯虚函数run()&#xff0c;使用时继承该类&#xff0c;并重…

c++综合学习

1.函数调用 传值调用&#xff1a;在函数内部修改形式参数&#xff0c;不改编实际参数的值&#xff1b;引用调用&#xff1a;即指针调用&#xff0c;传入的是变量的指针&#xff0c;则在函数内部修改形式参数&#xff0c;实际参数跟着改变。 2. 数组 数组名即该数组的首地址&a…

CSPM 未来发展的思考

由于数据泄露的持续威胁以及云的短暂和快节奏的特性&#xff0c;只有在最基础的层面上保护您的云才有意义。组织已经转向 CSPM 解决方案来锁定他们的平台。 今天我们来聊聊什么是CSPM&#xff0c;它如何去产生有有效的帮助&#xff0c;未来会向哪发展。 什么是 CSPM&#xff1…

阿拉德手游服务端Centos搭建教程

阿拉德手游服务端Centos搭建教程 大家好我是艾西&#xff0c;又有几天没有更新文章了。这几天看了看还是有不少人对手游感兴趣&#xff0c;今天给大家分享一款早些年大火的pc游戏&#xff0c;现在也有手游了“阿拉德”。 你是否还记得DNF&#xff0c;一天你不小心救了赛丽亚&a…

Win10系统电脑开机黑屏一直转圈无法进入桌面怎么办?

Win10系统电脑开机黑屏一直转圈无法进入桌面怎么办&#xff1f;有用户电脑开机了之后无法进入到桌面中&#xff0c;开机了之后&#xff0c;电脑桌面只有显示一个黑屏和转圈的图标&#xff0c;一直都无法进入到桌面中。强制重启电脑之后依然是这样&#xff0c;那么这个情况怎么去…

今天公司来了个拿 30K 出来的测试,算是见识到了基础的天花板

今天上班开早会就是新人见面仪式&#xff0c;听说来了个很厉害的大佬&#xff0c;年纪还不大&#xff0c;是上家公司离职过来的&#xff0c;薪资已经达到中高等水平&#xff0c;很多人都好奇不已&#xff0c;能拿到这个薪资应该人不简单&#xff0c;果然&#xff0c;自我介绍的…

Mysql-存储过程简单入门

定义&#xff1a; 存储过程的英文是 Stored Procedure 。它的思想很简单&#xff0c;就是一组经过 预先编译 的 SQL 语句 的封装。 执行过程&#xff1a;存储过程预先存储在 MySQL 服务器上&#xff0c;需要执行的时候&#xff0c;客户端只需要向服务器端发出调用 存储过程的命…

Godot引擎 4.0 文档 - 循序渐进教程 - 监听玩家输入

本文为Google Translate英译中结果&#xff0c;DrGraph在此基础上加了一些校正。英文原版页面&#xff1a; Listening to player input — Godot Engine (stable) documentation in English 监听玩家输入 在上一课创建您的第一个脚本的基础上&#xff0c;让我们看看任何游戏…

SpringBoot集成SpringSecurity从0到1搭建权限管理详细过程(认证+授权)

前言 最近工作需要给一个老系统搭建一套权限管理&#xff0c;选用的安全框架是SpringSecurity&#xff0c;基本上是结合业务从0到1搭建了一套权限管理&#xff0c;然后想着可以将一些核心逻辑抽取出来写一个权限通用Demo&#xff0c;特此记录下。 文章目录 前言1、SpringSecuri…

Elastic Stack

一、简介 ELK是一个免费开源的日志分析架构技术栈总称&#xff0c;官网https://www.elastic.co/cn。包含三大基础组件&#xff0c;分别是Elasticsearch、Logstash、Kibana。但实际上ELK不仅仅适用于日志分析&#xff0c;它还可以支持其它任何数据搜索、分析和收集的场景&#…

接口测试:Eolink Apikit 和 Postman 哪个更好用?

接口测试&#xff1a;Eolink Apikit 和 Postman 哪个更好用&#xff1f; 很多做服务端开发的同学&#xff0c;应该基本都用过 Postman 来测试接口&#xff0c;虽然 Postman 能支撑日常工作&#xff0c;但是总感觉还是少了点什么&#xff0c;比如需要 Swagger 来维护接口文档&am…

nginx压测记录

nginx压测记录 1 概述2 原理3 环境3.1 设备与部署3.2 nginx配置/服务器配置 4 netty服务5 步骤6 结果7 写在最后 1 概述 都说nginx的负载均衡能力很强&#xff0c;最近出于好奇对nginx的实际并发能力进行了简单的测试&#xff0c;主要测试了TCP/IP层的长链接负载均衡 2 原理 …

YOLOv5区域检测+声音警报

YOLOv5区域检测声音警报 1. 相关配置2. 检测区域设置3. 画检测区域线&#xff08;不想显示也可以不画&#xff09;4. 报警模块5. 代码修改5.1 主代码5.2 细节修改&#xff08;可忽略&#xff09; 6. 实验效果 本篇博文工程源码下载 链接1&#xff1a;https://github.com/up-up-…

远程桌面连接工具在哪里下载?

在市场上&#xff0c;有很多种不同的工具可用。一些远程桌面连接工具&#xff08;如RayLink&#xff09;具有高清流畅、操作简单和连接速度快的特点。而其他一些连接工具则更注重保护安全和数据保密性。不同的远程桌面连接工具各有特点&#xff0c;需要根据不同的需求进行选择。…

[AI图片生成]自己搭建StableDiffusion安装过程

前言 最近尝试玩玩AI图片生成,安装一路坑 出个一路安装成功的记录 开始 找个空间大的盘符,这玩意将来会很占空间.一个模型大约5g左右,你可能还会装很多模型创建个目录,路径不要有中文安装git 下载地址 详细教程 (如果有忽略)下载 Python3.10.0,记得勾选添加到环境变量选项,安…

ChatGPT帮你写简历找工作

随着随着毕业时间的到来&#xff0c;应届生将要面临求职问题&#xff0c;根据官方的统计&#xff0c;2023届高校毕业生预计达1158万人&#xff0c;就业市场竞争激烈&#xff0c;无论是校园招聘&#xff0c;招聘会&#xff0c;线上招聘除了自身的准备和个人能力&#xff0c;都会…

2023 hnust 大三下 人工智能导论课程 期中考试复习笔记

前言 ★大概率考✦个人推测考点※补充内容没有完全覆盖“人工智能导论复习2023.pdf”的重点致谢&#xff1a;hwl、lyf、lqx 题型 问答&#xff1a;5*10分综合&#xff1a;15分设计&#xff1a;25分开放题/论述题&#xff1a;10分 第1章 绪论 人工智能的定义 智能 思考与…