C语言小游戏——扫雷

news2024/12/18 0:45:06

前言

结合前边我们所学的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语言基础语法来实现的扫雷小游戏,希望可以对你有所帮助,感谢阅读!

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

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

相关文章

32岁测试工程师,陷入中年危机,最终我裸辞了....

前言 今年32岁&#xff0c;我从公司离职了&#xff0c;是裸辞。 前段时间&#xff0c;我有一件事情一直憋在心里很难受&#xff0c;想了很久也没找到合适的人倾诉&#xff0c;就借着今天写出来。 我一个十几年IT经验&#xff0c;七年测试经验的职场老人&#xff0c;我慢慢涨…

02 Android开机启动之BootLoader及kernel的启动

Android开机启动之BootLoader及kernel的启动 1、booloader的启动流程 第一阶段:硬件初始化,SVC模式,关闭中断,关闭看门狗,初始化栈,进入C代码 第二阶段:cpu/board/中断初始化;初始化内存以及flash,将kernel从flash中拷贝到内存中,执行bootm,启动内核 2、kernel的启…

学习如何将Jenkins与UI测试报告完美整合,事半功倍,轻松获取高薪职位!

目录 引言 &#xff08;一&#xff09;在本地整合出报告 1.在cmd分别安装pytest和allure-pytest 2.进入需要执行的代码所在的路径 3.运行测试报告&#xff0c;代码如下 4.解析此json文件&#xff0c;代码如下&#xff08;新打开cmd进入路径&#xff09; 5.打开此HTML文件…

包管理工具

包 package&#xff0c;代表了一组特定功能的源码集合。 包管理工具 管理包的应用软件&#xff0c;可以对包进行下载安装、更新、删除、上传等操作。 借助包管理工具&#xff0c;可以快速开发项目&#xff0c;提升开发效率。 常用包管理工具 npm&#xff08;nodejs官方内…

百度API实现自动写诗

作者介绍 张琪&#xff0c;男&#xff0c;西安工程大学电子信息学院&#xff0c;2022级研究生 研究方向&#xff1a;机器视觉与人工智能 电子邮件&#xff1a;3126743452qq.com 王泽宇&#xff0c;男&#xff0c;西安工程大学电子信息学院&#xff0c;2022级研究生&#xff0…

Spring——Spring_IOC

1.Spring_IOC概念引入 控制反转 2.Spring_IOC代码测试 IOC代码演示 控制反转&#xff1a;就是创建对象的权力交给了容器 1.创建一个接口&#xff0c;定义一个抽象方法 package org.example;public interface Empdao {int addemp(); } 2.创建一个实现类&#xff0c;实现这…

两台电脑之间怎么互相传文件?

​随着技术的发展&#xff0c;我们似乎可以从家中或工作电脑远程访问另一台电脑。同时&#xff0c;一些用户也在想&#xff0c;“我能不能把文件从一台电脑远程传输到另一台电脑&#xff0c;这样我就可以在本地电脑上随心所欲地查看和编辑文件了”。 这个问题的答案是…

Android自定义一个省份简称键盘

hello啊各位老铁&#xff0c;这篇文章我们重新回到Android当中的自定义View&#xff0c;其实最近一直在搞Flutter&#xff0c;初步想法是&#xff0c;把Flutter当中的基础组件先封装一遍&#xff0c;然后接着各个工具类&#xff0c;列表&#xff0c;网络&#xff0c;统统由浅入…

PostgreSQL实战之物理复制和逻辑复制(八)

目录 PostgreSQL实战之物理复制和逻辑复制&#xff08;八&#xff09; 8 级联复制 8.1 级联复制物理架构 8.2 级联复制部署 PostgreSQL实战之物理复制和逻辑复制&#xff08;八&#xff09; 8 级联复制 实际上PostgreSQL支持备库既可接收主库发送的将WAL&#xff0c;也支持…

Java泛型基本知识附面试题

一次平平无奇的面试 为什么要写这篇文档&#xff0c;主要就是在字节二面的时候&#xff0c;面试官提了这么一个问题 面试官&#xff1a;Java中的List<Integer>里有可能存String类型元素吗&#xff1f; 当时的我&#xff1a;应该…不可以吧&#xff0c;好像编译器会报错…

