游戏实践:扫雷

news2024/11/13 13:24:08

一.游戏介绍

虽然很多人玩过这个游戏,但还是介绍一下。在下面的格子里,埋的有10颗雷,我们通过鼠标点击的方式,点出你认为不是雷的地方,等到把所有没有雷的格子点完之后,及视为游戏胜利。

上面的数字的意思就是它的一圈的格子有几颗雷。 

 明白了游戏的玩法,那么我们就可以来写一下这个游戏。

二.游戏的实现

我们首先来创建三个文件,分别是用来实现游戏内容的头文件game.c,来测试的text.c文件,还有头文件game.c。

1.游戏的大纲(text.c)

我们可以先把游戏大体的思路给顺下来:

比如在正式写游戏内容的实现之前,我们是不是需要写一下游戏的目录(按1开始游戏,或者按0退出游戏之类的)。

(1)目录(menu函数)

像是游戏的目录:

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

(2)选择开始与结束(text函数)

我想让他按1开始游戏,按0退出游戏,我是不是就可以用一个do  while循环来实现:

void test()
{
	int input = 0;
    srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);//1 0 x
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("游戏结束,退出游戏\n");
			break;
		default:
			printf("选择错误,重新选择\n");
			break;
		}

	} while (input);
}

 (3)游戏内部需要做的(game函数)

此时我想按1来进行游戏,我是不是就可以在1的后面加上一个game()函数,来实现游戏内容。我们在game.c文件里实现好这些功能后,在这个函数里直接调用就行了。

注意:这里看不懂没关系,只是想让大家知道这个游戏我们要干啥。

要实现游戏内容,我们就需要初始化棋盘,布置雷,打印棋盘,排查雷。这些都是在game.c文件里来实现,最后在text.c文件里调用就行了。

void game()
{
	//完成扫雷游戏
	//mine数组中存放布置好的雷的信息
	char mine[ROWS][COLS] = { 0 };//数组全部初始化为'0'

	//show数组中存放排查出的雷的信息
	char show[ROWS][COLS] = { 0 };//数组全部初始化为'*'

	//初始化棋盘
	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');

	//布置雷
	//就9*9的棋盘上随机布置10个雷
	SetMine(mine, ROW, COL);
	//DisplayBoard(mine, ROW, COL);

	//打印棋盘
	DisplayBoard(show, ROW, COL);

	//排查雷
	FindMine(mine, show, ROW, COL);
}

2.游戏内容的实现

先把game.h的内容放过来,来让大家知道我们都要进行哪几个步骤:

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>


#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2

#define EASY_COUNT 10


//声明函数

//棋盘初始化的函数
void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set);

//打印棋盘
void DisplayBoard(char arr[ROWS][COLS], int row, int col);


//布置雷
void SetMine(char arr[ROWS][COLS], int row, int col);

//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

(1)初始化棋盘

我们创建一个函数来初始化我们的棋盘:共有四个参数

第一个参数就是我们的棋盘。

第二个参数是我们棋盘的行。

第三个参数是我们棋盘的列。

第四个参数是我们需要把棋盘初始化成什么(比如0,*)。

void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	for (i = 0; i < rows; i++)
	{
		int j = 0;
		for (j = 0; j < cols; j++)
		{
			arr[i][j] = set;//两个for循环实现整个棋盘的初始化
		}
	}
}

(2)打印棋盘

这个函数需要三个参数:分别是棋盘,行和列。

