基于Java的推箱子游戏设计与实现(论文 + 源码)

【免费】关于基于JAVA的推箱子游戏.zip资源-CSDN文库icon-default.png?t=N7T8https://download.csdn.net/download/JW_559/89325018

基于Java的推箱子游戏设计与实现

摘    要

社会在进步,人们生活质量也在日益提高。高强度的压力也接踵而来。社会中急需出现新的有效方式来缓解人们的压力。此次设计符合了社会需求,Java推箱子游戏可以让人们在闲暇之余,体验游戏的乐趣。具有操作简单,易于上手的特点。

推箱子游戏的玩法十分简单——控制人物绕过障碍物,到达目的地。此次毕业设计基于Java语言。将游戏地图做成通用的关卡设计,关卡用二维数组实现,在二维数组中设置值域来表示不同对象,运用二维数组的遍历算法来加载对应图片实现了游戏图片初始化状态。同时,通过初始化多个不同二维数组实现了游戏地图关卡的设计,方法巧妙且简单易行,有效的解决了图片排布问题。充分运用类和方法的调用来实现游戏关卡的初始化。用读取键值的方法判断游戏人物移动、停止、到达目的地。舒缓的音乐配合有趣的步骤,相信能引起很多人的兴趣。作为一个具有悠久历史的游戏,也能够引起人的怀念和共鸣。

关键词  Java 游戏 二维数组 算法 读取键值 栈

Sokoban based on Java

Abstract

Social progress, quality of life is also increasing. High-intensity pressure also follows. The emergence of new social urgently needed an effective way to relieve people's stress. This is designed to meet the needs of the community, Java Sokoban game allows people in her spare time, experience the fun of the game. With simple operation, easy to use features. 

Sokoban game’s rule is very simple - control characters around obstructions, to arrive at the destination. The graduation project is based on Java language. Game map to make a generic level design, level with two-dimensional array implementation, set the domain in a two-dimensional array to represent different objects, using the two-dimensional array of times calendar calculation method is realized to load the corresponding picture game image initialized state. At the same time, through the initialization of several different two-dimensional arrays realized the design of the game map level, a method is clever and simple, easy to effectively solve the problem of the picture arrangement. Make full use of calling classes and methods to implement the initialization of the game levels with reading the key value method to judge the characters move, stop, or reaching its destination. Soothing music with interesting step, which will hopefully lead to a lot of people's interest. As a game with a long history, but also can cause people to miss and resonance.

Key Words: Java game; two-dimensional arrays; algorithm; key value method; stack;

引    言

策略性游戏可以锻炼人的思维能力还能缓解人的压力,使人们暂时忘却生活当中的烦恼,增强人们的逻辑思维能力,游戏的艺术美也吸引着越来越多的玩家和厂商,寓教于乐,在放松人们心情的同时还可以活跃双手。在人类的社会生活当中,游戏占有很大的比重,并且随着社会的发展而不断发展。而且游戏本身具有激发人类潜在行为的特质,是一种能够吸引人们参与其中的活动,其本身具有强烈的吸引力使游戏者卷入其中;再者适当的游戏、合理的时间安排,能够让玩家在娱乐的同时还可以锻炼其反应速度及灵敏程度,亦可让玩家从压力中释放出来。因此游戏逐渐成为人们生活中不可缺少的一部分,游戏产业也正逐步发展成熟。

经典的推箱子游戏是一个来自日本的古老游戏,目的是在训练你的逻辑思考能力。它的玩法也非常简单,在一个狭小的仓库中,要求把木箱放到指定的位置,稍不小心就会出现箱子无法移动或者通道被堵住的情况,所以需要巧妙的利用有限的空间和通道,合理安排移动的次序和位置,控制人物不停的移动将箱子推到目的位置才能顺利的完成任务。难点在于移动的位置,以及箱子到达指定位置的顺序,只有多加思考才能获得游戏的胜利。反复推敲,锻炼了人们的耐性。本次的开发尽量多的设置了关卡数目,增强游戏的耐玩性,同时在画面上有所提高,借鉴了许多达人的经验和技术,引发了我对游戏的热爱,丰富了个人生活,相信推箱子游戏在今后的社会总会越来越引人注目。

1  系统分析

1.1  技术可行性分析

1.1.1  可行性目的

通过推箱子游戏中使用的Java技术,让我能够更加熟练的使用Eclipse。同时了解相关运行环境的配置。将理论知识和实际操作结合起来。达到学以致用的目的。网上资料的查询极大的提高了我的自学能力。希望经过此次设计,锻炼自己的思考,解决问题的能力。对系统开发的流程有更深层次的理解,检验学习成果和实际动手能力,对底层知识有更深的了解。为今后的工作打好基础。

1.1.2  可行性研究前提

基本需求:通过规范的开发流程,采用面向对象的分析设计方法实现游戏美观,易玩,及时等特性。操作性方面主要通过键盘的借口实现,操作键位是上下左右。

主要开发目标:通过此次研究熟练Java的相关知识和技术的应用,界面美化的工作需要同学的帮助,了解团队和合作的重要,熟悉不同领域相关技术的交叉,完成Java推箱子游戏的基本功能。

条件假定和限制:Java相关技术的使用不是很熟练,如果有些游戏bug没有及时发现,相关升级版本需要之后弥补,更正。

可行性研究所采用的方法和步骤,通过研究分析推箱子小游戏所需要的功能以及实现的方法、确定主体结构。利用所学到的知识,以最简洁、最容易的办法,边开发边测试边修改,实现一个初级游戏软件。

评价尺度,实现基础的推箱子功能,如输赢判定,人物的移动位置,箱子的移动位置,同时加强画面的优化,音乐的选定等基础功能。更强的优化需要以后的升级和修改,实现相关功能就达到目标。

1.1.3  算法可行性分析

管理可行性:

此次设计基于Java,有面向对象,可移植性,安全性,并发机制,支持可视化图形界面等特点。易于管理。

经济可行性: 

经济可行性是指可以使用的资源的可能性(资源包括人力资源、自然资源和资金条件)。

经济可行性的内容

经济可行性包括两个方面的内容:一是某一备选方案占有和使用经济资源的可能性,进而实现政策目标的可能性;二是实施某一政策方案所需花费的成本和取得的收益。政府的财政资源是有限的,任何政策方案占有和使用的经济资源也是有限的。因此,任何一项公共政策都存在一个争取公共经济资源的问题。一般说来,“公共政策的经济资源的占有量与其政策目标的期望值成正比例关系。”当然,这还涉及到一个成本效益问题。如果某一方案的成本大于收益,显然这项政策是不可行的。

经济可行性的方法

评估经济可行性有两个基本方法:成本-效益分析或损益分析,成本-效能分析(或称成本-有效性分析)。

经济可行性的标准

经济可行性的具体标准有投入产出比(O/I)、效率(efficiency)、效力(effectiveness)、利润率(profitability)等。这里主要特别说明效率和效力这两个概念。效率是以最小的投入取得最大的产出;效力则是以最小的成本实现即定的目标。二者虽然相关,但却不能混淆,最高效率和最高效力不一定出现在同一个点上。举一个简单的例子,你购买一本书的最小成本是20元,但当你同时买10本同样的书时,只需180元。这后一种显然更有效力(一本书的成本只要18元),但问题是同样的书你只要一本就够了,显然这后一种就不能满足你最基本的目标了。

本次设计注重游戏功能的实现,达到设计目的,不用于其他的商业用途。通过此次设计增强Java技术和实践的结合。同时了解可视化界面,设计操作界面和页面的跳转更换。操作环境需要Eclipse。相关资料可以上网查询。硬件方面可以普通笔记本可以达到要求。

技术可行性:

对于本游戏,可以使用如VB,Java,Delphi等相关的编程语言,但是考虑到编写程序的难易程度以及对编译语言的了解程度,本游戏选择Java程序语言作为编程语言。需要对变量定义、变量初始化、界面初始化、游戏初始化等,然后就可以进入游戏,处理游戏过程中的各种操作。同时进行技术可行性分析时,要注意以下一些问题。 

1.全面考虑系统开发过程所涉及的所有技术问题

软件开发涉及多方面的技术,包括开发方法、软硬件平台、网络结构、系统布局和结构、输入输出技术、系统相关技术等。应该全面和客观地分析软件开发所涉及的技术,以及这些技术的成熟度和现实性。

2.尽可能采用成熟技术

成熟技术是被多人采用并被反复证明行之有效的技术,因此采用成熟技术一般具有较高的成功率。另外,成熟技术经过长时间、大范围使用、补充和优化,其精细程度、优化程度、可操作性、经济性等方面要比新技术好。鉴于以上原因,软件项目开发过程中,在可以满足系统开发需要、能够适应系统发展、保证开发成本的条件下,应该尽量采用成熟技术。

3.慎重引入先进技术

在软件项目开发过程中,有时为了解决系统的特定问题,为了使所开发系统具有更好的适应性,需要采用某些先进或前沿技术。在选用先进技术时,需要全面分析所选技术的成熟程度。有许多报道的先进技术或科研成果实际上仍处在实验室阶段,其实用性和适应性并没有得到完全解决,也没有经过大量实践验证,在选择这种技术时必须慎重。例如,许多文章中已经报道了指纹识别技术,而且市场上也有实验性产品,但指纹识别技术至今仍有许多重大技术难题没有突破,离具体应用仍有一定距离。因此,在项目开发中要谨慎选用这种技术。如果不加分析,在项目中盲目采用指纹识别技术,应用时肯定会出现许多难以解决的具体问题。

4.着眼于具体的开发环境和开发人员

许多技术总的来说可能是成熟和可行的,但是在开发队伍中如果没有人掌握这种技术,而且在项目组中又没有引进掌握这种技术的人员,那么这种技术对本系统的开发仍然是不可行的。例如,分布对象技术是分布式系统的一种通用技术,但是如果在开发队伍中没有人掌握这种技术,那么从技术可行性来看就是不可行的。

5.技术可行性评价

技术可行性评价是通过原有系统和欲开发系统的系统流程图和数据流图,对系统进行比较,分析新系统具有的优越性,以及对设备、现有软件、用户、系统运行、开发环境、运行环境和经费支出的影响,然后评价新系统的技术可行性。

社会可行性:

社会可行性是在特定环境下对项目的开发与实施。
  社会就是由许多个体汇集而成的有组织有规则或纪律的相互合作的生存关系的群体。没有分工与合作关系的个体所聚集成的群体不成为社会。本次设计基于学习的需要,所做毕业设计的内容不会在社会上进行商业运作。网上所查的资料以及相关的知识的引用,属于学术交流,不涉及版权,以及法律责任。同时不会对社会产生负面的影响,不存在不可行性。

算法实现:以人为中心,出现两种可能:①人在空位 ②人在目标位置上

  • 有六种可能:(注:x1,y1, x2, y2为坐标的偏移量,i ,为人所在的坐标 )

