基于Qt的连连看游戏的设计_第1页
基于Qt的连连看游戏的设计_第2页
基于Qt的连连看游戏的设计_第3页
基于Qt的连连看游戏的设计_第4页
基于Qt的连连看游戏的设计_第5页
已阅读5页,还剩41页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

摘要在现今电子信息高速开展的时代,电子游戏已然成为群众最受欢送的娱乐消遣方式,经典的连连看是个老少皆宜的小游戏,它实现由各式各样的成对图片组成,然后存储在一个二维的数组中,计算机随机产生各种不同类型的图片,根据计算机时钟控制它在一定的时间内随机产生,用户可根据鼠标和回车键点击图片、假设两次点击的图片一样,那么消掉图片。本文用QT来设计与实现简单的连连看游戏的根本功能,玩家可以在游戏区域中通过键盘控制来选取相同的两个物件,采用特定的消除规那么对它们进行消除的操作,当游戏区域中的所有方块对都被消除后玩家即可胜利。文章对该游戏的算法以及游戏图案的绘制进行详细的介绍。实现起来较简单,同时也比拟实用。关键词:Qt;游戏设计;算法;数组;信号与槽ABSTRACTInthecurrenteraofrapiddevelopmentofelectronicinformation,electronicgamehasbecomethemostpopularentertainmentpopularpastime,classicRussiansquareisaenjoyedbyyoungandoldlittlegame,itachievedbyfoursquareofcolorpiece,andthenstoredinatwodimensionalarray,computerrandomgenerationsevendifferenttypesofsquare,accordingtothecomputerclockcontrolitincertaintimekeepproduced,theusercanaccordingtothekeyboardfourthedirectionkeycontrolblockturns,movesleft,movetotheright,movedownoperationandtheprogramaccordingtothesevensquarearestackedintoadifferentmodel.AndLaurasquareisbasedonsquareinRussia,givetheRussiansquarenewchallengepattern,itsinspirationfromthenetworkanotherkindofpopularvideogames-tombraider.Playerstotheidentityoftheadventurersintothegame,playersneedonlytoacertainscore,canchallengehigherdifficultylevelsofthegame,ofcourse,ifyouaregood,youwillhavethechancetoopenthemysterioushideorgans,themorefullofimaginationandstimulationofplaywillwaitforyoutakeyourchallenge.Keywords:Qt;Gamedesign;Algorithm;Array;Signalsandslots.目录TOC\o"1-2"\h\z\u摘要IABSTRACTII第一章绪论21.1游戏背景21.2游戏概述2第二章方案论证42.1选择开发语言4第三章需求分析113.1软硬件需求113.2游戏功能需求11第四章游戏总体设计134.1总体设计134.2游戏开始模块设计144.3游戏设置模块设计144.4游戏核心模块的设计15第五章具体实现165.1模型层设计165.2视图层设计175.3其它相关技术的实现18第六章游戏测试196.1按键事件的功能测试206.2图片消失测试206.3声音和显示测试206.4测试结果分析20总结21致谢22参考文献23附录源代码24第一章绪论1.1游戏背景说到连连看,就不得不从经典小游戏说起,连连看是一款古老的风行全球的经典游戏,它最早出现在PC机上,我国的用户都是通过红白机了解、喜欢上它的,相信有很多人到现在还是对它念念不忘的。无可争议,《连连看》是有史以来最伟大的游戏之一。在曾经发布过的所有游戏中,《连连看》还被认为是仅有的一个能够真正吸引广泛人群的作品,曾今造成的轰动与经济价值可以说是游戏史上的一件大事,它看似简单却变化无穷,令人着迷,相信大多数玩家都还记得为它痴迷得茶饭不思的那个连连看时代。但是随着网络信息的高速开展,连连看也要跟随时代的开展,以满足群众的需要。到如今,网络上已经出现了各种不同版本的连连看,它赋予玩家冒险家的角色,不断挑战你的想象,其全新的设计,创新的玩法,为经典的连连看蒙上了一层更加神秘的色彩。1.2游戏概述游戏简介游戏“连连看〞顾名思义就是找出相关联的东西,这个连连看在网上根本是用在小游戏中,就是找出相同的两样东西,在一定的规那么之内可以做为相关联处理。“连连看〞的开展经历了从桌面游戏、在线游戏、社交游戏三个过程。游戏“连连看〞是源自台湾的桌面小游戏,自从流入大陆以来风行一时,也吸引众多程序员开发出多种版本的“连连看〞。这其中,顾方编写的“阿达连连看〞以其精良的制作广受好评,这也成为顾方“阿达系列软件〞的核心产品。并于2004年,取得了国家版权局的计算机软件著作权登记证书。随着Flash应用的流行,网上出现了多种在线Flash版本“连连看〞。如“水晶连连看〞,“果蔬连连看〞等,流行的“水晶连连看〞以华美界面吸引了一大批的女性玩家。2023年,随着社交网络的普及和开放平台的兴起,“连连看〞被引入了社交网络。“连连看〞与个人空间相结合,被快速的传播,成为一款热门的社交游戏,其中以开发者Jonevey在Manyou开放平台上推出的“宠物连连看〞最为流行。游戏功能本次设计连连看主要是在原连连看对战的根底上设计挑战模式,具体的功能如下所述:游戏运行界面简单美观,操作简单,运行稳定;能够根据不同的等级模式播放不同的游戏背景音乐,包括操作方向键、消行时的声音,音量由玩家操作控制;设计不同的游戏难度,当玩家到达一定的积分,可以进入相关难度的等级;玩家可直接操作界面上的相关按钮来控制游戏的开始、暂停、设置、退出等功能。第二章方案论证2.1选择开发语言根据自己以前所学的关于C语言、C++、Java、以及Qt的相关知识,并通过网上查找相关资料,了解到C、C++、VB、Delphi、C#、Java等均可以现劳拉方块游戏的设计。下面简单介绍下VB、C++、Java、Qt各自的特点:VB的特点全称VisualBasic,它是以Basic语言作为其根本语言的一种可视化编程工具。在中国乃至全世界都能看到它的身影,它曾是在中国最为流行的编程工具,到现在还占据着非常重要的地位,对于它的好坏大家都有一定的了解,VB作为一种较早出现的开发程序以其容易学习,开发效率较高,具有完善的帮助系统等优点曾影响了好几代编程人员,但是由于VB不具备跨平台这个特性,从而也决定了VB在未来的软件开发中将会逐渐地退出其历史舞台;它对组件技术的支持是基于COM和ActiveX,对于组件技术不断完善开展的今天,它也显出了它的落后性;同时VB在进行系统底层开发的时候也是相对复杂的,调用API函数需声明,调用不方便,不能进行DDK编程,不可能深入Ring0编程,不能嵌套汇编;而且面向对象的特性差;网络功能和数据库功能也没有非常突出的表现,综上所述,VB作为一种可视化的开发工具由于其本身的局限性,导致了它在未来软件开发中逐步被其他工具所代替。C++的特点C/C++的哲学就不一样了,同一份程序代码,只要在该平台重新Compile成该平台的执行档,就能在该平台执行,假设文字模式下的程序,确实可以跨平台,程序完全不需修改,但GUI盛行以后,由于各GUI的Library都不一样且没有标准,所以GUI程序并没方法跨平台Compile,因为各平台都有专属的Library。但是C/C++优势就是执行速度快,假设能解决GUILibrary的问题,那么跨平台即可解决。除了GUILibrary需要统一外,还得看该Library设计的好不好才行,LinuxGUI我没写过就不说了,假设在Windows平台,Borland的C++Builder使用Delphi的VCLLibrary,Microsoft的VisualC++可以用MFC和.NETFramework,首先来看Borland的C++Builder,它使用标准的ANSIC++语言开发,利用VCL写出来的程序也算蛮漂亮的,执行速度很快,比拟麻烦的是C++Builder当初为了缩短上市时间,并没有设计自己的Library,而是藉用Delphi的Library,导致C++Builder在Compile时,是先用Delphi的Compiler将VCLcompile成objectfile后,再用C++Builder将你写的C++程序compile成objectfile,最后再用Linker将所有的objectfilelink起来,由于这都是IDE在做,对程序设计师似乎影响不大,但VCL由于是Delphi的Library,所以假设想深入研究VCL的sourcecode时,那么必须学Delphi的Pascal才行,否那么看不懂VCLsourcecode,这也是很多人对C++Builder却步的原因。再来看Microsoft的VisualC++,MFC用的是完整的ANSIC++语言,所以语言局部不是问题,但假设你看过用MFC写的程序,你一定会惊讶为什么这么复杂,程序代码非常冗长不好看,且MFC是有名的难学,假设VisualC++搭配.NETFramrwork,那么无法使用ANSIC++,得用其.NET平台版本的C++/CLI,相信这点很多人就有意见了,不过.NETFramework由于设计的不错,所以写出来的程序相当精简漂亮,感觉和C++Builder差不多,不过无论是C++Builder或VisualC++开发的GUI,所开发出来的程序都无法跨平台,当然也无法跨平台Compile。2.1.3JavaJava具有平安性、可移植性、多线程机制以及跨平台的良好特性,但是由于本人对Java语言不是很熟悉,所以此方案也予以否决。2.1.4Qt的Qt拥有一个单一的Library,让你开发各种不同平台的程序,目前支持Windows、Linux、Mac、UNIX、EmbeddedLinux,讲白话点,就是它提供了一个Library让你开发GUI程序,写好之后,只要在各平台重新Compile后,就可以在各平台执行,而且使用完整的ANSIC++语言,且不限Compiler,只要是C++的Compiler都可以,重要的是,该Library相当漂亮,写出来的程序很像C++Builder或.NETFramework的那样精简,不会向MFC那样复杂。目前Qt已经到第四个版本,GUI局部算支持的相当完整,且支持数据库、XML、Multi-Thread、Socket等方面的programming。假设以后台角度来说,无论后端是什么数据库,只要透过相同的Interface,不同数据库的Class来实做这个Interface,前端GUI的程序写法完全不用改变,同理,面对不同的OS,理论上只要透过相同的Interface,不同OS的Class各自实做这个Interface,前端GUI的程序也完全不用改变,最后只要靠Compiler将程序compile成各平台的原生程序即可,这样即可保证其执行速度,不用再靠VirtualMachine。但很可惜这个理想,这么多年来都没人可以做出来,或许是我孤陋寡闻吧。Qt无疑是GUI终极解决方案,有强力的ANSIC/C++语言背书,又有单一的GUILibrary,且精简漂亮,又能Compile成各平台的原生执行档,几乎是最完美的解决方案了。2.1.5经过以上比拟好,考虑到Qt的众多良好特性,尤其是其跨平台性,加上自己最近正在学习Qt,为了能够更进一步掌握Qt编程,因此决定使用Qt开发连连看游戏。2.2Qt关键技术的介绍Qt特点的具体介绍1.可移植性Qt是一个跨平台GUI工具箱,不仅适用于Unix,它同样适用于MSWindows。如果开发平台是MSWindows,可能选择的GUI工具箱为MicrosoftFoundationClasses〔MFC〕,这样就会失去众多的Unix用户。相反,如果开发平台是Unix,可能选择其它工具箱,如Motif等,同样会失去众多的Windows用户。如果选择的GUI工具箱为Qt,那么只要在不同的平台上简单的编译源代码,就可以使原程序在不同的平台上运行,从而解决丧失用户的问题。Qt把在处理不同窗口系统时的潜在问题隐藏了起来。为使Qt使用方便,Qt包含了一系列类,这些类使开发人员防止了在文件处理、时间处理等方面存在的依赖操作系统方面的细节。2.国际化所谓国际化,通俗的讲,就是指在某国开发的软件可以方便的被其它国家的人使用。Qt为本地化应用提供完全的支持,所有用户界面文本都可以基于消息翻译表被翻译成各国语言。另外,Qt完全支持双字节16bit国际字符标准。利用Qt开发跨平台的国际化软件是一个方便、增量的过程。在开发过程中,利用Qt的linguist界面工具就能方便的将开发的软件翻译成各国语言,从而实现软件的国际化。3.面向对象Qt是一个C++工具箱,它由几百个C++类构成。在程序设计中可以使用这些类,如果Qt没有提供真正适合需求的组件,那么可以方便的修改现有的组件或者重新编写组件。Qt具有模块设计和注重软件构件或元素的可重用性的特点。一个组件不需要知道它的内容,而通过Qt特有的signal和slot机制与外界通信、交流。使用Qt进行应用程序的开发,可以充分利用其面向对象和模块化的特征,从繁琐的编程中解脱出来,专注于应用程序本身的实现。4.可用户化的外观Qt支持主题,所以基于Qt的应用软件能在Motif外观、Windows外观,以及另一些用户化的外观之间互换,甚至改变运行时间。这些应用程序不管是在XWindows下还是在MicrosoftWindows下都可以独立操作、运行。5.独有的SignalSlot机制SignalSlot机制是Qt最重要的特征。在MSWindows中,程序通过消息机制和事件循环来实现图形对象行为的触发和处理;在Qt中,程序在一个类中定义多个Signal和Slot,Signal就相当于“事件〞,而Slot就相当于响应事件的“方法〞。为了实现“事件驱动〞,需要将一个类的Signal和另一个类的Slot连接起来(使用connect)。采用这种机制是一种平安可靠的方法,它允许回调。并支持对象之间在彼此不知道对方信息的情况下进行合作,这使Qt非常适合于真正的构件编程。6.开发程序的方便性Qt提供了一个可视化的开发工具QtDesigner,使用该工具就像在Windows中使用VisualC++那样可以直接向工程中添加各种组件,而不需要一步一步地编写代码,这个特点是其它非可视化编程工具望尘莫及的。QtDesigner中包含全面的联机帮助文档,包括超文本方式的QtManual,man帮助手册页和补充指南。这些帮助不管是对于初学者还是专业人士,都是非常方便的。7.强大的功能Qt的强大功能主要表达在以下几方面:拥有一套完整的组件,用户可以直接基于这些现成的组件开发出优秀的界面;拥有丰富的API函数,大概有250多个C++类;具有优越的绘画功能和2D/3D图形润色功能,Qt的绘画工具类Qpainter,可以在任意一个绘画设备上润色图形,对于更高级的2D/3D图形可以结合使用OpenGL和Qt的组件,使用OpenGL就像用任意一个Qt组件一样方便,而且效果比纯粹使用OpenGL作2D/3D图形更好;支持XML。Qt的类库Qt类库大致可以分为三个局部:控件,框架和工具。1.控件控件局部包括环境控件,主窗口控件,标准对话框,根本的GUI控件,扩展GUI控件,GUI组织控件,以及帮助系统控件。环境控件为应用程序提供全局效劳的类,包括系统设定、国际化等。例如QTranslator,Qapplication。主窗口类为应用程序提供界面框架,可以在上面添加菜单、工具条等,为应用程序提供集装箱的功能,如QMainWindow。标准对话框类是为翻开/关闭文件,选择颜色等预先设计的标准对话框,如QColorDialog,QFileDialog。根本控件包括所有的GUI控件,如按钮、组合框等,如QPushButton。扩展的控件包括树状视图、进度条等,如QListView。GUI组织类负责对各种控件进行组织以构成复杂的对话框,如QGroupBox。帮助系统控件是为应用程序提供在线帮助的类,QStatusBar,QToolTip。2.框架框架局部包括的是一些抽象的类,通常不可见,如对象模型、抽象控件、绘图、拖放、控件外观。对象模型是框架的根底,如QObject。可见的控件一般从抽象控件派生,如QButton。绘图类控制绘图,如QBrush。拖放类控制拖放操作,如QDragObject。控件外观类控制控件的外观如颜色、字体等。例如QColor。3.工具工具局部包括时间日期和链表树等数据结构,它们和GUI无关。普通工具包括链表、堆栈、队列、树等常见数据结构,如QArray。图形处理工具控制图像的编码/解码算法。如QImageIO。I/O控制工具处理I/O的一些类,如QFile。时间和日期工具类处理时间和日期,如Qdate,QTime。另外还有其他杂类如Qsignal,QIconSet等。Qt对象通讯机制对象间通讯是面向对象程序设计的一个极其重要的内容,类似于MicrosoftMFC的消息映射和事件循环,Qt的对象间通讯采用的是信号—槽(signal—slot)机制,信号就好似是事件,而槽那么是响应事件的方法。如果需要实现对象间的通讯,只需要把一个对象的信号和另外一个对象的槽使用连接(connect)起来。信号—槽机制说明:Qt下对象间的通讯用信号—槽机制来实现。信号—槽机制是Qt的一个中心特征并且也是它与其它图形工具包的最不相同的局部。图2-1直观地表示了这种机制是如何工作的。图2-1信号与槽的连接原理图在图形用户界面编程中,经常希望一个窗口部件的一个变化被通知给另一个窗口部件。更一般地,希望任何一类对象可以和其它对象进行通讯。例如,如果正在解析一个XML文件,当遇到一个新的标签时,也许要通知列表视图正在用来表达XML文件的结构。较老的工具包是使用一种被称作回调的通讯方式来实现同一目的。回调是指一个函数的指针,所以如果希望一个处理函数通知一些事件,可以把另一个函数(回调)的指针传递给处理函数,处理函数在适当的时候调用回调函数。回调有两个主要缺点:首先他们不是类型平安的,从来都不能确定处理函数使用了正确的参数来调用回调;其次回调和处理函数是非常强有力地联系在一起的,因为处理函数必须知道要调用哪个回调。在Qt中有一种可以替代回调的技术:使用信号和槽。当一个特定事件发生的时候,一个信号被发射。Qt的窗口部件有很多预定义的信号,但是总是可以通过继承来参加自己定义的信号。槽就是一个可以被调用处理特定信号的函数。Qt的窗口部件有很多预定义的槽,通常也可以参加自己的槽,这样就可以处理感兴趣的信号了。信号—槽机制是类型平安的:一个信号的签名必须与它的接收槽的签名相匹配。实际上一个槽的签名可以比它接收的信号的签名少,因为它可以忽略额外的签名。因为签名是一致的,编译器就可以帮助检测类型是否匹配。信号和槽是宽松地联系在一起的:一个发射信号的类不用知道哪个槽要接收这个信号。Qt的信号和槽的机制可以保证如果把一个信号和一个槽连接起来,槽会在正确的时间使用信号的参数而被调用。信号和槽可以使用任何数量、任何类型的参数。它们是完全类型平安的,不会再有回调核心转储。从QObject类或者它的一个子类(比方QWidget类)继承的所有类都可以包含信号槽。当对象的状态发生改变的时候,信号被发送给其它对象,从而实现了该对象与其它对象的通信。对象在发射信号时,无须知道有没有槽接收它所发射的信号,而槽是正常的成员函数,一个槽不知道它是否被任何信号连接,这就是信息封装,这种封装确保了对象可以用作一个软件组件。此外,使用对象时也无须知道这种通讯机制的实现细节。在信号—槽机制实现的过程中,可以把许多信号和单一槽相连,也可以把一个信号和许多槽相连。把一个信号和另一个信号直接相连也是可以的。(这时,只要第一个信号被发射时,第二个信号立刻就被发射)。总体来看,信号和槽构成了一个强有力的组件编程机制。第三章需求分析3.1软硬件需求本次的开发环境所采用的操作系统为Linux操作系统的Ubuntu10.10版本,编程环境是基于QT4.7的Qtcreator版本,由于本游戏对硬件的要求不是很严格,所以硬件需求不做讨论。3.2游戏功能需求本次设计是在传统的连连看上设计实现对战的连连看,玩家通过到达一定的积分来获得继续闯关的时机,还有时机开启神秘的应藏关,以此来增加游戏的可玩性。游戏的根本规那么:程序随机产生任意成对的图片,当定点击开始游戏时,电脑根据时间参数随机生成固定的成对图片,游戏再次开始,玩家可通过鼠标上的左键,自由的点两张图片。如果点击两次时,两张图片相同,且满足程序的算法那么这两张图片可消去。消去图片后,游戏可给玩家加分,假设在规定的时间内,玩家没有消掉所有的图片那么游戏失败。由于是闯关模式,到达一定分数的玩家可以继续挑战新的游戏,游戏的难度会相应增加,并且还增加了新玩法。具体的游戏功能如下:游戏界面需求:设计良好的游戏界面可以让玩家充分感受到游戏带来的娱乐性,游戏的背景取自网上中的图片,表达了游戏的挑战性。鼠标处理事件需求:通过点击主窗体中相应的按钮,可以实现游戏的开始、暂停、结束,通过点击选项设置中相应的按钮,可设置声音的大小及方向键↓的功能。显示需求:当两次点击的图片相同且满足算法可以消去,当到达一定分数的时候,游戏会进入下一关,并有障碍了。游戏闯关设计需求:随着游戏的难度不同,玩法会发生改变,需要在游戏中设置障碍,蒙手游戏。如果玩家能到达并完成最后一关,那么玩家挑战成功,游戏结束。图3.1游戏开始界面第四章游戏总体设计4.1总体设计整体设计思想:进入游戏后,有三个按钮可供玩家选择:开始游戏,游戏设置,退出游戏,在进入相应子菜单后也可返回到主菜单,每个菜单的具体设计将在后面介绍,以下是总体的游戏流程图。主菜单主菜单开始游戏暂停继续键盘方向键控制游戏返回主菜单退出游戏设置选项第一关过关第二关过关第…关过关第六关失败设置声音设置网格挑战成功设置加速图4-1游戏总体流程图设计4.2游戏开始模块设计此模块为本次设计的核心模块,玩家在主菜单设置好游戏选项后点击开始按钮后开始游戏,并进入游戏窗口,游戏窗口大体是这样设计的:首先最上面一栏显示当前处于第几关,游戏区域分为两局部,主游戏区显示当前游戏画面,其宽设置为10个单位的小方块图片的边长,高为20,游戏区域右边的上面局部设置了3个功能按钮:重新开始游戏、暂停、返回主菜单按钮;游戏区域右边的下面局部那么显示主菜单界面,该界面在游戏开始后处于隐藏状态,当玩家点击“返回主菜单〞按钮后,主菜单会重新显示出来,同时游戏界面处于隐藏状态。在开始游戏后,当玩家获得一定积分后,会进入下一关,如果失败,那么必须重新开始。玩家在顺利完成第五关后,这时,玩家就能进入神秘的隐藏关,一次来增加游戏难度〔相信那将会很有趣〕。4.3游戏设置模块设计游戏设置模块提供了3个设置选项:是否显示游戏网格、音量设置以及音效设置,这些设置的灵活性可以方便不同水平用户的自由选择,以便一步步晋级。而音效效果那么可以增加用户玩游戏的乐趣。设置好游戏选项后,即可返回主菜单开始游戏,在游戏的过程中也可以随时暂停返回主菜单,再进行重新设置游戏选项,这样更加方便用户的使用。4.4游戏核心模块的设计连连看所要求的是:1:两个目标是相同的2:两个目标之间连接线的折点不超过两个。〔连接线由x轴和y轴的平行线组成〕那么分析一下连接的情况可以看到,一般分三种情况1:直线相连2:一个折点3:两个折点:可以发现,如果有折点,每个折点必定有且至少有一个坐标〔x或者y〕是和其中一个目标点是相同的,也就是说,折点必定在两个目标点所在的x方向或y方向的直线上。所以设计思路就是:假设目标点p1,p2,如果有两个折点分别为z1,z2那么,所要进行的是1:如果验证p1,p2直线连线,那么连接成立2:搜索以p1,p2的x,y方向四条直线〔可能某两条直线会重合〕上的有限点,每次取两点作为z1,z2,验证p1到z1/z1到z2/z2到p2是否都能直线相连,是那么连接成立。连连看消去算法实现在检验两张图片能否消掉的时候,我们要让两张图片同时满足两个条件才行,就是两者配对并且连线成功。分3种情况:(从下面的这三种情况,我们可以知道,需要三个检测,这三个检测分别检测一条直路经。这样就会有三条路经。假设这三条路经上都是空按钮,那么就刚好是三种直线〔两个转弯点〕把两个按钮连接起来了)1.相邻2.假设不相邻的先在第一个按钮的同行找一个空按钮。1).找到后看第二个按钮横向到这个空按钮所在的列是否有按钮。2).没有的话再看第一个按钮到与它同行的那个空按钮之间是否有按钮。3).没有的话,再从与第一个按钮同行的那个空按钮竖向到与第二个按钮的同行看是否有按钮。没有的话路经就通了,可以消了.3.假设2失败后,再在第一个按钮的同列找一个空按钮。1).找到后看第二个按钮竖向到这个空按钮所在的行是否有按钮2).没有的话,再看第一个按钮到与它同列的那个空按钮之间是否有按钮。3).没有的话,再从与第一个按钮同列的那个空按钮横向到与第二个按钮同列看是否有按钮。没有的话路经就通了,可以消了。假设以上三步都失败,说明这两个按钮不可以消去。第五章具体实现5.1模型层设计图形的产生通过图形工厂类ShapeFactory的getShape(ShapeListenerlistener)方法随机产生方块的某种状态,这里运用了工厂设计模式。图形的变形图形的变形是通过函数char*MyItem::itemChange(unsignedchar*currentItem)来实现的,该函数首先是在内存中开辟一个新的4*4数组,用来保存变化后的方块,通过两个for循环,依次将数组中个元素的横坐标与列坐标交换位置,即可使原来的方块逆时针旋转90度,到达旋转方块的目的。判段消掉图片如果两在张图片满足一个拐点,没有拐点。两个拐点那么该两张图片就可以消掉,同时需要用一个全局变量fullRowNum来保存此次一共消除了多少张,以便算分,没有拐点10分,一个拐点20分,二个拐点的是30分。具体是通过函数voidGameArea::clearRow()来实现的。5.2视图层设计图片的显示方块的显示是通过调用GameArea类中的draw_currentMap()方法实现的,首先判断存储方块的数组的值,但凡值为1的成员那么给该数组控制的对应游戏区域的坐标通过调用painter.drawPixmap()绘制图片,具体的坐标和范围以及图片来源都是有painter.drawPixmap()中的参数给定的。在调用painter.drawPixmap()函数之前,还可以设置图片颜色,具体是通过painter.setPen()h和painter.setBrush()来实现的这样就能显示方块,而且可以不断的改变颜色,使游戏界面富有动感。游戏区域的显示游戏区域的绘制包括网格和游戏区的方块的绘制,具体通过调用GameArea类中的draw_gameArea()函数来实现,在该函数中调用到了绘制网格的draw_Grid()函数和显示图片的draw_currrentMap()函数,在draw_Grid()函数中调用Painter类的painter.drawLine()函数绘制网格,具体的起始点和结束点同样由传递参数获得。首先需要设置游戏区域大小,可以通过this->gameArea->setGameAreaPi〔〕实现,还需要安置新的坐标原点可以通过调用该函数。5.3其它相关技术的实现键盘事件响应连连看是通过鼠标左键来控制游戏的运行,那么是具体如何实现的呢?这就需要用到键盘的左击事件,通过响应鼠标的按下事件来实现。玩家通过鼠标左键来控制图片的点击。具体代码实现:通过重新实现虚函数QWidget::keyPressEvent来响应相应的键盘按键事件。声音的实现声音的实现在这里用到了一个单独的类MyBoxAudio来封装,声音的实现要用到库类中的Phonon类,首先创立一个媒体对象medioObject和用于输出声音的设备接口对象audioOutput,有了这两个对象以后再调用Phonon::createPath()函数生成路径,然后绑定音频文件〔必须为.wav格式的〕,最后调用medioObject.play()函数,即可实现声音的播放。第六章游戏测试6.1选项按钮的功能测试〔1〕点击“游戏开始〞:游戏正常开始,结果正常;〔2〕点击“游戏设置〞:弹出游戏设置对话框;能够选中向下键↓选项和是否绘制网格选项,声音大小可调,点击“返回〞按钮能够回到主菜单,结果正常;〔3〕点击“退出游戏〞:游戏正常退出,结果正常;〔4〕点击“暂停〞:游戏停止,“暂停〞变为“取消暂停〞,再点击“取消暂停〞:游戏继续,结果正常;〔5〕点击“返回主菜单〞:游戏退回到主菜单界面,结果正常;6.2按键事件的功能测试〔1〕两次点击相同图片,假设满足算法,图片消失,那么结果正常;〔2〕图片点击测试:游戏过程中,点击鼠标左键:图片在没有其他图片阻挡的情况下可变灰色,结果正常;6.3图片消失测试〔1〕当点击两张相同图片:两站图片同时消失,结果正常;〔2〕当图片消失,且满足一条直线时分数增加10分,满足一个拐点分数增加20分,满足两个拐点,分数增加30分;6.4声音和显示测试〔1〕进入游戏时:背景音乐正常播放,图片消失时,有背景音乐播放;〔2〕在游戏过程中,游戏区域背景颜色不断改变;在开始最后一关时:游戏区域越来越大,结果正常;6.5测试结果分析经过测试,本游戏实现了根本的连连看的功能,运行比拟稳定,不过有些细节方面可能需要改良,游戏在很多方面还需要进一步完善。总体的游戏界面效果如下列图所示:图6.1游戏界面效果总结游戏设计与实践是一项复杂而庞大的工作,在选题之后,我才意识到过程的艰难,因为以前从来都没有接触过游戏设计,刚开始有点迷茫和彷徨。后来通过翻阅书籍和在网上查阅资料,逐渐找到了一些感觉,在老师的指导下,自己也手动编写了几个简单的游戏,打地鼠游戏和网络N子棋双人对战游戏,本文以连连看游戏为例予以说明。本次设计让我初步懂得了电子游戏涉及到的有关技术、方法,包括电子游戏选题、构思、设计步骤等。并实现一些可演示的游戏软件,其中有很多应用了学习的相关技术,并且做到了界面、声音都能实际演示。此次设计过程中印象最深的收获有:1、学到了很多新知识,并且对老知识进行了回忆。经过长时间的学习,更进一步熟悉了Qt编程、通过不断上机实验,调试程序,总结经验,从对课题的不理解到能够开始动手去做,提出新问题并自己想方法去解决问题,自己多实践,所以增强了动手能力。2、提高了中、英文资料的检索能力。这次毕业设计过程中我查阅了多资料,包括一些期刊、杂志,还有网络中的电子文档、电子书籍、网页及下载的视频教学课程;不但有中文资料还有英文资料。这些资料,使我的眼界更开阔,对课题的认识更加深刻,编写程序的时候思路更加清楚,少走了很多弯路。回忆此次设计过程,我学到了许多书本上没有学到的知识。通过这次自己制作的软件,丰富了自己的实践技能,扩张了本专业的知识面,使我受益匪浅,同时也体验到了搞软件开发的难度。在这次设计的同时,由于我对这样的软件开发还只是一个开始,了解的不多,这其中或许还有很多的缺乏,有些模块做得不是很好,有些功能还不能够完全的实现,如播放背景音乐时,只能播放一遍,因为游戏Qt类库中封装的东西太多,有些函数它底层的具体实现可能还没有真正的理解,所以,这也许就是本次游戏设计的缺乏之处。致谢今天,毕业设计也告一段落了,也就意味着我的大学时代即将结束。回想毕业设计这几个月,回想大学这四年的时光,感慨万千。值得留恋,值得追忆的,实在太多。还有很多老师,同学,朋友要感谢。首先,要感谢我的指导老师黄同成老师,他认真负责、踏实努力的工作精神,一丝不苟、严谨治学的专业作风,给我留下了深刻的印象。黄老师教给我的不仅是科学知识,他还教给了我做人的道理,所有这些都为我今后的人生道路奠定了坚实的根底,使我受益终生。同时,也要感谢成老师,黄磊老师,感谢信息工程系所有老师四年来的悉心教诲。我们所在的实验室是一个温暖的大集体,也要感谢我们实验室各位老师给我的帮助。也要感谢与我同寝室的同学四年来,在工作和学习中给与我的鼓励和帮助。最后,我还要向我的父母表示最真诚的感谢和祝福,是他们的辛勤和汗水养育了我,是他们的精神鼓舞了我,使我能够不懈努力和拼搏。致谢人:陈严2012参考文献[1]MarkSummerfield著.白建平等译.Qt高级编程[M].电子工业出版社2023.8.[2]StanleyB.Lippman等著.李师贤等译.C++Primer中文版[M].人民邮电出版社2023.7.[3]W.RichardStevens、StephenA.Rago著.尤晋元等译.UNIX环境高级编程[M].人民邮电出版社2023.10.[4]Stanleyb.Lippman著.侯捷译.深度探索C++对象模型[M].华中科技大学出版社2001.5.[5]谭浩强著.C程序设计第三版[M].清华大学出版社2005.7.[6]严蔚敏、吴伟民著.数据结构[M].清华大学出版社2023.9.[7]宋劲杉编著.LinuxC编程一站式学习[M].电子工业出版社2023.12.[8]KennethA.Reek著.徐波译.C和指针[M].人民邮电出版社2003.9.[9]JasmineBlanchette、MarkSummerfield著.闫锋欣等译.C++GUIQt4编程[M].电子工业出版社2023.8.[10]丁林松、黄丽琴编著.Qt4图形设计与嵌入式开发[M].人民邮电出版社.2023.4.附录源代码Mainwindow.cpp#include<resolv.h>#include<stdlib.h>#include<netinet/in.h>#include<arpa/inet.h>#include<unistd.h>#include<QScrollBar>#include"mainwindow.h"#include"ui_mainwindow.h"#include"udp.h"#include<QImage>#include<QTime>#include"llk.h"#include<iostream>usingnamespacestd;MainWindow::MainWindow(QWidget*parent):QMainWindow(parent),ui(newUi::MainWindow){ui->setupUi(this);connect(this,SIGNAL(recvMessage(QString,QString)),this,SLOT(onRecvMessage(QString,QString)));//this->setCentralWidget(link);//link->setMaximumSize(300,300);ui->editChatRec->setReadOnly(true);//link=newllk();size=6;isLinkE=false;sendMessage("55",8838,"o17",true);}MainWindow::~MainWindow(){deleteui;}voidMainWindow::changeEvent(QEvent*e){QMainWindow::changeEvent(e);switch(e->type()){caseQEvent::LanguageChange:ui->retranslateUi(this);break;default:break;}}voidMainWindow::on_btnSend_clicked(){QStringstring=ui->lineEdit->text();if(ui->radiosingle->isChecked()==true){sendMessage(string,8838,'c'+ui->editChat->text(),true);}else{string="55";sendMessage("55",8838,'c'+ui->editChat->text(),true);}QStringstr=trUtf8("自己对")+string+trUtf8("发送:")+"\n"+ui->editChat->text();ui->editChatRec->setPlainText(ui->editChatRec->toPlainText()+"\n"+str);ui->editChat->clear();QScrollBar*bar=ui->editChatRec->verticalScrollBar();bar->setSliderPosition(bar->maximum());}Ui::MainWindow*MainWindow::getUi(){returnui;}voidMainWindow::onRecvMessage(QStringmsg,QStringipAdd){//QStringtime=QTime::currentTime().toString();QStringstring=time+"\n"+QString(trUtf8("收到来自"))+ipAdd+trUtf8(":的消息:")+"\n"+msg.right(msg.length()-1);switch(msg.at(0).toAscii()){case'o'://如果接受的是上线消息ui->listWidget->addItem(msg.right(msg.length()-1));break;default://如果接受的是普通消息ui->editChatRec->setPlainText(ui->editChatRec->toPlainText()+"\n"+string);break;}QScrollBar*bar=ui->editChatRec->verticalScrollBar();bar->setSliderPosition(bar->maximum());}voidMainWindow::on_action_begin_triggered(){/*link=newllk();link->setsize(6);link->arrayInit(6);link->Create(6);link->show();isLinkE=true;*///size=4;if(isLinkE){//link=newllk();//link->setsize(8);//link->arrayInit(8);//link->Create(8);link->close();isLinkE=false;}else{link=newllk();link->setsize(size);link->arrayInit(size);link->Create(size);link->show();isLinkE=true;}if(isLinkE==false){link=newllk();link->setsize(size);link->arrayInit(size);link->Create(size);link->show();isLinkE=true;}}voidMainWindow::on_action_close_triggered(){this->close();link->close();}voidMainWindow::on_action_pause_triggered(){if(isLinkE)link->setEnabled(false);}voidMainWindow::on_action_return_triggered(){link->setEnabled(true);}voidMainWindow::on_action_easy_triggered(){size=6;if(isLinkE){//link=newllk();//link->setsize(8);//link->arrayInit(8);//link->Create(8);link->close();isLinkE=false;}else{link=newllk();link->setsize(6);link->arrayInit(6);link->Create(6);link->show();isLinkE=true;}if(isLinkE==false){link=newllk();link->setsize(6);link->arrayInit(6);link->Create(6);link->show();isLinkE=true;}}voidMainWindow::on_action_soso_triggered(){size=8;/*llk*lin;lin=newllk();//this->setCentralWidget(lin);//lin->setGeometry(30,30,500,500);lin->setsize(8);lin->arrayInit(8);lin->Create(8);lin->setVisible(true);lin->close();*/if(isLinkE){//link=newllk();//link->setsize(8);//link->arrayInit(8);//link->Create(8);link->close();isLinkE=false;}else{link=newllk();link->setsize(8);link->arrayInit(8);link->Create(8);link->show();isLinkE=true;}if(isLinkE==false){link=newllk();link->setsize(8);link->arrayInit(8);link->Create(8);link->show();isLinkE=true;}}voidMainWindow::on_action_diffcult_triggered(){size=10;/*llk*lin;lin=newllk();//this->setCentralWidget(lin);//lin->setGeometry(30,30,500,500);lin->setsize(8);lin->arrayInit(8);lin->Create(8);lin->setVisible(true);lin->close();*/if(isLinkE){//link=newllk();//link->setsize(8);//link->arrayInit(8);//link->Create(8);link->close();isLinkE=false;}else{link=newllk();link->setsize(10);link->arrayInit(10);link->Create(10);link->show();isLinkE=true;}if(isLinkE==false){link=newllk();link->setsize(10);link->arrayInit(10);link->Cremybutton.cpp#include"mybutton.h"MyButton::MyButton(intvalue,QWidget*parent){this->value=value;this->setParent(parent);QObject::connect(this,SIGNAL(clicked()),this,SLOT(mySlot()));}voidMyButton::mySlot(){emitmyClicked(this->value);}

