射击游戏 Java(通用9篇)
下载下来的源码是反编译的,我按照自己的思路,尽量模拟跟它一样的功能效果,用自己的代码实现,并且自己写了一个地图编辑器。用到的技术大概有:swing基本控件,线程,XML读写,IO,反射的简单应用,2D绘图。
最重要的一个自定义类:Canvas。
每个canvas都有一个render方法和update方法,每个canvas又可以添加别的canvas,类似swing的component结构,每个canvas执行render和update的时候都会遍历所有子canvas执行render和update,从而实现所有canvas都执行渲染和更新。游戏的刷新机制:
这个刷新机制是直接学的原代码里面的实现机制,看它没注释的代码着实蛋疼,还是请教了我师傅desolatecity大神才理解的--!。
最高层是一个继承JFrame的GameFrame,实现了Runnable,游戏启动后会单独运行不断循环刷新,每隔大概15ms就执行一次render,并将整个循环所用时间通过update方法传给canvas,最高层canvas再一层一层传递下去,实现所有canvas的渲染和更新。大致代码实现如下:
[java] view plaincopy
1.while(gameOn){
2.// 获取开始时的系统时间
3.long startTime = System.currentTimeMillis();4.5.// 标记时间所用变量
6.long l1;
7.long l2 = System.currentTimeMillis();8.long l3 = System.currentTimeMillis();9.10.// 执行for循环,直到经过了step毫秒
11.for(l1 = l3l2){ 12.l3 = System.currentTimeMillis();13.}
14.// for循环结束,开始渲染和更新
15.l2 = System.currentTimeMillis();// 重置l2
16.17.this.getCurrentCanvas().render(g2);// 渲染
18.19.this.getGraphics().drawImage(bufImg, 0, 0, null);// 将缓冲图片画到JFrame
20.21.long endTime = System.currentTimeMillis();// 获取结束时的系统时间
22.23.this.getCurrentCanvas().update(endTime 元素”的映射关系将时间和对应元素存储到一个IdentityHashMap里,然后游戏的主canvas在update的时候遍历IdentityHashMap,若当前时间满足map里面的时间,则将对应的元素提取出来,添加到当前的子canvas列表里面,从而一个新的元素(或敌人,或提示消息等)就被添加到了界面上。这里我用到了一个比较少用的IdentityHashMap,原本直接用的是HashMap,后来发现一个时间有时候要对应多个元素,然后上网查到了这个东东,但是由于键是按照对象来存储的,所以要把时间用String对象来存储,搞得读取和存储的时候各种麻烦。结果后来师傅一指点才知道,可以直接用HashMap来存储“时间--ArrayList”,这样又方便又直接。--!后来嫌麻烦也不去改了。。
地图编辑器:
地图编辑器没有什么特别费脑袋的地方,就是各种swing控件的运用,还有xml的读写,简单的反射应用等。
由于整个游戏基本上都是在边学变写,所以很多地方写的很粗糙,以至于后来去整理的时候发现前面的代码结构简直丑死了--,改都该了半天。
最后附上源码下载地址,如果有兴趣的话可以互相探讨学习。
下载地址:http://download.csdn.net/download/jianglihui0330/4493082
游戏截图:
1. Java语言概述
Java诞生于网络时代, 虽然它的历史短暂, 但它的发展壮大并不是偶然的, 而是有着内在的基础和外在的机遇。
2. Java的开发运行环境
JDK:从初学者角度来看, 采用JDK开发Java程序能够很快理解程序中各部分代码之间的关系, 有利于理解Java面向对象的设计思想。
JCreator是一个Java程序开发工具, 也是一个Java集成开发环境 (IDE) 。无论你是要开发Java应用程序或者网页上的Applet元件都难不倒它。
3. 本论文的研究意义和内容
本论文主要研究的内容有:
拼图游戏, 必须有图片, 拼图就是把一张图片分为大小相同的几张, 然后在游戏中打乱他们的顺序, 让玩家把他们移动。
上述的情况需要用到PS技术, 在PS中可以把图片切割成大小相等的图片。在此游戏中将“jiwei.jpg”用PS分割成了相等的16张。
玩家通过开始按钮开始游戏, 在游戏中有计数功能和计时功能。
所谓计数功能就是记录玩家从游戏开始后, 到目前为止一共走了多少步, 也就是一共移动了多少次图片。
所谓计时功能就是记录玩家从游戏开始以后, 到目前为止一共用了多长时间, 直到游戏结束即玩家成功完成拼图。
每移动一步我们要判断到这一步我们是否完成了拼图。
二 游戏开发环境及相关技术的介绍
开发环境: (1) 硬件要求:CPU PII以上, 64MB内存, 100MB硬盘空间; (2) 软件要求:Windows 98/NT/2000/XP, Internet Explorer 5.0; (3) 开发包:JDK; (4) 开发工具:JCreator3.5。
三 程序的相关技术
程序需要解决的主要技术问题:
拼图游戏就是把一张图片分为大小相同的几张, 通过玩家对他们的移动, 直到不再是四分五裂的图片而变成一张完整的图片。
在PS中可以把图片切割成大小相等的图片。在此游戏中将“jiwei.jpg”用PS分割成了相等的16张。
玩家通过开始按钮开始游戏, 在游戏中有计数功能和计时功能。
计数功能记录玩家从游戏开始以后, 到目前为止一共走了多少步, 也就是一共移动了多少次图片。
每移动一步我们要判断到这一步我们是否完成拼图, 我们要设计算法实习判断拼图是否完成, 如果拼图完成显示对话框“success!”对话框。
每点击一次开始, 16张图片就随机地变换位置, 然后重新开始游戏。
四 程序分析和具体实现
Move Frame中的内部类:MoveCanvas类和Move Panel类是两个内部类。 (1) MoveCanvas类主要实现16张小图片的加载、对小图片移动时的监听判断及点击开始图标以后的图片重新随机排列, 以及判断玩家是否成功完成了图片排列。 (2) MovePanel类主要实现计数、计时的重置和加载大图片 (jiwei.jpg) 。添加“开始”按钮, 计时lable, 步数lable。
五 总结
本程序设计实现了以Java为平台的拼图游戏的开发, 运行的方式由程序进行控制, 具有一定的可玩性。经过细心的调试和排错解决了绝大部分的问题。
参考文献
关键词:Java;小游戏;魔方;Java语言
中图分类号:TP311.52
现代社会,电脑游戏爱好者云集,并且越来越多的人加入到这个行列中来,这一现象表明电脑游戏成绩斐然,成为IT产业中增长最快的部分之一。纵观IT产业的历史,计算机游戏已经成为技术创新背后的动力,玩者渴望更加强大的硬件计算能力;渴望游戏不受不同的软件的限制,即游戏玩家希望游戏可以运行在不同的操作系统之上,无论他们的操作系统是Windows还是Unix或者其他,无论是将图形强制在人工智能上还是网络安全性上,都希望可以畅通无阻。游戏开发者和玩家常常是前沿计算机技术的最早采用者。
1 游戏开发的基本概念和理论
1.1 游戏开发的背景和意义。本游戏开发的背景是出于小时候对小游戏的喜爱,以及现在社会的要求,对小游戏的开发就成为了我的毕业设计。小游戏开发的意义是:首先,这个游戏的开发能够增长Java水平,其次,就是游戏开发可以促使计算机业的技术提高,使中国计算机水平有所提高。再次,用Java编写程序可以使减少不必要的麻烦,即Java语言可以运行在不同的操作系统之上。
1.2 游戏开发的理论和概念。传统的游戏由于使用的语言只能运行在单一的环境下,没有可移植性,当游戏从一种操作系统放到另外一种操作系统下的时候,游戏就失去了他的功能,不可能在给人们带来乐趣,使许多游戏玩家感到苦恼,玩游戏的乐趣突然没有了。因此,处于玩者的需要,本游戏运用的是可以在不同环境下运行的JAVA语言编写而成的。游戏一旦生成,随处可玩。
电脑小游戏应举具备的特点:(1)易于学习。既然小游戏面向的是普通的电脑用户而不是计算机高手,那么他们不可能深入的学习小游戏的技巧;(2)可中断性。多任务处理是电脑的基本特征。电脑用户常常希望一心多用,他们希望上网时能听音乐,聊天或者更多的其他事情。而小游戏、音乐、聊天是使用的同一台计算机;(3)丰富的社会交互。不管一个小游戏设计得多好,只要玩家找到了它的根本模式或者玩完了所有的游戏路径很快就会厌烦这个小游戏;(4)无违法内容。既然所有年龄/性别的人群都玩游戏并且常常在公共/工作场合,你应该避免明显的暴力或者色情内容。
1.3 游戏语言介绍。本游戏应用的是Java语言,Java是一个由SUN公司开发成功的新一代编程语言,它的最大特点就是:使用它可在各式各样不同种机器,不同种操作平台的网络环境中开发软件,即SUN公司所宣扬的“一次编写,到处运行”。
在SUN公司的“Java白皮书”中对Java有如下的定义:Java:一种简单的,面向对象的,分布式的,健壮的,安全的,结构中立的,可移植的,高效性的,多线程和动态的语言。
这个定义充分地表现了Java语言的特点:(1)简单性。Java是一种简单的语言。Java取消了其它的许多编程语言中十分繁琐的和难以理解的内容,例如C/C++中的指针,C++中类的多重继承等。Java语言在外观上让大多数程序员都感到很熟悉,这样程序员不需要经过长时间训练就能够学会使用这种新型的程序开发工具;(2)面向对象。Java是一种面向对象的语言。这里的“对象”是指应用程序的数据及其操作方法。Java程序的设计思想不同于C语言基于过程的程序设计思想。设计面向对象的程序需要将编程重点放在资料和接口上;(3)分布式特性。Java是一種分布式的语言。Java有一个很周全的程序库,且很容易与HTTP和TCP/IP通信协议相配合。Java应用程序能在网络上开启并连结使用对象,就如同透过URL链接使用一个本地文件系统;(4)健壮性。用Java编写的程序在多种情况下都能稳定地执行。Java与C/C++最大的不同点是在于Java有一个专门的指针模型,它的作用是排除内存中的数据被覆盖和毁损的可能性;(5)安全性。Java是一种安全的网络编程语言。Java是被设计用于网络及分布的环境中的,所以Java程序的安全性自然是非常重要的。Java拥有数个阶层的互锁保护措施,能有效地防止病毒的侵入和破坏行为的发生;(6)结构中立性。众所周知,网络是由很多不同机型的计算机组合而成的。这些计算机的CPU和操作系统体系结构均有所不同。
2 游戏功能的实现和基本操作方法
2.1 游戏的功能实现。游戏的功能是:通过编程,使其出现一个正方体,这个正方体是有着不同颜色的六个面,并且它的每个面被分成九个小的正方形,排列规则是中间一个小正方形,四周围着其余的八个,外观效果是和我们小时侯玩的魔方是一个样子的,这个功能的实现必须是要使图形化界面是一个三维立体空间,否则是不会出现正方体的效果的,在编程中通过定义坐标的方法使其有着边长为1cm的小正方形。
2.2 游戏的基本操作方法
(1)游戏的开始。游戏的开始设置为S键,是Start的首字母,很容易理解的。在程序运行后就会出现游戏界面,这里在编写游戏时考虑到玩家的感受,所以游戏界面中有提示的,会告诉你开始按S。然后你就可以玩了,当你玩了好半天但还是没有成功的话,你会觉得你这局不行了,这就要使游戏重新开始了,那就要通过键盘的操作使游戏重新开始;(2)游戏的玩法。在程序执行以后就可以发挥你的才智来玩这个游戏了,不要小看了这个游戏,这与现实中的魔方有着旗鼓相当的水平,如果你小的时候就没有玩好魔方,那你玩这个游戏一样的玩不转。这个游戏只需要用鼠标就可以做到了。在你按下S键后就开始了。首先呢,你要先打乱模仿的次序,使的魔方的六个面中的每个面上不在是相同的颜色,这时考验你智力的时候到了,你要想办法使魔方的各个面重新回到相同的颜色,你就成功了。
3 游戏的发展前景
3.1 电脑小游戏的现状。每个人都对过去、未来和未知事物有幻想和期盼。每个人也都有自己想要做而不一定能够完成的事情。电脑游戏营造的虚拟空间和身份模拟则成了实现或释放这些情绪的途径之一。游戏者能在游戏中扮演与现实中的自己截然不同的角色,置身于任何一个时间和空间,完成自己潜意识中或童年的梦想。
3.2 电脑小游戏的未来。凡是玩过电脑小游戏的人都会感觉到,电脑小游戏给他们的生活带来了很多的乐趣,所以它很有发展前途。
(1)电脑小游戏对电脑的要求不高;(2)这个游戏简单;(3)当这个小游戏充分得到人们的认可时,可以发展成手机游戏,因为现在手机游戏更有发展潜力,这就需要更多的Java小游戏,只有Java小游戏能运行在手机之上,所以,它的商业存在价值更不能忽略,并且会成为Java小游戏开发的主要动力;(4)要实现Java小游戏的技术要求并不难。只要有好的游戏,就会有更广的使用量。
4 结束语
从整个游戏的设计过程来看,本游戏具有稳定性,可扩展性的,但是由于时间的关系使游戏的性能没有得到更深的设计,性能不是很高,如果有想对本游戏进一步开发的读者可以对此游戏进行修改从而建立功能更强大的游戏。
参考文献:
[1]张基温,朱嘉钢,张景莉.Java程序开发教程[M].北京:清华大学出版社,2002.
[2]张基温,陶利民.Java程序开发例题与习题[M].北京:清华大学出版社,2002.
[3]陈炜,张晓蕾,侯燕萍等.Java软件开发技术[M].北京:人民邮电出版社 2005.
[4]孙印杰,刘斌,孙玉强.Java编程案例精解[M].北京:电子工业出版社,2005.
基于教育游戏的Java程序设计课程教学改革与实践
本文针对当前Java教学中重要性日益凸显的实践环节进行了论述,从教育游戏的概念及教育游戏在Java教学中应用的.可行性入手,提出了基于“Robocode”教育游戏的“Java程序设计”课程教学设计模式,并对该模式进行了详细的阐述.
作 者:佟延秋 作者单位:重庆交通大学,重庆,400074 刊 名:计算机教育 英文刊名:COMPUTER EDUCATION 年,卷(期):2009 “”(22) 分类号:G642 关键词:教育游戏 Java教学 教学设计Reference
Java世界泰山北斗级大作《Thinking In Java》切入Java就提出“Everything is Object”。在Java这个充满Object的世界中,reference是一切谜题的根源,所有的故事都是从这里开始的。
Reference是什么?
如果你和我一样在进入Java世界之前曾经浪迹于C/C++世界,就一定不会对指针陌生。谈到指针,往日种种不堪回首的经历一下子涌上心头,这里不是抱怨的地方,让我们暂时忘记指针的痛苦,回忆一下最初接触指针的甜蜜吧!还记得你看过的教科书中,如何讲解指针吗?留在我印象中的一种说法是,指针就是地址,如同门牌号码一样,有了地址,你可以轻而易举找到一个人家,而不必费尽心力的大海捞针。
C++登上历史舞台,reference也随之而来,容我问个小问题,指针和reference区别何在?我的答案来自于在C++世界享誉盛名的《More Effective C++》。
1.2.3.4.没有null reference。reference必须有初值。使用reference要比使用指针效率高。因为reference不需要测试其有效性。指针可以重新赋值,而reference总是指向它最初获得的对象
设计选择:
当你指向你需要指向的某个东西,而且绝不会改指向其它东西,或是当你实作一个运算符而其语法需要无法有指针达成,你就应该选择reference。其它任何时候,请采用指针。
这和Java有什么关系?
初学Java,鉴于reference的名称,我毫不犹豫的将它和C++中的reference等同起来。不过,我错了。在Java中,reference可以随心所欲的赋值置空,对比一下上面列出的差异,就不难发现,Java的reference如果要与C/C++对应,它不过是一个穿着reference外衣的指针而已。
于是,所有关于C中关于指针的理解方式,可以照搬到Java中,简而言之,reference就是一个地址。我们可以把它想象成一个把手,抓住它,就抓住了我们想要操纵的数据。如同掌握C的关键在于掌握指针,探索Java的钥匙就是reference。
一段小程序
我知道,太多的文字总是令人犯困,那就来段代码吧!
public class ReferenceTricks {
public static void main(String[] args){
ReferenceTricks r = new ReferenceTricks();
// reset integer
r.i = 0;
System.out.println(“Before changeInteger:” + r.i);
changeInteger(r);
System.out.println(“After changeInteger:” + r.i);
// just for format
System.out.println();
// reset integer
r.i = 0;
System.out.println(“Before changeReference:” + r.i);
changeReference(r);
System.out.println(“After changeReference:” + r.i);
}
private static void changeReference(ReferenceTricks r){
r = new ReferenceTricks();
r.i = 5;
System.out.println(“In changeReference: ” + r.i);
}
private static void changeInteger(ReferenceTricks r){
r.i = 5;
System.out.println(“In changeInteger:” + r.i);
}
public int i;
}
对不起,我知道,把一个字段设成public是一种不好的编码习惯,这里只是为了说明问题。
如果你有兴趣自己运行一下这个程序,我等你!
OK,你已经运行过了吗?结果如何?是否如你预期?下面是我在自己的机器上运行的结果:
Before changeInteger:0
In changeInteger:5
After changeInteger:5
Before changeReference:0
In changeReference: 5
After changeReference:0
这里,我们关注的是两个change——changeReference和changeInteger。从输出的内容中,我们可以看出,两个方法在调用前和调用中完全一样,差异出现在调用后的结果。
糊涂的讲解
先让我们来分析一下changeInteger的行为。
前面说过了,Java中的reference就是一个地址,它指向了一个内存空间,这个空间存放着一个对象的相关信息。这里我们暂时不去关心这个内存具体如何排布,只要知道,通过地址,我们可以找到r这个对象的i字段,然后我们给它赋成5。既然这个字段的内容得到了修改,从函数中返回之后,它自然就是改动后的结果了,所以调用之后,r对象的i字段依然是5。下图展示了changeInteger调用前后内存变化。
Reference +--------+Reference +--------+
---------->| i = 0|---------->| i = 5|
|--------||--------|
| Memory || Memory |
||||
||||
+--------++--------+
调用changeInteger之前调用changeInteger之后
让我们把目光转向changeReference。
从代码上,我们可以看出,同changeInteger之间的差别仅仅在于多了这么一句。
r = new ReferenceTricks();
这条语句的作用是分配一块新的内存,然后将r指向它。
执行完这条语句,r就不再是原来的r,但它依然是一个ReferenceTricks的对象,所以我们依然可以对这个r的i字段赋值。到此为止,一切都是那么自然。
Reference +--------++--------+
---------->| i = 0|| i = 0|
|--------||--------|
| Memory || Memory |
||Reference |--------|
||---------->| i = 5|
+--------++--------+
调用changeReference之前调用changeReference之后
顺着这个思路继续下去的话,执行完changeReference,输出的r的i字段,那么应该是应该是新内存中的i,所以应该是5。至于那块被我们抛弃的内存,Java的GC功能自然会替我们善后的。
事与愿违。
实际的结果我们已经看到了,输出的是0。
肯定哪个地方错了,究竟是哪个地方呢?
参数传递的秘密
知道方法参数如何传递吗?
记得刚开始学编程那会儿,老师教导,所谓参数,有形式参数和实际参数之分,参数列表中写的那些东西都叫形式参数,在实际调用的时候,它们会被实际参数所替代。
编译程序不可能知道每次调用的实际参数都是什么,于是写编译器的高手就出个办法,让实际参数按照一定顺序放到一个大家都可以找得到的地方,以此作为方法调用的一种约定。所谓“没有规矩,不成方圆”,有了这个规矩,大家协作起来就容易多了。这个公共数据区,现在编译器的选择通常是“栈”,而所谓的顺序就是形式参数声明的顺序。
显然,程序运行的过程中,作为实际参数的变量可能遍布于内存的各个位置,而并不一定要老老实实的呆在栈里。为了守“规矩”,程序只好将变量复制一份到栈中,也就是通常所说的将参数压入栈中。
打起精神,谜底就要揭晓了。
我刚才说什么来着?将变量复制一份到栈中,没错,“复制”!
这就是所谓的值传递。
C语言的旷世经典《The C Programming Language》开篇的第一章中,谈到实际参数时说,“在C中,所有函数的实际参数都是传„值‟的”。
马上会有人站出来,“错了,还有传地址,比如以指针传递就是传地址”。
不错,传指针就是传地址。在把指针视为地址的时候,是否考虑过这样一个问题,它也是一个变量。前面的讨论中说过了,参数传递必须要把参数压入栈中,作为地址的指针也不例外。所以,必须把这个指针也复制一份。函数中对于指针操作实际上是对于这个指针副本的操作。
Java的reference等于C的指针。所以,在Java的方法调用中,reference也要复制一份压入堆栈。在方法中对reference的操作就是对这个reference副本的操作。
谜底揭晓
好,让我们回到最初的问题上。
在changeReference中对于reference的赋值实际上是对这个reference的副本进行赋值,而对于reference的本尊没有产生丝毫的影响。
回到调用点,本尊醒来,它并不知道自己睡去的这段时间内发生过什么,所以只好当作什么都没发生过一般。就这样,副本消失了,在方法中对它的修改也就烟消云散了。
也许你会问出这样的问题,“听了你的解释,我反而对changeInteger感到迷惑了,既然是对于副本的操作,为什么changeInteger可以运作正常?”
呵呵,很有趣的大脑短路现象。
好,那我就用前面的说法解释一下changeInteger的运作。
所谓复制,其结果必然是副本完全等同于本尊。reference复制的结果必然是两个reference指向同一块内存空间。
虽然在方法中对于副本的操作并不会影响到本尊,但对内存空间的修改确实实实在在的。
回到调用点,虽然本尊依然不知道曾经发生过的一切,但它按照原来的方式访问内存的时候,取到的确是经过方法修改之后的内容。
于是方法可以把自己的影响扩展到方法之外。
多说几句
这个问题起源于我对C/C++中同样问题的思考。同C/C++相比,在changeReference中对reference赋值可能并不会造成什么很严重的后果,而在C/C++中,这么做却会造成臭名昭著的“内存泄漏”,根本的原因在于Java拥有了可爱的GC功能。即便这样,我仍不推荐使用这种的手法,毕竟GC已经很忙了,我们怎么好意思再麻烦人家。
在C/C++中,这个问题还可以继续引申。既然在函数中对于指针直接赋值行不通,那么如何在函数中修改指针呢?答案很简单,指针的指针,也就是把原来的指针看作一个普通的数据,把一个指向它的指针传到函数中就可以了。
同样的问题到了Java中就没有那么美妙的解决方案了,因为Java中可没有reference的reference这样的语法。可能的变通就是将reference进行封装成类。至于值不值,公道自在人心。
评论 09:50浏览(171)评论(1)分类:收藏相关推荐
2008-06-27
public class ReferenceTricks {
public static void main(String[] args){
ReferenceTricks r = new ReferenceTricks();
// reset integer
r.i = 0;
System.out.println(“Before changeInteger:” + r.i);
changeInteger(r);
System.out.println(“After changeInteger:” + r.i);
// just for format
System.out.println();
// reset integer
r.i = 0;
System.out.println(“Before changeReference:” + r.i);
changeReference(r);
System.out.println(“After changeReference:” + r.i);
}
private static void changeReference(ReferenceTricks r){
r = new ReferenceTricks();
r.i = 5;
System.out.println(“In changeReference: ” + r.i);
}
private static void changeInteger(ReferenceTricks r){
r.i = 5;
System.out.println(“In changeInteger:” + r.i);
}
public
举的例子不太相符,用来理解java传 参机制倒是不错的例子
第一,谈谈final, finally, finalize的区别。
final―修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载。
finally―再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。
finalize―方法名。Java技术允许使用 finalize 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。
第二,Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)?
匿名的内部类是没有名字的内部类。不能extends(继承) 其它类,但一个内部类可以作为一个接口,由另一个内部类实现。
第三,Static Nested Class 和 Inner Class的不同,说得越多越好(面试题有的很笼统)。
Nested Class (一般是C++的说法),Inner Class (一般是JAVA的说法)。Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用上。具体可见http: //www.frontfree.net/articles/services/view.asp?id=704&page=1
注: 静态内部类(Inner Class)意味着1创建一个static内部类的对象,不需要一个外部类对象,2不能从一个static内部类的一个对象访问一个外部类对象
第四,&和&&的区别,
电脑资料
&是位运算符。&&是布尔逻辑运算符。
第五,HashMap和Hashtable的区别。
都属于Map接口的类,实现了将惟一键映射到特定的值上。
HashMap 类没有分类或者排序。它允许一个 null 键和多个 null 值。
Hashtable 类似于 HashMap,但是不允许 null 键和 null 值。它也比 HashMap 慢,因为它是同步的。
第六,Collection 和 Collections的区别。
Collections是个java.util下的类,它包含有各种有关集合操作的静态方法。
Collection是个java.util下的接口,它是各种集合结构的父接口。
第七,什么时候用assert。
断言是一个包含布尔表达式的语句,在执行这个语句时假定该表达式为 true。如果表达式计算为 false,那么系统会报告一个 Assertionerror。它用于调试目的:
assert(a >0); // throws an Assertionerror if a <= 0
断言可以有两种形式:
assert Expression1 ;
assert Expression1 : Expression2 ;
Expression1 应该总是产生一个布尔值。
Expression2 可以是得出一个值的任意表达式。这个值用于生成显示更多调试信息的 String 消息。
断言在默认情况下是禁用的。要在编译时启用断言,需要使用 source 1.4 标记:
javac -source 1.4 Test.java
要在运行时启用断言,可使用 -enableassertions 或者 -ea 标记。
要在运行时选择禁用断言,可使用 -da 或者 -disableassertions 标记。
要系统类中启用断言,可使用 -esa 或者 -dsa 标记。还可以在包的基础上启用或者禁用断言。
本文着眼于Java技术的应用, 开发一款益智类RPG (角色扮演) 游戏——魔塔。该游戏操作简单, 但对智力、谋略却有一定的考验。游戏中设有多种情景对话, 让玩家有一种身临其境的感觉, 同时, 该游戏拥有存档的功能, 使玩家不会因为每次都重新开始而烦恼。
故为丰富硬件平台的应用软件, 借助Java语言面向对象的特点, 充分利用封装、继承、多态的特性, 将这一经典游戏呈现。
1 游戏开发背景和开发环境
1.1 游戏开发背景
计算机在人们的生活中扮演着举足轻重的角色, 它是现代社会不可或缺的。人们可以使用计算机办公、娱乐、购物等等, 计算机的发展让我们的生活变得更加丰富, 更加便捷。在计算机上玩游戏, 也成为我们主要的娱乐方式之一。但纵观整个游戏领域, 绝大多数的主流游戏都是使用C语言或C++语言开发的。使用Java语言编写的游戏微乎其微。造成这一现象的原因可能是每种语言的特性所决定的, Java语言也有它的局限性。但是, 这并不代表Java语言就不能开发游戏。本文就是基于Java语言开发一款角色扮演类的小游戏。
1.2 游戏开发环境
2 游戏介绍
2.1 游戏背景
很久很久以前, 一位武功高强的魔法师因为厌恶国王, 所以将国王最疼爱的公主抓了起来, 美丽的公主被魔法师囚禁在一座神秘之塔里面。国王知道后, 十分的气愤, 随后下重金招募了诸多勇士。经过层层淘汰选拔, 最终只留下了一位勇士。这位武功高强的勇士手持长剑进入满是魔法师的魔塔之中, 营救美丽的公主。可是万万没有想到, 刚刚进入塔中就遭到了坏人的暗算, 不仅武器和法术都丢失了, 还被关入了监狱, 幸好得到了一同坐牢的小偷和仙子的帮助让你逃了出来, 于是我们的英雄一边练功一边开始了他艰苦的救美之行……
游戏刚刚开始, 勇士会与仙子进行对话, 让玩家大致了解整个游戏的背景及流程, 并且仙子用自己最后的一点法力, 恢复了勇士的功力, 随后游戏将真正开始。在游戏中, 勇士通过击杀怪物, 获取金币和经验, 玩家可以在勇士商店或者经验老人那里使用金币和经验, 提升勇士的生命值、攻击力、防御力。再结合隐藏在魔塔的各个角落的宝物, 最终击败魔王, 营救公主, 获得游戏胜利!如若玩家在于怪物的战斗中失利, 则游戏失败!
2.2 游戏操作
游戏菜单页面操作:鼠标操作
勇士上、下、左、右移动:键盘上、下、左、右键;
与游戏设定人物对话:键盘空格键;
游戏中商店操作:鼠标操作;
获取游戏中“怪物手册”:按X键查看, 按X键关闭;
获取游戏中“风之罗盘”:按Z键打开, 鼠标点击, 按Z键关闭;
退出游戏:按Q键;
重新开始:按R键;
游戏存档:按S键;
读取存档:按A键。
3 需求分析
3.1 功能需求
本人所要设计的游戏应用主要涉及下列功能模块:与npc对话、查看怪物手册、商店交易、楼层跳转、游戏存档与读取、战斗画面的显示、重新开始和音乐播放。功能结构如图2所示:
3.2 性能需求
计算机配置:安装java环境, jdk6.0以上;
响应时间:每一次玩家触发事件后, 程序的响应时间不得超过5秒;
数据准确性:玩家在游戏的过程中, 数据不能出现错误;玩家保存进度后, 读取时数据应与保存时一致;
3.3 可靠性和可用性需求
可靠性:在玩家完整的进行一次游戏的过程中, 不会出现程序运行错误、闪退的情况。同时能够完成功能需求中的各个功能模块。
可用性:能够保证在两周时间内, 程序能够正常运行的比例在90%以上。
3.4 可维护性和可扩展性需求
可维护性:能够做到在不影响玩家数据的情况下, 修复程序Bug。
可扩展性:作为游戏开发, 一成不变往往会使玩家产生情感疲劳, 所以开发新的功能成为一种必要。所以, 该游戏应该能确保在不影响之前功能情况下, 添加新的功能模块。
4 程序实现
4.1 游戏整体流程
在此对游戏的整个流程做如下的介绍。游戏伊始, “勇士”会被赋予初始属性值, 游戏过程中, 将会遇到四种情况:1.物品;2.商店;3.NPC;4怪物。获取物品, 可以提高玩家的属性值或是获取道具;遇到商店, 玩家可以根据自己的情况, 对“勇士”属性进行提升或是买卖钥匙;遇到NPC, 诸如“前辈”、“小偷”、“仙子”、“公主”等, 这些人物的设定主要是情节所需, 值得注意的是“公主”, 当玩家遇到她时, 意味着游戏即将结束, 当我们完成“公主”最后的命令——杀死“魔王”, “勇士”成功, 游戏结束;遇到怪物, 无非两种结局:成功, 游戏继续;失败, “勇士”战死, 游戏结束。流程图如图3所示。
4.2 主菜单设计
主菜单效果图如图4所示。
主菜单由背景图片、开始游戏、读取游戏、游戏说明、退出游戏五部分组成。显示效果如图4所示。在主菜单主要借助于鼠标操作。
当点击开始游戏, 主菜单关闭, 进入游戏主界面并开始游戏;
当点击读取游戏, 主菜单关闭, 程序读取之前保存数据, 进入游戏主界面并开始游戏;
当点击游戏说明, 进入游戏说明界面, 游戏说明主要介绍了游戏背景及游戏的基本操作等;
当单机退出游戏, 主菜单关闭, 程序结束运行。
5 结束语
关键词:混淆技术;Java;编程;算法
中图分类号:TP312 文献标识码:A 文章编号:1674-7712 (2012) 18-0038-01
一、前言
Java作为一种新一代的编程语言,其因编程简单、跨平台性可操作性强被许多的开发人员和公司喜爱,而且如今已经成为应用程序的主流开发软件。然而,Java编译器在编译时是将代码引用到的变量和方法符号保留在字节码文件中,并且这些符号都有语义信息,因此使得开发的程序很容易被反编译,导致软件被破解。最终将使得开发者的知识产权受到侵害。为了保护开发者的权益,代码混淆技术变应运而生。
二、混淆技术的发展
早在1997年Collberg便开始了对代码混淆的研究,在他发表的文章中提出了代码混淆变换的各种类型,他将其分为四类:代码外形混淆、控制命令混淆、内部数据混淆以及预防混淆。随后Kelly等人构造了一种用来实现构造代码的混淆算法机制。在国内,近些年了也有一些学者逐渐意识到了代码混淆技术在进行程序编写中的重要性,大量研究之后取得了较大的成果。比较有代表的有李永祥的多分语句控制迷惑技术,李长春的执行重整混淆算法等。由于混淆技术具有非常重要的软件保护作用,相信未来肯定会有更多的人和组织加入到代码混淆技术的相关研究课题中来。
三、混淆技术介绍
(一)混淆变换原理
作为一种非常实用的软件保护策略,代码混淆技术的基本思想是将应用程序在保持语句含义不变的前提下实现P到P’的变换。此变换中必须满足条件:P‘和P具有相同的运行结果;若P‘出错终止或终止失败,P也必须出错地终止或终止失败;P‘产生与P一样的输出。两个程序唯一不同的只是P‘比P更难去进行反编译,并且P‘可读性差以及相关工具难以解析。因此经过这种变换可以到达混淆的目的,使软件不易被攻击。
(二)混淆的应用领域
代码混淆的应用范围很广,归纳起来主要有一下几种领域:⑴分布式计算和软件保护;⑵法保护和DRM;⑶同形加密;
(三)混淆的分类
代码混淆技术根据混淆对象的不同可以分为四种:代码外形混淆、控制命令混淆、内部数据混淆和预防混淆。
1.代码外形混淆。Java混淆器使用到的混淆方法中代码外形混淆最为典型,该算法可以将Java所有源代码中包含的类的功能隐藏。如果最初的格式信息被除去后代码将不能恢复,因此称这种混淆为单向变换。程序经过这种变换后时间和空间复杂度不会受影响,因为它并没有额外执行代价。
代码外形混淆主要使用的技术有删除(删除程序和中的注释、调试信息、未被调用的方法和類等)和改名(程序中的变量名、常量名、类名、方法名等)。此变换可以使程序的理解变难。
2.控制命令混淆。控制命令混淆能增加程序的复杂度和程序的反编译时间,它是通过改变程序的判断条件或添加可控判断条件以及对程序的结构和流程进行调整来实现的。常常用到的控制命令混淆主要有排序、聚集和计算变换。
3.内部数据混淆。内部数据混淆技术将会利用数据流中的难点问题,向程序中引入使程序精度降低或难度增加的因素,进而可以影响反编译器对程序的分析结果。内部数据混淆只会变换代码中的数据结构,而不修改软件代码。
进行内部数据混淆的主要方法有四种:变量分裂与变量合并、数据结构变换、静态数据动态生成、类继承转换。
4.预防变换。预防变换是利用某些专用反汇编工具的弱点而设计的。具体混淆可以分为针对特定目标实施的预防变换或者是依据已知的反编译算法实现的混淆。
5.四种混淆技术的分析和比较。代码外形混淆使攻击者解读程序造成不便,同时也能针对反编译工具的算法使之反编译难以实施。内部数据混淆改变逻辑变量。控制命令混淆使程序变得更加复杂从而增强程序的抵抗性能。预防混淆较多时候都是具有一定的针对性。内部数据混淆和控制混淆都会在增加程序复杂度的同时造成程序执行效率的下降,而代码外形混淆则不会影响执行效率。
四、标示符重命名混淆算法
标示符重命名混淆属于代码外形混淆的范畴。它是将字节码文件中的一些类名、接口名、方法名等替换为其他无意义的名字。这并没有造成程序的额外开销,抗攻击能力也不强。
重命名是因为进行内部数据混淆和控制混淆时都会增加程序的开销,而这并不是我们想要的。有时候我们经常需要一种可以抵抗攻击并且不会造成程序执行效率下降的算法,而重命名混淆正是这样的。当一些名字被毫无意义的字符替换后,攻击者很难从中读出该名字所代表的意义,这便使得攻击者在反编译是造成了困难。
当程序中一个实体被重命名后,所有与其相关的内容必须更新,否则会引起运行出错。但是有一些是不能被重命名的。这便有了代码混淆范围的提出。以下三种标示符是不在范围内的:(1)子类中一个超类或接口中抽象方法的实体方法;(2)超类中继承方法的重写;(3)特殊属性明确规定不可进行替换。
标示符重名算法可以分为四种:静态方法重写、替换非法提示符、无关联方法重载、部分标识符滥用。
五、算法分析
衡量一个混淆算法性能好坏的重要指标是对程序执行开销的影响。内部数据混淆和控制命令混淆都增加了程序的二外执行开销从而影响了程序的运行效率。重命名混淆只是将名字替换,很多时候都会将名字缩短,使文件变得更小,不会造成执行效率的下降,同时也使攻击者将花费更长的时间来理解和反编译程序。
六、总结
代码混淆技术是时下最常用的,同时也是最有效的保护Java软件的方法,新型的混淆算法一定会随着技术的发展而被发现。虽然代码混淆技术在一定程度上保护了软件的安全以及开发者的权益,但只有我们杜绝使用盗版软件同时不去侵犯他人的知识产权才能切实的保护好开发者的权益。
参考文献:
[1]魏会生.基于JAVA类文件保护的探讨[J].工会博览·理论研究,2011,3:25-26.
[2]魏衍君,王应战.Java语言混淆器模型研究[J].科技信息,2012,4:61-62.
尽管关于Java中文问题的讨论已经相当多了,但由于Java的相关技术标准繁多,面向Java的Web服务器、应用服务器以及JDBC数据库驱动等都没有官方的标准,所以Java应用在处理中文时所存在的问题不仅没有消失而且随着所选用的服务器、驱动程序以及运行环境等因素的不同而变化,那么我们如何从众多现象中找出问题所在,并进行分析和解决呢?与大部分的讨论不同,本文将主要从如何预测、发现和检查问题的角度给出建议,帮助开发人员找出可能引起问题的各种源头,从而更好地解决Java的中文问题。
引言
尽管对于Java中文处理问题的讨论已不乏其数,但由于Java技术涉及内容广(J2EE包含了十几种相关技术),技术供应商繁多,面向Java的Web服务器、应用服务器以及JDBC数据库驱动等都没有官方的标准,所以Java应用在处理中文过程中出了存在固有的问题外也存在随着选用的服务器,驱动程序的不同而带来的Java中文问题的多变性,增加了问题的复杂度。那么,我们如何在这么纷繁的现象中找到问题的症结呢?
Java中文问题的一般解决办法
事实上,Java的中文问题都是由于Java应用所采用的缺省编码格式与目标或者应用所要读入字符的编码格式不同而造成的(具体参见文献1)。对于如何解决Java的中文问题,通常有四种方法:
1)选择JDK的中文本地化版本。尽管Java2 JDK的中文本地化版本(java.sun.com/products/jdk/1.2/chinesejdk.html)并不是一个官方的版本,Sun公司也没有承诺会对该本地化版本进行升级,但其仍不失为一个Java中文问题的解决方案。
2)选择合适的编译参数。对于Java的国际版本来讲,我们也可以在编译Java应用的时候通过指定确定的编码机制来实现其编译结果对中文的支持。例如,对于需要支持繁体中文和简体中文应用可以通过javac -encoding big5 sourcefile.java 和javac -encoding gb2312 sourcefile.java来编译源程序。
3)通过编程的方式实现字符编码的转换代码。通过编程的方式来解决Java的中文问题,已经成为了一种较为普遍的做法。下面就是一种最常见的字符编码转换函数,其将字符的编码格式转换为中文Windows系统的GBK编码形式。
public static String toChinese(String strvalue)
{
try{
if(strvalue==null)
return null;
else
{
strvalue = new String(strvalue.getBytes(“ISO8859_1”), “GBK”);
return strvalue;
}
}catch(Exception e){
return null;
}
}
4)定义字符输出集。对于JSP应用,我们可以通过<%@ page contentType=“text/html; charset=GBK” %>或<%@ page contentType=“text/html; charset=GB2312” %>来定义JSP页面的字符输出集。当然,我们也可以通过HTML的标记
存在的问题
根据方法实现的方式,我们可以将以上四种方法分为两类,一类是通过利用某些标准或者规则来实现的方法,上面的1)、2)、4)都属于此类;一类是通过针对性的编程来实现的方法,上面所提的方法3)就属于此类。
由于方法1),2),4)是具有规范性的一类方法,所以方法比较简单,解决方案也不具备较大的针对性,较为通用,例如我们可以采用方法2)的编译方式通过编译Java源文件来实现内码的预置,而无需考虑源码到底有哪些部分出现了Java的中文处理问题,诸如输出乱码等等。
但是,正由于这些方法不具备针对性,解决问题的方法过于统一,所以在某些情况下,它们并不能彻底地解决Java的中文问题。举一个非常常见的例子。在通常情况下,用户的Java应用往往需要与其它Java应用接口进行交互,例如通过某种版本的JDBC访问数据库。由于JDBC的驱动所支持的编码随着提供商乃至版本的不同而不同,所以如果在数据库的输入输出过程中出现中文不能正确处理问题时,我们需要在数据的输入和输出过程做两次正好相反的编码转换,这对于方法1),2),4)来说,往往是无法解决的。当然,对于方法2,我们也可以通过采用一些技巧使来满足上面的情况,一个最有效的办法就是尽量将Java应用的各个部分组件化。例如我们可以通过将数据库的读入和输出代码分解在不同的源文件上来实现分别编译,从而满足不同的字符编码要求。但是通常的程序设计都不太可能满足这种要求,因为这种程序的划分结果很可能是不合理的。例如,我们将数据库的读出和写入方法封装到一个类中是比较合适的一种设计,但如果将该类的这两个方法分别实现在两个文件里则变得非常不合理。因此对于1),2),4)方法来说,虽然实现比较简单,但却具有一些无法克服的缺点。这也是那些实现起来相对复杂的编程方法得以流行的原因。
相对于方法1),2),4)来说,方法3)具有更好的针对性和灵活性。程序可以根据不同的情况做出灵活的处理,在任何需要的地方进行字符的编码转换,但是该方法的特点也对软件的开发人员提出了更高要求--必须能够准确的捕捉到有可能发生中文处理问题的地方,并做出正确的判断和处理。
分析的原则
总的说来,所有解决Java中文处理的方法都不是很复杂,
相反的是,由于Java技术特别是J2EE技术涉及的内容繁多,各种Web服务器、应用服务器以及JDBC数据库驱动等参差不齐,所以如何正确而及时的发现应用的中文处理问题则变得相对复杂的多。那么我们如何来发现这些问题呢?
通常,Java处理中文时所产生的问题都是由于用户的Java应用所采用的缺省编码格式与目标或者应用所要读入字符的编码格式不同而造成的,而引起这些不同的一个主要原因就是用户的Java应用与其它应用进行了编码格式不匹配的数据交换(包括直接或间接的数据输入、输出)。所以,为了及时发现问题,我们可以由这一点入手,根据以下的原则对应用进行分析:
1. 注意字符变量情况。由于变量的字符编码形式较为隐蔽,多次变量间数值的改变和运算可能会引起字符集的改变;在变量与页面所提交数据的各种操作中,较容易发生不同编码格式字符进行运算的情况。
2. 注意任何形式的字符读入与输出。之所以要提到任何形式,是因为Java应用大多数都是作为网络应用开发的,所以与其它语言的应用相比,Java应用需要面对网络世界各种各样的字符数据交换形式。例如各种表单的数据提交,URL形式的数据读入,经过加密运算的字符数据交换,网页控件选择结果的输入,控件内容的的显示(如List控件)等等。
3. 小心使用第三方的组件和应用。由于第三方组件和应用的实现是非透明的,所以一般情况下,我们很难判断这些组件或驱动的缺省编码格式是什么,也无法对其进行控制。因此,在使用它们所提供的接口函数进行数据交换的时候要特别注意,如果确实出现中文无法正确处理情况,应首先检查我们自己的代码并调整相关代码以适应这些接口,因为这些组件或者应用基本上不会提供调整编码机制的接口。必要时,我们可能需要采用其它可替换的组件或者应用。
4. 注意被请求对象所含有的数据输入与输出。这是非常隐蔽的一类情况,当我们的应用以对象的方式(例如序列化的对象)进行交互时,如果这个对象内部含有字符数据的处理过程,或者含有某些数据的输入、输出,甚至是抛出一段用中文注解的异常,都可能出现中文无法正确显示等问题。由于这些行为往往被封装在对象中,所以我们在编写程序时,很容易忽略这种可能情况。并且这种情况带有一定的不可预见性,例如我们可能不清楚这个对象会在什么时候抛出什么样的异常,所以这时我们就需要做一定的测试工作。
5. 注意数据库的数据访问过程。Java通过JDBC与数据库建立连接。对于JDBC驱动程序来说,由于目前大部分的JDBC驱动程序并不是针对中文系统而设计的(中文数据大都采用ISO-8859-1编码方式),所以一般情况下在数据读写过程中往往都需要字符编码的转化。但是我们仍建议用户在使用这些JDBC驱动时,仔细阅读它的说明。如果确实无法弄清JDBC字符数据的编码到底是什么,我们的建议是做一些必要的测试。例如下面是一组在简体中文Win平台下,采用Weblogic 6.0所提供的JDBC驱动从MSSQL Server2000中正确读入中文字符的代码(例子中进行了字符运算):
...
Class.forName(“weblogic.jdbc.mssqlserver4.Driver”).newInstance;
conn = myDriver.connect(“jdbc:weblogic:mssqlserver4”, props);
conn.setCatalog(“labmanager”);
Statement st = conn.createStatement();
//execute a query
String testStr;
String testTempStr = new String() ;
testStr = new String(testTempStr.getBytes(“ISO-8859-1”));//编码转化
DatabaseMetaData DBMetaData =conn.getMetaData();
ResultSet rs = DBMetaData.getTables(null, null,null,new String[]{“TABLE”} );
while (rs.next()){
for(int j=1; j<=rs.getMetaData().getColumnCount(); j++){
testStr = testStr +String(rs.getObject(j).toString().getBytes(“ISO-8859-1”));
}
}
然而,需要注意的是,不同的JDBC驱动对相同的数据库的支持并不同,而同一类JDBC驱动对不同的数据库的支持也不相同,也就是说我们的字符转化代码在JDBC驱动改变甚至是版本变化情况下都有可能无法正确工作。例如对于上面的例子,在同样的环境下改用i.net的Una 2000 Driver Version 2.03 for MS SQL Server时,是无法正确处理中文的。原因很简单,这个JDBC驱动本身支持的就是GBK的编码机制,所以根本就不需要做任何的编码转化。
6. 必要的测试。由于Java中文问题的产生随着Web服务器,浏览器,运行环境和开发工具的不同都可能发生变化,所以为了更好的避免问题的发生,我们必须作一些针对性的测试。另外,在我们确实无法通过分析来确定Java的中文处理问题是否可能发生的情况下或者无法知道问题的发生是由于哪个环节(是Web服务器,浏览器还是JDBC数据驱动等等)引起的时候,测试工作则变得非常重要。并且我们可能需要较为全面的测试,例如对Web服务器,浏览器和JDBC数据驱动等都要做测试,这样有利于我们找出那些隐藏在多个环节协调过程中所产生的问题。
结论
事实上,Java中文处理之所以存在问题,其根本原因是由于 作的中文字符(变量)的编码格式与目标的编码格式不同造成的,所有这些问题其实都是发生在字符的读入、输出过程中的,只要我们把握住这一环节,就可以更好的发现、分析、处理和预防Java的中文问题了。
【射击游戏 Java】推荐阅读:
射击射击游戏06-26
射击运动枪支弹药管理办法09-20
游戏游戏角色05-28
民间游戏手指游戏09-24
游戏大全晨会游戏11-22
游戏集锦破冰游戏01-04
游戏名称游戏操作09-11
表演游戏与角色游戏10-14
拼图游戏大全闯关游戏10-20
玩游戏女生游戏11-20