void DisplayBoard(char arr[ROWS][COLS], int row, int col)
{
	int i = 0;
	//打印列号
	printf("------扫雷游戏------\n");
	for (i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	//列号打印完毕
	
	//分别是打印行号和棋盘
	for (i = 1; i <= row; i++)
	{
		int j = 0;
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
}

(3)布置棋盘

这个步骤就很重要了,因为是我们布置雷的过程。

我们想要随机的布置雷的方位,我们就需要利用好time.h。

void SetMine(char arr[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;//这里的rand函数需要与srand函数配合使用,目的就是生成一个随机数
		int y = rand() % col + 1;//这里的x和y的范围都是1~10
		if (arr[x][y] == '0')
		{
			arr[x][y] = '1';//注意这里的1和0都是字符
			count--;
		}
	}
}

注意:在使用rand函数生成随机数之前,通常需要调用srand函数来设置随机数种子。随机数种子是一个起始值,它会影响后续rand函数生成的随机数序列。如果每次程序运行时都使用相同的随机数种子,那么每次生成的随机数序列都会相同。

(4)知道雷的数量

因为当我们扫到一个雷的时候,会反馈给我们周围雷的数量,所以要有那么一个步骤:

我们可以把每一个格子都加起来,看看有几个1。

static 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] + 
		mine[x + 1][y + 1] + 
		mine[x][y + 1] + 
		mine[x - 1][y + 1] - 8*'0';
}

如果用上面的方式,会显得有点麻烦,还可以这样写: 

static int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
	int i = 0;
	int count = 0;
	for (i = x - 1; i <= x + 1; i++)
	{
		int j = 0;
		for (j = y - 1; j <= y + 1; j++)
		{
			count += (mine[i][j] - '0');//因为是字符1,所以我们要减去字符0,得到数字1
		}
	}
	return count;
}

(5)排查雷

四个参数:一个是有0和1的参数,一个是让玩家看的参数,另外两个是行和列。

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;
	while(win<row*col-EASY_COUNT)
	{
		printf("请输入要排查的坐标:");
		scanf("%d %d", &x, &y);
		//判断坐标的有效性
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] == '*')
			{
				if (mine[x][y] == '1')
				{
					printf("很遗憾,你被炸死了\n");
					DisplayBoard(mine, ROW, COL);//被炸死了直接把带有雷的棋盘弄出来
					break;
				}
				else
				{
					//该坐标不是雷,就得统计坐标周围有几个雷
					int count = GetMineCount(mine, x, y);
					show[x][y] = count + '0';//我们的count是数字,所以要加上字符0的ASCII码值
					DisplayBoard(show, ROW, COL);
					win++;
				}
			}
			else
			{
				printf("该坐标已经被排查了,重新输入坐标\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, ROW, COL);
	}
}

到这里游戏内容的步骤就完成了。下面的完整的代码分享。

三.完整代码分享

game.h文件

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>


#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2

#define EASY_COUNT 10


//声明函数

//棋盘初始化的函数
void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set);

//打印棋盘
void DisplayBoard(char arr[ROWS][COLS], int row, int col);


//布置雷
void SetMine(char arr[ROWS][COLS], int row, int col);

//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

text.c文件:

#include "game.h"


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

void game()
{
	//完成扫雷游戏
	//mine数组中存放布置好的雷的信息
	char mine[ROWS][COLS] = { 0 };//数组全部初始化为'0'

	//show数组中存放排查出的雷的信息
	char show[ROWS][COLS] = { 0 };//数组全部初始化为'*'

	//初始化棋盘
	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');

	//布置雷
	//就9*9的棋盘上随机布置10个雷
	SetMine(mine, ROW, COL);
	//DisplayBoard(mine, ROW, COL);

	//打印棋盘
	DisplayBoard(show, ROW, COL);

	//排查雷
	FindMine(mine, show, ROW, COL);
}

void test()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);//1 0 x
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("游戏结束,退出游戏\n");
			break;
		default:
			printf("选择错误,重新选择\n");
			break;
		}

	} while (input);
}

int main()
{
	test();
	return 0;
}

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++)
	{
		int j = 0;
		for (j = 0; j < cols; j++)
		{
			arr[i][j] = set;
		}
	}
}

