大连大学嵌入式期末大作业.docx
- 文档编号:4420937
- 上传时间:2022-12-01
- 格式:DOCX
- 页数:18
- 大小:835.58KB
大连大学嵌入式期末大作业.docx
《大连大学嵌入式期末大作业.docx》由会员分享,可在线阅读,更多相关《大连大学嵌入式期末大作业.docx(18页珍藏版)》请在冰豆网上搜索。
大连大学嵌入式期末大作业
《嵌入式高级编程》
————连连看游戏程序
姓名:
专业班级:
计科111
学号:
任课教师:
王明军
日期:
2014年6月20号
目录
一、系统分析与总体设计2
1、选题的意义2
2、需求分析3
3、总体设计3
二、系统的详细设计7
1、图案方块的连接判断7
三、系统实现与调试10
1、鼠标交互功能的实现10
2、绘图功能的实现11
2.1绘图方案的设计11
2.2绘图资源的载入与初始化12
2.3游戏区域的绘制13
四、系统运行的结果14
总结16
一、系统分析与总体设计
1、选题的意义
连连看来源于街机游戏《四川麻将》和《中国龙》,是给一堆图案中的相同图案进行配对的简单游戏,在2003年,一个叫做朱俊的网友将这种形式搬到了PC上,立刻成为办公一族的新宠,并迅速传遍了世界各地。
饱受工作压力的人们没有太多的时间进行复杂的游戏,而对于这种动动鼠标就能过关的游戏情有独钟。
之后村子的连连看风靡版,阿达的连连看奥运版,连连看反恐版,还有敏敏连连看,水晶连连看等遍地开花,造就了一个连连看的新世界。
连连看游戏有多种地图样式和道具系统、大大加强了游戏的可玩性,是一款老少皆宜的休闲佳品。
网络小游戏制作的目的是满足了人们休闲的需要,在紧张工作之余休闲类的小游戏能够给人带来最大程度的放松,也可以增进人们之间的交流,沟通,通过游戏还可以认识更多的朋友,也可以到达跨省、跨市,甚至跨国间人们互相娱乐的目的。
2、需求分析
关于连连看的功能描述如下:
运行游戏并进行初始化工作,将整个游戏区域分成纵向和横向扩展的若干个小方块,并且这些小方块是由多种动物图案成对地分布于游戏区域的不同位置。
玩家可以通过选取相同的两个物件来对它们进行消除的操作,直到将游戏区域中的所有方块对都被消除后为胜利
图1.1运行的初始效果
3、总体设计
3.1系统的开发环境
Intel®Pentium®42.0GHz,512M内存,500G硬盘
lMicrosoft®Windows™2000Professional
lWCE
3.2系统总体功能,系统的结构,模块图、每个功能的详细说明
3.2.1类设计
这个游戏的主要类是游戏模式类,类名为PocketLianDlg。
这个类主要对包括图案方块的销毁判断,游戏胜利判断以及整个游戏用户交换功能的实现。
它uml图如下
CLinkToLinkDlg
m_mem3DBkDC:
CDC
m_mem3DBkBmp:
CBitmap
m_memAnimalDC:
CDC
m_memAnimalBmp:
CBitmap
m_MemDC:
CDC
m_memBitmap:
CBitmap
m_map:
int
m_nRow:
int
m_nCol:
int
m_nX1:
int
m_nY1:
int
GameDraw(CDC*pDC):
void
StartNewGame():
void
IsLink(intx1,inty1,intx2,inty2):
BOOL
IsWin(void):
BOOL
X1_Link_X2(intx,inty1,inty2):
BOOL
Y1_Link_Y2(intx1,intx2,inty):
BOOL
OneCornerLink(intx1,inty1,intx2,inty2):
BOOL
TwoCornerLink(intx1,inty1,intx2,inty2):
BOOL
YThrough(intx,inty,BOOLbAdd):
BOOL
XThrough(intx,inty,BOOLbAdd):
BOOL
LineX(intx,inty1,inty2):
BOOL
LineY(intx1,intx2,inty):
BOOL
这些成员函数和成员变量的算法分析与设计以及核心算法中有详细介绍
3.2.2游戏地图设计
对于整个游戏区域,可以把它看作一个是由若干个小方块构成的地图,而且每一个小方块放置着不同的动物图案,可将其称之为图案小方块。
这些图案小方块零散地分布在地图的不同位置区域,并且每一个图案小方块都有与其对应的完全一样的另外一个小方块,如图1.4所示。
如图1.2所示,整个游戏游戏区域被抽象成一个有坐标位置属性的平面,平面上零散地分布着若干个小方块,并且这些小方块的物种起码是成对出现的。
经过前面的描述和分析后,可以把游戏区域地图用一个数组m_map来表示。
m_map是把地图设计成一个动态分配的int整形一维数组,对地图中的行列数的表达,用一个转换法则即可。
可以在LinkToLinkDlg类对象定义中添加地图核心数据的成员变量,具体如下:
//地图位置相关属性组
int*m_map;//动态地图数据头指针(一维数组)
intm_nRow;//地图的行数(虚拟)
intm_nCol;//地图的列数(虚拟)
上面的成员变量中定义了一个整形指针标量m_map,用于记录动态分配出来的一维数组地图空间的首地址。
对于地图区域中的某个小方块的类型,可以用一个整形的ID来进行识别。
这里为标识地图的行列位置分别添加m_nRow和m_nCol变量。
现在,地图的数据结构已经设计好。
下面对游戏进行初始化。
由于方块需要成对地出现,因此在做地图的初始化时,不仅仅是对动物种类做简单的随机取数,然后将该随机选取出来的物件放到地图区域中去就了事,而是需要成对地对物种进行成对选取,就是说地图中的小方块必须是偶数个。
前面提到过,把地图数组设置成动态分配方式,目的是让其数据空间可以根据行列数的需求动态地获取,而对于实际不同大小比例的地图可以预先定义几组关于行列数的宏来实现。
当需要创建时,根据宏值的不同分配不同大小的地图空间即可。
接下来在LinkToLinkDlg类的构造函数对地图数据进行相关的初始化:
#defineROWCOUNT8//行数
#defineCOLCOUNT12//列数
......
CLinkToLinkDlg:
:
CLinkToLinkDlg(CWnd*pParent/*=NULL*/)
:
CDialog(CLinkToLinkDlg:
:
IDD,pParent)
{……
//初始化行列数
m_nRow=ROWCOUNT;
m_nCol=COLCOUNT;
//根据行列数动态分配内核数据数组空间
m_map=newint[m_nRow*m_nCol];
}
CLinkToLinkDlg:
:
~CLinkToLinkDlg()
{
//释放动态数组空间
delete[]m_map;
}
在LinkToLinkDlg类对象的实现中,定义了一些关于地图行列数的宏,如ROWCOUNT和COLCOUNT,并且在LinkToLinkDlg类对象的构造函数中,进行了行列的真实确认赋值,并根据当前行列数的大小对地图数据空间进行动态创建。
因为地图数据是用new在堆栈动态创建的,所以在销毁该对象时要将这些内存空间释放,如代码所示在LinkToLinkDlg类对象的析构函数中调用delete将m_map指向的所有空间都释放掉。
3.2.3数据的初始化工作
接下来,再分配好的空间中放上适当的图案方块物件,对数据进行初始化。
即需要对地图空间内的数据进行成对性的随机布局,因此可以将该功能的实现封装在StartNewGame()函数里面,其代码如下:
voidCLinkToLinkDlg:
:
StartNewGame()
{
//初始化地图,将地图中所有方块区域位置置为空方块状态
for(intiNum=0;iNum<(m_nCol*m_nRow);iNum++)
{
m_map[iNum]=BLANK_STATE;
}
//部下随机种子
srand(time(NULL));
//生成随机地图
//将所有匹配成对的动物物种放进一个临时的地图中
CDWordArraytmpMap;
for(inti=0;i<(m_nCol*m_nRow)/6;i++)
for(intj=0;j<6;j++)
tmpMap.Add(i);
//每次从上面的临时地图中取走(获取后并在临时地图删除)
//一个动物放到地图的空方块上
for(i=0;i { //随机挑选一个位置 intnIndex=(int(rand()*0.1+rand()*0.01+rand()))%tmpMap.GetSize(); //获取该选定物件放到地图的空方块 m_map[i]=tmpMap.GetAt(nIndex); //在临时地图除去该动物 tmpMap.RemoveAt(nIndex); } //更新显示 Invalidate(TRUE); } 在游戏进行初始化的过程中,应该先对整个地图中的各个区域做必要的初始化操作,将它们的状态设置为BLANK_START空白方块状态(无动物图案方块),关于BLANK_START空白方块状态的定义,跟其他动物方块的物种定义表达类似,也是用整数ID来对它进行标识,不过不同的是,由于他代表该方块区域无图案,所以这里用-1的宏值来表示,具体定义如下: #defineBLANK_STATE-1//空方块(没有任何动物) 可以看到,对图案方块的布局,先用srand()函数对时间函数布下随机种子,然后调用rand()函数对具体的图案方块的种类进行随机的获取。 在这里需要引入一个临时地图tmpMap,该临时地图的大小与内核数据地图的大小一致,并且先添置好4组完全一样的图案类型ID数据(0~(m_nCol*m_nRow)/4),然后再将已经安放在tmpMap中的图案作随机抽取,并放到内核地图数据中去,将取出的元素从tmpMap中除去。 二、系统的详细设计 1、图案方块的连接判断 对于选中的两个方块的销毁,他们必须符合下面3个条件: (1)选中的两个方块图案相同。 (2)选中的两个方块之间没有障碍物阻碍的情况下,可以用若干个垂直的直线线段连接起来。 (3)这些将它们连接起来的直线线段的折点不超过两个(连接线由x轴和y轴的平行线组成)。 现在针对 (2)和(3)进行分析,如图1.3。 如图1.3所示可知道,同种物件的连接方式大致可以分成以下3种: (1)直接方式 (2)有一个折点的垂直线段连接。 (3)有两个折点的垂直线段连接.。 1.直接连接方式 在直接连接方式中,必须要求所选定的两个方块在同一水平直线上(可以为x方向或y方向),并且两个方块之间没有任何其他图案方块。 2.一个这点连接方式 所选定的两个方块如果通过折点的方式连接,那么对于折点来说,每个折点必定有且至少有一个坐标(x或y)是和其中一个目标点相同的,即折点必定在两个目标点所在的x方向或y方向的直线上。 此外,对于一个折点连接的情况,折点应该为第一个选中方块的横向线或纵向线与第二个选中方块的纵向线和横向线相交而得出。 3.两个折点的连接方式 这种方式的两个折点所连成的直线与两物件的直接连线可以构成平行线,因此可以根据这个规律,将这条水平线在游戏区域允许的条件上下移动,然后通过判断整条带垂直折线点的曲线之间有无障碍物方式来确定是否可以连同。 这种情况可以分为两种情况: (1)选中的两图案方块在同一直线,两折点间的直连线可在其这两个方块之间的空间位置作移动,其约束是不超过游戏边界区域。 (2)选中的两图案方块不在同一直线,两折点间的直连线可在两个方块之间的空间位置作移动,其约束是两方块之间的区域。 经过上面详细的分析后,可以对选定的两方块是否可以作抵消操作可以这样设计下去。 首先,对简单的直接连情况进行判断,看其是否符合条件,假如不能,再加深一个级别的复杂度,对一个折点的情况进行判断,依次类推,如下图所示。 图1.3 图1.4 根据如图1.4所示的流程图,可以对选定的两个方块(分别在(x1,y1)以及(x2,y2)两个区域位置,其中x,y分别代表行与列的概念)是否可以抵消作以下实现。 把该功能封装在IsLink()函数里面。 这里把直接连接方式分为直通,左通,右通3种情况,如1.7图所示。 下面简单介绍直通和左通两种情况(右通与左通类似) (1)直通: 直通就是在选定的两个方块直连线中,没有被任何方块所阻碍。 (2)左通: 左通就是选定的两个方块的直连线之间有其他方块阻碍,但是通过它的左侧可以将它们无阻碍地连通。 直连方式中的此种情况跟前面分析的两个折点连接方式中的其中一点相当类似,如1.8图所示。 它们之间的区别就是,左通的连接线直接在其相邻的位置连通,从而不构成垂直折点的效果,而两个折点连同方式中的其中一个类似的情况是,线的连通起码要偏移一个方块的距离来形成连通。 图1.5图1.6 同理,有上通和下通,它们的情况与左通和右通类似。 算法代码 BOOLCPocketLianDlg: : X1EqualX2(intx,inty1,inty2) { if(y1>y2) { intn=y1; y1=y2; y2=n; } //直通 for(inti=y1+1;i<=y2;i++) { if(i==y2) returnTRUE; if(m_Player[i*m_nCol+x]>-1) break; } //左通 if(XThrough(x-1,y1,FALSE)&&XThrough(x-1,y2,FALSE)) returnTRUE; //右通 if(XThrough(x+1,y1,TRUE)&&XThrough(x+1,y2,TRUE)) returnTRUE; returnFALSE; } BOOLCPocketLianDlg: : Y1EqualY2(intx1,intx2,inty) { if(x1>x2) { intx=x1; x1=x2; x2=x; } //直通 for(inti=x1+1;i<=x2;i++) { if(i==x2) returnTRUE; if(m_Player[y*m_nCol+i]>-1) break; } //上通 if(YThrough(x1,y-1,FALSE)&&YThrough(x2,y-1,FALSE)) returnTRUE; //下通 if(YThrough(x1,y+1,TRUE)&&YThrough(x2,y+1,TRUE)) returnTRUE; returnFALSE; } BOOLCPocketLianDlg: : LineX(intx,inty1,inty2) { if(y1>y2) { inty=y1; y1=y2; y2=y; } for(inty=y1;y<=y2;y++) { if(m_Player[y*m_nCol+x]>-1) returnFALSE; if(y==y2) returnTRUE; } returnFALSE; } 三、系统实现与调试 1、鼠标交互功能的实现 对于用户交互的实现,这里选择鼠标交互方式。 下面简单描述一下通过鼠标交互方式实现的功能。 鼠标选取两个图案方块后,程序将自动判断所选定的两个方块是否能进行抵消操作,能则进行抵消操作。 在游戏过程中,我们不断重复上面描述的功能,直到游戏的胜利结束。 下面将鼠标事件处理工作归纳为如图1.7所示 2、绘图功能的实现 在完成以上所有的交互以及内部数据关联的运算处理后,最后要将这些数据展现到屏幕上。 2.1绘图方案的设计 对于游戏的绘制实现,这里采用内存位图映射的方式,先将整个游戏区域的图像绘制到内存位图中,然后再一次性地将它拷贝到屏幕上予以显示,如图1.12所示 图1.7 2.2绘图资源的载入与初始化 根据图1.所示的描述方案,可以在内存创建两个内存位图,并对它们的图像进行载入。 在需要使用的时候,则可以从这些内存位图中直接去拷贝,并绘制到游戏区域内存位图中去,接下来添加关于绘图的成员变量,如下所示。 //内存位图属性组 CDCm_mem3DBkDC;//3D框架的内存设备环境 CBitmapm_mem3DBkBmp;//3D框架的内存位图 CDCm_memAnimalDC;//动物图像的内存设备环境 CBitmapm_memAnimalBmp;//动物图像的内存位图 CDCm_MemDC;//游戏区域内存设备环境 CBitmapm_memBitmap;//游戏区域内存位图 这里,对3D框架位图以及动物图案位图分别创建了对应的设备环境m_mem3DBkDC和m_memAnimalDC,并且位它们分配了关联的内存位图变量m_mem3DBkBmp和m_memAnimalBmp。 而对于游戏区域的内存绘制,亦为它创建了一个内存设备环境m_MemDC以及关联的内存位图m_memBitmap。 在完成以上工作后,需要在程序开始运行的时候,一次行对它们进行适当的初始化。 可以将这些绘图的具体初始化加载在CLinkToLinkDlg对话框类的初始话函数OnInitDialog中,代码如下所示。 //获取程序框架的设备环境 CDC*pWinDC=GetDC(); //内存设备环境以及内存位图的创建,初始化,关联 //3D方块边框图样内存位图 m_mem3DBkDC.CreateCompatibleDC(pWinDC); m_mem3DBkBmp.LoadBitmap(IDB_BITMAP_3D_FRAMES); m_mem3DBkDC.SelectObject(&m_mem3DBkBmp); //动物图样内存位图 m_memAnimalDC.CreateCompatibleDC(pWinDC); m_memAnimalBmp.LoadBitmap(IDB_BMP_ANIMAL); m_memAnimalDC.SelectObject(&m_memAnimalBmp); //整个游戏区域内存位图 m_MemDC.CreateCompatibleDC(pWinDC); m_memBitmap.CreateCompatibleBitmap(pWinDC, m_nCol*FRONTWIDTH+5, m_nRow*FRONTHEIGHT+5); m_MemDC.SelectObject(&m_memBitmap); //开始一个新的游戏 StartNewGame(); //放在最桌面的前面显示 HWNDhWnd=: : AfxGetMainWnd()->m_hWnd; : : SetWindowPos(hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE| SWP_NOSIZE); //Settheiconforthisdialog.Theframeworkdoesthisautomatically //whentheapplication'smainwindowisnotadialog SetIcon(m_hIcon,TRUE);//Setbigicon SetIcon(m_hIcon,FALSE);//Setsmallicon //TODO: Addextrainitializationhere returnTRUE;//returnTRUEunlessyousetthefocustoacontrol 在上面的代码中,现获取该程序的屏幕设备环境,然后在将前面提到的3个内存设备环境以及关联的内存位图与该屏幕设备环境兼容,而对于两个用于存储外部位图图像的内存位图,则调用LoadBitmap()函数对他们相应的位图资源进行载入以及相关的初始化工作。 2.3游戏区域的绘制 在完成绘图物件的初始化工作后,接下来就可以对整个游戏区域的绘制进行实现,对整个游戏区域的绘制,可以将风卷在GameDraw()函数里,其代码清单如下所示。 voidCLinkToLinkDlg: : GameDraw(CDC*pDC) { //绘制背景颜色 pDC->FillSolidRect(0,0,m_nCol*FRONTWIDTH+5,m_nRow*FRONTHEIGHT+5,BKCOLOR); for(inti=0;i { for(intj=0;j { if(m_map[i*m_nCol+j]==BLANK_STATE) { continue; } //绘制方块边框 pDC->BitBlt(j*FRONTWIDTH,i*FRONTHEIGHT, BKWIDTH,BKHEIGHT, &m_mem3DBkDC, 0,BKHEIGHT, SRCCOPY); //绘制方块 //因为要使得效果透明,所以由图样的底色以及表面两部分构成 pDC->BitBlt(j*FRONTWIDTH,i*FRONTHEIGHT, FRONTWIDTH-2,FRONTHEIGHT-12, &m_memAnimalDC, FRONTWIDTH-2,m_map[i*m_nCol+j]*(FRONTHEIGHT-12), SRCAND); pDC->BitBlt(j*FRONTWIDTH,i*FRONTHEIGHT, FRONTWIDTH-2,FRONTHEIGHT-12, &m_memAnimalDC, 0,m_map[i*m_nCol+j]*(FRONTHEIGHT-12), SRCPAINT); } } } 在上面程序中,先调用FillSolidRect()函数来绘制整个游戏区域的背景,在对游戏区域中有动物图案的方块进行3D边框的绘制,绘制的方法示从3D边框的内存位图中拷贝,然后在根据内核地图中每一个方框区域的图案物种从动物内存位图m_memAnimalBmp中通过与它关联的m_memAnimalDC进行动物图案的拷贝。 四、系统运行的结果 图1.8 图1.9 总结 本文用EmbeddedVisualC++来设计与实现简单的连连看游戏的基本功能,对该游戏的算法以及游戏图案的绘制进行详细的介绍,其中核心内容包括图案方块的销毁判断,游戏胜利判断以及整个游戏用户交换功能的实现。 算法比较简单,运行速度快,具有鲁棒性。 但是,游戏实现的功能单一化及界面较简单,可以考虑不同难度系数的游戏,设置多种级别。 此外,还
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 大连 大学 嵌入式 期末 作业