当前位置:文档之家› 武汉理工大学数据结构与算法综合实验连连看

武汉理工大学数据结构与算法综合实验连连看

武汉理工大学数据结构与算法综合实验连连看学生学号Xxx实验课成绩学生实验报告书实验课程名称数据结构与算法综合实验开课学院计算机科学与技术学院指导教师姓名xx学生姓名xx学生专业班级xxxx2015-- 2016学年第 2 学期实验课程名称:数据结构与算法综合实验int count = 0;for (int i = 0; i<nPicNums; i++){for (int j = 0; j <nRepeatNum; j++){m_Map[count / nCols][count%nCols] = i;count++;}}4)由于生成的地图是规则的,因此,需要将地图中的花色打乱。

实现思路是:随机选择两个元素,将其值对调,重复若干次。

●消子判断的流程1)获得选中的两张图片的行号和列号。

2)判断选中的图片是否同色,不同色,则不能相消。

判断选中的图片是否为同一个图片,如果为不为同一个图片,则不能相消。

3)判断连通性,如以下三种情况均不满足,则结束。

①首先判断能否一条直线连通。

②如果不能一条直线连通,则判断能否两条直线连通。

③如果不能两条直线连通,则判断能否三条直线连通。

4)获得连通路径,绘制连线。

5)消除图片●一条直线消子算法①判断两个顶点,行是否相同,若相同,则判断两个顶点在X方向是否连通。

在CGameLogic类定义RowLink()函数事项X方向的连通判断。

依次判断在X方向两个顶点间每一个顶点,是否都为空,全为空表示可以连通,否则不能连通。

实现代码如下:bool CGameLogic::RowLink(int m_Map[10][15],Vertex v1,Vertex v2){//将两个点的列进行调整,使nCol1的值小于nCol2的值int row=v1.row;int col1=v1.col;int col2=v2.col;if(col1>col2){int temp=col1;col1=col2;col2=temp;}//判断两个顶点间是否有不为空的图片for(int i=col1+1;i<=col2;i++){if(i==col2){return true;}if(m_Map[row][i]!=BLANK){break;}}return false;②判断两个顶点,列是否相同,若相同,则判断两个顶点在Y方向是否连通。

在CGameLogic类定义ColLink()函数事项Y方向的连通判断。

依次判断在Y方向两个顶点间每一个顶点,是否都为空,全为空表示可以连通,否则不能连通。

实现代码如下:bool CGameLogic::ColLink(int m_Map[10][15],Vertex v1,Vertex v2){int row1=v1.row;int row2=v2.row;int col=v1.col;if(row1>row2){int temp=row1;row1=row2;row2=temp;}for(int i=row1+1;i<=row2;i++){if(i==row2){return true;}if(m_Map[i][col]!=BLANK){break;}}return false;}两条直线消子算法若一条直线无法连通,则判断两条直线的情况。

在CGameLogic类中定义OneCornerLink()函数判断两点是否能两条直线连通。

先判断两个顶点的X和Y方向的直线相交的两个顶点,是否为空。

若能构成两条指向连通,那么相交的顶点必须为空才行。

若顶点有一个为空,则判断该顶点与两个顶点,横向与纵向一条直线是否连通,若都连通,则表示两条直线消子成功,否则不能相消。

实现代码如下:bool CGameLogic::OneCornerLink(int m_Map[10][15],Vertex v1,Vertex v2) {int row1=v1.row;int col1=v1.col;int row2=v2.row;int col2=v2.col;//判断相交的顶点是否为空if(m_Map[row1][col2]==BLANK){//判断两个同行的顶点是否一条直线连通if(LineY(m_Map,row1,row2,col2)&&LineX(m_Map,row1,col1,col2)){Vertex V={row1,col2,BLANK};AddVertex(V);return true;}}if(m_Map[row2][col1]==BLANK){//判断两个同列顶点是否一条直线连通if(LineY(m_Map,row1,row2,col1)&&LineX(m_Map,row2,col1,col2)){Vertex V={row2,col1,BLANK};AddVertex(V);return true;}}return false;}三条直线消子算法若两条直线无法连通,则判断三条直线的情况。

在CGameLogic类中定义TwoCornerLink()函数判断两点能否三条直线连通。

三条直线消子时,假设选择的两张图片的位置为(nRow1,nCol1)和(nRow2,nCol2),则先寻找与Y轴平行的连通线段。

如果Y轴没有找到可以连通的三条直线,则寻找以X轴平行的连通线段。

1)搜索关键路径假设玩家选择的两个顶点为V0(row0,col0),V3(row3,col3),步骤如下:第一步:从地图的第一行开始扫描,当前扫描到nRow行。

第二步:设置拐点:V1(nRow,col0),V2(nRow,col3)。

第三步:判断V1和V2是否水平方向向上连通,如果连通,则V1到V2的连线即为关键路径。

如果不连通则接着扫描下一行,重复第二~四步。

2)判断三条直线连通采用枚举法判断三条直线连通,假设玩家选择两个顶点为V0和V3,判断三条直线连通的具体实现的具体步骤如下:①找到其中一条关键路径V1,V2。

