jewelry-
学生学号
1
实验课成绩
学生实验报告书
实验课程名称
开课学院
指导教师姓名
学生姓名
学生专业班级
数据结构与算法综合实验
计算机科学与技术学院
伍新华
蒋正琪
物联网
1502
2016
--
2017
学年
第
2
学期
1
实验课程名称:
数据结构与算法综合实验
实验项目名称
实验者
同组者
蒋正琪
连连看游戏综合实践
专业班级
物联网
1502
报告成绩
组别
完成日期
年
月
日
第一部分:实验分析与设计
(可加页)
一、实验目的和要求
1.
目的
(
1
)了解
MFC
框架,包括
MFC Dialog
应用程序和
GDI
编程。
(
2
)< br>了解线性结构,
掌握数组和栈操作,
掌握数组的遍历、
消子和胜负判断等算法。
2
.
要求
开发程序使用二维数组来保存游戏地图的数据 ,实现连连看的核心功能。欢乐连连
看的功能有:主界面、开始游戏、消子、判断胜负、提示、重排、计 时、游戏模式。
二、分析与设计
1.
数据结构的设计
1)
顶点存储
添加
global.h< br>文件,
定义结构体
tagVertex,
用于保存游戏地图中一个点的行号、< br>列号、值信息。
typedefstructtagVertex
{
int row;//
行
int col;//
列
int info;//
信息类
}Vertex;
2)
游戏地图存储结构
使用二位数组来保存连连看游戏地图,在给每一种图片一个编号, 并将这些编号保
存在二位数组中。
用户在屏幕上选择两张图片,对应为 数组中的两组坐标。分别实现三个消子判断
算法:一条直线连通、两条直线连通、三条直线连通,并使用 者三个算法进项消子
判断。若符合消子规则,就在屏幕上消除一对图片,并把数组对应元素清空。列对< br>应的元素编号。
2.
核心算法设计
(1)
随机开局算法
1)
计算游戏中元素个数:行数
*
列数。
2)
计算每种花色重复数:行数
*
列数
/
花色数。
①
判断(行数
*
列数
%
花色数)是否为
0
。如果不为
0
,则进行异常处理。
②
判断每一种花色的重复数能否被
2
整除,如果不能被二整除,则进行异常
2
处理。
3)
按从左到右,从上到下,将花色数填入游戏地图。
实现代码如下:
intnRepeatNum = nRows * nCols / nPicNums;
int count = 0;
for (inti = 0; i
{
for (int j = 0; j
{
m_Map[count / nCols][count%nCols] = i;
count++;
}
}
4)
由于生成的地图是规则的,因此,需要将地图中的花色打乱。实现思路是:随机
选择两个元素,将其值对 调,重复若干次。
(2)
消子判断的流程
1)
一条直线消子算法
①
判断两个顶点,行是否相同,若相同,则判断两个顶点在
X
方向是否连通。
在
CGameLogic
类定义
RowLink
()< br>函数事项
X
方向的连通判断。
依次判断在
X
方向
两个 顶点间每一个顶点,是否都为空,全为空表示可以连通,否则不能连通。
实现代码如下:
boolCGameLogic::RowLink(intm_M ap[10][15],Vertex v1,Vertex v2)
{
int row=;
int col1=;
int col2=;
if(col1>col2)
{
int temp=col1;
col1=col2;
col2=temp;
}
for(inti=col1+1;i<=col2;i++)
{
if(i==col2)
{
return true;
}
if(m_Map[row][i]!=BLANK)
{
break;
}
}
return false;
②
判断两个顶点,列是否相同,若相同,则判断两个顶点在
Y
方向是否连通。
3
在
CGameLogic
类定义
ColLink
()函数事项
Y
方向的连通判断。依次判断在
Y
方 向
两个顶点间每一个顶点,是否都为空,全为空表示可以连通,否则不能连通。
实现代码如下:
boolCGameLogic::ColLink(intm_M ap[10][15],Vertex v1,Vertex v2)
{
int row1=;
int row2=;
int col=;
if(row1>row2)
{
int temp=row1;
row1=row2;
row2=temp;
}
for(inti=row1+1;i<=row2;i++)
{
if(i==row2)
{
return true;
}
if(m_Map[i][col]!=BLANK)
{
break;
}
}
return false;
}
2)
两条直线消子算法
若一条直线无法连通,则判断两条直线的情况。在
CGameLogic
类中定义
O neCornerLink
()
函数判断两点是否能两条直线连通。
先判断两个顶点的
X
和
Y
方向的直线相交的两个顶点,
是否 为空。
若能构成两条
指向连通,那么相交的顶点必须为空才行。
若顶点有一个为空,则判断该顶点与两个顶点,横向与纵向一条直线是否连通,
若都连通,则表示两 条直线消子成功,否则不能相消。
实现代码如下:
boolCGameL ogic::OneCornerLink(intm_Map[10][15],Vertex v1,Vertex v2)
{
int row1=;
int col1=;
int row2=;
int col2=;
if(m_Map[row1][col2]==BLANK)
{
if(LineY(m_Map,row1,row2,col2)&&Lin eX(m_Map,row1,col1,col2))
{
4
Vertex V={row1,col2,BLANK};
AddVertex(V);
return true;
}
}
if(m_Map[row2][col1]==BLANK)
{
< br>if(LineY(m_Map,row1,row2,col1)&&LineX(m_Map,row 2,col1,col2))
{
Vertex V={row2,col1,BLANK};
AddVertex(V);
return true;
}
}
return false;}
3)
三条直线消子算法
实现代码如下:
boolCGameLogic::TwoCornerLink( intm_Map[10][16],Vertex v1,Vertex v2)
{
int row1=;
int col1=;
int row2=;
int col2=;
for(int col=0;col<16;col++)
{
if(m_Map[r ow1][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[r ow][col1]==BLANK&&m_Map[row][col2]==BLANK)
{
if(LineX(m_Map,row,col1,col2))
5
{
if(L ineY(m_Map,row,row1,col1)&&LineY(m_Map,row,row2,co l2))
{
Vertex V1={row,col1,BLANK};
Vertex V2={row,col2,BLANK};
AddVertex(V1);
AddVertex(V2);
return true;
}
}
}
}
return false;
}
4)
胜负判断算法
当所有元素被消掉,进行胜 负判断,遍历地图中所有元素的值,当所有元素都为
空时,表示获胜,游戏结束,否则继续游戏。
实现代码如下:
if (m_() <= 0 && !k(cgc.m_Map)) {
KillTimer(PLAY_TIMER_ID);
int result = MessageBox(_T(
你输啦
提示
if (result = IDOK) {
GetDlgItem(IDC_BUTTON_START)->EnableWindo w(TRUE);
}
else {
exit(0);
}
IsPlaying = false;
}
else if (m_() > 0 &&k(cgc.m_Map))
{
KillTimer(PLAY_TIMER_ID);
int result;
result = MessageBox(_T(
好吧你赢啦
~
提示
if (result = IDOK) {
GetDlgItem(IDC_BUTTON_START)->EnableWindow(TRU E);
}
else {
exit(0);
}
}
5
)重排
当进行游戏的过程中会出现无法再进行消子的情况,
点击重排按钮就可以将剩下
子进行随机重排 以便客户能够正常进行消子操作。
首先在
CGameLogic
类中定义一个
6
DisOrderMap
()函数来对剩下的元素进行重排,实现代码如下:
void CGameLogic::DisOrderMap(intm_Map[10][16])
{
intnRows = 10;
intnCols = 16;
srand((int)time(NULL));
intnVertexNum = nRows * nCols;
for (inti = 0; i
{
//
随机获得两个坐标
int nIndex1 = rand() % nVertexNum;
int nIndex2 = 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
类,
在这个类
中将写有相关游戏说明的图片加载进界面中去,加上滚动条。
实现代码如下:
BOOL CHelpDialog::OnInitDialog()
{
CDialogEx::OnInitDialog();
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
HICON m_hIcon;
m_hIcon
=
AfxGetApp()->LoadIcon(IDR_MAINFRAME);//I DR_ICON
为图标资源名
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
//
加载图片资源
HANDLE bmp = ::LoadImage(NULL, _T(
IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
//
获得当前对话框的视频内存
CClientDC dc(this);
//
创建与视频内存兼容的内存
DC
m_CompatibleDC(&dc);
//
将位图资源选入
DC
m_Object(bmp);
//
初始化内存
DC
m_CompatibleDC(&dc);
CBitmapbmpMem;
7
jewelry-
jewelry-
jewelry-
jewelry-
jewelry-
jewelry-
jewelry-
jewelry-
本文更新与2021-01-22 03:52,由作者提供,不代表本网站立场,转载请注明出处:https://www.bjmy2z.cn/gaokao/547957.html
-
上一篇:英文陆空对话范例--飞行员必备
下一篇:陆空对话范例