1学生学号0121510870631实验课成绩学生实验报告书实验课程名称数据结构与算法综合实验开课学院计算机科学与技术学院指导教师姓名伍新华学生姓名蒋正琪学生专业班级物联网15022016--2017学年第2学期2实验课程名称:数据结构与算法综合实验实验项目名称连连看游戏综合实践报告成绩实验者蒋正琪专业班级物联网1502组别同组者完成日期年月日第一部分:实验分析与设计(可加页)一、实验目的和要求1.目的(1)了解MFC框架,包括MFCDialog应用程序和GDI编程。(2)了解线性结构,掌握数组和栈操作,掌握数组的遍历、消子和胜负判断等算法。2.要求开发程序使用二维数组来保存游戏地图的数据,实现连连看的核心功能。欢乐连连看的功能有:主界面、开始游戏、消子、判断胜负、提示、重排、计时、游戏模式。二、分析与设计1.数据结构的设计1)顶点存储添加global.h文件,定义结构体tagVertex,用于保存游戏地图中一个点的行号、列号、值信息。typedefstructtagVertex{introw;//行intcol;//列intinfo;//信息类}Vertex;2)游戏地图存储结构使用二位数组来保存连连看游戏地图,在给每一种图片一个编号,并将这些编号保存在二位数组中。用户在屏幕上选择两张图片,对应为数组中的两组坐标。分别实现三个消子判断算法:一条直线连通、两条直线连通、三条直线连通,并使用者三个算法进项消子判断。若符合消子规则,就在屏幕上消除一对图片,并把数组对应元素清空。列对应的元素编号。2.核心算法设计(1)随机开局算法1)计算游戏中元素个数:行数*列数。2)计算每种花色重复数:行数*列数/花色数。①判断(行数*列数%花色数)是否为0。如果不为0,则进行异常处理。3②判断每一种花色的重复数能否被2整除,如果不能被二整除,则进行异常处理。3)按从左到右,从上到下,将花色数填入游戏地图。实现代码如下:intnRepeatNum=nRows*nCols/nPicNums;intcount=0;for(inti=0;inPicNums;i++){for(intj=0;jnRepeatNum;j++){m_Map[count/nCols][count%nCols]=i;count++;}}4)由于生成的地图是规则的,因此,需要将地图中的花色打乱。实现思路是:随机选择两个元素,将其值对调,重复若干次。(2)消子判断的流程1)一条直线消子算法①判断两个顶点,行是否相同,若相同,则判断两个顶点在X方向是否连通。在CGameLogic类定义RowLink()函数事项X方向的连通判断。依次判断在X方向两个顶点间每一个顶点,是否都为空,全为空表示可以连通,否则不能连通。实现代码如下:boolCGameLogic::RowLink(intm_Map[10][15],Vertexv1,Vertexv2){introw=v1.row;intcol1=v1.col;intcol2=v2.col;if(col1col2){inttemp=col1;col1=col2;col2=temp;}for(inti=col1+1;i=col2;i++){if(i==col2){returntrue;}if(m_Map[row][i]!=BLANK){break;}}returnfalse;4②判断两个顶点,列是否相同,若相同,则判断两个顶点在Y方向是否连通。在CGameLogic类定义ColLink()函数事项Y方向的连通判断。依次判断在Y方向两个顶点间每一个顶点,是否都为空,全为空表示可以连通,否则不能连通。实现代码如下:boolCGameLogic::ColLink(intm_Map[10][15],Vertexv1,Vertexv2){introw1=v1.row;introw2=v2.row;intcol=v1.col;if(row1row2){inttemp=row1;row1=row2;row2=temp;}for(inti=row1+1;i=row2;i++){if(i==row2){returntrue;}if(m_Map[i][col]!=BLANK){break;}}returnfalse;}2)两条直线消子算法若一条直线无法连通,则判断两条直线的情况。在CGameLogic类中定义OneCornerLink()函数判断两点是否能两条直线连通。先判断两个顶点的X和Y方向的直线相交的两个顶点,是否为空。若能构成两条指向连通,那么相交的顶点必须为空才行。若顶点有一个为空,则判断该顶点与两个顶点,横向与纵向一条直线是否连通,若都连通,则表示两条直线消子成功,否则不能相消。实现代码如下:boolCGameLogic::OneCornerLink(intm_Map[10][15],Vertexv1,Vertexv2){introw1=v1.row;intcol1=v1.col;introw2=v2.row;intcol2=v2.col;if(m_Map[row1][col2]==BLANK){if(LineY(m_Map,row1,row2,col2)&&LineX(m_Map,row1,col1,col2))5{VertexV={row1,col2,BLANK};AddVertex(V);returntrue;}}if(m_Map[row2][col1]==BLANK){if(LineY(m_Map,row1,row2,col1)&&LineX(m_Map,row2,col1,col2)){VertexV={row2,col1,BLANK};AddVertex(V);returntrue;}}returnfalse;}3)三条直线消子算法实现代码如下:boolCGameLogic::TwoCornerLink(intm_Map[10][16],Vertexv1,Vertexv2){introw1=v1.row;intcol1=v1.col;introw2=v2.row;intcol2=v2.col;for(intcol=0;col16;col++){if(m_Map[row1][col]==BLANK&&m_Map[row2][col]==BLANK){if(LineY(m_Map,row1,row2,col)){if(LineX(m_Map,row1,col1,col)&&LineX(m_Map,row2,col2,col)){VertexV1={row1,col,BLANK};VertexV2={row2,col,BLANK};AddVertex(V1);AddVertex(V2);returntrue;}}}}for(introw=0;row10;row++){if(m_Map[row][col1]==BLANK&&m_Map[row][col2]==BLANK){6if(LineX(m_Map,row,col1,col2)){if(LineY(m_Map,row,row1,col1)&&LineY(m_Map,row,row2,col2)){VertexV1={row,col1,BLANK};VertexV2={row,col2,BLANK};AddVertex(V1);AddVertex(V2);returntrue;}}}}returnfalse;}4)胜负判断算法当所有元素被消掉,进行胜负判断,遍历地图中所有元素的值,当所有元素都为空时,表示获胜,游戏结束,否则继续游戏。实现代码如下:if(m_GameProgress.GetPos()=0&&!cgc.IsBlank(cgc.m_Map)){KillTimer(PLAY_TIMER_ID);intresult=MessageBox(_T(你输啦),_T(提示));if(result=IDOK){GetDlgItem(IDC_BUTTON_START)-EnableWindow(TRUE);}else{exit(0);}IsPlaying=false;}elseif(m_GameProgress.GetPos()0&&cgc.IsBlank(cgc.m_Map)){KillTimer(PLAY_TIMER_ID);intresult;result=MessageBox(_T(好吧你赢啦~),_T(提示));if(result=IDOK){GetDlgItem(IDC_BUTTON_START)-EnableWindow(TRUE);}else{exit(0);}}5)重排当进行游戏的过程中会出现无法再进行消子的情况,点击重排按钮就可以将剩下7子进行随机重排以便客户能够正常进行消子操作。首先在CGameLogic类中定义一个DisOrderMap()函数来对剩下的元素进行重排,实现代码如下:voidCGameLogic::DisOrderMap(intm_Map[10][16]){intnRows=10;intnCols=16;srand((int)time(NULL));intnVertexNum=nRows*nCols;for(inti=0;inVertexNum;i++){//随机获得两个坐标intnIndex1=rand()%nVertexNum;intnIndex2=rand()%nVertexNum;intnTemp=m_Map[nIndex1/nCols][nIndex1%nCols];m_Map[nIndex1/nCols][nIndex1%nCols]=m_Map[nIndex2/nCols][nIndex2%nCols];m_Map[nIndex2/nCols][nIndex2%nCols]=nTemp;}}6)帮助在原有的基础上重新插入一个对话框,重新定义一个CHelpDialog类,在这个类中将写有相关游戏说明的图片加载进界面中去,加上滚动条。实现代码如下:BOOLCHelpDialog::OnInitDialog(){CDialogEx::OnInitDialog();ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX0xF000);HICONm_hIcon;m_hIcon=AfxGetApp()-LoadIcon(IDR_MAINFRAME);//IDR_ICON为图标资源名SetIcon(m_hIcon,TRUE);//SetbigiconSetIcon(m_hIcon,FALSE);//Setsmallicon//加载图片资源HANDLEbmp=::LoadImage(NULL,_T(theme\\picture\\Help1.bmp),IMAGE_BITMAP,0,0,LR_LOADFROMFILE);//获得当前对话框的视频内存CClientDCdc(this);//创建与视频内存兼容的内存DCm_dcHelp.CreateCompatibleDC(&dc);//将位图资源选入DCm_dcHelp.SelectObject(bmp);//初始化内存DCm_dcMen.CreateCompatibleDC(&dc);8CBitmapbmpMem;bmpMem.CreateCompatibleBitmap(&dc,500,400);m_dcMen.SelectObject(&bmpMem);//绘制背景到内存中m_dcMen.BitBlt(0,0,800,600,&m_dcHelp,0,0,SRCCOPY);//绘制帮助信息显示区域this-GetDlgItem(IDC_BUTTON_HELP)-GetWindowRect(&m_rtHelp);this-ScreenToClient(&m_rtHelp);//绘制帮助信息UpdateHelp(0);//表示滚动条的初始位置为0//设置滚动条范围CBitmapbmpHelp;bmpH