②人在目标位置上 同样也有六种可能:

仍然使用问题1的广度优先扩展,容易找出所有和主角所在空间相邻的箱子,判断箱子是否可以从主角所在空间推动也不难,先看是哪一面相邻,再看箱子另一面是否为空。程序设计思路:

对于工人的操作很简单:4个方向的移动,工人移动箱子也随之移动。

地图数据最为关键:第一关的地图都要更换,这些位置也要变,首先我们设计一个二维数组map.我们所地图想象成一个网格,每个格子就是图片的大小30像素,工人和箱子每步移动的距离也是30像素

假设工人移动方式向右,其它方向原理是一致的,P1、P2分别代表工人移动趋势方向前的两个方格

(1)前方P1是围墙:

如果工人前方是围墙 {

退出规则判断,布局不做任何改变

}

(2)前方P1是通道或目的地

如果工人前方是通道或目的地 {

工人可以进入到P1方格,修改相关位置的格子状态值

}

(3)前方P1是箱子

在这种情况,需要判断箱子(P1)前方P2处的物体,来判断工人是否可以移动,此时有以下可能:

一、P1处为箱子(BOX)或者放到目的地的箱子,P2处为通道:工人可以进到P1方格,P2方格的状态可以修改为箱子,修改相关格子的状态值

二、P1处为箱子或者放到目的地的箱子,P2处为目的地:工人可以进到P1方格,P2处为放到目的地的箱子,修改相关格子的状态值

三、P1处为箱子,P2处为墙:退出判断规则布局不做任何改变

1.1.4  平台选择

Eclipse是一个开放源代码的软件开发项目,专注于为高度集成的工具开发提供一个全功能的、具有商业品质的工业平台。它主要由Eclipse项目Eclipse工具项目Eclipse技术项目三个项目组成,具体包括四个部分组成——Eclipse Platform、JDT、CDT和PDE。JDT支持Java开发、CDT支持C开发、PDE用来支持插件开发,Eclipse Platform则是一个开放的可扩展IDE,提供了一个通用的开发平台。它提供建造块和构造并运行集成软件开发工具的基础。

分析对象的技巧在于它的重复利用及维护效率。如果要把设计出来的程序在不同的显示平台上执行,就要作大幅度的更动甚至重写,这样就失去了面向对象属性,所以在本程序分析时将不变与易变的因素分别做成对象,如地图文件、小人与箱子的移动以及程序的运算逻辑就是不变的项目,而绘图及显示平台会因为环境而有所不同属于易变的项目。

虽然大多数用户很乐于将 Eclipse 当作 Java集成开发环境(IDE)来使用,但 Eclipse 的目标却不仅限于此。Eclipse 还包括插件开发环境(Plug-in Development Environment,PDE),这个组件主要针对希望扩展 Eclipse 的软件开发人员,因为它允许他们构建与 Eclipse 环境无缝集成的工具。由于 Eclipse 中的每样东西都是插件,对于给 Eclipse 提供插件,以及给用户提供一致和统一的集成开发环境而言,所有工具开发人员都具有同等的发挥场所。

1.2  需求分析

1.2.1  引言

随着计算机在日常工作中的普及,软件开发行业作为其必不可少的组成部分,被人们所认可。在我国,软件行业日渐成熟,小作坊式的开发形式,已经不能满足我国对于软件规范化、实用性的要求,软件开发流程化及各个职能部门工作的有效划分和正确协作,是现在软件行业面临的一个较大的问题。软件需求分析是软件开发的出发点,为设计起到指导性作用,所以需求分析在软件行业及开发流程中起着非常重要的作用。 

“需求分析”,就是对需要解决的问题进行详细分析,弄清楚需要解决的问题。开发人员需要了解顾客的需求,然后体现在软件中。如果说软件开发过程中,开发人员需要了解自己做什么,顾客需要告诉开发人员自己需要什么,而需求分析就是连接开发人员和顾客之间的重要纽带。只有真正理解顾客的需求,才能设计出顾客所需要的软件。

在过去很长一段时间,开发人员的认为需求分析是整个开发过程中最简单的一个环节。然后越来越多的开发人员认识到它才是整个开发过程中的核心部分。正所谓“磨刀不误砍柴工”。只有真正理解了顾客的需求,才能顺利开发出顾客真正需要的软件。如果一味追求进度,而忽略需求分析,很可能南辕北辙,开发变得毫无意义。 

一、什么是软件需求分析 

通俗地说,软件需求分析是解决做什么,怎么做的问题。告诉客户及开发人

员,需要实现哪些功能,以何种方式,在什么平台去进行操作,开发结束后,应交付哪些东西。 

需求分析就是分析软件用户的需求是什么.如果投入大量的人力,物力,财力,时间,开发出的软件却没人要,那所有的投入都是徒劳.如果费了很大的精力,开发一个软件,最后却不满足用户的要求,从而进行重新开发,这种返工是让人痛心疾首的。这个问题是最典型也是最常见的,现在这个问题一般很好避免,都知道项目的一些敏感性的东西,例如想会有哪些地方设计的不好可能导致以后的使用出现BUG。

二、需求分析的任务  

简言之,需求分析的任务就是解决"做什么"的问题,就是要全面地理解用户的各项要求,并准确地表达所接受的用户需求。 

(1)、了解顾客的要求  

  这是需求分析的重点任务,也是最基本的任务。只有正确了解、理解顾客的要求,才能顺利完成需求分析。  

(2)、分析系统的数据要求 

软件产品是指软件开发商根据市场需要开发的、具有一定适用性和潜在客户的、可销售的软件成品。它区别于应特定客户需求或根据订单开发的软件商品,通常应具有更高的通用性和适应性。但它的通用性和适应性不是轻而易举就能达到的。要实现软件的产品化,就必须在软件产品的设计上下一番功夫。

三、需求分析的过程 

需求分析阶段的工作,可以分为四个方面:问题识别,分析与综合,制订规格说明,评审。

(1)、问题识别 

就是从系统角度来理解软件,确定对所开发系统的综合要求,并提出这些需求的实现条件,以及需求应该达到的标准.这些需求包括:功能需求(做什么),性能需求(要达到什么指标),环境需求(如机型,操作系统等),可靠性需求(不发生故障的概率),安全保密需求,用户界面需求,资源使用需求(软件运行是所需的内存,CPU等),软件成本消耗与开发进度需求,预先估计以后系统可能达到的目标。

(2)、分析与综合 

逐步细化所有的软件功能,找出系统各元素间的联系,接口特性和设计上的限制,分析他们是否满足需求,剔除不合理部分,增加需要部分.最后,综合成系统的解决方案,给出要开发的系统的详细逻辑模型(做什么的模型)。

(3)、制订规格说明书 

即编制文档,描述需求的文档称为软件需求规格说明书.请注意,需求分析阶段的成果是需求规格说明书,向下一阶段提交。 

(4)、评审 

对功能的正确性,完整性和清晰性,以及其它需求给予评价.评审通过才可进行下一阶段的工作,否则重新进行需求分析。 

四、需求分析的方法 

需求分析的方法有很多.这里只强调原型化方法,其它的方法如:结构化方法,动态分析法等。原型化方法是十分重要的。原型就是软件的一个早期可运行的版本,它实现了目标系统的某些或全部功能。 

原型化方法就是尽可能快地建造一个粗糙的系统,这系统实现了目标系统的某些或全部功能,但是这个系统可能在可靠性,界面的友好性或其他方面上存在缺陷。建造这样一个系统的目的是为了考察某一方面的可行性,如算法的可行性,技术的可行性,或考察是否满足用户的需求等。比如,为了考察是否满足用户的要求,可以用某些软件工具快速的建造一个原型系统,这个系统只是一个界面,然后听取用户的意见,改进这个原型。以后的目标系统就在原型系统的基础上开发。 

原型主要有三种类型(软考考过):探索型,实验型,进化型。

(1)探索型:目的是要弄清楚对目标系统的要求,确定所希望的特性,并探讨多种方案的可行性。

(2)实验型:用于大规模开发和实现前,考核方案是否合适,规格说明是否可靠。

(3)进化型:目的不在于改进规格说明,而是将系统建造得易于变化,在改进原型的过程中,逐步将原型进化成最终系统。 

在使用原型化方法是有两种不同的策略:废弃策略,追加策略。废弃策略:先建造一个功能简单而且质量要求不高的模型系统,针对这个系统反复进行修改,形成比较好的思想,据此设计出较完整、准确、一致、可靠的最终系统。系统构造完成后,原来的模型系统就被废弃不用.探索型和实验型属于这种策略。 

 1.2.2  游戏需求

玩家是通过对小人的移动操作来控制推动箱子的,并且玩家需要避过障碍物以及死角,才能将其推放到指定位置从而达到过关的目的。如果玩家将箱子推入死角导致箱子无法移动或不能移动到指定位置则闯关失败,可以通过悔步或重新开始等操作来重新挑战本关。

1、能够显示主菜单和功能

游戏需要提供主菜单让玩家进行游戏设置,同时能能够把地图文件中的信息转换成为图像显示到主游戏界面上。

2、能够实现键盘操作功能

  能够接收到键盘输入的方向键信息,并根据不同的方向键把游戏任务移动到相应的位置,例如,当玩家单击方向键“上”时,如果向上的位置是可移动的,那么就当把游戏人物向上移动一个方格。

3、能够把放置到位置上的箱子进行变色显示

当玩家把箱子推到指定位置的格子时,需要把这个箱子进行变色。这样就能明确地显示出该箱子是否已经放置到指定位置上。

4、支持游戏扩展功能

玩家可以自己扩展原游戏地图文件,从而生成新的游戏地图。

5、游戏胜负判断功能

在游戏中,当玩家把全部的箱子都推到箱子放置点时,玩家胜利通过当前游戏关口,进行下一关口的游戏,如果玩家无法将指定的箱子全部推到放置点时,玩家失败。玩家可以选择重新进行当前关口的游戏,还是退出游戏。

6、支持关口选择功能

玩家在游戏中可自行选择需要挑战的关口。

7、游戏提供支持背景音乐功能

通过主菜单,在游戏开始后,可以选择播放或者禁止播放背景音乐。

8、系统数据流图(DFD)

1)顶层数据流图

2)0层数据流图

3)1层数据流图

1.2.3  软硬件需求

硬件环境需求:

CPU:Intel i5-6500;

内存:4G;

内存剩余资源:500M;

软件环境需求:

JDK 1.7及其以上的版本。

Eclipse MRAS。

1.2.4  接口控制

使用键盘的接口控件操作,上下左右相关键位控制小人的移动。

addKeyListener

public void addKeyListener(KeyListener l)
添加指定的按键侦听器,以接收发自此组件的按键事件。如果 l 为 null,则不会抛出异常并且不执行动作。

Java.awt.event
接口 KeyListener

用于接收键盘事件(击键)的侦听器接口。旨在处理键盘事件的类要么实现此接口(及其包含的所有方法),要么扩展抽象 KeyAdapter 类(仅重写有用的方法)。

