UDC _______________ 学号_ _
毕业设计(论文)
论文题目

JAVA扫雷游戏的设计与实现
Thesis Topic
Design and Implementation of Mine Game
毕业设计(论文)任务书
毕业设计(论文)题目:JAVA扫雷游戏的设计与实现毕业设计(论文)哀求及原始数据(资料):1.学习和节制打算机编程干系的基本知识;2.理解和利用JAVA面向工具的特色;3.熟习JAVA的可移植性,跨平台性等多种特性;4.设计并实现扫雷游戏的基本功能;5.深入剖析扫雷游戏的算法实现;6.演习检索文献资料和利用文献资料的能力;7.演习撰写技能文档与学位论文的能力。
毕业设计(论文)紧张内容:1.进行可行性剖析以及需求剖析;2.论述毕业设计所需开拓环境以及开拓工具;3.实现程序的概要设计; 4.在概要设计的根本上进行详细设计,编写实现各个类;5. 展示JAVA编程的扫雷游戏源代码;6.进行系统测试。学生应交出的设计文件(论文):1.内容完全、层次清晰、阐述流畅、排版规范的毕业设计论文;2.包括毕业设计论文、源程序等内容在内的毕业设计电子文档及其它干系材料。
紧张参考文献(资料):秦亮. 利用JAVA实现扫雷游戏的算法解析. 软件开拓与设计(2011年06期)张洪斌. JAVA2高等程序设计[M]. 中科多媒体出版社,2010孙鑫. JAVA WEB 开拓详解[M]. 电子工业出版社, 2006.189-274萨师煊,王珊. 数据库系统概论(第三版)[M]. 北京:高档教诲出版社,2009.王家华. 软件工程[M]. 东北大学出版社,2012尹伟民. JAVA程序设计之网络编程. 北京:中国电力出版社, 2009赵生慧. JAVA面向工具程序设计. 北京:高档教诲出版社, 2010王梅. JAVA并发程序—设计原则与模式. 北京:中国电力出版社, 2008JON TITUS. ECN TECHNICAL EDITOR: “THE ECLIPSE OF STAND[J]. JOURNAL OF ZHONGKAI AGROTECHNICAL COLLEGE” , VOL.19,NO.2, 2006.W.CLAY,RICHARDSON,DONALD,”AVONDOLIO. THE JAVA HIGH CLASS WEAVES A DISTANCE: JDK 5”, SCIENTIFIC & TECHNOLOGY BOOK REVIEW,NO.3,2006ALICE WOUDHUYSEN.CHINA INTERNET:THE LONG MARCH TOWARD E-COMMERCE[J].THEECONOMIST INTELLIGENCE UNIT. 2007
Java扫雷游戏的设计与实现
摘 要扫雷这款游戏有着很长的历史,从扫雷被开拓出来到现在进行了无数次的优化,这款游戏变得越来越让人爱不释手了,大略的玩法在加上一个好看的游戏界面,每一处的细节都表示了扫雷的魅力。以是本次的毕业设计我将开拓一款扫雷游戏。
本次毕业设计因此JAVA措辞作为开拓环境,利用Eclipse设计并开拓一个类似Windows扫雷的游戏,实现其基本功能。论文首先先容了课题背景,其次进行了需求剖析及可行性剖析;然后设计游戏流程,先容雷区中的雷怎么安顿和产生雷的随机算法;末了先容游戏中可能会触发的各种韶光,比如鼠标点击韶光和清理掉没有雷的格子,个中鼠标事宜包括点击到或没有点击到雷触发的事宜和点击到重新开始以及菜单触发的事宜,清理掉没有雷的格子就须要利用“递归”的方法来使该功能可以大略的实现。
关键词:扫雷;Eclipse;事宜;递归
Design and Implementation of Mine Game
AbstractMine the game has a long history, from the mine was developed to now numerous optimization, the game is becoming more and more let a person fondle admiringly, simple style with a nice game interface, every detail reflects the charm of mine. So I'm going to develop a minesweeper game.
The graduate design study was designed with the JAVA language as a development environment, using Eclipse to design and develop a game like Windows minesweeper to implement its basic functions. The paper firstly introduces the background of the project and analyzes the requirements and feasibility analysis. Then the game process was designed to introduce the random algorithm of how the thunder in the minefield was placed and produced. Finally introduced the game may trigger a variety of time, such as a mouse click on the clear time and there is no ray of diamonds, mouse events including click to or no click to ray trigger events and click to restart and menu trigger events, clearing out squares no ray will need to use the "recursive" methods to make the function can be simple to implement.
Key words: Mine game; Visual Basic 6.0; Affairs; Recursion
目 录摘 要i
Abstractii
1绪论1
1.1课题背景及意义1
1.2开拓工具的选用及先容1
1.3选题目的和意义2
1.4本文紧张研究的内容2
2需求剖析3
2.1可行性剖析3
2.2扫雷游戏功能描述3
2.3扫雷游戏用例图4
2.4扫雷游戏功能需求4
2.5扫雷游戏界面需求5
2.6扫雷游戏功能模块6
3游戏的概要剖析与设计7
3.1设计构想7
3.2流程方案8
3.3界面方案9
3.4算法思想9
4游戏的详细设计11
4.1游戏初始化11
4.2雷区的支配12
4.3游戏中紧张模块的先容与利用13
4.3.1鼠标事宜13
4.3.2地雷及雷区表面探测情形14
4.3.3打消未靠近地雷的格子15
4.3.4游戏难度的选择16
4.3.5菜单栏的功能16
4.4游戏的判断16
4.4.1游戏成功完成16
4.4.2游戏失落败16
4.5类设计17
4.5.1MineGame类17
4.5.2Block类18
4.5.3BlockView类19
4.5.4Record类20
4.5.5ShowRecord类21
4.5.6MineArea类22
4.5.7LayMines类23
5游戏实现25
5.1游戏难度自定义25
5.2扫雷28
5.2.1玩家通过右键进行扫雷,并显示小红旗28
5.2.2玩家因触碰到雷而导致游戏结束29
5.2.3玩家扫雷成功29
5.2.4玩家游戏数据显示30
5.3程序打包发布过程32
6游戏测试结果33
6.1游戏难度自定义测试33
6.2扫雷测试35
6.3玩家游戏数据显示测试37
6.4游戏数据显示区测试39
6.5递归算法测试43
结 论44
参考文献45
致 谢47
外文原文48
中文翻译55
绪论课题背景及意义在1964年 有一个叫“方 块”的游戏,这是扫雷最原始的版本。后来,这个游戏被改成了另一种游戏,叫做“Rlogic”。在这个游戏中,玩家扮演了一名军队的军人,接管了一项困难的任务:为指挥中央探路。当然游戏不会这么大略,这条路上充满了地雷,玩家须要小心翼翼的探索出一条没有地雷的安全的道路,如果被雷炸去世游戏就会结束。一年后,汤姆·安德森(Tom Anderson)在之前游戏的根本上又编写了一款新的游戏,这便是扫雷游戏。1979年, 两名工程师在打算机的操作系统上搭载了这款小游戏,从此往后扫雷游戏开始风靡环球。如今,越来越多的人喜好上了这款大略易上手的小游戏,这个小游戏可以在任何韶光在任何平台上进行游戏,让人可以在游戏中享受到乐趣并且还能在一定程度上磨炼玩家的思维能力。扫雷这款游戏有着很长的历史,从扫雷被开拓出来到现在进行了无数次的优化,这款游戏变得越来越让人爱不释手了,大略的玩法在加上一个好看的游戏界面,每一处的细节都表示了扫雷的魅力。以是本次的毕业设计我将开拓一款扫雷游戏。扫雷游戏深受大家的喜好,本次的毕业设计也是迎合大家的喜好,开拓一款扫雷小游戏,同时也可以提高自己编程水平。开拓工具的选用及先容Eclipse是一款非常好用的编译软件,它也经历了很永劫光的发展,并且是由许多公司联合开拓的免费软件。2011年5月,公布稳 定版4.2;2012年4月公布代号为Ganymeode的4.3版;2013年5月公布代号为Galieleo的4.4版;2013年7月公布代号为Helomios的4.5版;2013年11月公布代号为Indigon的4.6版;2014年3月公布代号为Jiuno的5.1版;2014年7月公布代号为Keplere的5.2版;2015年3月公布代号为Lunam的5.3版;2015年8月公布代号为Marse的5.4版。Eclipse是目前主流的编写代码的软件,可以支持预编译,在写代码的同时就能知道是否书写缺点,而不用等到运行的时候才创造。原来这个软件只能编写Java措辞,但是经由多年的开拓设计出了许多的插件,将这些插件安装进去往后就可以编写其他措辞了,这也便是他被大部分人所喜好的缘故原由。正是由于插件的利用,Eclipse变得很灵巧,可以通过安装插件来实现原来没有的功能,让软件更加的便利。Eclipse一开始是由两个团队联合设计开拓出来的,由于该软件的强大功能使得许多公司纷纭加盟该项目联合开拓。而且这个项目是开源的,任何人都能对其进行开拓修正,这让Eclipse的名气愈来愈大,后来连甲骨文这种大公司都加入这个项目之中。这种免费的开拓软件也很受许多公司的喜好,通过安装插件可以利用各种措辞。Java措辞是一种深受大家喜好的措辞,由于它是面向工具的,以是在理解了这种措辞之后就会在代码的设计上有更深刻的理解。如果没有JDK,你编写的Java代码是无法运行的,这是由于我们须要利用他自带的类库来帮助我们设计,由于不同的软件都可以编写代码,措辞规范也就显得尤为主要,以是在开始编写代码之前一定要安装好JDK。现在在网上是有着许许多多的JDK版本,个中以Sun公司发布的最好,其他公司也有开拓并发布出来。有的在性能上乃至超过了Sun公司的JDK,有的则在在实行的效率上高于Sun公司的JDK。但是我们还是选择利用它的缘故原由是由于它是最稳定的JDK,经由多年的开拓和完善,是其他JDK所不能比较的。以是我们要闇练的利用它。选题目的和意义经历了大学四年的学习之后,我已经学习了一些关于设计和编程的理论知识,本次的毕业设计利用学过的知识编写一个扫雷小游戏,是对我平时学习成果的一次考验。在设计当中让我的知识在实践中交融贯通并得到提升,并且能创造许多平常创造不了的问题,期望能通过本次的毕业设计让我的能力再一次提高。这次毕设一定会让我收成许多,在今后的事情生涯中能轻松的胜任任何任务。本文紧张研究的内容扫雷游戏风靡环球,受到很多人的喜好。我研究了这个扫雷游戏之后,创造有两个关键点:第一点是鼠标事宜的处理,包括鼠标点击菜单项中按钮的事宜,点击雷区中任意一格的事宜,点击界面上按钮的事宜等。第二点是初始化雷区,包括随机天生雷的位置,界面的初始化,打算周围雷数等。详细哀求如下:(1)扫雷游戏分为三种难度,分别是初、中、高等,点击游戏左上角的“游戏”菜单后会涌现“低级”、“中级”、“高等”三种选项。除此之外玩家还可以自定义难度。(2)在玩家选择难度之后游戏将会改变界面大小,并改变雷的总数。当玩家点开第一个格子时雷区开始布雷同时计时开始。(3)若玩家想放弃本局游戏并重新开始的话,可以通过点击扫雷信息统计区中的按钮,来结束当前的游戏并开始新的游戏。(4)当玩家认为某个格没有雷,可以直接用鼠标单击这个格或者把鼠标放在该格子上按下空格键。如果玩家的判断是精确的,则会显示周围8个格子中地雷的总数,如果玩家判断缺点,该格子下藏着雷的话,游戏就好结束,系统自动弹框提示玩家失落败。(5)若玩家认为某个格下有雷,在该格子上鼠标右键就可以标记一个玩家认为该格是雷的图标,也便是在格子上标记一个小红旗的图案。玩家每标记一个红旗(不管玩家的判断精确与否),界面上的计数区都会把雷数减一。(6)当所有的雷都标记精确后,游戏会自动弹框显示“您真厉害,请输入您的名字,记录上榜!”。(7)若玩家在游戏过程中单击了有雷的格子,游戏失落败并且记时停滞,游戏会将剩余的雷全部显示出来,自动弹框显示“你输了,请连续努力!
”,之后玩家可以开始一局新的游戏。(8)如果玩家不清楚游辱弄法,可以点击菜单栏上的帮助来获取游辱弄法及游戏窍门。(9)对付自定义难度,系统会有一个阈值,行数在9到16之间,列数在9到30之间,地雷数在10到99之间。如果玩家设置的值超过该阈值,系统会自动将超过的数值变成阈值。需求剖析可行性剖析扫雷游戏是一款玩法大略的小游戏,无论是孩子还是老人,都可以在安歇的时候玩上一局从而轻松而有效地舒缓压力。而且真正的扫雷高手还可以通过竞速(在最短的韶光内完成扫雷)来感想熏染乐趣。(1)投资可行性:扫雷游戏所占内存少,可以搭载在任意平台,有投资的代价。(2)财务可行性:从受益者的角度来看,不需太多的经费就能开拓这款扫雷小游戏。(3)组织可行性:制度可行的项目方案,做年夜大好人员的配给,保持组员间的良好沟通,定期开会谈论,确保项目能够定时交付。(4) 经济可行性:可以给开拓的企业创造效益,给社会增加事情岗位,并且提高人们的生活质量。(5) 法律可行性:任何的产品都须要确保它没有触犯法律才能开始设计。但是扫雷游戏并不会触犯任何法律,而且不会和企业之间发生冲突。游戏的开拓不会陵犯任何人的利益,也不会违法。(6) 技能可行性:扫雷游戏的功能大略,只需稍有履历的开拓职员就能轻易开拓出来,以是技能方面不是太大的问题,紧张须要明白扫雷的玩法才能更好的设计与实现该游戏。扫雷游戏功能描述游戏界面可以分为三个模块:菜单栏,游戏数据显示区域以及雷区。菜单栏包括游戏难度的选择和排行榜的查询以及游戏帮助。游戏数据显示区域包括地雷计数区、计时区和重新开始按钮。雷区便是玩家的游戏区域,当玩家在游戏过程中用鼠标点击某一模块,系统会自动作出相应的相应,这便是游戏中的鼠标事宜。当玩家点开第一个格子时雷区开始布雷同时计时开始。然后会在该格子上显示周围8个格子的雷数(如果没有雷则自动点开周围的格子),玩家就须要通过这些数字来判断雷的位置,将是雷的格子标记为小红旗。若玩家认为已标记的格子时缺点的,可以再次右击该格子来取消标记。当某一格子被标记时,对付该格子的单击操作是无效的(防止玩家误点击导致游戏失落败)。如果玩家将某一格周围8个格子中的雷标记了出来,双击该格子会自动将周围的格子点击一遍,这样可以简化玩家的操作。当玩家将全部的地雷标记出来并且其他的格子点开时,游戏结束。但是如果玩家欠妥心点到了地雷就会游戏失落败,系统自动显示出所有的地雷。如果玩家标识的地雷数量超过了该难度下规定的雷数,计数区会以负数显示超出的雷数并且游戏不会结束。扫雷游戏用例图
图2-1 扫雷游戏用例图从上述扫雷游戏功能描述以及用例图可以剖析出,全体扫雷游戏中,玩家所能进行的操作有:选择难度、开始游戏、重新开始游戏和记录查询等。
扫雷游戏功能需求本次扫雷设计须要实现的紧张功能有:玩家可以选择得当的游戏难度点击游戏界面左上角菜单栏中的“游戏”菜单,会涌现涌现“低级”、“中级”、“高等”、“自定义”四种选项。在玩家选择难度之后游戏将会改变界面尺寸,并改变雷的总数。前三种雷数和尺寸都是固定的,无需玩家设置,而自定义则是玩家自己定义的。进行扫雷游戏游戏界面包括菜单栏,游戏数据显示区域以及雷区,当玩家点击雷区中的任意一格的时候游戏开始,雷区开始随机布雷,玩家须要在最短的韶光内找出雷区中所有的地雷,并加以标识。扫雷的基本操作包括鼠标左键单击和右键单击两种。个中左键用来点开玩家认为不是雷的格子,右键标记玩家认为是雷的格子。左键单击:玩家在判断出该格子下没有雷时单击该格子,可以将该格子点开。如果该格子周围有雷就会显示周围雷的数目(由于周围最多只有8个格子,以是最多只能显示8);如果格子上什么也不显示(也便是为空),系统就会自动调用递归的方法打开附近的格子。如果点到了有地雷的格子,那么游戏结束,系统显示所有雷的位置。右键单击:玩家可以通过利用鼠标右键单击来标记自己认为是雷的格子,通过标记可以有效的提高扫雷游戏的效率。再次右击该格子可以取消标记,且格子被标记的时候鼠标单击无效(防止玩家误操作导致游戏失落败)。游戏计时当点击雷区任意一个格子的时候雷区开始布雷同时计时开始,计时标准是一秒增加1。如果游戏失落败时,则计时停滞。如果玩家开始了新游戏,计时也会重新开始。标记地雷当玩家认为格子下有雷时可以右击格子来标记该格子,被标记的格子显示小红旗。再次右击可以取消标记,且格子被标记的时候鼠标单击无效(防止玩家误操作导致游戏失落败)。如果玩家标识的地雷的数量超过了该难度下规定的雷数,计数区会以负数来显示超过的雷数并且游戏不会结束。统计功能当玩家游戏胜利后会弹框提示并可以输入玩家的名字,确认后本次游戏的记录会被保存。玩家可以点击菜单栏上的“游戏”菜单,再点击个中的“扫雷榜”即可查看游戏的最佳记录。退出点击关闭按钮可以结束游戏。扫雷游戏界面需求游戏菜单玩家有5项可以选择,玩家在点击低级时游戏界面的尺寸会变为低级的大小,雷区重新初始化,变为一共99的格子,个中有10颗是地雷;中级一共有1616个格子,个中有40颗是地雷;高等一共有1630个格子,个中有99颗是雷。除此之外,玩家还可以自定义难度,在弹框中填写雷数与尺寸。玩家通过点击鼠标右键来标记自己认为是雷的格子,通过标记可以有效的提高扫雷游戏的效率,再次点击右键可以取消标记。扫雷榜,记录玩家不同难度的最短韶光。游戏区域游戏区域由扫雷信息统计区和雷区组成,个中扫雷信息统计区又分为计数区、计时区、重新开始按钮。雷区的雷数,每个难度对应的雷数都不同,低级、中级、高平分离对应10、40、99个雷。计数区初始显示的雷数由难度而定,每次标记地雷雷数均减1,如果玩家标记的地雷的数量超过了该难度下规定的雷数,计数区会以负数显示超过的雷数。当玩家点开第一个格子雷区开始布雷同时计时开始,一秒加1,直到游戏胜利或者游戏失落败的时候停滞计时。扫雷游戏功能模块游戏在功能上分为6个模块:游戏界面布雷鼠标事宜地雷判断游戏胜利(结束)游戏失落败(结束)游戏的概要剖析与设计设计构想如今天下上很多人都在利用Windows操作系统,以是人们也对系统自带的小游戏管窥蠡测。扫雷游戏的玩法大略,只要玩家进行一定的判断就可以轻松的游戏,以是玩扫雷的时候可以很轻松的玩。除了游戏本身带给人们的乐趣以外,游戏的玩法也在磨炼玩家的思维,如今大部分人都是依赖脑力劳动,这就可以通过在空隙的时候玩玩扫雷来磨炼一下自己。以是就可以理解,为什么在各种电子产品上都搭载这个小游戏了。虽然游戏比较大略,但是还是须要熟习一下规则。玩家须要在最短的韶光内找出雷区中所有的地雷,并加以标识,其他没有雷的格子全部点开后游戏胜利。但是如果点到了地雷则游戏失落败。游戏的操作很大略,当玩家用鼠标左键点击自己认为不是地雷的格子会点开该格子,用鼠标右键点击格子会标记该格子,再次右击可以取消标记。玩家可以通过雷区中被点开的格子上显示的数字来判断该格子周围8个格子所隐蔽的地雷,例如:点开的格子显示数字“2”,则表示该格子周边的8个格子里隐蔽着2颗地雷。如果点开的格子下没有雷且周围8个格子里也没有雷,则系统会自动点开那8个格子,然后递归判断这些格子周围有没有雷。本次的扫雷游戏设计,须要编写7个Java类:MineaGamae.java类、MineAra.java类、Block.jaav类、BlockVaiw.java类、LayMinas.java类、Record.java类和ShowRecrd.java类。MineGame.javaMineGame类是游戏的入口,用来初始化游戏资源,比如界面尺寸和雷数等。同时也卖力难度的转换。(2) MineArea.javaMineArea类是支配雷区的雷,除了初始化雷区以外还可以相应玩家的鼠标操作。(3) Block.javaBlock类是一个POJO类,紧张记录了雷区一个个格子的属性,比如名字,周围雷的数目等等。(4) BlockView.javaBlockView类用来显示块的属性,并且利用卡片布局来使格子分为了高下两层,当玩家点击格子后,会使下面的属性浮现出来。(5) LayMines.javaLayMines类是打算不是雷的格周围雷个数的类,以及设置点选之后的图片样式。创建的工具lay是MineArea中最主要的成员。(6) Record.javaRecord类是通过IO流将游戏记录储存在本地的文件中,紧张实现通关后弹窗提示通关的窗口,以及记录成绩。(7) ShowRecord.javaShowRecord类是显示扫雷记录的类。流程方案有三个部分,分别是游戏选择难度后、玩家第一次点击格子和为不是地雷的格子自动点开。游戏选择难度后,获取该难度设定的雷数与界面尺寸显示界面,但是还没有布雷。当玩家第一次点开格子的时候系统随机布雷并启动定时器,为什么要在点过一次格子之后才布雷呢?这便是要让玩家第一次不会点到地雷,要不然玩家该多忧郁,这样才能提高玩家的游戏欲。之后是最主要的一步,便是如何将格子周围没有雷的格子自动点开,我们可以利用递归的方法来奥妙的判断并点开周围的格子。整体方案如图3-2所示:图3-2 整体方案图
界面方案界面方案如图3-3所示:①②③⑤④⑥图3-3 方案样图解释如下:①:游戏主界面(Interface)。②:菜单(Menu)。③:地雷数显示区(MineNumberArea)④:重新开始(Restart)。⑤:扫雷用时显示区(TimeArea)。⑥:地雷区(MineArea)。
算法思想随机布雷扫雷游戏哀求在雷区随机布雷,雷数不能太多,这样就没法很好的判断周围是否有雷了;但也不能太少,这样会涌现点一下就会点开一大片的空缺区域。利用java自带的Math.random()方法产生随机数,经由打算后得到将随机数转换成一个整数,这个整数便是雷的位置的角标。游戏的目标是在将所有的地雷标记出来,并将其它不是雷的格子点开。打算方格周围雷数当没有雷的格子被点击后,会显示该格子周围8个格子里所有的雷数,玩家通过这个数字就可以判断出雷的位置,以是周围雷数的打算也很主要。游戏的详细设计游戏初始化玩家点开游戏,此时系统自动加载界面,分别是雷区、菜单区、扫雷数据显示区,如图4-1所示:扫雷数据显示区地雷区图4-1 游戏初始界面游戏界面相对打算机自带的扫雷游戏比较简洁,紧张由游戏数据显示区域以及雷区构成。我们利用ImageIcon工具来存放地雷的图标,可以图标大小最好要小一些,否则会在格子上显示不全。对地雷区的初始化是很主要的,我们利用一个循环即可实现初始化。玩家点开游戏之后可以点击菜单栏选择扫雷游戏的难度,不同的难度就代表了不同的地雷总数和尺寸,自定义的难度也会设置雷数和尺寸,设置的这些数据全部存放在几个变量之中,当雷区要初始化的时候程序会调用这么变量属性,然后通过一个循环来完成初始化。紧张代码如下:
而之前所说的循环初始化实在便是循环的加载组件,雷区便是由一个个组件构成的,通过循环将所有的格子都支配到雷区,然后再随机产生地雷并支配到雷区上。组件位置的摆放是按照其在数组中的位置来摆放的,所有的格子组件都存放在一个二维数组之中,组件在这个数组中的下标便是他在布局中的位置。菜单栏是由菜单组件构成的,也便是JMenu组件,这个是菜单组件,用来定义未点击时的菜单样式,这个组件有可以设置JMenauItem组件,这是菜单项的意思,是当玩家点击了菜单后展示出来的子菜单栏。扫雷游戏的计时区以及计数区又是利用另一种组件完成的,叫做JTextField,这个组件是文本显示的组件,在设置了不可的属性后,该组件在显示的外不雅观上会有变革,边框会变灰一些,意味着该组件不能够点击或者输入。然后利用一个方法随着韶光动态的在韶光区以一秒为单位增加,计数区则会随着用户标记雷而减一,可以减到负数。在设置界面的时候还须要进行一些设置,比如设置属性来让玩家在关闭游戏窗口时,系统会自动开释资源,并关闭窗口。
雷区的支配当玩家第一次点开格子的时候系统随机布雷并启动定时器,但是为什么要在点过一次格子之后才布雷呢?原来这便是要让玩家第一次不会点到地雷,要不然玩家该多忧郁,这样才能提高玩家的游戏欲。详细实现如下所示:判断地雷区是否处于可动作状态:判断为左键且该格子为未探测状态:
支配地雷:
判断地雷该当被支配的位置:
游戏中紧张模块的先容与利用鼠标事宜我们通过点击鼠标左键或者鼠标右键来完成游戏,利用系统自带的MouseDown和MouseUp事宜来相应玩家的操作。函数原型如下:组件名称:
组件名称:
这两个原型中的参数,Button参数值分别表示玩家用鼠标的左键或者右键进行点击的。其意义如下:1:左键 2:右键如果同时按两个按键,那么系统就会传回3,由于点左键是1,点右键是2,一起点便是两个值相加了。在本次的扫雷设计中,我们会用鼠标的MouseUp事宜来相应玩家的操作,个中鼠标左键用来点开玩家认为没有雷的格子,鼠标右键用来标记玩家认为下面藏有雷的格子。利用MouseaUp事宜而不用MouseaDown事宜的缘故原由是,前者是在当鼠标按键抬起是触发,而后者是当按键按下就触发。如果玩家在点击某一个格子的时候溘然创造彷佛点错了,此时玩家只要连续按下鼠标右键,再抬起的时候就会创造格子被标记成地雷了,现在的游戏一样平常都有这个功能,这可以有效的提升玩家的游戏体验。在人机交互的界面上,鼠标的操作是很主要的,但是程序的设计不合理会使鼠标无法发挥应有的功能。在鼠标点击事宜中利用MouseUp来相应事宜在上面也进行理解释,这样就可以很奥妙的让玩家体会到游戏的知心之处,可以有效的提升玩家的游戏体验。当鼠标左键点击格子时:
当鼠标右击标识有雷的格子时:
地雷及雷区表面探测情形在雷区的设计上,我利用循环加载组件的方法让雷区布满格子,如果玩家点击了格子就会让该格子下面隐蔽的组件显示出来如图4-2和图4-3所示:
图4-2地雷随机天生
图4-3 地雷被标记玩家通过单击格子来点开格子,右击格子标记地雷。由于利用了两个数组记录地雷的位置以及被点开的信息,以是可以通过两层嵌套循环来判断该格子周围雷的数目,而且系统会点开该格子周围8个格子中没有雷的格子,这又须要用到递归调用来一贯进行这个点开格子并验证的过程,直到不符合条件为止。利用这种嵌套循环以及递归调用,都会使一个耗时耗力的问题变得随意马虎办理起来,使得代码构造也变得清晰明了,并且会提高系统的打算速率。
打消未靠近地雷的格子开始之前须要先容并学习一下“递归”,递归的狭义阐明便是一个方法调用自己本身,通过一个判断语句决定是否结束调用。在代码的设计上也是一种非常主要的代码构造,通过这种方法编写代码,会使得代码构造看起来相称大略明了。但是须要把稳的是,如果操作不当会是系统无限循环调用,使得游戏崩溃,以是在编写代码时必须利用判断的语句来掌握循环调用的结束,以停滞该方法的递归调用。当玩家在进行游戏时点击了任意一个格子,系统会检测周围8个格子下是否藏雷,如果雷都被标记或者没有雷就会被点开并循环调用连续判断被点开格子周围的雷数。设计的时候须要考虑的判断条件:玩家点击了某一个格子后判断该格子下是否藏雷;如果没有雷则判断周围8个格的雷数并显示;若雷都被标记出来或者本来就没有雷则点开周围的格子递归判断被点开格子周围的雷。由于递归是循环调用方法本身,以是须要一个判断语句来结束调用,当被点开的格子周围有雷时在格子上显示雷数并结束递归调用。递归方法虽然很好但也有一些的缺陷,除了却束条件的选取很主要外,如果在扫雷设计中将雷区的尺寸设置过大,而地雷数却很少的话会使的循环调用变慢。以是在游戏的玩法设计上也要小心谨慎,不可以胡乱定义,以免造成系统包袱,使得游戏无法顺利进行下去。代码部分如下所示:游戏难度的选择我设计的扫雷有在难度的选择上有三种难度,分别是初、中、高等,这三种难度定义的雷数和雷区的尺寸是固定的,如果玩家想要自己定义扫雷的难度可以自己设置雷数和尺寸,只要打开“自定义”配置弹窗,在之后的弹框里按提示输入雷数和尺寸,行数最大为24,列数最大为30,如果玩家设置的雷数超过了范围(比如雷数大于格子的总数或小于零),系统会默认雷数为行数减一与列数减一的乘积。菜单栏的功能低级:设置格子总数为99,地雷总数为10颗雷,尺寸为300380然后重新开始游戏。中级:设置格子总数为1616,地雷总数为40颗雷,尺寸为480580然后重新开始游戏。高等:设置格子总数为1630,地雷总数为99颗雷,尺寸为800500然后重新开始游戏。自定义:设置格子总数为最大2430,最多雷数为2430的难度,然后重新开始游戏。扫雷榜: 打开并显示韶光最短的扫雷记录,可以进行更新和重新记分。游戏的判断游戏成功完成游戏哀求玩家在最短的韶光内完成游戏,当玩家将所有的雷标记出来并且其它格子都点开往后游戏胜利,系统会弹出提示框见告玩家“您真厉害,请输入您的名字,记录上榜!”,系统会记录玩家最短完成游戏的韶光。游戏失落败如果玩家不幸点击到了有雷的格子,该格子的地雷会引爆其他的地雷,游戏失落败,系统会将剩下的地雷全部显示出来,并弹框提示“你输了,请连续努力!
”,玩家可以选择弹框上的重新开始游戏选项来开始一局新的游戏。格子类的工具有一个标识该格子是否是雷的属性,通过该属性来判断玩家点到的是不是地雷。在游戏结束时也是通过该属性来判断哪些格子下有雷并显示出来。详细代码如下所示:
类设计MineGame类MineGame类紧张卖力开始游戏,菜单的设计,以及难度的转换。展示该类的UML图如图4-4所示。
图4-4 MineGame类的类图(1)成员变量bar 是窗体的菜单栏变量。fileMenu1 是扫雷游戏的菜单,叫做“游戏”。fileMenu2 是扫雷的另一个菜单,叫做“帮助”。低级 是扫雷游戏的难度变量。中级 是扫雷游戏的难度变量。高等 是扫雷游戏的难度变量。扫雷榜 是扫雷的统计信息变量。mineArea 是MineArea雷的工具,是设计雷区的变量。file 是文件变量,用来读取扫雷记录。hashtable 是用来临时存放扫雷记录。showHeroRecord 是用来显示扫雷记录的变量。(2)成员方法MiwneGaame()通过该方法设置了游戏整体的位置和布局,并实现菜单栏功能,初始化统计信息。actionPerformed(ActionEvent e)是相应点击菜单项的方法,通过该方法可以实现选择不同难度调度游戏的雷数和尺寸。玩家点选不同的菜单项会让该方法实行不同的操作。main()方法是游戏开始的方法,通过new了一个MineGame的工具来实现游戏的开始。
Block类Block类是一个POJO类,紧张记录了雷区一个个格子的属性,比如名字,周围雷的数目等等。展示该类的UML图如图4-5所示。图4-5 Block类的类图
成员变量Name是记录格子名字的变量。isMine是标记格子下有无地雷的变量。isMark是标记格子被标记状态的变量。mineIcon记录了块的图标的变量。isOpen是标记格子的点开状态的变量。arounfdMinqeNmber是记录格子周围8个格子中雷的数量的变量。成员方法。Block()无参布局方法,以防止创建缺点参数的工具。Block(String name,int aroundMineNumber,ImageIcon mineIcon,boolean isMine,boolean isMark,boolean isOpen)全参布局方法,可以为变量赋值。setNamqe()方法可以设置块的名字。getName()获取块的名字。setAounMineNuber()方法可以设置块周围雷的数目。setMineIicon()方法可以设置块的图标。getMineIcon()获取块的图标。setIsMinae()方法可以设置块是否是雷。getAroundMineNumber()获取块周围雷的数目。getIsMine()获取块是否是雷。setIsMarek()方法可以设置块是否被标记。getIsMark()获取块是否被标记。setIsOpen(boolean p)设置块是否被挖开。getIsOpen()获取块是否被挖开。toString()以字符串的格式输出该工具。BlockView类BlockView类继续了JPanel类,紧张支配每一个格子的布局,用来定义每个格子的属性。显示该类的UML图如图4-6所示。图4-6 BlockView类的类图
成员变量blockeNameOrIcona 该变量用来显示格子的名字和图标属性。blockeCoverq 是一个标记变量。card 卡片式布局,显示第一次添加的组件。成员方法BlockView()布局方法,初始化变量,设置块上属性显示的位置为居中,并添加组件。giveView()方法,给每一个格子供应视图,如果该格子下有雷,会调用方法授予该格子“地雷”的图标,但被覆盖不才面。如果下面没有雷,会显示该格子周围地雷的数目,同样会被覆盖住。该方法被调用时显示雷或者数字。seeBlouckNamerOrIcon()方法是用来让块的属性显示出来。seeBlouckCovear()方法是让cover遮盖块的属性。getBlouckCovear()方法是得到用来遮盖的按钮。Record类Record类紧张实现通关后弹窗提示通关的窗口,以及记录成绩。当玩家扫雷成功时,该工具供应了保存成绩到文件的界面。展示该类的UML图如图4-7所示。图4-7 Record类的类图
成员变量time 用来给游戏计时。grade 记录难度的变量。key 表示一个判断的变量。message 记录成绩的数据变量。textName 一个文本显示组件。label 一个可输入文本输入框组件。确定,取消 两个按钮组件,一个代表确定,一个代表取消。成员方法Record() 布局方法,初始化变量,设置窗口是否可以调度大小。setGrade() 方法可以设置成绩。writeRecord() 方法可以读写记录,如果没有记录会先创建一个新的文档来保存记录,下次直接修正覆盖记录。setTime() 方法是用来设置韶光的。actionPerformed(ActionEvent e) 方法是相应鼠标的点击事宜的方法,当玩家点击弹窗上的任意位置都会触发,但是只有点到精确的位置才会实行操作。比如点击确认,就可以把玩家的游戏记录存放到本地的文件中。ShowRecord类ShowRecord类是显示扫雷记录的类。展示该类的UML图如图4-8所示。
图4-8 ShowRecord类的类图
成员变量file 记录成绩的文档。name 名字。hashtable 是记录成绩的变量。show 是一个显示成绩的按钮组件变量。Rescore 是一个初始分数的按钮组件变量。Label1[] 显示成绩的组件。Label2[] 显示成绩的组件。Label3[] 显示成绩的组件。成员方法ShowRecord() 方法是该类的布局方法,初始化成员变量。
readAndShow() 方法会把在文档中记录的玩家通关信息筛选出来(按游戏完成是花费的韶光最短为条件筛选),并显示到弹出的对话框中。
actionPerformed(ActionEvent e)方法是相应玩家操作的方法,当玩家想要显示游戏记录的时候系统会相应玩家的哀求并调用显示成绩的方法,在弹框中刷新成绩。
MineArea类MineArea类紧张用于雷区的初始化以及鼠标事宜的相应。展示该类的UML图如图4-9所示。
图4-9 MineArea类的类图
成员变量reStart 是用来显示一个重新开始的按钮。block 是一个二维数组,定义了所有雷区的格子。blockView 是一个二维数组,是给每一个格子供应显示视图的。lay 是卖力定义每一个格子下有雷或者没有雷。row, colum 是卖力记录雷区行列数的变量。mineCount 是记录地雷总数的变量。markMount 是记录玩家标记的地雷数的变量。mark 是ImageIcon类型的变量,用来存放地雷图标。time 是记录韶光的变量。grade 是记录难度的变量,分别有“低级”、“中级”、“高等”三种难度。pCenter 是JPanel类型的变量,定义布局中部的控件pNorth 是JPanel类型的变量,分别位于布局的北部的控件。showTime 是显示扫雷韶光的变量。showMareedCoint 是显示玩家标记后剩余的雷数的变量。record 是一个对话框变量,用来显示玩家的最好记录,当玩家点击菜单中的英雄榜时会显示该对话框。lose 是游戏失落败时显示的对话框变量。spendTime 是一个标记变量。panel 一个轻量级容器变量,嵌套在对话框中。str 显示失落败的提示语的一个文本框变量。reStart1 是一个按钮工具,位于失落败对话框里,玩家点击后会触发与reStart一样的操作。成员方法MineArea()方法是该类的布局方法,初始化组件和一下工具,设置字体颜色、边框颜色等,并调用初始化雷区的方法来初始化雷区。
initMineArea()方法用来设置雷数和游戏界面所有格子的数量,初始化雷区。
initMine()方法是真正实行初始化的方法。
setRow(int row)方法用来设置行数。
setColum(int colum)方法用来设置列数。
setMineCount(int mineCount)方法用来设置地雷总数。
setGrade(int grade)方法用来设置难度。
actionPerformed(ActionEvent)方法是相应鼠标点击格子的事宜的方法,当点击的格子下面没有雷,该方法会显示该格子周围雷的数目,有雷则显示雷的图标。
show()方法是显示格子内容,并且利用递归调用来显示周围格子的内容,直到这个格子周围有雷。
mousePressed(MouseEvent)方法相应玩家对格子进行的鼠标左键单击事宜和鼠标右键点击事宜。
inquireWin()方法是在玩家在游戏过程中知足得胜条件是触发的方法,同时会调用其他方法弹框提示玩家游戏结束。
LayMines类LayMines是打算不是雷的格周围雷个数的类,以及设置点选之后的图片样式。标明该类的UML图如图4-10所示。
图4-10 LayMines类的类图
成员变量mineIcon 图片资源变量。成员方ayMines() 布局方法,定义图片资源。
layMinesForBlock(Block block[][], int mineCount) 方法会判断是否是第一次点击格子,如果玩家是第一次点击格子,开始随机产生雷,但是雷不会支配到第一次点的格子上。如果不是第一次点击且该格子没有雷时司帐算周围8个格子中有雷的数目并显示出来。
游戏实现游戏难度自定义图5-1 选择难度以及游戏自定义
图5-2 低级难度
图5-3 中级难度
图5-4 高等难度
图5-5 自定义难度如图5-1所示,玩家可以自己选择游戏难度,个中有低级,中级,高等以及自定义四种难度,所对应的游戏界面的尺寸也不相同,以及地雷的总数也不相同,雷数越多则难度越大,同时玩家可以自定义游戏难度,通过输入行列数以及地雷数设置游戏界面的大小以及难度。如图5-2、图5-3、图5-4、图5-5所示,分别展示了低级、中级、高等以及自定义难度的游戏界面尺寸和雷数。
扫雷玩家通过右键进行扫雷,并显示小红旗图5-6 扫雷图玩家在游戏过程中会对某一格周围是否有雷进行判断,当玩家认为格子下有雷时就可以通过利用鼠标右键点击该格子,将该格子标识为小红旗如图5-6所示。
玩家因触碰到雷而导致游戏结束图5-7 扫雷失落败图如图5-7所示,当玩家在点开了有雷的格子时,游戏失落败,系统会自动将所有的地雷显示出来,并且会弹出一个窗口提示玩家:“你输了,请连续努力!
”。除此以外还有两个选项,当玩家选择重新开始按钮时,游戏界面初始化,雷区中的雷全部取消,等待玩家第一次点击格子后开始布雷;如果用户点的是取消的话,就可以关掉这个提示的弹框。
图5-8 扫雷成功图如图5-8所示,当所有的地雷用都被玩家用小红旗标识出来,并且非雷的格子也被点开时游戏结束,计时停滞,系统弹框提醒玩家“您真厉害,请输入您的名字,记录上榜!
”,玩家可以在这个界面输入自己的名字来保存扫雷成绩。
图5-9扫雷榜图如图5-9所示,每当玩家成功扫完所有的雷后,系统会自动的记录本次的成绩,保存在本地的txt文档中,内容是三种难度,玩家姓名以及对应难度玩家所用的最少游戏韶光。当玩家点击查看英雄榜的时候系统默认只显示三种难度和匿名。
图5-10 最佳成绩显示图
图5-11 重新记分显示图如图5-10所示,玩家点击关闭时此窗口会关掉这个弹窗,当点击重新记分时,统计信息会清空,点击显示成绩就好刷新并将历史最好的成绩显示出来。界面也会发生变革,可以显示出游戏用时。
程序打包发布过程至此扫雷游戏已经编写好了,我们可以将这个游戏打包发布,这就须要利用jar.exe命令来将编写好的扫雷游戏的class文件打包发布。编写清单文件。首先须要利用“记事本”,根据哀求自己编写一个清单文件,格式和内容要和这里给的样子一样,详细内容如下:将清单文件保存到E:workspace扫雷bincomzxmine中,也便是和编写的扫雷游戏程序天生的字节码存放的位置相同,担保这些文件放在一个目录下。须要把稳的是,清单文件中的所有内容均为键值对的形式存放,键值直接必须空一个空格。
天生JA件。E:workspace扫雷jarcfmGame.jarMymoon.mf.class,这条命令中有一些参数须要明白:①参数c意味着要让系统天生一个文件,这个文件叫做JAR。②参数f意味着要让系统产生JA件的名字。③参数m意味着显示清单文件的名字。末了就可以将这个天生的JA件复制到任何一个安装了Java运行环境(电脑上的jdk版本不能太低)的电脑上,玩家就可直接用鼠标双击图标来运行自己编写的扫雷小游戏了。游戏测试结果游戏难度自定义测试游戏难度自定义测试用例:表6-1 自定义难度测试用例表预期结果
选择不同的难度后可以精确的初始化雷区
输入条件
分别点击低级、中级、高等和自定义
测试结果
点选不同难度后系统会自动改变雷区大小和地雷数
图6-1 游戏难度以及自定义测试
图6-2 低级难度测试
图6-3中级难度测试
图6-4 高等难度测试
图6-5 自定义难度测试如图6-1所示,本次扫雷游戏设计将游戏的难度设定为初、中、高以及自定义四种难度,前三种难度对应的游戏界面的尺寸以及地雷总数是不同的,难度越大雷数越多,尺寸也越大,玩家扫雷时就须要更加的动脑思考才能通关。除了固定的难度以外还可以自定义难度,玩家须要自己输入尺寸与雷数,系统根据玩家的哀求生产新的游戏,难度可以更加的灵巧,这样可以让玩家更满意。图6-2、图6-3、图6-4、图6-5测试了四种难度的选择,由图可以看出难度的选择功能正常,可以自由变换尺寸和地雷总数。
扫雷测试扫雷胜利测试用例:表6-2 扫雷胜利测试用例表预期结果
成功的将所有地雷标记出来后,游戏可以立马结束且会弹框提示输入玩家名字
输入条件
将所有地雷标记并将非雷格子点开
测试结果
游戏结束并且显示了哀求玩家输入名字的弹框
扫雷失落败测试用例:表6-3 扫雷失落败测试用例表
预期结果
点击了有雷的格子后游戏可以立马结束且弹框提示玩家游戏失落败
输入条件
点击有雷的格子
测试结果
游戏精确的结束且弹框提示了游戏失落败的提示
图6-6 游戏完成并且扫雷成功测试如图6-6所示,玩家可以通过左键单击格子点开格子,右键单击标识地雷的办法完成游戏。当玩家将所有的地雷都标识出来且其他的格子都被点开的情形下,游戏胜利。系统会弹框提示玩家成功完成了游戏任务“您真厉害,请输入您的名字,记录上榜!
”。玩家可以在弹出的弹框中输入自己的名字,若不输入则默认为匿名,然后系统会保存玩家的游戏记录。当玩家点击扫雷榜的时候可以查看自己用时最短的游戏记录。
图6-7 游戏完成但是扫雷失落败测试如图6-7所示,玩家可以通过左键单击格子点开格子,右键单击标识地雷的办法完成游戏。当玩家在进行扫雷游戏的时候,欠妥心点击了有雷的格子,这时候地雷被引爆了,所有未被标记的和已被标记的都被引爆,游戏结束。此时系统会自动将所有的地雷显示出来,方便玩家查看之前标记的精确与否,可以总结履历。然后系统弹框提示“你输了,请连续努力!
”,玩家可以点击重新开始的按钮重开游戏,连续寻衅扫雷游戏,也可以选择结束游戏。
预期结果
点击“最佳成绩”按钮时会显示玩家最佳的游戏记录
输入条件
打开游戏的扫雷榜,点击“最佳成绩”按钮
测试结果
游戏可以精确的显示玩家的游戏记录
重新记分测试用例:表6-5 重新记分测试用例表
预期结果
点击“重新记分”按钮时会打消玩家以往的游戏记录
输入条件
打开游戏的扫雷榜,点击“重新记分”按钮
测试结果
点击按钮后游戏记录消逝,再点击“最佳成绩”按钮只会显示默认的成绩
图6-8 扫雷榜测试
图6-9 最佳成绩测试
图6-10 重新记分测试如图6-8和图6-9所示,玩家在进行游戏时,如果成功的扫完雷,系统会提示并保存游戏记录。在扫雷榜上玩家可以进行查看。但是当玩家反复通关后,系统会自动的将用时最短的扫雷记录显示出来,以是玩家在查看记录的时候只能看到最快一次通关的记录。通过图6-10可以看出,当玩家点击了“重新记分”按钮后,之前游戏记录都会被打消掉,只会显示默认的数据:韶光为999秒,名字是匿名。
游戏数据显示区测试计时区显示测试用例:表6-6 计时区显示测试用例表预期结果
第一次点击雷区的格子时,计时区开始计时,游戏结束时计时停滞,重新开始游戏时,计时归零
输入条件
点击雷区的任意一格,然后结束游戏,末了点击“重新开始”按钮
测试结果
当点击雷区任意一格后计时开始,计时正常。然后点击有雷的格子结束游戏创造计时停滞。点击“重新开始”后计时区的计时精确归零
图6-11 开始计时测试
图6-12 计时停滞测试
图6-13 重新计时测试如图6-11,图6-12,图6-13所示,当点击雷区中的任意一格后,计时区开始正常计时。当游戏结束时计时区的计时就会停滞,末了点击了“重新开始”后计时区的计时归零。地雷数显示区测试用例:表6-7 地雷数显示区测试用例表
预期结果
标记地雷后计数区的数字会减1,如果标记数超过地雷数,计数区会用负数显示
输入条件
先标记一颗地雷,然后将所有的地雷标记出来
测试结果
标记一颗地雷后,计数区可以精确的减少1个,然后当所有的地雷全被标记后,如果连续标记,计数区可以精确的以负数表示
图6-14 计数区测试
图6-15 计数区负数显示测试如图6-14,图6-15所示,当标记了一颗地雷后计数区中的数字会相应的减少一个,表示有一颗雷被找到了。但是如果标记数超过了地雷的数目,计数区会以负数显示,表示有的地雷标记错了。
递归算法测试递归调用测试用例:
表6-8 递归调用测试用例表
预期结果
当点击一个周围八个格子中都没有雷的格子时,系统会将这8个格子也点开
输入条件
点开一个周围没有雷的格子
测试结果
系统精确的将周围的八个格子点开,如果这些格子中周围的格子没有雷的话还会自动点开
图6-16 递归算法测试
如图6-16所示,当点击一个周围八个格子中都没有雷的格子时,系统会将周围的格子点开,被点开的格子也会显示周围的地雷数。如果被点开的格子周围还是没有地雷,系统就会递归调用再把周围的格子点开。
扫雷游戏的代码编写完成,且基本功能也实现了,虽然与电脑上自带的扫雷游戏比较在界面上还是有着一些差距,一些小细节也没有完善,但已经让我很满意了,我会在往后连续完善这些细节,让这个扫雷游戏变得愈来愈好玩。在大略的测试后,该游戏也达到了我的预期,以是本次的设计就到此结束了。
结 论毕业设计对付我们来说并不是大略的一个毕业考察而已,这是我们的一个机会,一个将大学四年所学到的知识结合起来,通过自己的构思完成一个别系的机会。在完成这个别系的过程中,一定会碰着许许多多的问题,这些问题就犹如大山挡在我们的面前,如何去办理这些问题也是我们要思考的。而当我们把困难都办理掉,成功完成毕业设计的时候,就解释我们成功的摆脱了只会理论知识,不会办理实际问题的状态,磨炼了我们学习新事物并加以利用以及创造问题并找到方法去办理的能力。
虽然这次的扫雷游戏看似大略,但是个中却涉及了GUI设计,这一部分在学校是没有深讲的,须要我自己去学习。个中有各种组件的调用,各种控件的利用等,我通过本次的毕业设计又学到了许多的新知识。
通过编写这次的扫雷游戏,我深刻的认识到了细节问题的主要性,这些问题看似无关紧要但是如果忽略会养成不好的编程习气,以是我们要着眼于细节,长于去创造身边的一些小事情,让自己的水平不断提高。而且我的编程能力在不断的编写代码的过程中也有了显著的提高。很多时候人们都认为知识学过了就行,但是当实际去用的时候就会创造这些知识是多么的陌生。以是我认为学过的知识就要多用,用实际操作来让知识真正变成自己的。
参考文献ᄃ[1] 耿祥义.Java大学实用教程[M].北京:清华大学出版社,2009.
[2] 冯锋,王运坚.Visual Basic 程序设计根本教程[M].西安:电子工业出版社,1999。
[3] 王鹏.JavaSwing图形界面开拓与案例详解[M].北京:清华大学出版社,2008。
[4] 李怀明.Visual Basic 6.0 中文版 参考详解[M].北京:清华大学出版社,1999。
[5] 丁振凡.Java措辞实验教程[M].北京:北京邮电大学出版社,2005。
[6] 郑莉.Java措辞程序设计[M].北京:清华大学出版社,2006。
[7] 伍俊良.VB课程设计与系统开拓案例[M].北京:清华大学出版社,2002。
[8] 孙全党,王吴迪,赵枫朝.Java程序设计运用教程[M].北京:电子工业出版社,2006。
[9] 雷之宇.Java项目开拓实践-网络篇[M].北京:中国铁道出版社,2005。
[10] 赵玉阳.Java从入门到精通[M].北京:清华大学出版社,2006。
[11] 何斌,刘醒.Visual Basic 6.0 运用指南[M].成都:四川大学出版社,1998。
[12] 毕广吉.Java程序设计实例教程[M].北京:冶金工业出版社,2007年。
[13] 李善茂.Visual Basic 6.0 高等编程技巧[M].西安:电子工业出版社,1999。
[14] 王保罗.Java面向工具程序设计[M].北京:清华大学出版社,2003年.公民邮电出版社,2004
[15] 刘腾红,孙细明.信息系统剖析与设计[M].北京:科学出版社,2003年。
[16] 林邦杰,彻底研究java[M].北京:电子工业出版社,2002年。
[17] 刘京华. Java Web整合开拓王者归来[M].北京:清华大学出版社,2010。
[18] 唐任仲.工程运用软件开拓技能[M].北京:化学工业出版社,1999。
[19] 谭浩强.Visual Basic 6.0 中文版 提高与运用[M].西安:电子工业出版社,1999。
[20] (美)阿诺德,Ken Arnold,等. Java程序设计措辞[M].北京:公民邮电出版社,2006.
[21] Bruce Eckel. Thinking in Java[M]. Upper Saddle River, New Jersey, USA: Prentice Hall, 2006.
[22] Holger Eichelberger,Klaus Schhmid.Flexible resource monitoring ofJava programs.[J].The Journal of Systems & Software,2014 Elsevier.
[23] Joshua Bloch. Effective Java[M]. Piscataway, N.J: IEEE Press, 2009.
[24] oug Twilleager,Jeff Kesselman,Athomas Goldberger,Daniel Petersen,Juan Carlos,Soto,Chris Melissinos.Java Technologies for games.[J].Computers in Entertainment(CIE),2004,Vol.2(2),pp.18-18 ACM.
致 谢感谢杰普基地的老师以及校内辅导老师,在这次我的毕业设计过程中,老师们对我的悉心的辅导,从一开始的开题报告与选择到后来的系统设计,从程序设计到论文的编写,他们纠正了我许多的不成熟的想法和考虑,给我提出了许多宝贵的建议,而且在程序设计与开拓过程中碰着的最困难的时候给予我连续努力完成设计的信心。老师们严谨的作风和对我的严格哀求,使我战胜了
通过这次毕业设计的全体开拓过程,我系统开拓过程从需求剖析到详细功能实现,再到终极测试和掩护的理解有了很大的进步,让我对系统开拓有了更深层次的认识。现在我的动手能力和独立办理问题的能力也得到了很大的磨炼和提高,这是这次毕业设计最好的收成。
末了,在全体系统开拓过程中,我身边的同学和朋友给了我很多的建议,让我很快的确定了系统的业务逻辑。在次,我衷心的向他们表示感谢。
在论文完成过程中,本人还得到了其他老师和许多同学的热心帮助,本人向他们表示深深的谢意!
末了向在百忙之中评审本文的各位专家、老师表示衷心的感谢!
Thinking in Java
Learning Java
At about the same time that my first book, Using C++ (Osborne/McGraw-Hill, 1989), came out, I began teaching that language. Teaching programming ideas has become my profession; I’ve seen nodding heads, blank faces, and puzzled expressions in audiences all over the world
since 1987. As I began giving in-house training with smaller groups of people, I discovered something during the exercises. Even those people who were smiling and nodding were confused about many issues. I found out, by creating and chairing the C++ track at the Software Development Conference for a number of years (and later creating and chairing the Java track), that I and other speakers tended to give the typical audience too many topics too quickly. So eventually, through both variety in the audience level and the way that I presented the material, I would end up losing some portion of the audience. Maybe it’s asking too much, but because I am one of those people resistant to traditional lecturing (and for most people, I believe, such resistance results from boredom), I wanted to try to keep everyone up to speed. For a time, I was creating a number of different presentations in fairly short order. Thus, I ended up learning by experiment and iteration (a technique that also works well in program design). Eventually, I developed a course using everything I had learned from my teaching experience. My company, MindView, Inc., now gives this as the public and in-house Thinking in Java seminar; this is our main introductory seminar that provides the foundation for our more advanced seminars. You can find details at www.MindView.net. (The introductory seminar is also available as the Hands-On Java CD ROM. Information is available at the same Web site.)
The feedback that I get from each seminar helps me change and refocus the material until I think it works well as a teaching medium. But this book isn’t just seminar notes; I tried to pack as much information as I could within these pages, and structured it to draw you through into the next subject. More than anything, the book is designed to serve the solitary reader who is struggling with a new programming language.
The singly rooted hierarchy
One of the issues in OOP that has become especially prominent since the introduction of C++ is whether all classes should ultimately be inherited from a single base class. In Java (as with virtually all other OOP languages except for C++) the answer is yes, and the name of this ultimate base class is simply Object. It turns out that the benefits of the singly rooted hierarchy are many.
All objects in a singly rooted hierarchy have an interface in common, so they are all ultimately the same fundamental type. The alternative (provided by C++) is that you don’t know that everything is the same basic type. From a backward-compatibility standpoint this fits the model of C better and can be thought of as less restrictive, but when you want to do full-on objectoriented programming you must then build your own hierarchy to provide the same convenience that’s built into other OOP languages. And in any new class library you acquire, some other incompatible interface will be used. It requires effort (and possibly multiple inheritance) to work the new interface into your design. Is the extra “flexibility” of C++ worth it? If you need it—if you have a large investment in C—it’s quite valuable. If
you’re starting from scratch, other alternatives such as Java can often be more productive.
All objects in a singly rooted hierarchy can be guaranteed to have certain functionality. You know you can perform certain basic operations on every object in your system. All objects can easily be created on the heap, and argument passing is greatly simplified. A singly rooted hierarchy makes it much easier to implement a garbage collector, which is one of the fundamental improvements of Java over C++. And since information about the type of an object is guaranteed to be in all objects, you’ll never end up with an object whose type you cannot determine. This is especially important with system-level operations, such as exception handling, and to allow greater flexibility in programming.
Containers
In general, you don’t know how many objects you’re going to need to solve a particular problem, or how long they will last. You also don’t know how to store those objects. How can
you know how much space to create if that information isn’t known until run time?
The solution to most problems in object-oriented design seems flippant: You create another type of object. The new type of object that solves this particular problem holds references to other objects. Of course, you can do the same thing with an array, which is available in most
languages. But this new object, generally called a container (also called a collection, but the Java library uses that term in a different sense so this book will use “container”), will expand itself whenever necessary to accommodate everything you place inside it. So you don’t need to know how many objects you’re going to hold in a container. Just create a container object
and let it take care of the details.
Fortunately, a good OOP language comes with a set of containers as part of the package. In C++, it’s part of the Standard C++ Library and is often called the Standard Template Library(STL). Smalltalk has a very complete set of containers. Java also has numerous containers inits standard library. In some libraries, one or two generic containers is considered good enough for all needs, and in others (Java, for example) the library has different types of containers for different needs: several different kinds of List classes (to hold sequences), Maps (also known as associative arrays, to associate objects with other objects), Sets (to hold one of each type of object), and more components such as queues, trees, stacks, etc.
From a design standpoint, all you really want is a container that can be manipulated to solve your problem. If a single type of container satisfied all of your needs, there’d be no reason to have different kinds. There are two reasons that you need a choice of containers. First, containers provide different types of interfaces and external behavior. A stack has a different interface and behavior than a queue, which is different from a set or a list. One of these might provide a more flexible solution to your problem than the other. Second, different containers have different efficiencies for certain operations. For example, there are two basic types of List: ArrayList and LinkedList. Both are simple sequences that can have identical interfaces and external behaviors. But certain operations can have significantly different costs. Randomly accessing elements in an ArrayList is a constant-time operation; it takes the same amount of time regardless of the element you select. However, in a LinkedList it is expensive to move through the list to randomly select an element, and it takes longer to find an element that is farther down the list. On the other hand, if you want to insert an element in the middle of a sequence, it’s cheaper in a LinkedList than in an ArrayList. These and other
operations have different efficiencies depending on the underlying structure of the sequence. You might start building your program with a LinkedList and, when tuning for performance,change to an ArrayList. Because of the abstraction via the interface List, you can change from one to the other with minimal impact on your code.
Object creation & lifetime
One critical issue when working with objects is the way they are created and destroyed. Each object requires resources, most notably memory, in order to exist. When an object is no longer needed it must be cleaned up so that these resources are released for reuse. In simple programming situations the question of how an object is cleaned up doesn’t seem too challenging: You create the object, use it for as long as it’s needed, and then it should be destroyed. However, it’s not hard to encounter situations that are more complex.
Suppose, for example, you are designing a system to manage air traffic for an airport. (The same model might also work for managing crates in a warehouse, or a video rental system, or a kennel for boarding pets.) At first it seems simple: Make a container to hold airplanes, then create a new airplane and place it in the container for each airplane that enters the air-trafficcontrol zone. For cleanup, simply clean up the appropriate airplane object when a plane leaves the zone.
But perhaps you have some other system to record data about the planes; perhaps data that doesn’t require such immediate attention as the main controller function. Maybe it’s a record of the flight plans of all the small planes that leave the airport. So you have a second container of small planes, and whenever you create a plane object you also put it in this second container if it’s a small plane. Then some background process performs operations on the objects in this container during idle moments.
Now the problem is more difficult: How can you possibly know when to destroy the objects? When you’re done with the object, some other part of the system might not be. This same
problem can arise in a number of other situations, and in programming systems (such as C++) in which you must explicitly delete an object when you’re done with it this can become quite complex.
Where is the data for an object and how is the lifetime of the object controlled? C++ takes the approach that control of efficiency is the most important issue, so it gives the programmer a choice. For maximum runtime speed, the storage and lifetime can be determined while the program is being written, by placing the objects on the stack (these are sometimes called
automatic or scoped variables) or in the static storage area. This places a priority on the speed of storage allocation and release, and this control can be very valuable in some situations. However, you sacrifice flexibility because you must know the exact quantity, lifetime, and type of objects while you’re writing the program. If you are trying to solve a more general problem such as computer-aided design, warehouse management, or air-traffic control, this is too restrictive.
The second approach is to create objects dynamically in a pool of memory called the heap. In this approach, you don’t know until run time how many objects you need, what their lifetime is, or what their exact type is. Those are determined at the spur of the moment while the program is running. If you need a new object, you simply make it on the heap at the point that you need it. Because the storage is managed dynamically, at run time, the amount of time required to allocate storage on the heap can be noticeably longer than the time to create storage on the stack. Creating storage on the stack is often a single assembly instruction to move the stack pointer down and another to move it back up. The time to create heap storage depends on the design of the storage mechanism.
The dynamic approach makes the generally logical assumption that objects tend to be complicated, so the extra overhead of finding storage and releasing that storage will not have an important impact on the creation of an object. In addition, the greater flexibility is essential to solve the general programming problem.
Java uses dynamic memory allocation, exclusively. Every time you want to create an object, you use the new operator to build a dynamic instance of that object. There’s another issue, however, and that’s the lifetime of an object. With languages that allow objects to be created on the stack, the compiler determines how long the object lasts and can automatically destroy it. However, if you create it on the heap the compiler has no knowledge of its lifetime. In a language like C++, you must determine programmatically when to destroy the object, which can lead to memory leaks if you don’t do it correctly (and this is a common problem in C++
programs). Java provides a feature called a garbage collector that
automatically discovers when an object is no longer in use and destroys it. A garbage collector is much more convenient because it reduces the number of issues that you must track and the code you must write. More importantly, the garbage collector provides a much
higher level of insurance against the insidious problem of memory leaks, which has brought many a C++ project to its knees.
With Java, the garbage collector is designed to take care of the problem of releasing the memory (although this doesn’t include other aspects of cleaning up an object). The garbage collector “knows” when an object is no longer in use, and it then automatically releases the memory for that object. This, combined with the fact that all objects are inherited from the single root class Object and that you can create objects only one way—on the heap—makes
the process of programming in Java much simpler than programming in C++. You have far fewer decisions to make and hurdles to overcome.
中文翻译Java编程思想
Java的学习
在我第一本书《Using C++》面市的险些同一韶光(Osborne/McGraw-Hill 于 1989 年出版),我开始教授那种措辞。程序设计措辞的教授已成为我的专业。自 1989 年以来,我便在世界各地见过许多昏昏欲睡、满脸茫然以及困惑不解的脸庞。开始在室内面向较少的一组人授课往后,我从作业中创造了一些特殊的问题。纵然
那些上课面带会心的微笑或者频频点头的学生,对许多问题也存在认识上的稠浊。在过去几年间的“软件开拓会议”上,由我主持 C++分组谈论会(现在变成了 Java 谈论会)。有的演讲人试图在很短的韶光内向听众贯注灌注过多的主题。以是到末了,只管听众的水平都还可以,而且供应的材料也很充足,但仍旧丢失了一部分
听众。这可能是由于问得太多了,但由于我是那些采纳传统授课办法的人之一,以是很想使每个人都能跟上讲课进度。
有段韶光,我体例了大量传授教化简报。经由不断的试验和修订(或称“反复”,这是在 Java 程序设计中非常有用的一项技能),末了成功地在一门课程中集成了从我的传授教化履历中总结出来的所有东西——我在很长一段韶光里都在利用。个中由一系列离散的、易于消化的小步骤组成,而且每个小课程结束后都有一些适当的练习。我目前已在 Java 公开研讨会上公布了这一课程,大家可到 http://www.BruceEckel.com 理解详情(对研讨会的先容也以 CD-ROM 的形式供应,详细信息可在同样的 Web 站点找到)。 从每一次研讨会收到的反馈都帮助我修正及重新订定学习材料的重心,直到我末了认为它成为一个完善的传授教化载体为止。但本书并非仅仅是一本教科书——我考试测验在个中装入尽可能多的信息,并按照主题进行了有序的分类。无论如何,这本书的紧张宗旨是为那些独立学习的人士做事,他们正准备深入一门新的程序设计措辞,而没有太大的可能参加此类专业研讨会。
单根构造
在面向工具的程序设计中,由于 C++的引入而显得尤为突出的一个问题是:所有类终极是否都应从单独一个根本类继续。在 Java 中(与其他险些所有 OOP 措辞一样),对这个问题的答案(购买后显示)都是肯定的,而且这个终级根本类的名字很大略,便是一个“Object”。这种“单根构造”具有许多方面的优点。
单根构造中的所有工具都有一个通用接口,以是它们终极都属于相同的类型。另一种方案(就象 C++那样)是我们不能担保所有东西都属于相同的基本类型。从向后兼容的角度看,这一方案可与 C 模型更好地合营,而且可以认为它的限定更少一些。但假期我们想进行纯粹的面向工具编程,那么必须构建自己的构造,以期得到与内建到其他 OOP 措辞里的同样的便利。需添加我们要用到的各种新类库,还要利用另一些不兼容的接口。天经地义地,这也须要付出额外的精力使新接口与自己的设计方案合营(可能还须要多重继续)。为得到 C++额外的“灵巧性”,付出这样的代价值得吗,当然,如果真的须要——如果早已是 C 专家,如果对 C有难舍的情结——那么就真的很值得。但如果你是一名新手,首次打仗这类设计,象 Java 那样的更换方案大概会更省事一些。 单根构造中的所有工具(比如所有 Java 工具)都可以担保拥有一些特定的功能。在自己的系统中,我们知道对每个工具都能进行一些基本操作。一个单根构造,加上所有工具都在内存堆中创建,可以极大简化参数的通报(这在 C++里是一个繁芜的观点)。 利用单根构造,我们可以更方便地实现一个垃圾网络器。与此有关的必要支持可安装于根本类中,而垃圾网络器可将适当的发给系统内的任何工具。如果没有这种单根构造,而且系统通过一个句柄来操纵工具,那么实现垃圾网络器的路子会有很大的不同,而且会面临许多障碍。
由于运行期的类型信息肯定存在于所有工具中,以是永久不会碰着判断不出一个工具的类型的情形。这对系统级的操作来说显得特殊主要,比如违例掌握;而且也能在程序设计时得到更大的灵巧性。但大家也可能产生疑问,既然你把好处说得这么天花乱坠,为什么 C++没有采取单根构造呢,事实上,这是早期在效率与掌握上权衡的一种结果。单根构造会带来程序设计上的一些限定。而且更主要的是,它加大了新程序与原有代C码兼容的难度。只管这些限定仅在特定的场合会真的造成问题,但为了得到最大的灵巧程度,C++终极决定放弃采取单根构造这一做法。而 Java 不存在上述的问题,它是全新设计的一种措辞,不必
与现有的措辞保持所谓的“向后兼容”。以是很自然地,与其他大多数面向工具的程序设计措辞一样,单根构造在 Java 的设计方案中很快就落实下来。
凑集与继续器
针对一个特定问题的办理,如果事先不知道须要多少个工具,或者它们的持续韶光有多长,那么也不知道如何保存那些工具。既然如此,若何才能知道那些工具哀求多少空间呢,事先上根本无法提前知道,除非进入运行期。
在面向工具的设计中,大多数问题的办理办法彷佛都有些轻率——只是大略地创建另一种类型的工具。用于办理特定问题的新型工具容纳了指向其他工具的句柄。当然,也可以用数组来做同样的事情,那是大多数措辞都具有的一种功能。但不能只看到这一点。这种新工具常日叫作“凑集”(亦叫作一个“容器”,但 AWT
在不同的场合运用了这个术语,以是本书将一贯沿用“凑集”的称呼。在须要的时候,凑集会自动扩充自己,以便适应我们在个中置入的任何东西。以是我们事先不必知道要在一个凑集里容下多少东西。只需创建一个凑集,往后的事情让它自己卖力好了。 幸运的是,设计优秀的 OOP 措辞都配套供应了一系列凑集。在 C++中,它们因此“标准模板库”(STL)的形式供应的。 Object Pascal 用自己的“可视组件库”(VCL)供应凑集。 Smalltalk 供应了一套非常完全的凑集。而 Java 也用自己的标准库供应了凑集。在某些库中,一个常规凑集便可知足人们的大多数哀求;而在另一些库中(特殊是C++的库),则面向不同的需求供应了不同类型的凑集。例如,可以用一个矢量统一对所有元素的访问办法;一个链接列表则用于担保所有元素的插入统一。以是我们能根据自己的须要选择适当的类型。个中包括集、行列步队、散列表、树、堆栈等等。 所有凑集都供应了相应的读写功能。将某样东西置入凑集时,采取的办法是十分明显的。有一个叫作“推”(Push)、“添加”(Add)或其他类似名字的函数用于做这件事情。但将数据从凑集中取出的时候,办法却并不总是那么明显。如果是一个数组形式的实体,比如一个矢量(Vector),那么大概能用索引运算符或函
数。但在许多情形下,这样做每每会无功而返。此外,单选定函数的功能是非常有限的。如果想对凑集中的一系列元素进行操纵或比较,而不是仅仅面向一个,这时又该怎么办呢,
办法便是利用一个“连续器”(Iterator),它属于一种工具,卖力选择凑集内元素,并把它们供应给继续器的用户。作为一个类,它也供应了一级抽象。利用这一级抽象,可将凑集细节与用于访问那个凑集的代码隔离开。通过继续器的浸染,凑集被抽象成一个大略的序列。继续器许可我们遍历那个序列,同时毋需关心根本构造是什么——换言之,不管它是一个矢量、一个链接列表、一个堆栈,还是其他什么东西。这样一来,我们就可以灵巧地改变根本数据,不会对程序里的代码造成滋扰。 Java 最开始(在1.0和 1.1版中)供应的是一个标准继续器,名为 Enumeration(列举),为它的所有凑集类供应做事。 Java 1.2 新增一个更繁芜的凑集库,个中包含了一个名为 Iterator 的继续器,可以做比老式的 Enumeration 更多的事情。
从设计角度出发,我们须要的是一个全功能的序列。通过对它的操纵,该当能办理自己的问题。如果一种类型的序列即可知足我们的所有哀求,那么完备没有必要再换用不同的类型。有两方面的缘故原由匆匆使我们须要对凑集作出选择。首先,凑集供应了不同的接口类型以及外部行为。堆栈的接口与行为与行列步队的不同,而行列步队的接口与行为又与一个集(Set)或列表的不同。利用这个特色,我们办理问题时便有更大的灵巧性。 其次,不同的凑集在进行特定操作时每每有不同的效率。最好的例子便是矢量( Vector)和列表( List )的差异。它们都属于大略的序列,拥有完备同等的接口和外部行为。但在实行一些特定的任务时,须要的开销却是完备不同的。对矢量内的元素进行的随机访问(存取)是一种常时操作;无论我们选择的选择是什么,须要的韶光量都是相同的。但在一个链接列表中,若想到处移动,并随机挑选一个元素,就需付出“惨重”的代价。而且假设某个元素位于列表较远的地方,找到它所需的韶光也会长许多。但在另一方面,如果想在序列中部插入一个元素,用列表就比用矢量划算得多。这些以及其他操作都有不同的实行效率,详细取决于序列的根本构造是什么。在设计阶段,我们可以先从一个列表开始。末了调度性能的时候,再根据情形把它换成矢量。由于抽象是通过继续器进行的,以是能在两者方便地切换,对代码的影响则显得微不足道。末了,记住凑集只是一个用来放置工具的储藏所。如果那个储藏所能知足我们的所有须要,就完备没必要关心它详细是如何实现的(这是大多数类型工具的一个基本观点)。如果在一个编程环境中事情,它由于其他成分(比如在 Windows 下运行,或者由垃圾网络器带来了开销)产生了内在的开销,那么矢量和链接列表之间在系统开销上的差异就或许不是一个大问题。我们可能只须要一种类型的序列。乃至可以想象有一个“完美”的凑集抽象,它能根据自己的利用办法自动改变基层的实现办法。
工具的创建和存在韶光
每个工具都哀求资源才能“生存”,个中最令人瞩目的资源是内存。如果不再须要利用一个工具,就必须将其打消,以便开释这些资源,以便其他工具利用。如果要办理的是非常大略的问题,如何打消工具这个问题并不显得很突出:我们创建工具,在须要的时候调用它,然后将其打消或者“毁坏”。但在另一方面,我们平时碰着的问题每每要比这繁芜得多。
举个例子来说,假设我们要设计一套系统,用它管理一个机场的空中交通(同样的模型也可能适于管理一个仓库的货柜、或者一套影带出租系统、或者宠物店的宠物房。这初看彷佛十分大略:布局一个凑集用来容纳飞机,然后创建一架新飞机,将其置入凑集。
对进入空中交通牵制区的所有飞机都如此处理。至于打消,在一架飞机离开这个区域的时候把它大略地删去即可。
但事情并没有这么大略,可能还须要另一套系统来记录与飞机有关的数据。当然,和掌握器的紧张功能不同,这些数据的主要性可能一开始并不显露出来。例如,这条记录反响的可能是离开机场的所有小飞机的翱翔操持。以是我们得到了由小飞机组成的另一个凑集。一旦创建了一个飞机工具,如果它是一架小飞机,那
么也必须把它置入这个凑集。然后在系统空闲期间,需对这个凑集中的工具进行一些后台处理。
问题现在显得更繁芜了:如何才能知道什么韶光删除工具呢,用完工具后,系统的其他某些部分可能仍旧要发挥浸染。同样的问题也会在其他大量场合涌现,而且在程序设计系统中(如 C++),在用完一个工具之后必须明确地将其删除,以是问题会变得非常繁芜。
最主要的问题之一是工具的创建及毁坏办法。工具须要的数据位于哪儿,如何掌握工具的“存在韶光”呢,针对这个问题,办理的方案是互异其趣的。 C++认为程序的实行效率是最主要的一个问题,以是它许可程序员作出选择。为得到最快的运行速率,存储以及存在韶光可在编写程序时决定,只需将工具放置在堆栈(有时也叫作自动或定域变量)或者静态存储区域即可。这样便为存储空间的分配和开释供应了一个优先级。某些情形下,这种优先级的掌握是非常有代价的。然而,我们同时也捐躯了灵巧性,由于在编写程序时,必须知道工具的准确的数量、存在韶光、以及类型。如果要办理的是一个较常规的问题,如打算机赞助设计、仓储管理或者空中交通掌握,这一方法就显得太局限了。 第二个方法是在一个内存池中动态创建工具,该内存池亦叫“堆”或者“内存堆”。若采取这种办法,除非进入运行期,否则根本不知道到底须要多少个工具,也不知道它们的存在韶光有多长,以及准确的类型是什么。这些参数都在程序正式运行时才决定的。若需一个新工具,只需在须要它的时候在内存堆里大略地创建
它即可。由于存储空间的管理是运行期间动态进行的,以是在内存堆里分配存储空间的韶光比在堆栈里创建的韶光长得多(在堆栈里创建存储空间一样平常只须要一个大略的指令,将堆栈指针向下或向下移动即可)。由于动态创建方法使工具本来就方向于繁芜,以是查找存储空间以及开释它所需的额外开销不会为工具的创建造成明显的影响。除此以外,更大的灵巧性对付常规编程问题的办理是至关主要的。
动态方法使该工具对付的一样平常逻辑的假设每每是繁芜的,以是找到存储和开释该内存的额外空间不会对创建工具产生主要的影响。此外,更多的灵巧性对付办理一样平常的方案问题是至关主要的。
Java 工具不具备与主类型一样的存在韶光。对付用 new 创建的工具,只要我们乐意,它们就会一贯保留下去。这个编程问题在 C和 C++里特殊突出。看来在 C++里碰着的麻烦最大:由于不能从措辞得到任何帮助,以是在须要工具的时候,根本无法确定它们是否可用。而且更麻烦的是,在 C++里,一旦事情完成,必须担保将工具打消。这样便带来了一个有趣的问题。如果 Java 让工具依然故我,若何才能防止它们大量充斥内存,并终极造成程序的“凝固”呢。在 C++里,这个问题最令程序员头痛。但 Java 往后,情形却发生了改不雅观。 Java 有一个特殊的“垃圾网络器”,它会查找用 new 创建的所有工具,并辨别个中哪些不再被引用。随后,它会自动开释由那些闲置工具霸占的内存,以便能由新工具利用。这意味着我们根本不必操心内存的回收问题。只需大略地创建工具,一旦不再须要它们,它们就会自动拜别。这样做可防止在 C++里很常见的一个编程问题:由于程序员忘却开释内存造成的“内存溢出”。
在 Java 中,垃圾网络器在设计时已考虑到了内存的开释问题(只管这并不包括打消一个工具涉及到的其他方面)。垃圾网络器“知道”一个工具在什么时候不再利用,然后会自动开释那个工具霸占的内存空间。采取这种办法,其余加上所有工具都从单个根类 Object 继续的事实,而且由于我们只能在内存堆中以一种办法创建工具,以是 Java 的编程要比 C++的编程大略得多。我们只须要作出少量的决议,即可战胜原来存在的大量障碍。