void DisplayBoard(char arr[ROWS][COLS], int row, int col)
{
	int i = 0;
	//打印列号
	printf("------扫雷游戏------\n");
	for (i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	//列号打印完毕
	
	//分别是打印行号和棋盘
	for (i = 1; i <= row; i++)
	{
		int j = 0;
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
}


void SetMine(char arr[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (arr[x][y] == '0')
		{
			arr[x][y] = '1';
			count--;
		}
	}
}

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


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

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

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

相关文章

租用马来西亚服务器:稳定高效的网络选择

马来西亚首都是吉隆坡。作为一个新兴的多元化经济国家&#xff0c;也属于亚洲四小龙之一。地理位置优越&#xff0c;中间隔着南中国海。一部分是北接泰国的位于马来半岛的西马来西亚&#xff0c;另一部分则是东马来西亚&#xff0c;在婆罗洲岛的北部。这种地理位置有利于促进该…

Qt | 事件第一节(QApplication、QGuiApplication、QCoreApplication)

一、QApplication、QGuiApplication、QCoreApplication 简介 1、继承关系见下图,其中左侧为顶级父类 2、一个程序中只能有一个 QCoreApplication 及其子类的对象。 3、QCoreApplication:主要提供无 GUI 程序的事件循环。 4、QGuiApplication:用于管理 GUI 程序的控制流和…

LangChain学习笔记与样程

LangChain 是一个开源的机器学习工具库&#xff0c;专门用于构建和部署基于语言的应用程序。这个库提供了一系列工具和接口&#xff0c;使开发者能够轻松地整合和使用大型语言模型&#xff0c;例如 OpenAI 提供的 GPT。LangChain 的核心特点包括模块化设计、灵活性和易用性&…

卷积神经网络结构组成与解释

卷积神经网络结构组成与解释 卷积神经网络是以卷积层为主的深度网路结构&#xff0c;网络结构包括有卷积层、激活层、BN层、池化层、FC层、损失层等。卷积操作是对图像和滤波矩阵做内积&#xff08;元素相乘再求和&#xff09;的操作。 1. 卷积层 常见的卷积操作如下&#x…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之十一 简单给视频添加水印图片效果

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之十一 简单给视频添加水印图片效果 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之十一 简单给视频添加水印图片效果 一、简单介绍 二、简单给视频添加水印图片效果实现…

Linux——信号量与基于环形队列的生产者消费者模型

目录 前言 一、信号量 二、信号量的接口 1.初始化 2.销毁 3.申请信号量 4. 释放信号量 三、基于环形队列的生产者消费者模型 1.环形队列的理解 2.生产者消费者的设计 3.单消费者单生产者环形队列的实现 4.多消费者多生产者环形队列的实现 前言 之前&#xff0c;…

MGRE中的OSPF配置

一、实验图 二、实验配置 R1 R2 R3 R4 R5 R6

EXCEL中COUNT和COUNTIF的参数类型有什么不同?

来看一下它们的语法&#xff1a; 1.COUNT(值) COUNT函数是计数数字的个数&#xff0c;注意是数值型数字&#xff0c;可不包括文本型数字&#xff0c;它的参数“值”可以是来自单元格的单一区域&#xff0c;如A1:C2&#xff0c;也可以是来自单元格的复合不规则区域&#xff0c…

技术方案应该这么写

简介 新入职一个华为十年工作经验的老Java。让写一个设计方案&#xff0c;其实也不算难&#xff0c;根据业务需要存取三千万数据&#xff0c;三天没写出来&#xff0c;最后做了辞退处理。其实我相信这个老技术员是有能力的&#xff0c;只是没有合适的机会表达。但是也侧面的说明…

9. Spring Boot 日志文件

本篇文章源码位置延续上个章节&#xff1a;SpringBoot_demo 本篇文章内容源码位于上述地址的com/chenshu/springboot_demo/logging包下 1. 日志的作用 发现和定位问题&#xff1a; 日志是程序的重要组成部分&#xff0c;它在系统、程序出现错误或异常时提供诊断和解决问题的线…

学习经验分享【32】本科/硕士开题报告、中期报告等写作经验分享

本科/硕士阶段首先就是要写开题报告&#xff0c;然后中期报告&#xff0c;这篇博文就是分享一下写报告的经验&#xff0c;避免被老师打回来。本人有丰富的写报告经验&#xff0c;有需要的朋友可添加文末联系方式与我联系。 一、本科开题报告的提纲 课题来源及研究的目的和意义…

C++内存分布

C代码编译过程 预处理 宏定义展开、头文件展开、条件编译&#xff0c;这里并不会检查语法编译检查语法&#xff0c;将预处理后文件编译生成汇编文件汇编将汇编文件生成目标文件(二进制文件)链接将目标文件链接为可执行程序 进程的内存分布 程序运行起来(没有结束前)就是一个…

openjudge_2.5基本算法之搜索_166:The Castle

题目 166:The Castle 总时间限制: 1000ms 内存限制: 65536kB 描述 Figure 1 shows the map of a castle.Write a program that calculates how many rooms the castle hashow big the largest room is The castle is divided into m * n (m<50, n<50) square modules.…

如何应对Android面试官 -> startActivity 流程详解

前言 本章主要讲解下 Activity 的启动流程&#xff1b; 整体概念 点击桌面图标&#xff0c;启动目标应用程序的 Activity&#xff0c;首先会跟 AMS 打交道&#xff0c;也就是 SystemServer 进程中启动的AMS&#xff0c;Launcher 进程和 SystemServer 进程中的 AMS 通信「一次跨…

(九)C++自制植物大战僵尸游戏自定义对话框的实现

植物大战僵尸游戏开发教程专栏地址http://t.csdnimg.cn/m0EtD 对话框在游戏的交互中非常重要。在游戏中&#xff0c;对话框不仅可以提醒用户下达任务指令&#xff0c;而且还可以让用户进行操作&#xff0c;自定义游戏中的各种属性。对话框在游戏的交互中非常常见且大量使用。Co…

树莓集团与天府新区信息职业学院在国际数字影像产业园成功举办授牌仪式

2024年4月12日&#xff0c;树莓集团与天府新区信息职业学院共同在国际数字影像产业园举办授牌仪式。这场仪式不仅标志着双方合作的正式开启&#xff0c;更是为未来的产教融合、学生实训与就业推荐树立了坚实的基石。 仪式上&#xff0c;天府新区信息职业学院领导与树莓集团的代…

Qt QStyle详解

1.简介 QStyle类是 Qt 框架中用于控制应用程序界面元素外观的一个抽象基类。这个类提供了一种方式来定制窗口部件&#xff08;widgets&#xff09;的绘制和行为&#xff0c;可以通过改变主题或风格来更改应用程序的外观&#xff0c;而无需修改窗口部件本身的代码。 Qt包含一组…

抽奖系统设计

如何设计一个百万级用户的抽奖系统&#xff1f; - 掘金 如何设计百万人抽奖系统…… 在实现抽奖逻辑时&#xff0c;Redis 提供了多种数据结构&#xff0c;选择哪种数据结构取决于具体的抽奖规则和需求。以下是一些常见场景下推荐使用的Redis数据结构&#xff1a; 无序且唯一奖…

系统边界图

系统边界图的定义&#xff1a; 系统边界图是系统工程和软件工程中的一种图形化工具&#xff0c;用于描述系统与外部世界之间的交互和界限。它展示了系统的组成部分以及这些组件如何与外部实体进行通信和交互。系统边界图通常包括系统内部的各个组件、外部实体以及它们之间的通信…

【Qt】:事件的处理

系统相关 一.鼠标事件二.键盘事件三.定时器 事件是应用程序内部或者外部产生的事情或者动作的统称。在Qt中使用一个对象来表示一个事件。所有的Qt事件均继承于抽象类QEvent。事件是由系统或者Qt平台本身在个同的的刻友出的。当用广投下鼠标、敲下键盘&#xff0c;或者是窗口需要…