然后使用组件的 addKeyListener 方法将从该类所创建的侦听器对象向该组件注册。按下、释放或键入键时生成键盘事件。然后调用侦听器对象中的相关方法并将该 KeyEvent 传递给它。

方法摘要

void

keyPressed(KeyEvent e)
按下某个键时调用此方法。

void

keyReleased(KeyEvent e)
释放某个键时调用此方法。

void

keyTyped(KeyEvent e)
键入某个键时调用此方法。

1.3  方案论证

学校开设的关于学习编程语言的课程有C语言、C++语言、Java程序语言等,皆可用于编写推箱子小游戏的程序。不同的语言有其不同的特点和优势,下面来逐一分析一下。

1.3.1  C++语言的优点

软件需求分析特别重要。在软件工程的历史中,很长时间里人们一直认为需求分析是整个软件工程中的一个简单步骤,但在过去十多年中越来越多的人认识到它是整个过程中最为关键的一个过程。只有通过软件需求分析,才能把软件功能和性能的总体概念描述为具体的软件需求规格说明,从而奠定软件开发的基础。许多大型应用系统的失败,最后均归结到需求分析的失败:要么获取需求的方法不当,使得需求分析不到位或不彻底,导致开发者反复多次地进行需求分析,致使设计、编码、测试无法顺利进行;要么客户配合不好,导致客户对需求不确认,或客户需求不断变化,同样致使设计、编码、测试无法顺利进行。

C++语言支持几乎所有的面对象程序设计特征。可以说,C++语言集中体现了近20年来在程序设计和软件开发领域出现的新的思想和新技术,这主要包括:                

(1)抽象数据类型。

(2)封装和信息隐藏。

(3)以继承和派生方式实现程序重用。

(4)以运算符重载和虚函数来实现多态性。

(5)以模版来实现类型的参数化。

C++是程序员和软件开发者在实践中创造的一般的高级程序设计语言是由计算机科学家在科研和教学环境中设计出来的,然而,C++语言却是由从事实际系统开发的程序员在实践中创造。因此,C++往往从编写实际程序的角度出发,为了程序员提供了各种各样、灵活、高效的语言特性。

正是这些良好的特性使得C++在很多领域,特备是大规模系统程序开发的开发方面,得到广泛应用。目前,许多成功的大型软件都是使用C++编写的。

C++是C语言的超集

所谓“C++是C语言的超集”是指包含C++中包含C语言的全部语法特征。因此,每一个用C语言编写的程序都是一个C++程序。

C++程序的设计宗旨就是在不改变C语言语法规则的基础上扩充新的特性。

实际上,能够很好地兼容C语言正是C++取得成功的原因之一,这是因为:

(1)C++继承了C语言简明、高效、灵活等众多优点。

(2)以前使用C语言编写的大批软件可以不加任何修改,直接在C++开发环境下维护。

(3)C语言程序员只需要学习C++扩充的新特性,就可以很快地使用C++编写程序。

由于具有以上特点,C++已经开始取代C语言工作,被广泛地应用于各行领域的程序设计工作中。时间表明,对于中型和大型程序的开发工作,使用C++的效果要比C言语好的多。C++正在从软件的可靠性,可重用性,可扩充性,可维护性等方面体现出它的优越性。

1.3.2  Java语言的优点

Java语言的流行除了因为它能够编制嵌入HTML文件中的Applet外,还在于Java语言本身的面向对象、简单、平台无关性、安全性、多线程等特点。其次,Java语言的结构与编写方式,与C++语言类似,因此学习Java语言,不仅要了解Java语言独有的编程特点,同时还要有程序设计基础和面向对象的概念。Java语言的主要特点如下: 
    1.简单、高效。 
    Java语言与C++类似,如果用户了解C++和面向对象的概念,就可以很快编写出Java程序;此外,Java又不同于诸如C++语言提供的各种各样的方法,它只提供了基本的方法,这样就减少了编程的复杂性,例如去掉了头文件、指针变量、结构、运算符重载、多重继承等复杂特性。Java语言虽然简单,却非常高效,它可以用面向对象的方法来描述用户的每一个动作。 
    2.面向对象。 
    面向对象的分析根据抽象关键的问题域来对系统进行分解。面向对象的设计是一种提供符号设计系统的面向对象的实现过程,它用非常接近实际领域术语的方法把系统构造成“现实世界”的对象。面向对象程序设计可以看作一种在程序中包含各种独立而又互相调用的对象的思想,这与传统的思想刚好相反:传统的程序设计主张将程序看作一系列函数的集合,或者直接就是一系列对电脑下达的指令。面向对象程序设计中的每一个对象都应该能够接受数据、处理数据并将数据传达给其它对象,因此它们都可以被看作一个小型的“机器”,即对象。
    Java语言是一种新的面向对象的程序设计语言,它除了几种基本的数据类型外,大都是类似C++中的对象和方法,程序代码大多体现了类机制,以类的形式组织,由类来定义对象的各种行为。Java同样支持类继承,这样也减少了程序设计的复杂性。 
    3.平台无关性 。

Java语言经编译后生成与计算机硬件结构无关的字节代码(Bytecode),这些字节代码被定义为不依赖任何硬件平台和操作系统。当Java程序在运行时,需要由一个解释程序对生成的字节代码解释执行。这体现了Java语言的与平台无关性,使得Java程序可以在任何平台上运行,如MS-DOS, Windows,Unix等,因此具有很强的移植性。 
    4.交互式特性。 
    Java是面向对象的网络编程语言,由于它支持TCP/IP协议,使得用户可以通过浏览器访问到Internet上的各种动态对象。并且在网络上用户可以交互式地进行各种动作,而多线程技术的引入使得这种交互式操作更为容易。 
    5.多线程机制。
    Java语言支持多线程机制,多线程机制使得Java程序能够并行处理多项任务。Java程序可以设计成具有多个线程,例如让一个线程负责数据的检索、查寻,另一个线程与用户进行交互,这样,两个线程得以并行执行。多线程机制可以很容易地实现网络上的交互式操作。 
    6.动态的内存管理机制。 
    Java语言采用了自动垃圾回收机制进行内存的管理。在C++语言中,程序员在编写程序时要仔细地处理内存的使用,例如当某个内存快使用完毕时,要及时释放,以供其它程序使用,一旦内存管理不当,就有可能造成内存空间浪费或程序运行故障。在Java系统中包括了一个自动垃圾回收程序,它可以自动、安全地回收不再使用的内存块,这样,程序员在编程时就无需担心内存的管理问题,从而使Java程序的编写变得简单,同时也减少了内存管理方面出错的可能性。 
    7.安全性 
    在类似Internet的这种分布式网络环境中,安全性是个不容忽视的问题。Java语言在安全性方面引入了实时内存分配及布局来防止程序员直接修改物理内存布局;通过字节代码的验证器对字节代码的检验,以防止网络病毒及其它非法代码侵入。此外,Java语言还采用了许多面向对象的异常处理机制,负责对一些异常事件进行处理,如内存空间不够,程序异常中止等的处理。以上介绍了Java语言的一些主要特点,除此之外它还具有动态性、类库丰富、高性能等特点,这些都使得Java语言在各个方面得以成熟和完善,成为大众日益青睐的程序设计语言之一。

1.3.3  C语言的优点

C语言是一种计算机程序设计语言。它既具有高级语言的特点,又具有汇编语言的特点。

它可以作为工作系统设计语言,编写系统应用程序,也可以作为应用程序设计语言,编写不依赖计算机硬件的应用程序。

它的应用范围广泛,具备很强的数据处理能力,不仅仅是在软件开发上,而且各类科研都需要用到C语言,适于编写系统软件,三维,二维图形和动画。具体应用比如单片机以及嵌入式系统开发。

在C的基础上,一九八三年又由贝尔实验室的Bjarne Strou-strup推出了C++。 C++进一步扩充和完善了C语言,成为一种面向对象的程序设计语言。C++目前流行的最新版本是Borland C++, Symantec C++和Microsoft VisualC++。

C++提出了一些更为深入的概念,它所支持的这些面向对象的概念容易将问题空间直接地映射到程序空间,为程序员提供了一种与传统结构程序设计不同的思维方式和编程方法。因而也增加了整个语言的复杂性,掌握起来有一定难度

优点:

1. 简洁紧凑、灵活方便。   

C语言一共只有32个关键字,9种控制语句,程序书写形式自由,区分大小写。把高级语言的基本结构和语句与低级语言的实用性结合起来。C 语言可以像汇编语言一样对位、字节和地址进行操作,而这三者是计算机最基本的工作单元。   

2.运算符丰富。   

C语言的运算符包含的范围很广泛,共有34种运算符。C语言把括号、赋值、强制类型转换等都作为运算符处理。从而使C语言的运算类型极其丰富,表达式类型多样化。灵活使用各种运算符可以实现在其它高级语言中难以实现的运算。   

 3.数据类型丰富。  

C语言的数据类型有:整型、实型、字符型、数组类型、指针类型、结构体类型、共用体类型等。能用来实现各种复杂的数据结构的运算。并引入了指针概念,使程序效率更高。另外C语言具有强大的图形功能,支持多种显示器和驱动器。且计算功能、逻辑判断功能强大。同时对于不同的编译器也有各种   

4.C是结构式语言。  

结构式语言的显著特点是代码及数据的分隔化,即程序的各个部分除了必要的信息交流外彼此独立。这种结构化方式可使程序层次清晰,便于使用、维护以及调试。C语言是以函数形式提供给用户的,这些函数可方便的调用,并具有多种循环、条件语句控制程序流向,从而使程序完全结构化。   

5.语法限制不太严格,程序设计自由度大。  

虽然C语言也是强类型语言,但它的语法比较灵活,允许程序编写者有较大的自由度。   

允许直接访问物理地址,对硬件进行操作。

由于C语言允许直接访问物理地址,可以直接对硬件进行操作,因此它既具有高级语言的功能,又具有低级语言的许多功能,能够像汇编语言一样对位、字节和地址进行操作,而这三者是计算机最基本的工作单元,可用来写系统软件。   

6.生成目标代码质量高,程序执行效率高。   

一般只比汇编程序生成的目标代码效率低10へ20%。   

7.适用范围大,可移植性好。  

C语言有一个突出的优点就是适合于多种操作系统,如DOS、UNIX、windows 98.windows NT;也适用于多种机型。C语言具有强大的绘图能力,可移植性好,并具备很强的数据处理能力,因此适于编写系统软件,三维,二维图形和动画,它也是数值计算的高级语言。

1.3.4  方案选择

面向对象是一种认识世界的方法,是一种程序设计方法。面向对象的观点认为,客观世界是由各种各样的实体,即对象组成的。每种对象都有自己的内部状态和运动规律,不同对象间的相互联系和相互作用就构成了各种不同的系统,并进而构成整个客观世界。按照这样的思想设计程序,就是面向对象的程序设计。

