数据结构-连连看

数据结构-连连看

Github项目地址
在这里插入图片描述
在这里插入图片描述

最终结果:

实验目的和要求

(1) 掌握C++开发工具和集成开发环境
(2) 掌握C++面向对象的编程思想和C++的基础编程
(3) 理解MFC基本框架,包括MFC Dialog和GDI编程
(4) 掌握数据结构,包括算法控制、数组、栈、图;同时掌握算法,比如数组的遍历、联通判断,文件读取、排序算法等
(5) 了解项目的调研和分析,学习软件工程的迭代思想,开发GUI应用程序
(6) 养成良好的编码习惯,提高C++语言编程能力,开发应用程序“欢乐连连看”

分析与设计

数据结构设计

定义一个CGraph的类来保存棋盘地图,使用一个数组 Vertices[MAX_NUM] 来保存每个顶点,用一个二维数组来AdjMatrix[MAX_NUM][MAX_NUM]来保存各个顶点的关系,也就是领结矩阵,以及一些方法来实现数据的调用,包含一些初始化,获取顶点和边,添加顶点和边,更新顶点和边的方法,如图所示:

在这里插入图片描述

核心算法设计

连连看总体按三个层次来设计:表示层,控制层和逻辑实现层。

  • 表示层:主界面在类CLLKDlg中是实现,主要是界面设计实现,内容主要是创建游戏界面和帮助界面。游戏界面CGameDig类来实现,帮助界面CHelpDialog来实现。 界面的设计主要是MFC编程,实现过程不在赘述了。
  • 控制层:CGameControl类的实现,包含的属性及方法如下图:
    在这里插入图片描述

定义 m_graph来保存游戏地图,定义两个顶点来保存选中的第一个和第二个顶点的位置。
在startGame()函数中初始化地图,Link()和Help()函数中调用逻辑实现层的方法来实现判断连接,返回路径数据,实现方法见逻辑实现层。isWin(int nTime)和isWin()是分别判断基本模式和休闲模式中判断结束的方法,主要区别主要是对时间的判断。
逻辑实现层:逻辑的实现靠类CGameLogic来实现,属性有
22
以及实现的函数:

  1. 初始化图结构的算法实现:定义一个数组int anTemp[MAX_NUM]保存,按顺序把要填的花色数字填进去,然后随机生成两个数表示位置,交换两个数,实现顺序打乱,实现代码如下:
//初始化地图
void CGameLogic::initMap(CGraph &g) {
	//初始化顶点
	int anTemp[MAX_NUM];
	for (int i = 0; i < MAX_PIC_NUM; i++) {
		for (int j = 0; j < REPEAT_NUM; j++) {
			anTemp[i * REPEAT_NUM + j] = i;
		}
	}
	//设置随机种子
	srand((unsigned)time(NULL));
	//随机交换两个数字
	for (int i = 0; i < 100; i++) {
		//随机得到两个坐标
		int index1 = rand() % MAX_NUM;
		int index2 = rand() % MAX_NUM;
		//交换两个数值
		int temp = anTemp[index1];
		anTemp[index1] = anTemp[index2];
		anTemp[index2] = temp;
	}
	//初始化顶点
	for (int i = 0; i < MAX_NUM; i++)
		g.AddVertex(anTemp[i]);
	//初始化边
	for (int i = 0; i < MAX_ROW; i++)
		for (int j = 0; j < MAX_COL; j++)
			this->UpdateArc(g, i, j);
}
  1. 连连看的主要算法是判断两个点的位置是否可以连接,采用深度优先搜索算法,顺便保存路径到数组中来实现表示层的显示,从一个顶点出发,从头开始查找一个可以和它相连的位置,然后再以它为基点查找下一个位置,记录路径和拐点数来判断结束条件。实现代码如下:
bool CGameLogic::SearchPathW(CGraph& g, int nV1, int nV2) {
	//深度优先搜索路径	
	//得到顶点数
	int nVexNum = g.GetVexNum();
	//遍历nV1行
	for (int nVi = 0; nVi < nVexNum; nVi++) {
		if (g.GetArc(nV1, nVi) && !this->isExit(nVi)) {
			//压入顶点,作为有效路劲的有效顶点
			this->PushVertex(nVi);
			if (this->m_nCornerNum > 2) {
				this->PopVertex();
				//this->m_nCornerNum = 0;
				continue;
			}
			//判断是否到头
			if (nVi != nV2) {
				//如果不是空就表示不通
				if (g.GetVertex(nVi) != BLANK) {
					this->PopVertex();
					continue;
				}
				//如果为空,递归
				if (this->SearchPathW(g, nVi, nV2)) {
					return true;
				}
			}
			else {
				return true;
			}
			this->PopVertex();
		}
	}
	return false;
}
  1. 重排的实现和数组的初始化的实现原理差不多,也是随机生成两个位置的,然后交换数据实现数据。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值