②判断V1和V0是否连通。

③判断V2和V3是否连通。

④如果同时满足V1和V0连通,V2和V3连通,则V0和V3满足三条直线连通。

否则,在此关键路径下V0和V3不连通,找到下一条关键路径,重复2~4,直到判断出V0和V3是否连通。

3)保存连通路径使用栈来保存连通路径中的关键点:起始点V0,拐点V1,拐点V2和终点V3。

保存连通路径的步骤如下:①保存其实点V0。

②判断是否存在能够满足三条直线消子的关键路径V1、V2。

③如果存在,保存顶点V1、V2、V3,如果不存在,在删除起始点V0。

实现代码如下:bool CGameLogic::TwoCornerLink(int m_Map[10][16],Vertex v1,Vertex v2) {int row1=v1.row;int col1=v1.col;int row2=v2.row;int col2=v2.col;for(int col=0;col<16;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)){Vertex V1={row1,col,BLANK};Vertex V2={row2,col,BLANK};AddVertex(V1);AddVertex(V2);return true;}}}}for(int row=0;row<10;row++){if(m_Map[row][col1]==BLANK&&m_Map[row][col2]==BLANK){if(LineX(m_Map,row,col1,col2)){if(LineY(m_Map,row,row1,col1)&&LineY(m_Map,row,row2,col2)){Vertex V1={row,col1,BLANK};Vertex V2={row,col2,BLANK};AddVertex(V1);AddVertex(V2);return true;}}}}return false;}4)胜负判断算法当所有元素被消掉,进行胜负判断,遍历地图中所有元素的值,当所有元素都为空时,表示获胜,游戏结束,否则继续游戏。

实现代码如下:if (m_GameProgress.GetPos() <= 0 && !cgc.IsBlank(cgc.m_Map)) { KillTimer(PLAY_TIMER_ID);int result = MessageBox(_T("很遗憾,时间到了!,是否重新开始游戏?"), _T("提示"));if (result = IDOK) {GetDlgItem(IDC_BUTTON_START)->EnableWindow(TRUE);}else {exit(0);}IsPlaying = false;}else if (m_GameProgress.GetPos() > 0 && cgc.IsBlank(cgc.m_Map)){KillTimer(PLAY_TIMER_ID);int result;result = MessageBox(_T("获胜!是否重新开始游戏?"), _T("提示"));if (result = IDOK) {GetDlgItem(IDC_BUTTON_START)->EnableWindow(TRUE);}else {exit(0);}}5)重排当进行游戏的过程中会出现无法再进行消子的情况,点击重排按钮就可以将剩下子进行随机重排以便客户能够正常进行消子操作。

首先在CGameLogic类中定义一个DisOrderMap()函数来对剩下的元素进行重排,实现代码如下:void CGameLogic::DisOrderMap(int m_Map[10][16]){int nRows = 10;int nCols = 16;srand((int)time(NULL));int nVertexNum = nRows * nCols;for (int i = 0; i<nVertexNum; i++){//随机获得两个坐标int nIndex1 = rand() % nVertexNum;int nIndex2 = rand() % nVertexNum;int nTemp = 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;}}然后在CGameControl类中定义一个DisOrder()函数来调用DisOrderMap()函数,最后再CGameDlg类的OnBnClickedButtonReset()函数中调用DisOrder()函数,实现代码如下:void CGameDlg::OnBnClickedButtonReset(){// TODO: 在此添加控件通知处理程序代码m_dcMem.BitBlt(0, 0, 800, 600, &m_dcBG, 0, 0, SRCCOPY);InvalidateRect(FALSE);m_gameControl.DisOrder();UpDateMap();}6)帮助在原有的基础上重新插入一个对话框,重新定义一个CHelpDialog类,在这个类中将写有相关游戏说明的图片加载进界面中去,加上滚动条。

相关主题