面向对象的程序设计吸取了结构化程序设计的先进思想,并把它们同几个支持用户用新方法进行程序设计的有力概念结合在一起。所有面向对象的程序设计语言一般都包含三个概念:封装、多态性和继承性。这种方法要求语言必须具备抽象、封装、继承和多态性这几个关键要素。

面向对象的程序设计,是通过数据和代码建立分块的内存区域,以便提供对程序进行模块化的一种程序设计方法,这些模块可以被用作样板,在需要时再建立其副本。

C++语言和Java语言在面向对象这方面都比较强,C++语言为了与C语言兼容,其是包含了些面向过程的成分;Java语言除了C++语言中非面向过程的部分,其程序编写过程就是设计、实现类,定义其属性、行为的过程。还有Java语言特有的“沙箱”机制是其安全性的保障,同时它去除了C++语言中易造成的错误指针,增加了自动内存管理等措施,保证了Java程序运行的可靠性。

对于变量声明、参数传递、操作符、控制语句等方面,Java使用了与C、C++相同的风格,使得熟悉C、C++的程序员能很方便地进行编程。同时,Java为了实现其简单、强壮、安全等特性,也去掉了C和C++中许多不合理的内容。Java语言和C语言、C++语言的       

区别有:
    1.全局变量.Java程序中,不能在所有类之外定义全局变量,只能通过在一个类中定义公用、静态的变量来实现一个全局变量。Java对全局变量进行了更好的封装。而在C语言和C++语言中,依赖于不加封装的全局变量常常造成系统的崩溃。
    2.不采用Goto语句.Java不支持C语言/C++语言中的Goto语句,而是通过例外处理语句Try、Catch、Finally等来代替,并处理遇到错误时跳转的情况,使程序更可读且更结构化。
  3.指针 Java不支持C语言/C++语言中的指针,因为由指针所进行的内存地址操作常会造成不可预知的错误,同时通过指针对某个内存地址进行显式类型转换后,可以访问一个C++中的私有成员,从而破坏安全性,造成系统的崩溃。Java对指针进行完全的控制,程序员不能直接进行任何指针操作,例如把整数转化为指针,或者通过指针释放某一内存地址等。

因此,经过再三比较三种语言之后,采用了Java语言来编写推箱子小游戏的程序代码。

各类语言使用热度如下图1-2所示:

图1-2 编程语言使用热度排行

图1-3热门编程语言使用热度变化曲线

2  概要设计

概要设计是一个设计师根据用户交互过程和用户需求来形成交互框架和视觉框架的过程,其结果往往以反映交互控件布置、界面元素分组以及界面整体板式的页面框架图的形式来呈现。这是一个在用户研究和设计之间架起桥梁,使用户研究和设计无缝结合,将对用户目标与需求转换成具体界面设计解决方案的重要阶段 。

概要设计的主要任务是把需求分析得到的系统扩展用例图转换为软件结构和数据结构。设计软件结构的具体任务是:将一个复杂系统按功能进行模块划分、建立模块的层次结构及调用关系、确定模块间的接口及人机界面等。数据结构设计包括数据特征的描述、确定数据的结构特性、以及数据库的设计。显然,概要设计建立的是目标系统的逻辑模型,与计算机无关。

2.1  游戏设计分析

分析对象的技巧在于它的重复利用及维护效率。如果要把设计出来的程序在不同的显示平台上执行,就要作大幅度的更动甚至重写,这样就失去了面向对象属性,所以在本程序分析时将不变与易变的因素分别做成对象,如地图文件、小人与箱子的移动以及程序的运算逻辑就是不变的项目,而绘图及显示平台会因为环境而有所不同属于易变的项目。

此次推箱子游戏需要用到Java GUI来对界面和图形进行编程。GUI全称Graphical User Interfaces,意为图形用户户界面,又称为图形用户接口,GUI指的就是采用图形方式显示的计算机操作用户界面, 实现GUI编程的必不可少的三个条件是组件、事件

组件

组件就是一些基本的图形元素,包含有两类组件,一类是像我们经常用到的按钮、文本框、文本域、多选按钮、单选按钮等;另一类是我们经常说到的容器,比如说窗体、Panel等,它的作用主要是用来组织界面上的组件或者单元。

AWT组件

AWT组件是重量级组件,它依赖于本地操作系统的GUI,缺乏平台独立性。但是AWT组件简单稳定,兼容于任何一个JDK版本。AWT所涉及到的类一般在Java.awt的包及其子包中。Java.awt中的类负责与本地操作系统进行交互,让本地操作系统显示和操作组件。AWT中的两个核心类是Container(容器)和Component类,如下图所示:

图2-1 Container和Component类

Component类

Java图形用户界面最基本组成部分是Component,Component类及其子类的对象用来描述以图形化的方式显示在屏幕上并能够与用户进行交互的GUI元素(标签、按钮)。

Container类

用来组织界面上的组件或者单元。有两种常用的Container(容器),一是Window,Window对象表示自由停泊的顶级窗口,另一个是Panel对象可作为容纳其他Component对象,但不能够独立存在,必须被添加到其他Container中,比如说Window或者Applet中。Container它有一定的范围和大小,一般都是矩形。也有一定的位置,这个位置可分相对位置和绝对位置。

一个Container中可以包含其他Container,Container中可以嵌套Container,当Container显示时候,它里面的元素也被小时出来,当Container隐藏时或者关闭时,它包含的元素也被隐藏。 

Component类与Container类关系

Component对象不能独立显示出来,必须放在某一Container对象中才可以显示出来。Container是Component的子类,Container的子类对象可以容纳别的Component对象。Container对象也可以被当作Component对象添加到其他Container对象中。   

事件

事件是指组件触发的动作事件,Java中不同的事件由不同的监听器处理,组件是事件源对象,而监听器主要用来接收来自事件源对象产生的动作事件,然后对其处理。

需要特别注意的是:

事件实现过程中产生的对象:事件、事件源、监听器。

事件:用户在界面上的某一个操作,通常使用各种输入设备,如鼠标、键盘等。

事件源:产生事件的组件,例如在一个按钮上的单击就是事件源。

事件监听

监听器:包含事件处理器,负责检查事件是否发生,若发生则激活事件处理器对其处理。

监听过程: 当事件源对象产生某种事件时,先封装该事件的信息,然后向监听器传送此事件对象,监听器在接收到事件对象后,为了能让监听器检查组件是否发生了该事件,会向该事件源对象(即该组件)注册事件监听器,然后事件处理器会检查事件是否发生,如果发生了,那么激活事件处理器进行处理。

要特别注意的是:

事件实现过程中产生的对象:事件、事件源、监听器。

事件:用户在界面上的某一个操作,通常使用各种输入设备,如鼠标、键盘等。

事件源:产生事件的组件,例如在一个按钮上的单击就是事件源。

监听器:包含事件处理器,负责检查事件是否发生,若发生则激活事件处理器对其处理。

监听过程: 当事件源对象产生某种事件时,先封装该事件的信息,然后向监听器传送此事件对象,监听器在接收到事件对象后,为了能让监听器检查组件是否发生了该事件,会向该事件源对象(即该组件)注册事件监听器,然后事件处理器会检查事件是否发生,如果发生了,那么激活事件处理器进行处理。

从面向对象的观念出发,本程序可分为以下几个对象:

1.地图文件的引用。

2.小人与箱子的移动。

3.程序运算逻辑。

4.绘图。

5.显示平台。

2.1.1  地图文件的引用

在设计游戏程序时,通常都是把游戏的画面布局数据存放在一个地图文件中。程序通过读取地图文件中的数据来获取画面的布局安排。

地图文件是20*20的变量数组文件,在地图不同的数字代表不同的意义。把这组数据保存到一个文件中,这个文件就是地图文件了。

Java读取txt文件内容。可以作如下理解:

1、首先获得一个文件句柄。File file = new File(); file即为文件句柄。即为两个端建立联系。

2、通过这条线路读取甲方的信息:new FileInputStream(file) 目前这个信息已经读进来内存当中了。接下来需要解读成乙方可以理解的东西

3、使用FileInputStream()。那么对应的需要使用InputStreamReader()这个方法进行解读刚才装进来内存当中的数据

4、解读完成后要输出呀。那当然要转换成IO可以识别的数据呀。那就需要调用字节码读取的方法BufferedReader()。同时使用bufferedReader()的readline()方法读取txt文件中的每一行数据。

部分代码如下:

    public static void readTxtFile(String filePath){

        try {

                String encoding="GBK";

                File file=new File(filePath);

                if(file.isFile() && file.exists()){ //判断文件是否存在

                    InputStreamReader read = new InputStreamReader(

                    new FileInputStream(file),encoding);//考虑到编码格式

                    BufferedReader bufferedReader = new BufferedReader(read);

                    String lineTxt = null;

                    while((lineTxt = bufferedReader.readLine()) != null){

                        System.out.println(lineTxt);

                    }

                    read.close();

        }else{

            System.out.println("找不到指定的文件");

        }

        } catch (Exception e) {

            System.out.println("读取文件内容出错");

            e.printStackTrace();

        }

     

    }

     

    public static void main(String argv[]){

        String filePath = "L:\\Apache\\htdocs\\res\\20121012.txt";

        readTxtFile(filePath);

    }

2.1.2  程序运行逻辑

程序中逻辑运算包含小人与箱子的移动、键盘事件的响应、保存数据以实现悔步以及重新开始的操作等等。

运行游戏载入相应的地图,屏幕中出现一名推箱子的工人其周围是围人可以走的通道、几个可以移动的箱子、和箱子的放置目的地。玩家通过按上下左右键控制工人推箱子、当所有的箱子推到目的地后出现过关信息,并显示下一关、

如果推错了,玩家通过单击鼠标右键可以撤消上次的移动操作、

还可以按空格键重玩这一关,直到通过全部关卡。

游戏中我们用到的是二维数组来完成游戏的基础绘图。

图2-2本地地图文件

2.1.3  绘图

绘图主要是用于在小人与箱子的移动后,原位置由草地填补,以此来表示小人与箱子的移动以及其画面的连贯性。

部分代码如下:

绘制地图:

mainpanel()

{

setBounds(15,50,600,600);

setBackground(Color.white);

addKeyListener(this);

myImage=new Image[10];

for(int i=0; i<10; i++)

{

    myImage[i] = Toolkit.getDefaultToolkit().getImage("pic\\"+i+".gif");

}

setVisible(true);

判断运动方向和填补空白:

void moveup()

{

if(map[manY-1][manX]==2||map[manY-1][manX]==4)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

map[manY][manX]=4;

else map[manY][manX]=2;

map[manY-1][manX]=8;

repaint();manY--;mystack.push(10);

}

else if(map[manY-1][manX]==3)

{

if(map[manY-2][manX]==4)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

map[manY][manX]=4;

else map[manY][manX]=2;

map[manY-1][manX]=8;

map[manY-2][manX]=9;

repaint();manY--;mystack.push(11);

}

else if(map[manY-2][manX]==2)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

map[manY][manX]=4;

else map[manY][manX]=2;

map[manY-1][manX]=8;

map[manY-2][manX]=3;

repaint();manY--;mystack.push(11);

}

