基于Java小游戏拼图的设计与实现
烟台工程职业技术学院
信息与传媒 系 移动互联应用技术 专业 2019 级
毕业设计(论文)
题目:基于Java小游戏拼图的设计与实现
姓名 ___ 学号
指导教师(签名)
二○二一年 月 日
烟台工程职业技术学院毕业设计(论文) 诚 信 承 诺 书 本人慎重承诺: 我所撰写的设计(论文)《基于Java小游戏拼图的设计与实现》是在老师的指导下自主完成,没有剽窃或抄袭他人的论文或成果。如有剽窃、抄袭,本人愿意为由此引起的后果承担相应责任。 毕业论文(设计)的研究成果归属学校所有。 学生(签名) 2020 年 11 月 1 日 |
基于Java小游戏拼图的设计与实现
XXX
[摘要]
拼图游戏是一款非常经典的小游戏,因为它比较简单有趣,老少皆宜。 拼图
游戏的设计对每一个Java语言设计者进行语言提高和进阶都是一个很好的锻炼机会。
拼图游戏的设计比较复杂,它涉及面广、牵涉方面多,如果不好好考虑和设计,将难以成功开发出这个游戏。在这个游戏的设计中,牵涉到图形界面的显示与更新、数据的收集与更新,并且在这个游戏的开发中,还要应用类的继承机制以及一些设计模式。因此,如何设计和开发好这个拼图游戏,对于提高Java开发水平和系统的设计能力有极大的帮助。在设计开发过程中,需要处理好各个类之间的继承关系,还要处理各个类相应的封装,并且还要协调好各个模块之间的逻辑依赖关系和数据通信关系。
此次设计所使用的语言为Java语言,开发环境为JDK Version1.7.0,开发工具为IDEA。主要应用Swing组件,Java小程序,事件及接口等。本系统主要是运用Swing组件和事件处理技术,进行界面的绘制,鼠标的操作,以及积分的显示和计时的显示等功能。
关键词:游戏;拼图;二维游戏
目录
第一章 绪 论 1
一、项目背景 1
二、项目开发目的及意义 1
第二章 关键技术 4
一、Java平台及体系 4
二、Java SE环境安装和配置 4
三、Java语言 4
四、Java的其他相关技术及功能 6
(一)、Java 虚拟机 6
(二)、ECLIPSE简介 7
第三章 系统需求分析及可行性分析 8
一、需求分析 8
(一)、功能需求 8
(二)、环境需求 8
二、可行性分析 8
(一)、技术可行性 8
(二)、经济可行性 9
(三)、社会可行性 9
第四章 游戏分析 10
一、游戏流程分析 10
二、总体设计方案 12
三、游戏功能分析 12
第五章 游戏设计 14
一、游戏功能设计 14
(一)、游戏框架 14
(二)、游戏难度 16
(三)、当前步数 17
(四)、历史记录 17
(五)、右侧数据栏 19
(六)、通关提示 21
二、游戏重点设计 24
(一)、开局载入图片 25
(二)、游戏时排序图片 25
(三)、判断拼图是否移动 26
第六章 实现及测试 28
一、测试的重要性 28
二、测试结果 28
总 结 31
致 谢 32
参考文献 33
附 录 34
第一章 绪 论
一、项目背景
随着信息技术的飞速发展、蓬勃进步,同时随着国际互连网与相关系统的迅速普及,不同国家、行业被Internet 连接在一起,互相通信,共享全世界的计算机资源.和信息。如何保证不同格式的资料或信息能够安全、高速、自由的交流、传输就成为一个迫切解决的问题。1996 年Sun公司Java语言的正式发表可以说是Internet的一次技术革命,Sun公司的一-位营销天才把一门试验性的跨平台语言由象征踏实的0ak (橡树),改名为香气四溢的Java (咖啡)时,可能他没有想到这门语言能有后来的辉煌。事实上,如果现在Sun 想为这门语言改名,以准确体现其在计算机行业的地位,似乎0ak 更形象。今天,虽然Java 语言并非真正意义上的遍地开花,但它已经出现在众多场合和设备中,而且它享有运行稳定、设计精良的美名。它实现了程序的运行不受平台的限制,在网络上不仅可以进行无格式的资料交换,还可以进行程序交换。Java 语言具备了其它语言所没有的独特优势,它- -出现就马上受到了各界人士的欢迎。Java 的出现无疑给计算机行业带来了-股清风,它带来了许多新鲜而有趣的思想和观念。
Java Swing组件在游戏的实现上扮演着不可或缺的重要角色,Swing是一个用于开发Java应用程序用户界面的开发工具包。它以抽象窗口工具包(AWT)为基础使跨平台应用程序可以使用任何可插拔的外观风格。Swing提供了本机的外观和手感,模拟多个平台的外观和感觉,同时还支持一个可插拔的外观和手感,使应用程序有一个拥有外观和感觉的基础平台。它 具有比AWT更强大和灵活的组件。除了熟悉的部件,如按钮,复选框和标签,Swing 提供了一些先进的零部件,如卡式面板,滚动窗格,树,表,列出,因此Swing 深受开发人员青睐。除此之外,他们只用很少的代码就可以利用Swing丰富、灵活的功能和模块化组件来创建优雅的用户界面。因此,可以推断Java Swing组件在未来游戏等各个相关领域依旧会保持良好的发展势头,发扬其优势,更好的服务于Java 游戏产业。
二、项目开发目的及意义
现代科学技术的发展,改变了人类的生活,作为新世纪的大学生,应该站在时代发展的前沿,掌握最先进的现代科学技术知识,以适应社会发展,应能够独立地完成各种应要面临的任务,成为一名有创新意识的新型人才。
目前,很多新的技术领域都涉及到了Java 语言。Java 语言是面向对象编程, 并涉及到网络、多线程等重要的基础知识,因此Java语言也是学习面向对象编程和网络编程的首选语言。该课题的主要目的是使Java 游戏开发者深入理解所学的Java语言,并实践于该游戏设计中,深刻体会以前所学的有关Java 程序设计方面的语言基础、异常处理、事件处理、应用程序以及图形用户界面设计等方面的知识,加深对结构化设计思想的理解,能对系统功能进行分析,并设计
合理的模块化结构等。学会使用Java 系统,其中包括对程序的调试、运行、保存等知识的运用,还包括提高程序开发功能,能运用合理的方法简化Java 程序的操作,开发过程中应培养分析问题、解决问题的能力。
基于Java组件技术的拼图游戏软件是一款具有娱乐性、益智性、便捷性的游戏软件。此软件可以使用户放松心情,享受于拼图游戏的乐趣之中。该游戏软件可以让用户选择适合自己的主题与难度,根据用户的不同水平,锻炼其图片记忆能力以及拼凑还原能力。游戏结束后亦可让用户清晰了解到自己的游戏状态水平,便于调整自己对这款游戏的新的难度要求。另外要求软件设计精致,画面亲和,人机交互高效快捷,能够给用户带来人性化的服务。软件面向的主流群体集中在年轻人,但也适宜儿童或者老人使用,提供了适宜各类用户群体的图片风格与难度设置。不论是旨在轻松娱乐,还是益智教育的目的,该软件都是一款家庭生活中以及学习生活的必备软件。
设计并实现基于Java组件技术的拼图游戏软件作为自己的毕业课题设计是对学校基础课程、专业课程以及实践课程的一次综合性考查。此外,Java Swing 组件在单机游戏平台上的应用一直处于热门,这次的系统全面的实践可以说是一次很好的锻炼,会对以后工作生活带来积极的影响。
第二章 关键技术
一、Java平台及体系
1、Java SE 标准版:是各种应用平台的基础,主要应用于桌面开发和低端商务应用的解决方案。
2、Java EE 企业版:以企业为环境开发应用程序的解决方案,这个版本以前称为J2EE。
3、Java ME 微型版:为在移动设备和嵌入式设备上运行的应用程序提供一个健壮且灵活的环境。
二、Java SE环境安装和配置
JRE(Java Runtime Environment,Java运行时环境)JVM(Java Virtual Machine,Java虚拟机)主要作用是进行Java程序的运行和维护。Java API(应用程序编程接口)主要作用是为编程人员提供已经写好的功能, 便于快速开发。Java 编译器(javac.exe)、Java运行时解释器(java.exe)、Java文档化工具(javadoc.exe)及其他工具和资源。其中JRE的三项主要功能如下:(这三项功能的作用基本上都是以安全为出发点)加载代码:由类加载器(Class Loader)完成。校验代码:由字节码校验器(Bytecode Verifier)完成。执行代码:由运行时解释器(Runtime Interpreter)完成。
三、Java语言
JAVA是Sun Microsystem 公司开发的编程语言,是一个简单,面向对象,分布式解释性,强壮,安全,与系统无关,可移植,高性能,多线程和动态的语言。下面简单介绍一下JAVA的基本特点。
(1)简单性
JAVA与C++语言非常相近,但Java比C++简单,它抛弃了C++中的一些不是绝对
必要的功能,如头文件、预处理文件、指针、结构、运算符重载、多重继承以及自动强迫同型。JAVA 实现了自动的垃圾收集,简化了内存管理的工作。
(2)面向对象
JAVA提供了简单的类机制和动态的构架模型。对象中封装了它的状态变量和方法,很好地实现了模块化和信息隐藏;而类则提供了一类对象的原型,通过继承和重载机制,子类可以使用或重新定义父类或超类所提供的方法,从而既实现了代码的复用,又提供了一种动态的解决方案。
(3)多线程
多线程使应用程序可以同时进行不同的操作,处理不同的事件。在多线程机
制中,不同的线程处理不同的任务,他们之间互不干涉,不会由于一处等待影响其他部分,这样容易实现网络_上的实时交互操作。
(4)分布性
Java是面向网络的语言。通过它提供的类库可以处理TCP/IP协议,用户可以通过URL地址在网络上很方便的访问其他对象。
(5)体系结构中立
Java是一种网络语言,为使Java程序能在网络的任何地方运行,Java 解释器生成与体系结构无关的字节码结构的文件格式。为了使Java的应用程序能不依赖于具体的系统,Java 语言环境还提供了用于访问底层操作系统功能的类组成的包,当程序使用这些包时,可以确保它能运行在各种支持Java的平台上。
(6)安全性
用于网络、分布环境下的Java必须要防止病毒的入侵,Java 不支持指针,一切对内存的访问都必须通过对象的实例变量来实现,这样就防止了程序员使用欺骗手段访问对象的私有成员,同时也避免了指针操作中容易产生的错误。
(7) JAVA 中输入/输出流概念
过滤流DataInputStream和DataOutputStream除了分别作为FilterInputStream 和Filter0utputStream的子类外,还分别实现了接口DataInput和Data0utput。接口DataInput中定义的方法主要包括从流中读取基本类型的数据、读取一行数据、或者读取指定长度的字节数,如readBoolean()、readInt()、readLine()、readFul1y() 等。接口Data0utput中定义的方法主要是向流中写入基本类型的数据或者写入一定长度的字节数组,如writeChar()、writeDouble()。DataInputStream可以从所连接的输入流中读取与机器无关的基本类型数据用以实现一种独立于具体平台的输入方式;DataOutputStream可以向所连接的输出流写入基本类型的数据。
四、Java的其他相关技术及功能
(一)、Java 虚拟机