2023口腔护理行业分析:市场需求多元化,细分市场持续多变

随着人们生活水平的提高以及口腔护理意识的提升&#xff0c;消费者对于口腔护理的诉求愈发多样化&#xff0c;对于与此相关的产品&#xff0c;包括牙膏、牙刷、牙齿美白产品、漱口水、牙线等产品的需求也日益提高&#xff0c;在这种情况下&#xff0c;口腔护理相关细分产品的销…

软件研发管理高效的关键:11项自动化功能

1、自动锁定需求缺陷 为了提高用户需求分析质量&#xff0c;尽早发现需求缺陷&#xff0c;CoCode开发云特开发了需求分析工具&#xff0c;使用AI&#xff0c;通过需求测试和一致性检测&#xff0c;能够在几分钟内快速分析用户需求缺陷&#xff0c;如歧义、重复、遗漏、不一致和…

深度学习神经网络学习笔记-多模态方向-09-VQA: Visual Question Answering

摘要 -我们提出了自由形式和开放式视觉问答(VQA)的任务。给定一张图像和一个关于图像的自然语言问题&#xff0c;任务是提供一个准确的自然语言答案。镜像现实场景&#xff0c;比如帮助视障人士&#xff0c;问题和答案都是开放式的。视觉问题有选择地针对图像的不同区域&#…

nodejs+vue飞机机票在线预订票网站

本机票预订系统以vue作为框架&#xff0c;b/s模式以及MySql作为后台运行的数据库&#xff0c;同时使用Tomcat用为系统的服务器。本系统主要包括首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;机票类型管理&#xff0c;机票信息管理&#xff0c;订票信息管理&#x…

STM32F4_DMA直接存储器详解

目录 1. 什么是DMA 2. DMA的主要特性 3. DMA功能 3.1 DMA功能框图 3.2 DMA事务 3.3 通道选择 3.4 仲裁器 3.5 DMA数据流 3.6 源、目标和传输模式 3.6.1 外设到存储器模式 3.6.2 存储器到外设模式 3.6.3 存储器到存储器模式 3.7 指针递增 3.8 DMA内存占用 3.9 存…

<SQL>《SQL命令(含例句)精心整理版(1)》

《SQL命令精心整理》 1 SQL基础2 关键字 select & distinct3 排序检索 - order by & desc & asc4 where 语句5 操作符 -and & or & not & in6 通配符6.1 LIKE % 谓词 下划线 方括号 7 计算、拼接、别名 1 SQL基础 名词概念数据库&#xff08;database…

Mit6.006-problemSet03

3-1 哈希练习&#xff08;Hash Practice&#xff09; (a) 按顺序插入整数keys A[47, 61, 36, 52, 56, 33, 92]到尺寸为7的哈希表中&#xff0c;使用哈希函数 h ( k ) ( 10 k 4 ) m o d 7 h(k)(10k4)mod7 h(k)(10k4)mod7。哈希表的每个插槽&#xff0c;存储一个key&#xff…

【Eslint】vscode 配置 eslint 教程

文章目录 一、初始化配置二、文件配置2.1、.eslintrc.js 文件2.2、.eslintignore 文件2.3、settings.json 文件 一、初始化配置 操作步骤&#xff1a; 选择&#xff1a;上下方向键确定&#xff1a;enter 回车键退出&#xff1a;Ctrl c 安装&#xff1a;npm install -g eslint初…

Java高并发核心编程(JUC)—线程池详细笔记

线程池 基本概述 线程池&#xff1a;一个容纳多个线程的容器&#xff0c;容器中的线程可以重复使用&#xff0c;省去了频繁创建和销毁线程对象的操作 线程池作用&#xff1a; 降低资源消耗&#xff0c;减少了创建和销毁线程的次数&#xff0c;每个工作线程都可以被重复利用…

加密与解密 调试篇 动态调试技术

OllyDbg调试器的使用 CPU窗口 我们进行载入的时候 主要返回的是CPU窗口 是最主要的窗口 对应面板的C 反汇编窗口 我们先查看CPU窗口 打开后是有 5个面板 主要查看反汇编窗口 我们可以对这些列进行操作 操作都是进行双击地址&#xff1a; 显示被双击行地址的相对地址 再次双…