else {map[manY][manX]=8;repaint();}

}

else if(map[manY-1][manX]==9)

{

if(map[manY-2][manX]==4)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

map[manY][manX]=4;

else map[manY][manX]=2;

map[manY-1][manX]=8;

map[manY-2][manX]=9;

repaint();manY--;mystack.push(11);

}

else if(map[manY-2][manX]==2)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

map[manY][manX]=4;

else map[manY][manX]=2;

map[manY-1][manX]=8;

map[manY-2][manX]=3;

repaint();manY--;mystack.push(11);

}

else {map[manY][manX]=8;repaint();}

}

if(map[manY-1][manX]==1)

{

map[manY][manX]=8;

repaint();

}

}

2.1.4  显示平台

“可移植性高”是Java的属性之一,Java的应用涉及许多领域,如手机、单机程序及浏览器等,不同的平台对于它的设定不尽相同,若将显示平台独立为一个类,将有助于主程序的完整性及移植程序的快速性。Java的可移植性:

1.Java作为一种编程语言:源代码可移植性

作为一种编程语言,Java提供了一种最简单同时也是人们最熟悉的可移植性–源代码移植。这意味着任意一个Java程序,不论它运行在何种CPU、操作系统或Java编译器上,都将产生同样的结果。这并不是一个新的概念。人们使用C、C++也可以产生同样的效果。但是使用C或C++编程人们可以有太多的选择,在许多细节上它都没有严格定义,如:未初始化变量的值、对已释放的内存的存取、浮点运算的尾数值等等。所以除非你一开始就严格按照系统无关的概念来进行设计,否则这种可移植性只能是一种理论上的设想而不能形成实践。总之,尽管C和C++有严密的语法定义,它们的语意(symantics)定义还不是标准的。这种语意上的不统一使得同一段程序在不同的系统环境下会产生不同的结果。有时即使系统情况完全相同而仅仅由于编译器的设置不同也会产生令人意想不到的结果。而Java就不同了。它定义了严密的语意结构,而使编译器不承担这方面的工作。另外,Java对程序的行为的定义也比C和C++严格,如:它提供了内存自动回收功能(GarbageCollection),使程序不能访问越界内存;它对未初始化的变量提供确定值等等。它的这些特性能够减小在不同平台上运行的Java程序之间的差异,也使得Java具有即使没有Java虚拟机的存在的情况下比C和C++更好的平台无关性。然而,这些特点也有它不利的一面。Java设想运行于具有32位字节长度且每字节为8位的计算机上,这就使得那些8位字长的计算机和一些巨型机不能有效的运行Java程序。在这样的平台上就只能运行那些可移植的C和C++程序了。

图2-3Java多线程图解

2.Java作为一个虚拟机:CPU可移植性

大多数编译器产生的目标代码只能运行在一种CPU上(如Intel的x86系列),即使那些能支持多种CPU的编译器也不能同时产生适合多种CPU的目标代码。如果你需要在三种CPU(如x86、SPARC和MIPS)上运行同一程序,就必须编译三次。

但Java编译器就不同了。Java编译器产生的目标代码(J-Code)是针对一种并不存在的CPU–Java虚拟机(JavaVirtualMachine),而不是某一实际的CPU。Java虚拟机能掩盖不同CPU之间的差别,使J-Code能运行于任何具有Java虚拟机的机器上。

虚拟机的概念并不是Java所特有的:加州大学几年前就提出了PASCAL虚拟机的概念;广泛用于Unix服务器的Perl脚本也是产生与机器无关的中间代码用于执行。但针对Internet应用而设计的Java虚拟机的特别之处在于它能产生安全的不受病毒威胁的目标代码。正是由于Internet对安全特性的特别要求才使得JVM能够迅速被人们接受。当今主流的操作系统如OS/2、MacOS、Windows95/NT都已经或很快提供对J-Code的支持。

作为一种虚拟的CPU,Java虚拟机对于源代码(SourceCode)来说是独立的。我们不仅可以用Java语言来生成J-Code,也可以用Ada95来生成。事实上,已经有了针对若干种源代码的J-Code编译器,包括Basic、Lisp和Forth。源代码一经转换成J-Code以后,Java虚拟机就能够执行而不区分它是由哪种源代码生成的。这样做的结果就是CPU可移植性。

将源程序编译为J-Code的好处在于可运行于各种机器上,而缺点是它不如本机代码运行的速度快。

3.Java作为一种虚拟的操作系统(OS)和图形用户界面(GUI):操作系统可移植性。

即使经过重新编译,大多数的用C和C++编写的Windows程序也不能在Unix或Macintosh系统上运行。这是为什么呢?因为程序员在编写Windows程序时使用了大量的WindowsAPI和中断调用,而Windows程序对系统功能的调用与Unix和Macintosh程序有很大的差别,所以除非将全套WindowsAPI移植到其它操作系统上,否则重编译的程序仍不能运行。

Java采用了提供一套与平台无关的库函数(包括AWT、UTIL、LANG等等)的方法来解决这个问题。就像JVM提供了一个虚拟的CPU一样,Java库函数提供了一个虚拟的GUI环境。Java程序仅对Java库函数提出调用,而库函数对操作系统功能的调用由各不同的虚拟机来完成。

总之,Java在可移植性方面的特点使它在Internet上具有广泛的应用前景。同时它本身具有的防病毒的能力也使它在需要高可靠性的应用中占有一席之地。

2.2  注意事项

小游戏在设计时要注意绘图部分的设计代码,还要注意通过输入流读取地图文件与图像文件部分的设计代码等等。

2.3  游戏流程图

图2-4系统功能模块

本程序包括5个模块,分别是初始化模块、画图模块、移动箱子模块、移动小 模块和功能控制模块,如图1所示。各个模块的功能描述如下:

(1)初始化模块。该模块包括屏幕初始化和游戏第一关的初始化。屏幕初始化用于输出欢迎信息和操

(2)画图模块。该模块主要是被其它模块调用,用于画墙、在空地画箱子、在目的地画箱子、画小人和画目的地。

(3)移动箱子模块。该模块用于移动箱子,包括目的地之间、空地之间和目的地与空地之间的箱子移动。

(4)移动小人模块该模块用于控制小人移动,从而推动箱子到目的地。

(5)功能控制模块。该模块是几个功能函数的集合,包括屏幕输出功能、指定位置状态判断功能和关卡重置功能。

2.4  函数模型

图2-5函数模型图

1.putoutChar()  

函数原型:void putoutChar(int y,int x,char ch,char fc,char bc)  putoutChar()函数在屏幕上的指定位置输出指定的字符。其中,x、y指明输出的位置,ch表示输出的字符,fc表示输出的字符颜色,bc 表示背景色。    

2.printWall()

 函数原型:void printWall(int x,int y)  printWall()函数用于画墙壁,传入参数x、y指明位置。该函数调用putoutChar()进行输出,以黑色为背景画绿色墙,用小方块表示墙(ASCII值为219)。    

3.printBox()  

函数原型:void printBox(int x,int y)  printBox()函数用于在非目的地画箱子,传入参数x、y指明位置。该函数调用putoutChar()进行输出,以黑色为背景白色箱子,用ASCII值为10的字符表示箱子。    

4.printBoxDes()  

函数原型:void printBoxDes(int x,int y)  printBoxDes()函数用于在目的地画箱子,传入参数x、y指明位置。该函数调用putoutChar()进行输出,以黑色为背景画黄色箱子,仍用ASCII值为10的字符表示箱子。    

5.printDestination()  

函数原型:void printDestination(int x,int y)  printDestination()函数用于画目的地,传入参数x、y指明位置。该函数调用putoutChar()进行输出,以黑色为背景画黄色目的地,用心型表示(ASCII值为003)。    

6.printDestination1()  

函数原型: void printDestination1(int x,int y,winer **win,winer **pw)  printDestination1()函数与printDestination()函数功能基本相同,都是画目的地函数,但是printDestination1()增加了记录每一个目的地位置的功能。其中x、y指明目的地的位置,每一关的所有目的地位置存放在结构体struct winer中,形成一条链表,**winer返回链表的头,**pw则指向链表的尾部。

7. printMan()  

函数原型: void printMan(int x,int y)  printMan()函数用于画小人。X、y指明画的位置。该函数通过软中断来实现,首先设置寄存器AX的高位和低位,设置高位0xa表示在光标位置显示字符;设置低位02(ASCII值),表示输出的字符;然后设置寄存器CX为01,表示重复输出的次数,这里只输出一次;最后产生类型为0x10的中断,表示显示器输出。    

8.init()  

函数原型: void init()  init()函数用于初始化屏幕。该函数首先用两个for循环初始化屏幕20*20范围内的状态,初始化为0,以后根据实际情况重新赋值;然后设置屏幕输出状态,最后移动光标到指定的位置输出操作提示信息以及版权信息。    

9.初始化游戏  

函数原型:level(); 这个函数分别初始化游戏的第一关。这些函数的功能和实现步骤相似。首先根据需要在指定的位置画墙壁和画箱子,在这里可以设置游戏的难度,初始化的墙壁越复杂,箱子越多,则游戏就越难。游戏的第一关至第四关难度依次增加。然后分别调用printDestination1()和printMan()函数画目的地和小人。函数返回包含各个目的地位置的链表。    

10.移动箱子  

函数原型: void moveBoxSpacetoSpace(int x,int y,char a)、void moveBoxDestoSpace(int x,int y, char a)、void moveBoxSpacetoDes(int x,int y,char a)、void moveBoxDestoDes(int x,int y,char a)  这几个函数实现的功能分别是人空地移动箱子到空地、从目的地移动箱子到空地、从空地移动箱子到目的地和中从目的地移动箱子到目的地。X、y指明小人当前所处的位置,字符a表示移动的方向,有“u”、“d”、“l”和“r”4个值,分别表示向上、下、左、右移动。这几个函数的实现原理大致相似。对于前面两个函数,首先判断移动的方向,人小人所在的位置沿着移动的方向移动一步画小人,移动两步画箱子(调用printBox()函数),并设置状态为“b”;对于后面两个参数,首先判断移动的方向,从小人所在的位置沿着移动方向移动一步画小人,移动两上在目的地画箱子(调用printBoxDes()函数),并设置状态为“i”,表明箱子在目的地上。    

11.isWin()  

函数原型: Judge(),int judge(int x,int y)  judge()根据结构体struct[x][y]中存的值来判断该点的状态。   

12.move()  

