连连看游戏的设计与实现
2021-03-14吕橙万珊珊
吕橙,万珊珊
(北京建筑大学电气与信息工程学院,北京 100044)
0 引言
“连连看”是一款风靡很多年的单机版小游戏,游戏规则简单,玩家可以将2 个相同图案的图片连接起来,连接线不多于3 根直线,即图片间连线的转角不超过2,就可以成功消除此对图片。该游戏改造成网络游戏后,一方面增强了该游戏的竞技性和合作性,把单机版中在规定时间内完成的游戏改变成了玩家之间的相互制约、相互竞争,也可以多人组队合作完成游戏;另一方面增强了该游戏的趣味性,游戏的类型从简单的宠物连连看拓展为多种形式,有果蔬连连看、奥特曼连连看、喜洋洋连连看、TWINS连连看、QQ连连看和植物大战僵尸连连看等等。
(1)胜利条件:消除全部图片,按剩余图片排名;其它玩家全部输掉。
(2)失败条件:30 秒内未成功消除一对图片;有玩家消除全部图片。
(3)名称说明
重排:将我方游戏池中的所有卡片重新排列一次。冰冻:禁止对手选择游戏池中的卡片,时间限制为5 秒。炸弹:随机炸掉一对符合消除条件的卡片。障碍:使对方游戏池中无卡片处随机增加6 对卡片。墨镜:使对方游戏池全部暗掉。反转:使对方游戏池里的卡片左右位置调换。
文献[1]着重阐述了基于Android 平台的连连看游戏界面的设计。文献[2]针对深度优先搜索查找算法进行了详细阐述。文献[3]采用JDK7.0,和MyEclipse 10 完成了连连看游戏的设计与实现。文献[4]则从人脸识别的角度讲述了连连看游戏的开发方法和过程。文献[5]则从课程思政角度讲述了中国风连连看游戏的设计与实现。
连连看游戏常用于学生课设、实验等实践环节,面向对象通常是计算机或计算机相近专业的高年学生。而对于低年级学生或初学者来说,利用编程实现这类游戏存在着明显的困难。本文利用Visual studio 2019 软件的EasyX 图形库实现了连连看游戏。
1 连连看游戏总体设计
1.1 游戏功能分析
1.1.1 初始化游戏界面
该部分主要是数据的初始化、通过鼠标点击事件选择游戏类型,以及生成随机数,并通过随机数加载图片形成连连看初始的界面。
1.1.2 图片的选择、判断与消除
该功能主要是通过鼠标点击事件选取所要消除的两个相同图片,然后对选中的图片进行判断:如果两张图片的图案相同,且连接线不多于3根直线,即图片间连线的转角不超过2,则消除此对图片,否则,不能消除,并给出“嘟声”警告。
1.1.3 游戏的提示
如果游戏界面中所有的图片全部消除,则提示“游戏结束”信息。如果当前状态没有任何可连通的相同图片时,则判断当前是否可以重排,并给出相关提示信息。如果玩家点击“提示”按钮,则可以获取系统帮助,继续游戏。
1.2 程序模块划分
1.2.1 游戏初始化模块
该模块是确定游戏运行的初始状态,主要包括进行游戏界面绘制、音乐和音效设置、难度设置、宠物类型设置、算法设置等等。
1.2.2 游戏引擎模块
该模块是程序运行的框架,主要包括连线消牌、炸弹函数、游戏重绘、最优路径提示、赠送时间、游戏循环设置等等。
1.2.3 游戏控制模块
该模块是游戏的执行部分,主要由游戏执行、游戏结束、当前界面是否有解、玩家时间是否耗尽、提示信息是否显示、统计玩家积分等等。
连连看游戏功能如图1 所示。
图1 连连看游戏功能
2 连连看游戏功能详细设计与代码实现
2.1 初始化模块
该模块是命名为Initial.h的头文件,所用到的函数如表1所示。
表1 初始化模块用到的主要函数
其中,初始化函数的主要功能是随机加载图片,核心代码如下:
void intial()
{
srand((unsigned)time(NULL));
int i,j;
int sort;
score=0;
p1.x=BLANK_STATE;
p1.y=BLANK_STATE;
p2.x=BLANK_STATE;
p2.y=BLANK_STATE;
//p1,p2两点设在画面之外,看不见
pen=::CreatePen(PS_SOLD,3,RGB(255,0,0));
fram_sign=false;
clue_sign=false;
//清空map二维数组
for(int i=0;i for(int j=0;j map[i][j]=0; //把中间全置成-1。-1 代表没有图,>0 代表有图,图的序号 for(int i=0;i { for(int j=0;j { map[i+2][j+2]=-1; num++; //总共需要的图片数量 } } //初始化map二维数组 int m_a[1000]={0}; for(int i=1;i<=num/2;i++)//保 证 图 片 成 对 出现,所以取一半 { while(1) { sort=rand()%39+1; if(sort_num[sort-1]<2) //每个图片不超过2张,总共不超过4张 { m_a[i]=sort; //放进地图中 m_a[i+num/2]=m_a[i]; sort_num[sort-1]++;//该图片数量加1 break; } } } int sum=num; int k=0; for(int i=0;i { for(int j=0;j { if(map[i][j]==-1) { k=rand()%sum+1; //随机数产生下一个m_a的下标 map[i][j]=m_a[k]; //放进地图中 //某张图片赋值给map 后,就删掉,后面的图片依次前移 for(int p=k;p<=sum-1;p++) m_a[p]=m_a[p+1]; sum--; } } } } 该模块是命名为GameEngine.h 的头文件,主要包含游戏引擎类的设计和相关函数的设计。游戏引擎类的设计如下: class GameEngine { private: protected: static GameEngine *m_pGameEngin;//指向自身的指针 HINSTANCE m_hInstance;//实例句柄 HWND m_hWnd;//窗口句柄 TCHAR m_szWindowsClass[32];//窗口类名 TCHAR m_szWndTitle[32];//窗口标题 Int m_iWidth,m_iHeight;//窗口的宽和高 int m_iFrameDelay;//游戏周期的间隔时间 bool start_sign;//游戏开始标记 public: GameEngine(HINSTANCE hInstance,LPTSTR sz⁃WindowClass,LPTSTR szTitle,int iWidth,int iHeight,int IDelay); virtual~GameEngine(); //访问方法 static GameEngine * GetEngine(){return m_pGa⁃meEngine;} HINSTANCE GetInstance (){return m_hIn⁃stance;} HWND GetWnd(){return m_hWnd;} void SetWnd(HWND hWnd){ m_hWnd =hWnd;} LPTSTR GetTitle(){return m_szWndTitle;} int GetWidth(){return m_iWidth;} void SetWidth(){m_iWidth=iWidth;} int GetHeight(){return m_iHeight;} void SetHeight (int iHeight){m_iHeight =iHeight;} int GetDelay(){return m_iFrameDelay;} void SetDelay(int iDelay){m_iFrameDelay = iDe⁃lay;} void SetStart(bool sign){start_sign=sign;} bool getStart(){return start_sign;} //初始化函数 BOOL initiallize(int cmdShow); //消息处理 LRESULT HandleEvent(HWND hWnd, UINT message,WPARAM wParam,LPARAM lParam); }; 该模块用到的函数如表2所示。 表2 游戏引擎模块用到的主要函数 其中,WinMain 函数是游戏的主函数,其核心代码如下: int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hpreInstance,LPSTR lpcmdline,int iShowCmd) { Msg msg; static int iticktrigger=0;//设置开始时间为0 int itickcount; if(!GameInitial(hInstance))//创建GameEngine 类对象g_pGame return 0; if(! GameEngine:: GetEngine()->Initiallize(SW_SHOWNORMAL)) //对窗口类对象wndclass 进行赋值并注册,创建窗口 return 0; ::ZeroMemory(&msg,sizeof(msg)); GameStartBg(); //绘制游戏背景 while(msg.message!=WM_QUIT) { if(::PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } else { ::Sleep(1); itickcount = ::GetTickCount();//返回从程序开始到现在的执行ms数 if(itickcount-iticktrigger>0) { if(GameEngine::GetEngine()->getStart()==true)//如果获取到的start_sign为真,开始游戏 GamePaint(); //游戏重绘 GameCycle(); //游戏循环 iticktrigger = itickcount + GameEngine::GetEn⁃gine()->GetDelav(); //设置下一次重绘时间 } } 该模块是Game.cpp 的C++文件,所用到函数如表3所示。 表3 游戏控制模块用到的主要函数 其中,判断是否连通是重点,其核心代码如下: //判断选中的两个图片是否可以连接 bool IsLink(int xl,int yl,int x2,int y2) { //x直连 if(x1==x2) { if(X1_Lin_X2(x1,y1,y2)) return true; } //Y直连i(y1=y2) if(Y1_Link_Y2(x1,x2,y1)) return true; //一个拐角 if(0neCormerLink(x1,y1,x2,y2)) return true: //两个拐角 if(TwoCornerLink(x1,yl,x2,y2)) return true; retun false; } 游戏实现了连连看游戏的基本功能,可以通过鼠标点击,实现连连看消牌操作,并统计积分。运行界面如图2所示。 图2 连连看游戏的运行界面 本文以连连看游戏为原型,利用C++语言和Visual Studio 2019 完成了游戏的基本运行,包括游戏的初始化设置、游戏引擎模块和游戏控制模块,游戏界面友好、操作简单,基本上满足了学生课设要求,提高学生的兴趣,带给学生具有挑战性的游戏类编程体验。2.2 游戏引擎模块
2.3 游戏控制模块
3 连连看游戏的测试与运行
4 结语