Java虚拟机可以理解为一个可运行Java字节码的虚拟计算机系统软件,它有一个解释器组件,可以实现Java字节码和计算机操作系统之间的通信。对于不同的运行平台,有不同的Java虚拟机。Java虚拟机屏蔽了底层运行平台的差别,实现了一次编译,到处运行。
Java虚拟机在编译和运行期间所做的工作如下图所示。

首先程序员通过编译工具软件将源代码编译成class字节码文件,Java虚拟机会根据设定好的classpath路径找到对应的class文件,通过java.exe运行工具来运行class字节码文件。然后虚拟机找到对应的class文件进行装载,在进行校验、解释。最后交给操作系统控制硬件执行。或通过JIT(Just in Time)编译器将class文件快速交给操作系统控制硬件执行,这些都是由虚拟机自动完成的,其解释器和JIT运行的区别主要体现在以下两个方面。
(1)解释器:每扫描一行,执行一行指令,就如同同声翻译一样,发言人员说一句,翻译人员就翻译一句,效率比较低。
(2)JIT代码生成器:将整个代码一次性翻译完,然后一次性运行,效率稍高。
(二)、ECLIPSE简介
Eclipse是一个开放源代码的、基于Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。幸运的是,Eclipse附带了一个标准的插件集,包括Java 开发工具(Java Development Tools, JDT)。
Eclipse是著名的跨平台的自由集成开发环境(IDE)。最初主要用来Java语言开发,但是目前亦有人通过插件使其作为其他计算机语言比如C++和Python的开发工具。Eclipse的本身只是一个框架平台,但是众多插件的支持使得Ec1 ipse拥有其他功能相对
固定的IDE软件很难具有的灵活性。
Eclipse最初由0TI和IBM两家公司的IDE产品开发组创建,起始于1999年4月。IBM提供了最初的Eclipse代码基础,包括Platform、JDT和PDE。目前由IBM牵头,围绕着Eclipse项目已经发展成为了一个庞大的Eclipse联盟,有150多家软件公司参与到Eclipse项目中,其中包括Borland、Rational Software、RedHat及Sybase等。Eclipse是-一个开发源码项目,它其实是Visual Age for Java 的替代品,其界面跟先前的Visual Age for Java 差不多,但由于其开放源码,任何人都可以免费得到,并可以在此基础上开发各自的插件,因此越来越受人们关注。近期还有包括Oracle在内的许多大公司也纷纷加入了该项目,并宣称Eclipse将来能成为可进行任何语言开发的IDE集大成者,使用者只需下载各种语言的插件即可。
Eclipse是一个开放源代码的软件开发项目,专注于为高度集成的工具开发提供一个全功能的、具有商业品质的工业平台。它主要由Eclipse项目、Eclipse工具项目和Eclipse技术项目三个项目组成,具体包括四个部分组成----Eclipse、Platform、JDT、CDT和PDE。JDT 支持Java开发、CDT 支持C开发、PDE 用来支持插件开发,Eclipse Platform 则是-一个开放的可扩展IDE,提供了-一个通用的开发平台。它提供建造块和构造并运行集成软件开发工具的基础。Eclipse Platform 允许工具建造者独立开发与他人工具无缝集成的工具从而无须分辨一个工具功能在哪里结束,而另一个工具功能在哪里开始。
本次程序中环境为JDK1.6,同时运用了eclipse开发工具。
第三章 系统需求分析及可行性分析
一、需求分析
(一)、功能需求
1、实现图片的切割及随机分布。
2、实现拼图游戏的拼图功能。
3、在数据栏里添加退出游戏、历史记录、当前步数和当前难度的功能。
4、实现鼠标事件响应模块功能
(二)、环境需求
1、下载安装jdk8.0软件包,将jdk安装后的bin目录路径复制下来,配置系统环境变量。
2、操作系统可以有以下几种:Win XP/Win Vista/Win 10。
3、硬件要求:因特尔处理器,主频2.0GHz,4G以上内存。
二、可行性分析
由于软件是一个初级产品,对其要求不是太苛刻,所以能够保证达到拼图游戏的一般功能。为避免开发失误,保证新系统的成功和运行,从技术、经济和社会三方面对被系统的可行性进行了分析和研究。
通过研究分析拼图游戏所具备的能力及实现的方法来确定主题结构。利用现阶段我所能达到的能力,以最简洁、最容易的办法,边开发边测试边修改,实现一个入门游戏软件。
(一)、技术可行性
本系统的开发基于Swing技术的拼图游戏开发。Swing 可以轻松开发功能丰富的应用程序。现有的技术已较为成熟,硬件、软件的性能要求、环境条件等各项条件良好,利用现有技术条件可以达到该系统的功能目标。本人在学校期间已
经掌握Java设计思想和代码编写。同时,考虑给予的开发期限也较为充裕,预计系统是可以在规定期限内完成开发的。
因此,java 拼图游戏具有技术可行性。
(二)、经济可行性
具有信息化的处理设施,并且拥有支持本系统的应用平台。因此无需再投入资金购买其他设施。系统的开发基于本人对程序开发的实践学习而来,无需资金投入,并且软件开发过程投入的成本不高,因此开发经费完全可以接受。游戏开发成功后可以提供娱乐、休闲等。
因此,java 拼图游戏开发也具有经济可行性。
(三)、社会可行性
本系统对用户的要求,除了需要具备在Microsoft Windows平台上使用个人电脑的知识外,并不需要特别的技术能力。在投入使用前,无需对操作系统的人员进行培训。这样既减少投入成本又简化了操作环节。
因此,java 拼图游戏也具有社会可行
第四章 游戏分析
本游戏为了设计、实现和后期维护的方便,以及游戏用户使用的便利,所以必须采取一定的设计原则。其主要设计原则有:
简单性:在实现游戏的功能的同时,尽量让游戏操作简单易懂,这对于一个游戏来说是非常重要的。
针对性:本游戏设计是针对java拼图游戏的需求定向开发设计,所以具有专业突出和很强的针对性。
实用性:要求本游戏能够满足java拼图游戏的需要,因此具有良好的实用性。
一致性:页面整体设计风格以及命名规则的一致性:整体框架和用图用色风格及变量、类名和其他元素的命名规则保持-致。功能一致性:完成同样的功能应该尽量使用同样的元素。元素风格一致性:界面元素的美观风格、摆放位置在同一个界面和不同界面之间都应该是一致的。变量命名规则的一致性:变量应该用统一的规则进行命名,做到任意变量均能从上下文推断其义。
先进性:本游戏采用eclipse做为开发工具,使用swing技术开发,软件具有良好的兼容性和游戏稳定性。因此本设计具有良好的先进性。
一、游戏流程分析
在进行游戏业务流程分析时,需要按照原有信息流动过程,逐个的调查分析所有环节的处理业务、处理内容、处理顺序和对处理时间的要求,弄清各个环节需要的信息、信息来源、流经去向、处理方法、计算方法、提供信息的时间和信息形态。
游戏流程分析可以帮助开发者了解该游戏处理过程,发现和处理游戏调查工作中的错误和疏漏。
Java拼图游戏的具体的流程图,流程如图4.1所示。
图4.1流程图
二、总体设计方案
游戏非常的简单,当运行程序后,设计本程序能够载入默认图片,第一关3*3为9格,第二关4*4为16格,第三关5*5为25格。在本程序中,对于图片的拼凑、判断图片是否可以移动等都是设计的关键。总体设计方案中主要说明判断拼图是否成功这点的设计。
把分好的图片存储到一个image数组中,对于可移动的块其实是一个按钮,每个按钮上都有一个icon,通过image数组中的图片通过imageicon的转化附给一个按钮,并将按钮数组首先附给一个向量,然后用随机数来确定对应向量的值,然后再附给对应数组按钮,同时去除该值。也就是说在附值的时候图片顺序不变,变的而是数组按钮的顺序。
对于图片的是否拼图成功提示,主要是在每个按钮中加个String的属性值,而且对于正确的排序的值与正在排的各个值比较,一旦所有的按钮对应值与正确的排序一致,则为成功。
三、游戏功能分析
程序运行主窗口显示程序界面,运行后可以直接开始,在拼图过程中无法重新开局,可以点击“退出”按钮,再次运行重新开始游戏,只有拼图成功才可以进行下一关。
在窗口的右边有一个“数据栏”,里面有难度、步数、历史记录和退出按钮,以及原图,如图所示4.3。