函数原型: void moid(int x,int y,char a)  Move()函数根据按下的键来处理小人的移动。小人移动的方向有上(MoveUp())、下(MoveDown())、左(MoveLeft())、右(MoveRight())4个,4个方向的处理方式一样。首先判断移动的方向,然后根据小人的当前位置、下一步位置以及下下一步位置所在的状态进行处理。  

(1)若下一步所在位置的状态为墙壁(“w”),则直接退出,不作任何处理。

(2)若下一步所在位置的状态为目的地(“i”)或者什么都没有(“0”),则:  ① 若当前位置的状态为目的地,则在当前位置画目的地(调用printDestination()函 数)、在下一步位置画小人(调用printMan()函数)。 ② 若当前位置的状态为非目的地,则输出空格清空当前位置的小人,并在下一步位置画 小人(调用printMan()函数)。        

(3)若下一步所在位置的状态为箱子(“b”),则:

① 如果下下一步位置的状态为“0”,则把箱子从空地移动到空地(调用 moveBoxSpacetoSpace()函数),然后把光标移动到下一步位置(如果当前位置的状态为目的地,则应先画目的地(调用printDestinanion()函数))。

② 如果下下一步位置的状态为目的地,则把箱子从空地移动到目的地(调用 moveBoxSpacetoDes()函数),然后把光标移动到下一步位置(如果当前位置的状态   为目的地,则应先画目的地(调用printDestination()函数))。

③ 其它情况则直接返回,不作任何处理。  

(4)若下一步所在位置的状态为箱子在目的地(“i”),则:

① 如果下下一步位置的状态为“0”,则把箱子从目的地移动到空地(调用 moveBoxDestoSpace()函数),然后把光标移动到下一步位置(如果当前位置的状态为目的地,则应先画目的地(调用printDestination()函数))。

② 如果下下一步位置的状态为目的地,则把箱子从目的地移动到目的地(调用 moveBoxDestoDes()函数),然后把光标移动到下一步位置(如果当前位置的状态为目的地,则应先画目的地(调用printDestination()函数))。

③ 其它情况则直接返回,不作任何处理。   

13.reset()  

函数原型:void reset(int i)  reset()函数的功能是重置当前关。该函数首先判断当前关是第几关,然后调用init()函数和初始化当前关的函数进行重置。   

14.主函数  

主函数首先进行显示状态的设置,初始化屏幕,初始化第一关,并显示操作提示信息和版权信息。然后根据按下的键(KeyPress()函数返回按下的键值)进行处理,处理过程由move()类函数进行(如果按下Esc键,则退出程序)。对于每一关,如果所有的表示目的地的状态都由“false”变成了“true”,则表示通过该关,可以进入下一关。

3  详细设计

3.1  游戏总体结构与代码

推箱子的小游戏界面如图3-1所示:

图3-1小游戏界面

(1)界面框架与按钮设计

本游戏界面简单清晰,操作界面优美,有很强的带入性,游戏操作模块分为:“悔一步”,“重来”,“上一关”,“下一关”,“第1关”,“最终关”,“选关”“音乐关”并且各个按钮的名称与相关功能为:

“悔一步”:返回上一移动状态(可以连续返回多步);

“重来”:重新开始当前关;

“上一关”:返回到当前关的上一关;

“下一关”:跳转到当前关的下一关;

“第1关”:游戏系统默认开始关为第一关,此按钮让玩家可以方便从其它关卡直接跳转到第一关;

“最终关”:可以跳转到最后一关,即游戏系统默认的最后一个关。

mainFrame()

{

super("推箱子v2.0");

setSize(720,720);

setVisible(true);

setResizable(false);

setLocation(300,20);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Container cont=getContentPane();

cont.setLayout(null);

cont.setBackground(Color.black);

Menu choice=new Menu("    选项");

choice.add(renew);choice.add(last);choice.add(next);choice.add(choose);choice.add(back);

choice.addSeparator();choice.add(exit);

renew.addActionListener(this);

last.addActionListener(this);

next.addActionListener(this);

choose.addActionListener(this);

exit.addActionListener(this);

back.addActionListener(this);

Menu setmuc=new Menu("    设置音乐")

setmuc.add(nor);setmuc.add(qin);setmuc.add(po);setmuc.add(guang);setmuc.add(eye);

nor.addActionListener(this);

qin.addActionListener(this);

po.addActionListener(this);

guang.addActionListener(this);

eye.addActionListener(this);

Menu help=new Menu("    帮助");

help.add(about);

about.addActionListener(this);

MenuBar bar=new MenuBar();

bar.add(choice);bar.add(setmuc);bar.add(help);

setMenuBar(bar);                                        

}

3.2  选关模块

“选关”:选择想要挑战的关卡。当游戏玩家想要自主选择关卡时,可以随意输入想要跳入的关卡,节约了时间,玩家同过选择的关卡可以有效地挑战自我,连接上次的游戏进度。

其中,这个部分的部分代码为:

void Tuixiangzi(int i)

{

Levelmap=new Readmap(i);

Levelmaptmp=new Readmap(i);

map=Levelmap.getmap();

manX=Levelmap.getmanX();

manY=Levelmap.getmanY();

maptmp=Levelmaptmp.getmap();

repaint();

}

int maxlevel(){return max;}

public void paint(Graphics g)

{

for(int i=0; i<20; i++)

for(int j=0; j<20; j++)

    {

    g.drawImage(myImage[map[j][i]],i*len,j*len,this);

}

g.setColor(new Color(0,0,0));

g.setFont(new Font("楷体_2312",Font.BOLD,30));

g.drawString("现在是第",150,40);

g.drawString(String.valueOf(level),310,40);

g.drawString("关",360,40);

}

推箱子选关模式如图3-2所示

图3-2  选关模块

3.3  地图的绘制形成

地图以二维数组的形式进行存储,不同的数家代表了不同的含义。在本小游戏的地图文件中,0~9这十个数字的定义如下所示:

编号0:代表未定义的区域;

编号1:代表障碍物(或者边界);

编号2:代表草地;

编号3:代表箱子(未到指定位置);

编号4:代表目的地;

编号5:代表小人向下移动方向;

编号6:代表小人向左移动方向;

编号7:代表小人向右移动方向;

编号8:代表小人向上移动方向;

编号9:代表到达指定位置时的箱子。

例如下图3-3所示(左边是二维数组的地图文件,右边是相对应的小游戏界面):

               

推箱子小游戏的游戏性,其主要功能是给用户一个良好的游戏界面,游戏中包括50关的地图文件。地图文件是是先写好的,所有界面信息以数的形式存放在一个20*20的二维数组当中并且把这些地图文件统一放在一个地图文件中,便于程序调用地图文件。然后,每一关就会按照这些数组数据重新绘制地图,从而达到小游戏的可用性及其相应的目的。

推箱子地图文件如图3-4所示:

图3-4地图文件

部分代码如下所示:

private int[][] mymap=new int[20][20];

FileReader r;

BufferedReader br;

String bb="";

int[] x;int c=0;

Readmap(int k)

{

level=k;

String s;

File f=new File("maps\\"+level+".map");

r=new FileReader(f);

br=new BufferedReader(r);

}

while ((s=br.readLine())!=null)

{

bb=bb+s;

}

byte[] d=bb.getBytes();

int len=bb.length();

int[] x=new int[len];

for(int i=0;i<bb.length();i++)x[i]=d[i]-48;

for(int i=0;i<20;i++)

{

for(int j=0;j<20;j++)

    {

mymap[i][j]=x[c];

        if(mymap[i][j]==5)

        {

mx=j;my=i;

        }

        c++;

    }

    }

3.4  小人与箱子移动的算法

小人与箱子的移动中包括了正移动以及“悔一步”的负移动。

正移动:小人向上、下、左、右的移动是一个判断算法,其判断都是通过判断小人前面是否是草地或者是箱子或者是障碍物(或者边界)。如果是障碍物或者是边界,就不能够进行移动;如果是没有箱子或者是障碍物,就可以自由移动;又如果是有箱子,就要判断是否可以移动箱子,最后再讨论箱子被推过的位置,小人移动的位置,以及它们的原位置和被遮挡住的新位置的图形变化等等,需要运用算法使其重新绘制地图,填补空白。算法判断完毕后,传出数据并且将其记录在一个堆栈中,以备“悔一步”时使用。

负移动:通过记录在堆栈中的数据来判断,前一步小人的移动方向以及移动中使用过的算法,逆向将代码重新运行,同时绘制并刷新地图以达到前一步的状态。

其中,这个部分的部分代码为:

void moveup()

 {

if(map[manY-1][manX]==2||map[manY-1][manX]==4)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

map[manY][manX]=4;

else map[manY][manX]=2;

map[manY-1][manX]=8;

repaint();manY--;mystack.push(10);

}

else if(map[manY-1][manX]==3)

{

if(map[manY-2][manX]==4)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

map[manY][manX]=4;

else map[manY][manX]=2;

map[manY-1][manX]=8;

map[manY-2][manX]=9;

repaint();manY--;mystack.push(11);

}

else if(map[manY-2][manX]==2)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

map[manY][manX]=4;

else map[manY][manX]=2;

map[manY-1][manX]=8;

map[manY-2][manX]=3;

repaint();manY--;mystack.push(11);

}

else {map[manY][manX]=8;repaint();}

}

else if(map[manY-1][manX]==9)

{

if(map[manY-2][manX]==4)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

map[manY][manX]=4;

else map[manY][manX]=2;

map[manY-1][manX]=8;

map[manY-2][manX]=9;

repaint();manY--;mystack.push(11);

}

else if(map[manY-2][manX]==2)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

map[manY][manX]=4;

else map[manY][manX]=2;

map[manY-1][manX]=8;

map[manY-2][manX]=3;

repaint();manY--;mystack.push(11);

}

else {map[manY][manX]=8;repaint();}

}

if(map[manY-1][manX]==1)

{

map[manY][manX]=8;repaint();

}

}

3.5  小人上下移动模块

在本小游戏系统中,小人与箱子的移动应该是能带给玩家较为逼真的视觉感受,这样才能体现系统的有效性与娱乐性。玩家通过控制小人,推动箱子在草地上避过障碍物与边界死角来到达指定的终点位置。

其中,这个部分代码分为上下左右移动。其中代码原理相同,转向利用下一步位置的判断。

void moveleft(){

……}

void movedown(){

……}

void moveright(){

……}

  小人向后转的代码如下:

void backup(int t)

{

int n=t;

if(n==10)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

{

map[manY][manX]=4;

}

else map[manY][manX]=2;

}

else if(n==11)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

{

map[manY][manX]=9;

}

else map[manY][manX]=3;

if(maptmp[manY-1][manX]==4||maptmp[manY-1][manX]==9)

{

map[manY-1][manX]=4;

}

else map[manY-1][manX]=2;

}

map[manY+1][manX]=8;

repaint();manY++;

}

小人移动如图3-5所示:

图3-5 小人移动

3.6  悔棋模块

