连连看实验报告 (自动保存的)

penelope11 贡献于2016-10-09

作者 liuchun  创建于2016-03-23 05:45:00   修改者peng shaoling  修改于2016-06-29 23:55:00字数9833

文档摘要:
关键词:

 学生学号 0121410880534 实验课成绩 学 生 实 验 报 告 书 实验课程名称 数据结构与算法综合实验 开课学院 计算机科学与技术学院 指导教师姓名 胡燕 学生姓名 彭莹沁 学生专业班级 软件1403班 2015 -- 2016 学年 第 2 学期 实验课程名称: 数据结构与算法综合实验 实验项目名称 线性结构与连连看游戏综合实验 报告成绩 实验者 彭莹沁 专业班级 软件1403班 组别 同组者 无 完成日期 2016年6 月30日 第一部分:实验分析与设计(可加页) 一、 实验目的和要求 1.目的 (1)调研连连看游戏,了解连连看游戏的功能和规则等。 (2)掌握集成开发工具(Visual C++ 6.0或Microsoft Visual Studio 2010)。 (3)掌握C++的基础编程。 (4)了解MFC框架,包括MFC Dialog应用程序和GDI编程。 (5)了解线性结构,重点掌握数组和栈操作,掌握数组的遍历、消子和胜负判断等算法。 (6)了解企业软件开发过程,了解系统需求分析和设计,应用迭代开发思路进行项目开发。 (7)养成良好的编码习惯和培养软件工程化思维,综合应用“C++编程、MFC Dialog、算法、线性结构”等知识,开发“连连看游戏”桌面应用程序,达到掌握和应用线性结构核心知识的目的。 2.要求 2.1游戏规则 (1)一条直线消子 选择的两张图片花色相同,处于同一水平线或者同一垂线上,并且两张图片之间没有其余的图片,则可以进行一条直线消子。 (2)两条直线消子 选择的两张图片花色相同,既不在同一水平线上也不在同一垂线上,两张图片的连通路径至少由两条直线组成,两条直线经过的路径必须是空白,中间只要有一张不同种类的图片则该路径无效。 (3)三条直线销子 使用一个折点的路径无法连通两张图片,连通路径有三条直线,且三条直线经过的路径上没有图片,则可进行三条直线消子。 系统主要业务流程图如下: 2.2功能要求 待开发的连连看游戏称为“欢乐连连看”,使用二维数组来保存游戏地图中的数据,实现了连连看的核心功能。 欢乐连连看游戏的功能结构图如下: (1)主界面 游戏主界面是进行各项操作的入口。 (2)开始游戏 玩家选择游戏模式,进入游戏后,选择开始游戏,系统根据主题风格生成一个图片布局(游戏地图),以供玩家点击消除。 游戏地图大小为400*640,是一个10行*16列的矩形,分成160个小正方形,存放160张图片,每张图片大小为40*40。 (3)消子 对玩家选中的两张图片进行判断,判断是否符合消除规则。只有符合以下条件的图片对才会消失: ①一条直线连通; ②两条直线连通; ③三条直线连通。 如果可以消除,从游戏地图中提示连接路径,然后消除这两张图片,并计算相应的积分。如果不能消除则保持原来的游戏地图。 (4)判断胜负 当游戏完成后,需要判断游戏胜负。不同模式下判断胜负的规则不同。 ①基本模式时,如果在5分钟之内将游戏地图中所有的图片都清楚,则提示玩家获胜。 ②休闲模式时,如果游戏地图中的所有图片都被消除,则提示玩家获胜。 (5)提示 可以提示界面上能够消除的一对图片。 (6)重排 根据随机数,重新排列游戏地图上的图片。 (7)计时 设定一定时间来辅助游戏是否结束。 (8)游戏模式 游戏模式有基本模式、休闲模式和关卡模式三种,可以根据是否定时等规则设置,增强趣味性。 二、 分析与设计 1.数据结构的设计 使用二维数组来保存游戏地图,给每一种图片编一个号,并将这些编号保存在二维数组中。 在global.h文件中,定义一个结构体Vertex用来保存游戏地图中一个点的行号、列号、值信息。 typedef struct Vertex{ int row;//行 int col;//列 int num;//编号 }vertex; 2.核心算法设计 2.1随机开局法 (1)计算游戏中元素个数:行数*列数 (2)计算每一种花色重复数:行数*列数/花色数 (3)随机数给二维数组赋值,如果某花色达到花色重复次数则重新复制。 2.2消子判断流程 (1)获得选中的两张图片的行号和列号。 (2)判断选中的两张图片是否同色,不同色则不能相消。判断选中的两张图片是否为同一个图片,如果为同一个则不能相消。 (3)判断连通性,如以下三种情况均不满足,则结束。 ①首先判断能否一条直线连通。 ②如果不能一条直线连通则判断能否两条直线连通。 ③如果不能两条直线连通则判断能否三条直线连通。 (4)获得连通路径,绘制连通线。 (5)消除图片。 (6)更新游戏地图。 4.3一条直线消子算法 ①判断两个顶点,行是否相同,若相同则判断两个顶点在x方向是否连通。 bool CGameLogic::LinkInRow(int** pGameMap,vetex v1,vertexv2) { 1:将顶点的列进行调整,使nCol1的值小于nCol2 2:使用for循环,判断两个顶点间是否有不为空的图片 for(int i=nCol1+1;inCol2) { int temp=nCol1; nCol1=nCol2; nCol2=temp; } for(int i=nCol1+1;i<=nCol2;i++) { if(i==nCol2) { path[0]=v1; path[2]=v2; return true; } //如果有不为空就返回false if(anMap[nRow][i]!=BLANK) { return false; } } return false; } // 一列上面是否连通 bool CGameLogic::LinkInCol(int anMap[][18], vertex v1, vertex v2,vertex path[4]) { int nRow1=v1.row+1; int nRow2=v2.row+1; int nCol=v2.col+1; //保证nRow1小于nRow2 if(nRow1>nRow2) { int temp=nRow1; nRow1=nRow2; nRow2=temp; } for(int i=nRow1+1;i<=nRow2;i++) { if(i==nRow2) { path[0]=v1; path[2]=v2; return true; } //如果有不为空的就返回false if(anMap[i][nCol]!=BLANK) { return false; } } return false; } //当行号与第一个点相同时两条直线是否连通 bool CGameLogic::LineY(int anMap[][18],vertex v1,vertex v2,vertex path[4]) { vertex temp; temp.col=v2.col; temp.row=v1.row; temp.num=anMap[temp.row+1][temp.col+1]; if(temp.num==BLANK) { if(LinkInRow(anMap,v1,temp,path)&&LinkInCol(anMap,v2,temp,path)) { path[0]=v1; path[1]=temp; path[2]=v2; return true; } } return false; } //当列号与第一个点相同时两条直线是否连通 bool CGameLogic::LineX(int anMap[][18],vertex v1,vertex v2,vertex path[4]) { vertex temp; temp.col=v1.col; temp.row=v2.row; temp.num=anMap[temp.row+1][temp.col+1]; if(temp.num==BLANK) { if(LinkInRow(anMap,v2,temp,path)&&LinkInCol(anMap,v1,temp,path)) { path[0]=v1; path[1]=temp; path[2]=v2; return true; } } return false; } //判断是否两条线连通 bool CGameLogic::OneCornerLink(int anMap[][18],vertex v1,vertex v2,vertex path[4]) { if(LineY(anMap,v1,v2,path)) { return true; } if(LineX(anMap,v1,v2,path)) { return true; } return false; } //两拐点列号相同连通 bool CGameLogic::CornerX(int anMap[][18],vertex v1,vertex v2,int nCol,vertex path[4]) { vertex temp1,temp2; temp1.col=nCol; temp1.row=v1.row; temp1.num=anMap[temp1.row+1][temp1.col+1]; temp2.col=nCol; temp2.row=v2.row; temp2.num=anMap[temp2.row+1][temp2.col+1]; if(temp1.num==BLANK&&temp2.num==BLANK) { if(LinkInRow(anMap,v1,temp1,path)&&LinkInCol(anMap,temp1,temp2,path)&&LinkInRow(anMap,temp2,v2,path)) { path[0]=v1; path[1]=temp1; path[2]=temp2; path[3]=v2; return true; } } return false; } //两拐点行号相同连通 bool CGameLogic::CornerY(int anMap[][18],vertex v1,vertex v2,int nRow,vertex path[4]) { vertex temp1,temp2; temp1.col=v1.col; temp1.row=nRow; temp1.num=anMap[temp1.row+1][temp1.col+1]; temp2.col=v2.col; temp2.row=nRow; temp2.num=anMap[temp2.row+1][temp2.col+1]; if(temp1.num==BLANK&&temp2.num==BLANK) { if(LinkInCol(anMap,v1,temp1,path)&&LinkInRow(anMap,temp1,temp2,path)&&LinkInCol(anMap,temp2,v2,path)) { path[0]=v1; path[1]=temp1; path[2]=temp2; path[3]=v2; return true; } } return false; } //判断是否三条线连通 bool CGameLogic::TwoConersLink(int anMap[][18],vertex v1, vertex v2,vertex path[4]) { for(int i=0;i<18;i++) {//两拐点列号相同的情况 if(CornerX(anMap,v1,v2,i-1,path)) { return true; } } for(int i=0;i<12;i++) {//两拐点行号相同的情况 if(CornerY(anMap,v1,v2,i-1,path)) { return true; } } return false; } //重排 void CGameLogic::ResetMap(int anMap[][18]) { int r1,c1,r2,c2; srand((unsigned)time(NULL)); //交换一百次 for(int i=0;i<100;i++) { //随机取两点 r1=rand()%10; c1=rand()%16; //如果改点为空则重新选择 while(anMap[r1+1][c1+1]==BLANK) { r1=rand()%10; c1=rand()%16; } r2=rand()%10; c2=rand()%16; while(anMap[r2+1][c2+1]==BLANK) { r2=rand()%10; c2=rand()%16; } int temp; //交换两点元素值 temp=anMap[r1+1][c1+1]; anMap[r1+1][c1+1]=anMap[r2+1][c2+1]; anMap[r2+1][c2+1]=temp; } } //判断地图是否为空 bool CGameLogic::IsBlank(int anMap[][18]) { for(int i=1;i<11;i++) { for(int j=1;j<17;j++) { if(anMap[i][j]!=BLANK) { return false; } } } return true; } GameControl.cpp文件中 // 开始游戏 void CGameControl::StartGame(int n) { CGameLogic gameLogic; gameLogic.InitMap(n,m_anMap); } // 获取元素编号 int CGameControl::GetElem(int nRow, int nCol) { return m_anMap[nRow][nCol]; } // 设置第一个点的坐标 void CGameControl::SetFirstPoint(int nRow, int nCol) { m_ptSelFirst.col=nCol; m_ptSelFirst.row=nRow; m_ptSelFirst.num=m_anMap[nRow+1][nCol+1]; } // 设置第二个点坐标 void CGameControl::SetSecondPoint(int nRow, int nCol) { m_ptSelSecond.col=nCol; m_ptSelSecond.row=nRow; m_ptSelSecond.num=m_anMap[nRow+1][nCol+1]; } bool CGameControl::Link(void) { CGameLogic gameLogic; InitPath(); if(gameLogic.IsLink(m_anMap,m_ptSelFirst,m_ptSelSecond,m_path)) { return true; } return false; } void CGameControl::Clear(void) { CGameLogic gameLogic; gameLogic.Clear(m_anMap,m_ptSelFirst,m_ptSelSecond); } vertex CGameControl::GetFirstPoint(void) { return m_ptSelFirst; } vertex CGameControl::GetSecondPoint(void) { return m_ptSelSecond; } //初始化路径 void CGameControl::InitPath() { for(int i=0;i<4;i++) { m_path[i].col=-2; m_path[i].num=-2; m_path[i].row=-2; } } //获取路径 vertex* CGameControl::GetPath() { return m_path; } bool CGameControl::Tip(vertex &v1,vertex &v2) { CGameLogic gameLogic; for(int i=1;i<11;i++) { for(int j=1;j<17;j++) { if(m_anMap[i][j]!=-1) { v1.row=i-1; v1.col=j-1; v1.num=m_anMap[i][j]; //从该行开始逐行遍历是否有连通的点 for(int m=i;m<11;m++) { for(int n=1;n<17;n++) { if(m==i&&n==j) {} else { v2.row=m-1; v2.col=n-1; v2.num=m_anMap[m][n]; if(m_anMap[i][j]==m_anMap[m][n]&&gameLogic.IsLink(m_anMap,v1,v2,m_path)) { return true; } } } } } } } return false; } //重排 void CGameControl::ResetMap() { CGameLogic gameLogic; gameLogic.ResetMap(m_anMap); } int CGameControl::IsWin(int nTime) { CGameLogic gameLogic; if (nTime<=0) { if(gameLogic.IsBlank(m_anMap)) { return 1;//时间用完图片消完,游戏胜利 } else return -1;//时间用完图片未消完,游戏失败 } else { if(gameLogic.IsBlank(m_anMap)) { return 1;//时间未用完,图片消完,游戏胜利 } else return 0;//时间未用完,图片未消完,游戏继续 } } 二、 调试说明(调试手段、过程及结果分析) 当出现错误时,设置断点调试程序,看每个变量的值的变化,或者在一些位置加上提示框语句,来判断函数是否调用成功。 三、 软件测试(测试效果.界面、综合分析和结论) 1.测试效果.界面 主界面 游戏界面 2.综合分析和结论 经过测试,消子的三种情况都已实现,提示、重排功能也已实现,基础模式以及关卡模式和休闲模式也均已实现,欢乐连连看的基本功能,通过线性结构基本实现。 本系统的核心在于消子算法,把消子算法和MFC成功结合起来,系统就已经完成了大半。 除了线性结构,连连看还可以通过图来实现,并且已完成非线性结构的连连看,在本次实验报告中暂未写出。 第三部分:实验小结、收获与体会 本次实验的难点为觉得在于如何把MFC和算法结合起来,线性结构的连连看的算法实际上比较简单,基本都是枚举法,但是因为MFC是第一次接触,所以觉得有点难。 在本次实验中发现一个问题,如果把10*16的游戏地图之间定义成一个anMap[10][16]的二维数组,因为连通路径所有的拐点都是在这个二维数组里,这样会导致在最外边的元素,相同花色但不相邻的元素不能消除,所以应该定义一个int型二维数组m_anMap[12][18]来存储10*16的游戏地图,二维数组大小为12*18,多了个外框是为了方便最外层相同元素相消,下标为0和12的行值为-1(表示没有图片),下标为0和18的列值为-1。 本次实验,加深了我对线性结构一些操作的掌握,学到了很多。

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 10 金币 [ 分享文档获得金币 ] 1 人已下载

下载文档