图4.3
第五章 游戏设计
一、游戏功能设计
运行程序直接进入程序界面,运行后即可开始游戏,直到通过当前关卡才可以进入下一关,难度增加,图片刷新。共三关,第一关简单,第二关中等,第三关困难。可以点击“退出”按钮后退出,再次运行程序后重新开始。如图5.1所示。
图5.1
(一)、游戏框架
游戏框架根据难度不同,框架不断变化。第一关难度简单格数为16块,而框架较大。第二关和第三关难度为正常和困难块数较多则框架较小。这是块与块之间的框架,而总体的框架是不变的。如图所示5.1.1。


图5.1.1
正如图5.1.1块与块之间不同,难度不同块数不同。第一关的块的框架是3*3块数为9块,第二关就不同为4*4块数为16,难度越高块数越多,共三关。但是大的框架是不变的是由setSize(850,750)建立的窗口。
主要代码如下:
public GameClient(){
HelpPanel panel = new HelpPanel(1);
panel2 = new GamePanel(1);//难度简单
panel2.setLayout(new BorderLayout());
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(panel,BorderLayout.EAST);
this.getContentPane().add(panel2,BorderLayout.CENTER);
this.setSize(850,750);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("人物拼图游戏");
this.setVisible(true);
}
public static void main(String[] args) {
new GameClient();
}
}
这个是运行代码,刚开始时的窗口。
if(level == EASY){
pics = new Image[9];
map = mapUtil.getMap(level);
W = 40;
int w = width/3;
int h = height/3;
for(int i=0;i<8;i++){
int x = i%3*w;
int y = i/3*h;
pics[i] = bufferedImage.getSubimage(x, y, w, h);
}
}else if(level == NORMAL){
pics = new Image[16];
map = mapUtil.getMap(level);
W = 30;
int w = width/4;
int h = height/4;
for(int i=0;i<15;i++){
int x = i%4*w;
int y = i/4*h;
pics[i] = bufferedImage.getSubimage(x, y, w, h);
}
}else{
pics = new Image[25];
map = mapUtil.getMap(level);
W = 24;
int w = width/5;
int h = height/5;
for(int i=0;i<24;i++){
int x = i%5*w;
int y = i/5*h;
pics[i] = bufferedImage.getSubimage(x, y, w, h);
}
}
(二)、游戏难度
实现游戏难度功能是比较简单的,它是随着关数不同难度也不一样。本游戏共三关,难度分别为:“简单”、“正常”、“困难”。
主要代码如下:
JLabel levelLabel = new JLabel("当前难度:");
panelNorth.add(levelLabel);
public void setLevel(int level){
this.level = level;
panelCenter.setSuccessPic(level);
if(level == EASY){
nowLevel.setText("简单");
}else if(level == NORMAL){
nowLevel.setText("正常");
}else{
nowLevel.setText("困难");
}
}
(三)、当前步数
当前步数是指本关所走的步数当这一关通过后当前步数清零,所走的步数越少会被记录历史记录。
主要代码如下:
JLabel nowStepLabel = new JLabel("当前步数:");
panelNorth.add(nowStepLabel);
private void RandomTheMap() {
int i =0;
//尝试移动一万次
while(i<10000){
int rate = (int) (Math.random()*100);
if(rate<25&&blank_x!=level+1){
moveUp();
i++;
}else if(rate<50&&blank_x!=0){
moveDown();
i++;
}else if(rate<75&&blank_y!=level+1){
moveLeft();
i++;
}else if(rate<100&&blank_y!=0){
moveRight();
i++;
}
}
(四)、历史记录
历史记录是指在本关所玩中步数最少的记录。通过File record 储存在D://GameRecordAboutSwing/recordJigsawGame.txt中。
主要代码如下:
JLabel historyStepLabel = new JLabel("历史记录:");
panelNorth.add(historyStepLabel);
panelNorth.add(histotyStep);
public int getRecord(int level){
File file = new File("D://GameRecordAboutSwing");
if(!file.exists()){
file.mkdirs();
}
File record = new File("D://GameRecordAboutSwing/recordJigsawGame.txt");
try{
if(!record.exists()){//如果不存在,新建文本
record.createNewFile();
fos = new FileOutputStream(record);
dos = new DataOutputStream(fos);
String s = "9999,9999,9999";
dos.writeBytes(s);
System.out.println(record.isFile());;
}
//读取记录
fis = new FileInputStream(record);
dis = new DataInputStream(fis);
String str = dis.readLine();
array = str.split(",");
}catch(Exception e){
e.printStackTrace();
}finally{
try {
if(fis!=null)
fis.close();
if(dis!=null)
dis.close();
if(fos!=null)
fos.close();
if(dos!=null)
dos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return Integer.parseInt(array[level-1]);
}
//更新关卡历史记录
public void writeRecord(int level,int step){
File record = new File("D://GameRecordAboutSwing/recordJigsawGame.txt");
try {
//清空原有记录
FileWriter fileWriter =new FileWriter(record);
fileWriter.write("");
fileWriter.flush();
fileWriter.close();
//重新写入文本
fos = new FileOutputStream(record);
dos = new DataOutputStream(fos);
array[level-1] = step+"";
String s = array[0]+","+array[1]+","+array[2];
dos.writeBytes(s);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
if(fos!=null)
fos.close();
if(dos!=null)
dos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
(五)、右侧数据栏
数据栏是运行程序后随游戏一起出现的一些数据包括:“当前难度”、“当前步数”、“历史记录”和“退出”按钮以及原图。如图所示5.1.5

图5.1.5
如上图5.1.5中的“当前难度”、“当前步数”和“历史记录”详解在5.1.2、5.1.3、5.1.4中。
数据栏主要代码如下:
private int level = 1;
public static final int EASY = 1,NORMAL = 2,HARD = 3,BLANK_STATE = -1;
static JLabel nowStep = new JLabel("0");
static JLabel histotyStep = new JLabel("9999");
static JLabel nowLevel = new JLabel();
JLabel levelLabel = new JLabel("当前难度:");
JLabel nowStepLabel = new JLabel("当前步数:");
JLabel historyStepLabel = new JLabel("历史记录:");
JButton button1 = new JButton("退出");
BorderLayout panel1 = new BorderLayout();//右侧
JPanel panelNorth = new JPanel(new GridLayout(4,2,10,30));
static SuccessPanel panelCenter = new SuccessPanel(1);
public HelpPanel(int level){
setLevel(level);
this.setVisible(true);
this.setLayout(new BorderLayout());//当前面板
panelNorth.add(levelLabel);
panelNorth.add(nowLevel);
panelNorth.add(nowStepLabel);
panelNorth.add(nowStep);
panelNorth.add(historyStepLabel);
panelNorth.add(histotyStep);//历史记录
panelNorth.add(button1);
this.add(panelNorth,BorderLayout.NORTH);
this.add(panelCenter,BorderLayout.CENTER);
button1.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e){
System.exit(1);
});
}
(六)、通关提示
这是在通过这一关,前往下一关的提示,提示内容是:“恭喜你通过正常关卡,完成步数是"+step+"n是否要进入下一关?”,这个内容是在没有刷新记录的情况下。还有一个是:“恭喜你通过正常关卡并刷新历史记录,完成步数是"+step+"n历史记录是"+record+",是否要进入下一关?”,这个是在刷新记录的下提示的。由JOptionPane单词形成对话框提示。如图所示5.1.6

图5.1.6
主要代码如下:
if(flag){
String msg;
int type;
int choice;
int record;
String title;
switch(level){//通关,是否进入下一关
case EASY:
this.removeKeyListener(this);
this.removeMouseListener(this);
record = mapUtil.getRecord(level);//历史记录
if(step<record){
msg = "恭喜你通过简单关卡并刷新历史记录,完成步数是"+step+"n历史记录是"+record+",是否要进入下一关?";
mapUtil.writeRecord(level, step);//更新历史记录
}else{
msg = "恭喜你通过简单关卡,完成步数是"+step+"n是否要进入下一关?";
}
type = JOptionPane.YES_NO_OPTION;
title = "过关";
choice = 0;
choice = JOptionPane.showConfirmDialog(null, msg,title,type);
if(choice==1){
System.exit(0);
}else if(choice == 0){
level++;
map = mapUtil.getMap(level);
successMap = mapUtil.getMap(level);
record = mapUtil.getRecord(level);//获取正常难度的历史记录
initializeMap();//初始化地图相关变量信息
RandomTheMap();//打乱图案顺序
step = 0;
HelpPanel.histotyStep.setText(record+"");
HelpPanel.panelCenter.setSuccessPic(level);
HelpPanel.nowLevel.setText("正常");
HelpPanel.nowStep.setText(step+"");
getPics();
this.addKeyListener(this);
this.addMouseListener(this);
repaint();
}
;break;
case NORMAL:
this.removeKeyListener(this);
this.removeMouseListener(this);
record = mapUtil.getRecord(level);//历史记录
if(step<record){
msg = "恭喜你通过正常关卡并刷新历史记录,完成步数是"+step+"n历史记录是"+record+",是否要进入下一关?";
mapUtil.writeRecord(level, step);//更新历史记录
}else{
msg = "恭喜你通过正常关卡,完成步数是"+step+"n是否要进入下一关?";
}
type = JOptionPane.YES_NO_OPTION;
title = "过关";
choice = 0;
choice = JOptionPane.showConfirmDialog(null, msg,title,type);
if(choice==1){
System.exit(0);
}else if(choice == 0){
level++;
map = mapUtil.getMap(level);
successMap = mapUtil.getMap(level);
initializeMap();//初始化地图相关变量信息
RandomTheMap();//打乱图案顺序
getPics();
step = 0;
record = mapUtil.getRecord(level);//获取困难难度的历史记录。
HelpPanel.histotyStep.setText(record+"");
HelpPanel.panelCenter.setSuccessPic(level);
HelpPanel.nowStep.setText(step+"");
HelpPanel.nowLevel.setText("困难");
this.addKeyListener(this);
this.addMouseListener(this);
repaint();
}
;break;
case HARD:
this.removeKeyListener(this);
this.removeMouseListener(this);
record = mapUtil.getRecord(level);//历史记录
if(step<record){
msg = "恭喜你通过困难关卡并刷新历史记录,完成步数是"+step+"n历史记录是"+record;
JOptionPane.showMessageDialog(this, msg);
mapUtil.writeRecord(level, step);//更新历史记录
}else{
msg = "恭喜通过困难关卡,完成步数是"+step;
JOptionPane.showMessageDialog(this, msg);
}
;break;
}
}
}
以上是通过提示代码,里面还有通过这一个打乱下一关的图片的代码。
二、游戏重点设计
这是程序运行后显示出来的界面,运行后图片打乱,右边有数据栏,里面有“当前难度”难度分为简单、正常、困难,“当前步数”是显示当前关卡所走的步数,“历史记录”是记录通过此关的最少步数和“退出”按钮是退出游戏,运行程序后重新开始。一共三关3幅图片,每关有规定的图片。如图所示5.2

图5.2程序运行效果
这个游戏程序简单易懂。在这里重要的介绍一下,图片的载入图片,换下一张图片,运行程序后打乱图片的算法和拼图过程中交换图片的算法。
(一)、开局载入图片
将素材放在D:GameJigsawGame路径下,在由bufferedImage语句和image单词进行导入代码中,每个图片的原图由“.png”格式命名。如图5.2.1所示

图5.2.1
根据图5.2.1所示,把图片进行分割打乱。根据上文的命名,用“pic+level+”载入图片。
部分代码如下:
private void getPics() {
BufferedImage bufferedImage = null;
int width = 0,height = 0;
try {
bufferedImage = ImageIO.read(new File("D:/Game/JigsawGame/pic"+level+".png"));
width = bufferedImage.getWidth();
height = bufferedImage.getHeight();
} catch (IOException e) {
e.printStackTrace();
}
(二)、游戏时排序图片
载入游戏时用RandomTheMap()打乱图片顺序,再用for把打乱的图片镶嵌的每个空格中。当图片行与图片行的差的绝对值的和等于1的时候,就是说明两张图片的位置可以交换啦。比如两图片的位置为【3.0】【3.1】,|(3-3)|+|(0-1)|=1;这样程序就判断两张图片是可以交换位置的。
部分代码如下:
public GamePanel(int level){
setSize(600, 600);
this.level = level;
map = mapUtil.getMap(level);
successMap = mapUtil.getMap(level);
initializeMap();//初始化地图相关变量信息
RandomTheMap();//打乱图案顺序
this.setVisible(true);
this.addKeyListener(this);
this.addMouseListener(this);
this.setFocusable(true);
getPics();
record = mapUtil.getRecord(level);
HelpPanel.histotyStep.setText(record+"");
HelpPanel.nowStep.setText(step+"");
repaint();
}
public void paint(Graphics g){
g.clearRect(0, 0, this.getWidth(), this.getHeight());
for(int i=0;i<map.length;i++)
for(int j=0;j<map.length;j++){
if(map[i][j]!=BLANK_STATE){
//画图
g.drawImage(pics[map[i][j]-
1],leftX+j*W,leftY+i*W,W,W,this);
(三)、判断拼图是否移动
判断图与图之间是否移动是拼图游戏的关键环节。使用movedown、moveup、moveright、moveleft单词实现与空快之间的上下左右移动。Blank代表空快。算法是【blank-x】【blank-y】=【blank-x-1】【blank-y】。然后用step记录步数。
部分代码如下:
private void moveDown(){
map[blank_x][blank_y] = map[blank_x-1][blank_y];
map[blank_x-1][blank_y] = BLANK_STATE;
blank_x = blank_x-1;
step++;
HelpPanel.nowStep.setText(step+"");
}
//空块与下一格交换
private void moveUp(){
map[blank_x][blank_y] = map[blank_x+1][blank_y];
map[blank_x+1][blank_y] = BLANK_STATE;
blank_x = blank_x+1;
step++;
HelpPanel.nowStep.setText(step+"");
}
//空块与左一格交换
private void moveRight(){
map[blank_x][blank_y] = map[blank_x][blank_y-1];
map[blank_x][blank_y-1] = BLANK_STATE;
blank_y = blank_y-1;
step++;
HelpPanel.nowStep.setText(step+"");
}
//空块与右一格交换
private void moveLeft(){
map[blank_x][blank_y] = map[blank_x][blank_y+1];
map[blank_x][blank_y+1] = BLANK_STATE;
blank_y = blank_y+1;
step++;
HelpPanel.nowStep.setText(step+"");
}
第六章 实现及测试
一、测试的重要性
软件测试不仅可以发现问题,还可以预防问题,降低风险等多种目的。测试是很重要的一个环节,如果没有做好,或许会对公司造成损失的要测试、影响客户体验的也需要测试指出。软件测试主要是要心细,一个软件往往大错误不多,最多的就是隐藏的bug。说通俗一点就是为了找出软件里面有没有bug,比如我开发了一个购物的软件,然后我在里面买东西,发现不用付款就可以结账成功,然后大量的人通过这个渠道买东西造成了公司大量损失。软件测试的作用就是去发现并指出问题的一个职业,对一个好的软件测试员来说,一个软件有很多的地方需要去测试,不仅是会造成损失的要测试、影响客户体验的也需要测试指出。这对一个产品的影响是非常大的,严重的可能直接无法使用,这么久的努力就白费了。所以学好软件测试是非常重要的,毕竟这也是为什么它前景好、工资高的的原因之-嘛!
二、测试结果
如图6.2.1图6.2.2为不同难度效果图

图6.2.1

图6.2.2
如图6.2.3图6.2.4为过程和通过效果图

图6.2.3

图6.2.4
总 结
相信在大学期间,很多同学都参与过或者是编写过拼图游戏软件的程序,那么这次作为毕业设计,要想更加出色的完成这个课题,并且具有独特之处,就是我编写程序之前首先要考虑到的问题。但是,对于拼图游戏而言,寻找游戏的创新突破口也有一定的难度。除了对于游戏功能方面的创新,还在制作拼图游戏的选材方面寻求突破,也就是对游戏界面的设计多花心思,多下功夫。尽力去满足更多用户群体的需求,争取满足不同用户的喜好。在做毕业设计以前,我对Java 游戏开发只是停留在理论知识的水平上,是“纸上谈兵”,缺乏实际的软件开发经验。这次通过做毕业设计,我完成了拼图游戏的软件开发任务。在整个开发过程中也遇到了很多问题,如载入图片的处理,随机排列图片,图片移动等。对其设计体会总结如下:
1.为了熟悉拼图游戏的相关运作和功能设计,我从网上下载了各种拼图游戏,了解并研究各自的功能设计,总结出哪些是好的功能设计,哪些是不必要的设计。对尝试过的拼图游戏进行总结,将各自的优点融入我的设计之中。
2. 完成了从“小而全”,到“全而精”的转变。设计过程中,经常会遇到困难,我学会通过反复思考和测试,找出自己的错误并加以改正,再进行下一个步骤。这个程序就是在这样反复的发现错误、改正错误中完成的。完成游戏雏形之后,再进行逐步的完善。
3.这是一个不断学习新鲜事物的过程,从设计初的不懂到最后能够顺利完成,我体会到在实践中学习的重要性,这对于将来我走上工作岗位具有重要意义,相信这也是布置此项毕业设计的初衷。
对于今后Java Swing 组件开发游戏的前景,相信绝大多数人给出的答案都是肯定的。的确,Java Swing组件给单机游戏市场带来了--股力量,在游戏市场所做出的贡献、对软件开发人员带来的便利,毋庸置疑。相信十年甚至几十年,单机游戏市场还会随着Java Swing 组件的这股力量继续稳步发展。也许若干年后,基于Java Swing组件的开发技术又能创造更辉煌的历史,也许那时候,游戏的界面会变得更加的生动、更加的逼真,能够给游戏玩家带来更高端的游戏体验。
致 谢
首先在这里要忠心地感谢老师对我们的教导和帮助,没有你的教育我们就不会好地掌握这方面的知识,更不能很好达到这次设计的目的。在设计的时候老师能够认真分析我们的出错和不足的地方,然后给我们提出一些修改建议,并对自己的意见详细讲给我们听,这些对于程序的完善提供了很好的帮助,这也给我们以后的设计提供了很好的设计分析的注意之处。此外还要谢谢其他同学,在我设计的时候他们也提供了很多宝贵的意见。没有大家的帮助,我的设计也不能做的令自己满意的。
参考文献
[1] 廖弘智,黄宗仁.Java轻松上手[M],北京:机械工业出版社:2008:52
[2]朱站立.Java程序设计实用教程[M],电子工业出版社,2006.10:58-70
[3] 肖旻.JAVA程序设计教程[M],北京:中国电力出版社,2003:75
[4]李斌.Java语言的特点管理[J],科学文摘,2009:03
[5]陈冲,麦中凡.Java语言特点及开发工具JDK[J],微电脑世界,2008:08
[6]陆慧恩.实用软件工程[M],北京:清华大学出版社,2006:105-110
[7]叶核亚.Java2程序设计实用教程[M],北京:电子工业出版社,2007:89-91
[8]郑莉.Java语言程序设计[M],清华大学出版社,2007.01:67-75
[9]朱福喜.Java程序设计技巧与开发实例[M],北京:人民邮电出版社,2004: 8-90
[10]唐大仕.Java程序设计[M],北方交通大学出版社,2007.05:56-62
附 录
GameClient
public class GameClient extends JFrame{
GamePanel panel2;
public GameClient(){
HelpPanel panel = new HelpPanel(1);
panel2 = new GamePanel(1);//难度简单
panel2.setLayout(new BorderLayout());
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(panel,BorderLayout.EAST);
this.getContentPane().add(panel2,BorderLayout.CENTER);
this.setSize(850,750);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("人物拼图游戏");
this.setVisible(true);
}
public static void main(String[] args) {
new GameClient();
}
}
HelpPanel
public class HelpPanel extends JPanel {
private int level = 1;
public static final int EASY = 1,NORMAL = 2,HARD = 3,BLANK_STATE = -1;
static JLabel nowStep = new JLabel("0");
static JLabel histotyStep = new JLabel("9999");
static JLabel nowLevel = new JLabel();
JLabel levelLabel = new JLabel("当前难度:");
JLabel nowStepLabel = new JLabel("当前步数:");
JLabel historyStepLabel = new JLabel("历史记录:");
JButton button1 = new JButton("退出");
BorderLayout panel1 = new BorderLayout();//右侧
JPanel panelNorth = new JPanel(new GridLayout(4,2,10,30));
static SuccessPanel panelCenter = new SuccessPanel(1);
public HelpPanel(int level){
setLevel(level);
this.setVisible(true);
this.setLayout(new BorderLayout());//当前面板
panelNorth.add(levelLabel);
panelNorth.add(nowLevel);
panelNorth.add(nowStepLabel);
panelNorth.add(nowStep);
panelNorth.add(historyStepLabel);
panelNorth.add(histotyStep);//历史记录
panelNorth.add(button1);
this.add(panelNorth,BorderLayout.NORTH);
this.add(panelCenter,BorderLayout.CENTER);
button1.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e){
System.exit(1);
}
});
}
public void setLevel(int level){
this.level = level;
panelCenter.setSuccessPic(level);
if(level == EASY){
nowLevel.setText("简单");
}else if(level == NORMAL){
nowLevel.setText("正常");
}else{
nowLevel.setText("困难");
}
}
}
MapUtil
public class MapUtil {
int[][] map;
FileInputStream fis = null;
FileOutputStream fos = null;
DataInputStream dis = null;
DataOutputStream dos = null;
String array[] = null;
int level = 1;
public static final int EASY = 1,NORMAL = 2,HARD = 3,BLANK_STATE = -1;
public int[][] getMap(int level){
switch(level){
case EASY:
map = new int[3][3];
for(int i=0;i<3;i++)
for(int j=0;j<3;j++){
map[i][j] = 3*i+j+1;
}
map[2][2] = BLANK_STATE;
;break;
case NORMAL:
map=new int[4][4];
for(int i=0;i<4;i++)
for(int j=0;j<4;j++){
map[i][j] = 4*i+j+1;
}
map[3][3] = BLANK_STATE;
break;
case HARD:
map=new int[5][5];
for(int i=0;i<5;i++)
for(int j=0;j<5;j++){
map[i][j] = 5*i+j+1;
}
map[4][4] = BLANK_STATE;
break;
}
return map;
}
//获取关卡历史记录
public int getRecord(int level){
File file = new File("D://GameRecordAboutSwing");
if(!file.exists()){
file.mkdirs();
}
File record = new File("D://GameRecordAboutSwing/recordJigsawGame.txt");
try{
if(!record.exists()){//如果不存在,新建文本
record.createNewFile();
fos = new FileOutputStream(record);
dos = new DataOutputStream(fos);
String s = "9999,9999,9999";
dos.writeBytes(s);
System.out.println(record.isFile());;
}
//读取记录
fis = new FileInputStream(record);
dis = new DataInputStream(fis);
String str = dis.readLine();
array = str.split(",");
}catch(Exception e){
e.printStackTrace();
}finally{
try {
if(fis!=null)
fis.close();
if(dis!=null)
dis.close();
if(fos!=null)
fos.close();
if(dos!=null)
dos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return Integer.parseInt(array[level-1]);
}
//更新关卡历史记录
public void writeRecord(int level,int step){
File record = new File("D://GameRecordAboutSwing/recordJigsawGame.txt");
try {
//清空原有记录
FileWriter fileWriter =new FileWriter(record);
fileWriter.write("");
fileWriter.flush();
fileWriter.close();
//重新写入文本
fos = new FileOutputStream(record);
dos = new DataOutputStream(fos);
array[level-1] = step+"";
String s = array[0]+","+array[1]+","+array[2];
dos.writeBytes(s);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
if(fos!=null)
fos.close();
if(dos!=null)
dos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
SuccessPanel
版权声明:
1.大文斗范文网的资料来自互联网以及用户的投稿,用于非商业性学习目的免费阅览。
2.《基于Java小游戏拼图的设计与实现》一文的著作权归原作者所有,仅供学习参考,转载或引用时请保留版权信息。
3.如果本网所转载内容不慎侵犯了您的权益,请联系我们,我们将会及时删除。