在推箱子小游戏中,数据的存储是非常重要的,不然就无法进行“悔一步”的操作。本小游戏系统受用了堆栈的存储方式来存储并且控制小人与箱子的移动以及地图文件的变换。而“悔一步”的操作让玩家可以进行反悔这一步操作,可避免因一时失手走错而导致的阻塞书面,可以节省玩家重新开始的时间。

其中,这个部分的部分代码为:

else if(e.getSource()==btnback||e.getSource()==back)

{

if(panel.isMystackEmpty())JOptionPane.showMessageDialog(this, "您还未移动!!!");

else

{

switch(panel.back())

{

case 10:panel.backup(10);break;

case 11:panel.backup(11);break;

case 20:panel.backdown(20);break;

case 21:panel.backdown(21);break;

case 30:panel.backleft(30);break;

case 31:panel.backleft(31);break;

case 40:panel.backright(40);break;

case 41:panel.backright(41);break;

}

}

推箱子悔棋如图3-6所示:

图3-6悔棋模块

3.7  音乐控制

在推箱子小游戏中,音乐的选择是非常重要的,通过音乐选择可以提高游戏的娱乐性。让游戏玩家可以再轻松越快的环境中进行游戏,同时游戏的随关卡转换也是本次设计的一大特点。使用了Java MIDI技术中的Sequence类和Sequencer容器和其中的getSequence()方法等。

其中,这个部分的部分代码为:

public void itemStateChanged(ItemEvent ie)

 {

int no=jc.getSelectedIndex();

switch(no)

{

case 0:sound.setMusic("nor.mid");

 if(sound.isplay())

 sound.mystop();

 sound.loadSound();

 btnmuc.setLabel("音乐关");

 nor.setEnabled(false);

 qin.setEnabled(true);

 guang.setEnabled(true);

 eye.setEnabled(true);

 po.setEnabled(true);

panel.requestFocus();

break;

case 1:sound.setMusic("qin.mid");

 if(sound.isplay())

 sound.mystop();

 sound.loadSound();

 btnmuc.setLabel("音乐关");

 nor.setEnabled(true);

 qin.setEnabled(false);

 guang.setEnabled(true);

 eye.setEnabled(true);

 po.setEnabled(true);

panel.requestFocus();

break;

case 2:……

case 3:……

case 4:sound.setMusic("eyes on me.mid");

if(sound.isplay())

sound.mystop();

sound.loadSound();

btnmuc.setLabel("音乐关");

nor.setEnabled(true);

qin.setEnabled(true);

guang.setEnabled(true);

eye.setEnabled(false);

po.setEnabled(true);

panel.requestFocus();break;

}

运行结果如图3-7所示:

图3-7 音乐选择

4  游戏测试

4.1  软件测试

4.1.1  软件测试简介

测试是软件开发过程中的一个非常重要的环节。通过测试可以用来检验一个系统的性能和品质是否达到系统最初设计时给出的各项需求指标。

测试的目的就是希望能以最少的人力和时间发现潜在的各种错误和缺陷。应根据开发各阶段的需求、设计等文档或程序的内部结构精心设计测试用例,并利用这些用例来运行程序以便发现错误,这个过程与整个软件开发过程基本上是平行进行的。一个规范化的测试过程通常包括以下基本的测试活动:

(1)制定测试计划。在充分考虑了整个项目的开发时间和开发进度以及一些人为因素和客观条件后制定测试计划,保证其是基本可行的。测试计划应主要包括测试的内容、进度安排、测试所需的环境等。

(2)编制测试大纲。测试大纲是测试的依据。

(3)根据测试大纲设计和生成测试用例,产生测试设计说明文档。

(4)实施测试。依据预先编制好的测试大纲和设计好的测试用例,对被测软件进行完整的测试。

(5)生成测试报告。

4.2 测试方法

软件测试方法可以分为静态测试和动态测试。

(1)静态测试:是指被测试程序不在机器上运行,而是采用人工检测和计算机辅助分析的手段对程序进行检测。

(2)动态测试:是指通过运行程序来发现错误,可以采用黑盒测试法和白盒测试法。黑盒测试法也称功能测试或数据驱动测试,其是在完全不考虑软件的内部结构和特性的情况下,测试软件的外部特性。在测试过程中,把程序看作一个不能打开的黑盒子,测试者在程序接口进行测试,只需要检查程序功能是否达到了系统功能需求各项指标,判断程序是否能在保持外部信息的完整性的同时适当程度地接受数据输入并产生相应的输出信息。经常使用的黑盒测试方法主要有等价类划分、边界值划分、错误推测和因果图等,主要应用于软件确认测试。白盒测试法也称结构测试或逻辑驱动测试,它是在知道产品内部工作过程前提下,根据程序的内部结构和逻辑来设计测试用例,对程序的路径和过程进行测试,检查是否满足设计的需要。白盒测试常用的技术有逻辑覆盖、循环覆盖和基本路径测试等。

4.3 测试步骤

有效的软件测试实际上分为4步进行,即:单元测试、集中测试、确认测试、系统测试。

(1)单元测试

单元测试也称模块测试,侧重于模块中的内部处理逻辑和数据结构。

(2)集成测试

即使所有模块通过了单元测试,但在集成以后仍可能出现问题,这就需要集成测试来发现错误。集成测试通常可以分为非增量式集成和增量式集成。

(3)确认测试

经过集成测试以后,软件就被集成起来,这时软件接口方面的问题都已解决,将进入确认测试阶段。确认测试的任务是进一步检查软件的功能和性能是否与用户要求的达成一致。

(4)系统测试

是将已经确认的软件、计算机硬件、外设和网络等其它因素结合在一起,进行系统的各种集成测试和确认测试,其目的是通过与系统的需求相比较,发现所开发的系统与用户需求相矛盾的地方。系统测试是为了发现错误而执行程序的过程,成功的测试是发现了至今尚未发现的错误的测试。

测试的目的就是希望能以最少的人力和时间发现潜在的各种错误和缺陷。应根据开发各阶段的需求、设计等文档或程序的内部结构精心设计测试用例,并利用这些实例来运行程序,以便发现错误。信息系统测试应包括软件测试、硬件测试和网络测试。硬件测试、网络测试可以根据具体的性能指标来进行,此处所说的测试更多的是指软件测试。

系统测试是保证系统质量和可靠性的关键步骤,是对系统开发过程中的系统分析系统设计和实施的最后复查。根据测试的概念和目的,在进行信息系统测试时应遵循以基本原则。

应尽早并不断地进行测试。测试不是在应用系统开发完之后才进行的。由于原始问题的复杂性、开发各阶段的多样性以及参加人员之间的协调等因素,使得毛开发各个阶段都有可能出现错误。因此,,测试应贯穿在开发的各个阶段,尽早纠正错误,消除隐患。

测试工作应该避免由原开发软件的人或小组承担,一方面,开发人员往往不愿召认自己的工作,总认为自己开发的软件没有错误;另一方面,开发人员的错误很对由本人测试出来,很容易根据自己编程的思路来制定测试思路,具有局限性。测试工作应由专门人员来进行,这样会更客观,更有效。

设计测试方案的时候,不仅要确定输入数据,而且要根据系统功能确定预期的输出结果。将实际输出结果与预期结果相比较就能发现测试对象是否正确。

在设计测试用例时,不仅要设计有效合理的输入条件,也要包含不合理、失效的输入条件。测试的时候,人们往往习惯按照合理的、正常的情况进行测试,而忽略了对异常、不合理、意想不到的情况进行测试,而这些可能就是隐患。

在测试程序时,不仅要检验程序是否做了该做的事,还要检验程序是否做了不该做的事。多余的工作会带来副作用,影响程序的效率,有时会带来潜在的危害或错误 。

严格按照测试计划来进行,避免测试的随意性。测试计划应包括测试内容、进度安排、人员安排、测试环境、测试工具和测试资料等。严格的按照测试计划可以;认证进度,使各方面都得以协调进行。

妥善保存测试计划、测试用例,作为软件文档的组成部分,为维护提供方便。

测试用例都是精心设计出来的,可以为重新测试或追加测试提供方便。当纠正锱 前的测试用例,或在其基础上修改,然后进行测试。

测试是开发过程中一个独立且非常重要的阶段,测试过程基本上与开发过程平行。

一个规范化的测试过程通常包括以下基本的测试活动。

(1)拟定测试计划。在制定测试计划时,要充分考虑整个项目的开发时间和开发进童以及一些人为因素和客观条件等,使得测试计划是可行的。测试计划的内容主要有测试的内容、进度安排、测试所需的环境和条件、测试培训安排等。

(2)编制测试大纲。测试大纲是测试的依据。它明确详尽地规定了在测试中针对系统的每一项功能或特性所必须完成的基本测试项目和测试完成的标准。

(3)根据测试大纲设计和生成测试用例。在设计测试用例的时候,可综合利用前面介绍的测试用例和设计技术,产生测试设计说明文档,其内容主要有被测项目、输人数据、测试过程、预期输出结果等。

(4)实施测试。测试的实施阶段是由一系列的测试周期组成的。在每个测试周期中,测试人员和开发人员将依据预先编制好的测试大纲和准备好的测试用例,对被测软件或设备进行完整的测试。

(5)生成测试报告。测试完成后,要形成相应的测试报告,主要对测试进行概要说明,列出测试的结论,指出缺陷和错误,另外,给出一些建议,如可采用的修改方法,各项修改预计的工作量及修改的负责人员。

总的来说测试包括一下基本流程和步骤:

4.4  游戏系统性能分析

经过对系统进行测试和运行。总结出游戏系统性能如下:

(1)界面友好,游戏操作方便

系统风格可爱,界面简单,功能较完善,游戏操作简单。 

(2)系统响应较快,运行较稳定

在系统运行时,游戏过程中的消息响应处理很快,且系统整体运行安全且稳定。

(3)部分系统功能仍需完善

由于开发时间等方面的原因,该系统还可以在联网进行玩家比赛、难度调节等方面予以完善。

5  项目经验与总结

 随着科学技术的发展,人们的生活水平越来越繁忙,在充满竞争的社会条件下,压力往往带给人们很多烦恼,所以合理的解压方式称为现代人的共同心愿. 为了给大家提供一个合理的解压平台, 我们在本次课程设计中为大家开发了一款适合休闲娱乐的小游戏, 本次课程设计是配合Java 程序设计课程,深入学习掌握Java 语言,熟练运用 Java 工具对系统的编写.通过课程设计各个项目的综合训练,培养学生实际分析问题,编程和动手能力,提高学生的综合素质。这次经历,学了不少东西。其实这次课程设计体会最深的就是独立思考

我充分了解了理论与课程设计相结合的重要性,理论基础上必须有实际上的应用,在实际的应用中才能发现个种问题,再灵活的应用理论知识去解决它们。在这一周的学习过程中,我不仅能够把以前所学知识联系起来,并且还学会了一些新的知识,在此期间通过对 Java 设计的系统训练,使我基本上达到了这周的课程设计目的,并且懂得了要想学好课,除了要有扎实的基础知识的功底深厚外,还需要有一定的实践动手能力,操作能力。

虽然软件的基本功能都已实现,但还是存在系统不稳定等多个问题尚待解决。这个游戏的开发查询了大量的资料。我在编程的过程中遇到了很多问题,有的是知识存储不足,有的是考虑不够周全,之所以能够顺利实现基本功功能,主要是离不开同学们的大力相助。事实证明,只靠自己是不能顺利完成一套功能完整的系统的,开发一个软件,最重要的是严谨,每个人并不能做到面面俱到,不管什么软件,只用运用到实际生活中才具有意义。所以在准备工作阶段中要正确分析需求了解现实应用,画出流程图,把大体框架做好,然后再逐一细化。

通过编写本次毕业设计程序,我完成了基于Java的推箱子小游戏的软件开发任务。在这其间,我遇到了许多问题,并且明白了理论与实际结合的重要性,在充分的理论基础上必须有足够的实际应用,这样才能找到问题,解决问题。巩固旧知识,学习新知识。

  • 在熟悉了推箱子的基础玩法之后,我逐步推算游戏的步骤,并且上网积极查阅有关知识和算法,并和老师讨论问题,重复修改优化界面。在这段过程当中遇到了各种问题。背景的选用如何更清新,人物和箱子组合怎样更美观,选什么样的音乐,以及如何修改算法,链接数据库,如何精简游戏的操作,节约资源,在此过程中我们遇到了意想不到的问题,我们借此机会学会了如何通过反复思考和测试找出自己的错误并加以改正,最终完成了程序。
  • 本次设计也让我得到一个不断学习新鲜事物的机会,从设计初的诸多不懂到最后能够顺利完成,期间我体会到在实践中学习的重要性,这对于将来我走上工作岗位具有重要意义通过毕业设计使我对Java这门课程加深了解,也对我今后的就业之路奠定了一定的基础。
  • 经过这些日子的不断努力,本次的毕业设计程序基本上完成了。回顾个设计过程我学到了许多书本上没有学到的知识。通过这次自己制作的软件丰富了自己的实践技能扩展了本专业的知识面,不仅使我受益同时也体验到了开发软件开发的难度与不断更新自己的重要性。由于我是初次涉及这类开发软件,因此这其中或许还有很多的不足之处,界面的设计及整体的布局还比较简单,没有特别突出特色,这也是我今后所要充实之处,在这里也恳请各位老师能够对我的作品指明不足并加以改正。
  • 来说,这次毕业设计还是比较成功的,这也是我在大学四年来完成的一个比较全面的实际例子。在这次设计的过程,我查阅了大量的资料,对Java有了更加全面的认识,于软件工程这些辅助性的教材也巩固了不少,为我这次的毕业设计提供了很大的帮助,同时锻炼并且增强了我这方面的能力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/634897.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

NDI入门教程二

一、移植到RK&#xff1a; 编译相关&#xff1a; ndi本身没有什么好移植编译的&#xff0c;本身提供的就是so库。但是ndi依赖其它第三方开源库&#xff1a; avahi; dbus; expat; libcap; libdameon。因为编译这些开源库的服务器也需要安装一些插件所以在自己虚拟机Ubuntu20.04…

notepad++ 批量转所有文件编码格式为UTF-8

1、安装notepad及PythonScript_3.0.18.0插件 建议两者都保持默认路径安装x64版本&#xff1a; 阿里云盘分享https://www.alipan.com/s/xVUDpY8v5QL安装好后如下图&#xff1a; 2、new Script&#xff0c;新建脚本&#xff0c;文件名为ConvertEncoding 3、自动打开脚本&#xff…

Jenkins 动态salve简单配置连接 EKS

安装Jenkins helm repo add jenkins https://charts.jenkins.io helm repo update # 当前版本 jenkins-5.1.18.tgz瘦身后的 values.yaml # grep -Ev ^\s*#|^$ values.yaml nameOverride: fullnameOverride: namespaceOverride: clusterZone: "cluster.local" kubern…

(Oracle)SQL优化基础(三):看懂执行计划顺序

往期内容&#xff1a; &#xff08;Oracle&#xff09;SQL优化基础&#xff08;一&#xff09;&#xff1a;获取执行计划 &#xff08;Oracle&#xff09;SQL优化基础&#xff08;二&#xff09;&#xff1a;统计信息 获取到执行计划后&#xff0c;对于新手朋友来讲可能不知道…

火箭升空AR虚拟三维仿真演示满足客户的多样化场景需求

在航空工业的协同研发领域&#xff0c;航空AR工业装配系统公司凭借前沿的AR增强现实技术&#xff0c;正引领一场革新。通过将虚拟信息无缝融入实际环境中&#xff0c;我们为工程师、设计师和技术专家提供了前所未有的共享和审查三维模型的能力&#xff0c;极大地提升了研发效率…

【华为】BFD与静态路由和RIP联用

【华为】BFD与静态路由和RIP联用 实验需求配置AR1AR2AR3AR4效果抓包查看 实验需求 如上图组网所示&#xff0c;在R1上配置到达R4的Loopback0。 4.4.4.4/32网段的浮动静态路由&#xff0c;正常情况下通过R3访问R4。 当R3故障时&#xff0c;自动选路通过R2访问R4的Loopback0;在R…

企业文件加密软件推荐:迅软DSE加密软件你用了吗?

一、挑选企业文件加密软件需考虑的因素&#xff1f; 1、安全性&#xff1a;软件应采用业界认可的强加密算法&#xff0c;以确保数据的安全性。 迅软特有的256位高强度加密算法&#xff0c;从根本上阻止一切破解的可能性。 2、易用性&#xff1a;软件应该易于部署和管理&…

如何停止 iPad 和 iPhone 之间共享短信,独立接收和发送消息

概括 在当今高度互联的数字世界中&#xff0c;Apple 设备之间的无缝连接性提供了极大的便利&#xff0c;尤其是在消息同步方面。iPhone 和 iPad 用户通常可以享受到设备间短信的自动同步功能&#xff0c;这意味着无论是在哪个设备上&#xff0c;用户都可以接收和回复消息。然而…

游戏联运的挑战与核心关键点

​游戏联运一个看似充满机遇与挑战的行业&#xff0c;吸引了很多创业者的加入。然而&#xff0c;真正踏入这个行业后&#xff0c;许多人会发现&#xff0c;手游代理并非想象中的那么简单。今天&#xff0c;溪谷软件就来和大家聊聊游戏联运是怎么做的&#xff0c;需要注意什么。…

react中的useEffect()的使用

useEffect()是react中的hook函数&#xff0c;作用是用于创建由渲染本身引起的操作&#xff0c;而不是事件的触发&#xff0c;比如Ajax请求&#xff0c;DOM的更改 首先useEffect()是个函数&#xff0c;接受两个参数&#xff0c;第一个参数是一个方法&#xff0c;第二个参数是数…

《计算机体系结构》期末考试复习笔记(一)试卷手写笔记(超重点)

一、MIPS 执行速率执行时间有效CPI【第1题】 二、Amdahl定律 - 性能加速比SP【第2题&#xff0c;第3题&#xff0c;第4题】 (百分比f 倍数r &#xff09; 三、哈夫曼编码 2-4扩展码【第5题】 四、互连函数【第9题】 就是每生成一个根节点&#xff0c; 就从小到大重新排…

后量子密码解决方案

什么是后量子密码学 (PQC)&#xff0c;为什么准备工作如此重要? 量子计算正在迅速发展;用不了多久&#xff0c;量子网络攻击就会成为可能。量子网络攻击将能够在几分钟内瘫痪大型网络。我们今天赖以保护我们的连接和交易的一切都将受到量子计算机的威胁&#xff0c;危及所有密…

【618狂欢】五款必抢好物!爆款数码好物让你轻松get新潮流!

随着科技的飞速发展&#xff0c;数码产品已经成为我们生活中不可或缺的一部分。它们不仅为我们提供了便捷的生活体验&#xff0c;更成为了我们展示个性和追求潮流的重要载体。而在每年的618购物狂欢节&#xff0c;各大电商平台都会推出众多优惠活动&#xff0c;让我们有机会以更…

Linux——进程信号

目录 一、信号的理解 二、信号的种类 2.1 标准信号 (1-31) 2.2 实时信号 (通常是34及以上) 三、信号的产生 3.1 用户通过终端产生信号 3.1.1 signal 函数 3.1.2 demo 测试 3.1.3 demo 现象 3.2 通过系统函数产生信号 3.2.1 demo 测试 3.3 由软件条件产生信号 3.3.1…

访问列表元素

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在Python中&#xff0c;如果想将列表的内容输出也比较简单&#xff0c;可以直接使用print()函数即可。例如&#xff0c;创建一个名称为untitle的列表…

JAVA开发 基础Jaccard来计算两个字符串之间的重复率

计算两个字符串之间的重复率 Jaccard实现代码基于最长公共子序列来计算两个字符串之间的重复率 Jaccard Jaccard方法&#xff0c;也称为Jaccard相似度或Jaccard相似系数&#xff0c;是一种用于衡量两个集合相似程度的指标。其逻辑基于集合之间的交集与并集的关系来衡量它们的相…

Linux bc命令(bc指令)(基本计算器)(任意精度计算语言:支持浮点数运算、变量赋值和自定义函数等)

文章目录 bc命令文档英文中文 Linux bc 命令详解bc 命令的基本用法启动 bc 环境进行基本计算退出 bc bc 中的数学功能执行高级数学计算平方根和指数函数对数函数 处理精度问题 变量和数组变量赋值和使用数组的使用 创建和使用自定义函数 bc 命令的高级用法在脚本中使用 bc基本脚…

注解大全更新中~

Slf4j 是什么&#xff1a;Slf4j 是 Lombok 提供的一种注解&#xff0c;用于在类中自动生成一个名为 log 的日志对象。通过使用 Slf4j 注解&#xff0c;可以方便地在代码中使用日志功能&#xff0c;而无需手动创建和初始化日志对象。 怎么用&#xff1a; 1.导入依赖的包lombok…

uniapp移动端骨架屏流程

1.使用微信开发者工具来生成骨架屏&#xff1b;在分窗模式下选择页面信息&#xff0c;下拉选择生成骨架屏&#xff1b;他会基于当前页面生成骨架屏的样式 点击确定&#xff1b; 会自动生成这两个文件&#xff1b;一个是html结构文件&#xff0c;一个是css样式文件。 然后把这两…

R语言使用 ggscidca包优雅的绘制支持向量机决策曲线

DCA(Decision Curve Analysis)临床决策曲线是一种用于评价诊断模型诊断准确性的方法&#xff0c;在2006年由AndrewVickers博士创建&#xff0c;我们通常判断一个疾病喜欢使用ROC曲线的AUC值来判定模型的准确性&#xff0c;但ROC曲线通常是通过特异度和敏感度来评价&#xff0c;…