Main.cpp#include<QtGui/QApplication>#include"mainwindow.h"#include<QtGui/QApplication>#include<errno.h>#include<sys/socket.h>#include<resolv.h>#include<stdlib.h>#include<netinet/in.h>#include<arpa/inet.h>#include<unistd.h>#include<iostream>#include<string>usingnamespacestd;constunsignedintMAXBUF=1024;void*thd_handler(void*window){MainWindow*w=(MainWindow*)window;intsockfd;structsockaddr_inmy_addr;socklen_taddrlen;charbuffer[MAXBUF];unsignedintmyport=8838;printf("serverstarted!\n");//createasocketforudpif((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0) //attention{perror("socketcreationfailure");exit(errno);}//initializesockaddr_inbzero(&my_addr,sizeof(my_addr));my_addr.sin_family=AF_INET;my_addr.sin_port=htons(myport);my_addr.sin_addr.s_addr=INADDR_ANY;//bindif(bind(sockfd,(structsockaddr*)&my_addr,sizeof(structsockaddr))==-1){perror("bindfailure");exit(errno);}printf("bindsuccess\n");addrlen=sizeof(structsockaddr);while(true){bzero(buffer,MAXBUF);intlen=recvfrom(sockfd,buffer,MAXBUF,0,(sockaddr*)&my_addr,&addrlen);if(len<0){perror("recvfrom");exit(errno);}emitw->recvMessage(QObject::trUtf8(buffer),inet_ntoa(my_addr.sin_addr));}//closeconnectionclose(sockfd);}intmain(intargc,char*argv[]){pthread_tntid;QApplicationa(argc,argv);MainWindoww;pthread_create(&ntid,NULL,thd_handler,&w);w.show();returna.exec();}udp.cpp#include"udp.h"#include<QString>#include<errno.h>#include<sys/socket.h>#include<resolv.h>#include<stdlib.h>#include<netinet/in.h>#include<arpa/inet.h>#include<unistd.h>voidsendMessage(QStringipAddress,unsignedintport,QStringmsg,boolisBroad){ //constunsignedintMAXBUF=1024;intsockfd;intaddr_len;intlen;structsockaddr_indest;//charbuffer[MAXBUF];charaddr[16];strcpy(addr,ipAddress.toAscii());//createasocketforudpif((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0) //attention{perror("socketcreationfailure");exit(errno);}if(isBroad){intbroad=1;setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&broad,sizeof(broad));strcpy(addr,"55");}//initializesockaddr_inbzero(&dest,sizeof(dest));dest.sin_family=AF_INET;dest.sin_port=htons(port);if(inet_aton(addr,(structin_addr*)&dest.sin_addr)==0){perror("ipaddressformatiserror");exit(errno);}//sendmsgtoserveraddr_len=sizeof(dest);//bzero(buffer,MAXBUF);len=sendto(sockfd,msg.toLocal8Bit(),msg.toLocal8Bit().length(),0,(sockaddr*)&dest,addr_len);if(len<0){printf("\n\rsenderror.\n\r");exit(errno);}//closeconnection::close(sockfd);}llk.cpp#include"llk.h"#include<iostream>#include"judge.h"llk::llk(){isFirstClick=true;llk::createBtnRerank();size=6;llk::createCurrentProgressBar(size);timer=newQTimer();currentTime=0;QObject::connect(timer,SIGNAL(timeout()),this,SLOT(timeProcess()));}voidllk::xxx(intx){clear(x);//std::cout<<x<<std::endl;//mybutton[x]->setVisible(false);//Widget::arrayInit(6);//progressBar[1]->setValue(20);}voidllk::addPic(QStringpath,inti){labelPic[i]=newQLabel(this);labelPic[i]->setGeometry(i*100+5,30,100,120);QPixmappixmap(path);labelPic[i]->setPixmap(path);labelPic[i]->setVisible(false);progressBar[i]=newQProgressBar();progressBar[i]->setGeometry(i*100+10,120,100,20);progressBar[i]->setParent(this);progressBar[i]->setValue(10);}voidllk::Create(intsize){createTimeProcessBar(size*size);timer->start(1000);charss[26][20]={"begin","./icon/icon1.png","./icon/icon2.png","./icon/icon3.png","./icon/icon4.png","./icon/icon5.png","./icon/icon6.png","./icon/icon7.png","./icon/icon8.png","./icon/icon9.png","./icon/icon10.png","./icon/icon11.gif","./icon/icon12.gif","./icon/icon13.gif","./icon/icon14.gif","./icon/icon15.gif","./icon/icon16.gif","./icon/icon17.gif","./icon/icon18.gif","./icon/icon19.gif","./icon/icon20.gif","./icon/icon21.gif","./icon/icon22.gif","./icon/icon23.gif","./icon/icon24.gif","./icon/icon25.gif"};createCurrentProgressBar(size);currentIndex=size*size;progressBarCurrent->setValue(0);for(unsignedinti=0;i<size*size;i++){mybutton[i]=newMyButton(i,this);mybutton[i]->setGeometry(20+i%size*60,150+i/size*60,60,60);intx,y;x=i/size+1;if((i+1)%size){y=(i+1)%size;}elsey=size;intm=array[x][y];//std::cout<<x<<","<<y<<std::endl;mybutton[i]->setIcon(QIcon(ss[m]));mybutton[i]->setIconSize(QSize(50,50));QObject::connect(mybutton[i],SIGNAL(myClicked(int)),this,SLOT(xxx(int)));//mybutton[i]->setIcon(QIcon(s));}}voidllk::arrayInit(intsize){array[size+1][0]=0;array[size+1][size+1]=0;array[0][size+1]=0;array[0][0]=0;for(inti=1;i<=size;i++){array[0][i]=0;array[size+1][i]=0;array[i][0]=0;array[i][size+1]=0;for(intj=1;j<=size;j++){array[i][j]=((i-1)*size+j-1)/4+1;}}for(inti=1;i<=size;i++){for(intj=1;j<=size;j++){intx1,x2,y1,y2,tmp1;//srand(unsigned(time(NULL)));x1=rand()%size+1;x2=rand()%size+1;y1=rand()%size+1;y2=rand()%size+1;tmp1=array[x1][y1];array[x1][y1]=array[x2][y2];array[x2][y2]=tmp1;}}for(inti=0;i<=size+1;i++){for(intj=0;j<=size+1;j++){std::cout<<array[i][j]<<"";}std::cout<<std::endl;}}voidllk::clear(intindex){if(isFirstClick){firstIndex=index;isFirstClick=false;std::cout<<firstIndex<<",";}else{std::cout<<index<<std::endl;intx1,y1,x2,y2;x1=firstIndex/size+1;x2=index/size+1;if((firstIndex+1)%size){y1=(firstIndex+1)%size;}elsey1=size;if((index+1)%size){y2=(index+1)%size;}elsey2=size;std::cout<<x1<<","<<y1<<std::endl;std::cout<<x2<<","<<y2<<std::endl;std::cout<<"**************"<<std::endl;

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论