IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言小游戏之——扫雷(含递归) -> 正文阅读

[C++知识库]C语言小游戏之——扫雷(含递归)

首先我们将这个小游戏分成了3个文件来写,分别是test.c、game.c、game.h

test.c内部主要是进入游戏的界面和呈现一个总体的框架

game.c内部主要进行在test.c内game函数里出现的各种函数功能的具体实现。

game.h内部主要进行对test.c内game函数里出现的各种函数进行声明,以及main函数所需要的头文件也一并包括在内,这样在main函数所在的文件里,只需要引进一个game.h就可以了。

我们给出代码,再结合代码进行说明:

test.c文件:

#include "game.h"
void game()
{
	char mine[ROWS][COLS] = { 0 };//雷信息'0'
	char show[ROWS][COLS] = { 0 };//棋盘信息 '*'
	//初始化棋盘
	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');
	//显示棋盘
	DisplayBoard(show, ROW, COL);
	//布置雷
	SetMine(mine, ROW, COL);
	//排查雷
	FindMine(mine, show, ROW, COL);
	
}
void menu()
{
	printf("******************************************************\n");
	printf("**1.Start                                0.Exit  *****\n");
	printf("******************************************************\n");
}
void test()
{
	int input = 0;
	do
	{
		menu();
		printf("请选择;>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误,请重新选择!\n");
			break;
		}
	} while (input);
	

}
int main()
{
	srand((unsigned int)time(NULL));
	test();
	return 0;
}

game.h文件:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
void DisplayBoard(char show[ROWS][COLS], int row, int col);
void SetMine(char mine[ROWS][COLS], int row, int col);
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

game.c文件:

#include "game.h"
#define EASY_COUNT 10
void Open(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	if (x > 0 && x <= ROW && y > 0 && y <= COL)
	{
		if (0 == GetMine(mine, x, y))
		{
			if (show[x][y] != ' ')
			{
				show[x][y] = ' ';
				int i = 0;
				int j = 0;
				for (i = x - 1; i <= x + 1; i++)
				{
					for (j = y - 1; j <= y + 1; j++)
					{
						Open(mine, show, i, j);
					}
				}
			}
		}
		else
		{
			show[x][y] = GetMine(mine, x, y) + '0';
			return;
		}
	}
}
int GetMine(char mine[ROWS][COLS], int x, int y)
{
	int i = 0;
	int j = 0;
	int count = 0;
	for (i = x - 1; i <= x + 1; i++)
	{
		for (j = y - 1; j <= y + 1; j++)
		{
			if (mine[i][j] == '1')
			{
				count++;
			}
		}
	}
	return count;
}
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set;
		}
	}
}
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("-----------------------------------------------|\n");
	for (i = 0; i <= 9; i++)
	{
		printf(" %d ", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf(" %d ", i);
		for (j = 1; j <= col; j++)
		{
			printf(" %c ", board[i][j]);
		}
		printf("\n");
	}
	printf("-----------------------------------------------|\n");
}
void SetMine(char mine[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;
	while (count > 0)
	{
		int x = rand() % 9 + 1;
		int y = rand() % 9 + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			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 (1)
	{
		printf("请输入要排查的坐标:>");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
		{
			if (show[x][y] != '*')
			{
				printf("你已经排查过该坐标了\n");
			}
			if (mine[x][y] == '1')
			{
				printf("很遗憾,被炸死了!\n");
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else
			{
				Open(mine, show, x, y);
				DisplayBoard(show, row, col);
			}
			//用来遍历数组来判断雷和空白的位置以判断是否结束游戏。
			int i = 0;
			int j = 0;
			int flag = 0;
			for (i = 1; i <= row; i++)
			{
				for (j = 1; j <= col; j++)
				{
					if ('*' == show[i][j])
					{
						flag++;
					}
				}
			}
			if (EASY_COUNT == flag)
			{
				printf("恭喜你,排雷成功!\n");
				break;
			}
		}
		else
		{
			printf("输入非法,请重新输入!\n");
		}
	}
	
}

首先从main函数进入,main函数内部第一行先不用管,是用来生成随机数的随机起点的,后面会说到。进入test函数,进入do while循环,打印菜单,通过输入数字来进入或退出游戏。

输入1进入game函数,game函数内实现游戏逻辑。

首先我们需要两个二维数组来分别储存游戏中呈现的棋盘信息和”雷“的信息。

为了区分,分别取名为"show"和”mine“。

我们在定义二维数组的行和列时,用了ROWS和COLS,这是考虑到,在将来排查的时候,边缘位置进行周围八个格子排查时会越界访问,所以在9x9的界面内,我们实际上在设计时,设计成11x11的二维数组,给外面围了一圈,这样就可以避免越界访问。

而我们呈现时是以9x9的方式进行呈现的。

所以在game.h内部,用#define宏定义ROW与COL为9,ROWS与COLS为前者的基础上加2,这样无论是9x9还是10x10,都在外面围了一圈来避免越界访问。

然后,我们初始化棋盘,将要展现出来的棋盘show初始化为全是字符' * ',将雷的棋盘全部初始化为字符' 0 ',不过我们只写一个初始化函数,所以我们在传参时,不仅仅要把创建的二维数组传进去,也要把所要初始化的内容传进去。

然后就是在game.h内部进行定义,在game.c内部进行相关函数的实现。

初始化棋盘,把show数组和mine数组分别初始化为字符‘ * ’和字符' 0 '。见InitBoard函数。

打印棋盘,注意,传进去的是我们的show数组,但是打印的时候只是打印9x9的棋盘,所以传的时候传的行和列为ROW和COL,用row和col接收。具体看game.c内的DisplayBoard函数。

布置雷,此时我们传进去的是mine数组,但是在游戏中只有9x9的棋盘,所以我们只在9x9的范围内随机生成10个雷,此时我们就需要用到随机数来生成相应的坐标。所以就有了在开头main函数里用srand来生成随机起点。布置雷的时候要进行判断,若mine数组内该坐标位置为不是字符' 1 ',那么可以将其改为字符' 1 '视为布置了一颗“雷”。每布置成功一次,EASY_COUNT减一,至于设置这样一个宏定义的目的是为了以后雷的数量可以根据需求方便更改。

排查雷:即Findmine函数,我们此时要把show数组和mine数组都传进去,排查的时候,输入要排查的坐标,然后在mine数组里判断是否有“雷”,若没有,因为我们打印的时候打印的是show数组,所以改变的是show数组的内容,mine数组只是用来存储“雷信息”的,用做判断的依据。

输入后要判断合法性,是不是在9x9的范围内。还要判断show数组该位置上是否为‘ * ’,否则意味着已经排查过该坐标了。

然后判断mine数组相应位置上有没有“雷”,有的话,游戏结束,打印mine数组,没有的话,就进入我们的Open函数来实现排除一片的递归操作。

所谓展开一片,就是排查到一个坐标的周围一圈都没有“雷”的时候就展开,然后将无“雷”的地方改为空格,不然会死递归,再去排查这周围的几个坐标有没有符合条件的,有的话重复上述操作。

直到没有,就在该位置上显示周围有几个“雷”。

为此,我们写一个查找周围有几个“雷”的函数,称为GetMine,思路是以输入坐标为中心的9宫格内用循环来统计该区域的mine数组有几个雷,然后将其赋给该坐标的show数组的相应位置即可。注意这个GetMine函数是在game.c里面直接定义使用的,因为这个函数和game函数是没有直接关系的。

判断输赢,即“雷”的数量小于等于show数组中' * '字符的个数,在这里写成了等于符号,所以我们每次排查雷之后就要对棋盘进行一次遍历,来统计“雷”和' * '的数量并进行对比。

这样就大概上实现了功能。

水平有限,欢迎指正。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-02-06 13:38:43  更:2022-02-06 13:39:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:56:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码