Java游戏编程读书笔记
|
|
Author: 一滴蔚蓝色 | Date: 2007-11-29 |
View: 1515 |
开发技术 - 新手上路 | Digg:
4
|
|
第1章 Java 2软件开发工具包 第2章 预备:学习Java 2 API Java程序的结构 2.1 Game Over!程序 2.1.1 import语句 C++注解:Java中的import关键字与C++中的#i nclude指示相似,仅有的不同是java中头文件和源文件之间没有差别。对类的声明和实现都包含在一个.java文件中。 2.1.2
给Java代码加注释 注意C风格注释不要嵌套。第一个“*/”会使最近的“/*”失去作用。 2.1.3 Java类声明 2.1.4 Java方法声明 C++注解:Java中的main方法与控制台C或C++应用程序中的典型main函数相似。注意在Java中,它必须在一个类中定义,而在C和C++中必须全局定义。此外,Java中的main方法总是返回void,与C或C++的main函数不同,它们可以有多个返回类型。 2.1.5 Java中的代码块 2.1.6 Java程序组成部分的关键点回顾 ◆使用import语句使编译器知道要用的库 2.2 比特和字节:原始的Java类型 程序中应写些什么呢?答案是:数据,程序没有数据就不能生存,尤其是游戏。 Java是面向对象语言。但是,Java不是百分百的面向对象,因为Java支持8种原始类型。 2.2.1
基本的整数类型 2.2.2
浮点类型 至今,通常使用哪种类型来存储浮点数还没有定论。双精度在本质上给了我们相对于浮点数两倍的精度,但是,这是有代价的——通常是内存的消耗。Java API中大部分的方法返回类型和数据成员时使用double型。 2.2.3
Char类型 字符由单引号括起来的单个字符表达,通常用16进制表示,范围从’\u0000’到’\uFFFF’(u告诉编译器你在用两个字节[16位]字符信息表示一个Unicode字符)。 C++注解:注意,与C++不同,Java中一个字符数组没有必要组成一个字符串。稍后将会看到,Java API定义了自己的String类型。一般只有敏感信息,如密码字段,才会作为字符数组处理。这是因为,Java对象在没有被Java虚拟机作为不被引用的对象清空之前一直驻留在内存中。如果有精明的黑客潜进系统,则把敏感数据留在内存中可能会造成危险的局面。 想得到更多的关于Unicode字符集的信息,以及字符的完整列表,可以到http://www.unicode.org网站上查看。 2.2.4
布尔型 2.2.5 String类型 复制数组: System.arrayCopy(Object src,int src_position,Object dst,int dst_position,int length); 其中,src指的是从中复制的源数组,src_position指源数组的开始下标,dst指的是复制的目的数组,dst_option指的是目的数组的开始下标,length指定复制的数组元素的个数。 多维数组: ◆在纸上简写出要解决问题。如果数据不能以行和列的方式组织,那么使用数组可能不是最好的解决方法。 2.2.6 强制转换变量类型 boolean gameStarted=true; int game=gameStarted?1:0; 虽然这里没有强转,但是一行代码也可以实现转换。 最后,关于变量还有需要注意的地方。在Java中,没有typedef操作符,也没有与#define预编译指令等价的操作。虽然这可能要花费一些时间来适应,但是它会帮助排除错误并且使代码更清晰。因此,对于那些喜欢写很多“神秘”代码的人,再也不能定义一个如fa26b9这样的变量类型了。 2.2.7
Java数据类型、数组和标识符需要记忆的要点 2.3 Java中的运算符 2.3.1
赋值运算符 2.3.2
比较运算符 2.3.3
算术运算符 2.3.4 自增和自减运算符 2.3.5 更多的整数运算符 1.“位”运算符 public final static int ALIVE=1; public final static int HUNGRY=2; public final static int ANGRY=4; public final static int HAIRY=8; 注意这里使用了独特的能力来描绘每一个属性。用这种方法,离右边最远的那一位表示妖怪是活是死,相邻的第二位表示妖怪是否饥饿……。这里无须对已定义的属性再定义可选择的属性,比如DEAD或NOT_HUNGRY。1即代表一个指定属性的真值,而0则相反。我们来创建一个int变量,名为attributes,初始值为0: int attributes=0; 要为妖怪设置属性,比如ALIVE且HAIRY,使用位或运算符,如下: attributes=ALIVE | HAIRY; 要使妖怪生气,则把attributes变量和ANGRY属性进行或运算即可: attributes |=ANGRY; 要访问每一个属性,则使用位与运算符。下面的代码片段对每个属性的存在进行测验: if(attributes & ALIVE>0) System.out.println(“I am alive!”); if(attributes & HUNGRY>0) System.out.println(“I am hungry!”); if(attributes & HAIRY>0) System.out.println(“I am hairy!”); 属性设置好后,如果想重置一个特殊的属性应该怎么办呢?要实现这一点,使用位与和非运算符。下面显示了从attributes变量中重置HAIRY属性的做法: attributes &= ~HAIRY 当然,如果只是想简单地重置妖怪的所有属性,只需把attributes变量设置为0即可。 attributes=0;
提示:位或、与、异或运算符不仅能够操作整数,也可以操作boolean变量。为简单起见,这里决定不作正式介绍,但是当有需求出现时,它们仍然是有效的操作。 2.3.6 使用点运算符 2.3.7 instanceof运算符 2.3.8 优先级顺序 2.3.9
关于运算符的记忆要点 2.4 条件语句 2.4.1
switch语句 2.4.2 Java中的循环语句 2.4.3 用break、continue和return提前退出循环 2.5 处理运行时异常 Java异常处理的目的在于:让我们的程序在出现运行错误时不至于崩溃,仍然可以继续运行,直到正常结束,这样可以最大可能的避免出现内存泄漏。 一般说来,当有异常存在时,它被“扔给”应用程序,应用程序中恰当的“catch”代码块会处理这个错误。特别地,声明运行时错误种类以及位置的信息会打印在标准输出设备上。 作为程序员有两种可以使用异常处理的主要方法。第一是在方法声明中可以声明throws子句,这在不想自己另外写代码处理异常时非常有用。第二是使用try和catch结构来显式地解决异常。 2.5.1 使用try和catch块 2.5.2
使用throws子句 2.5.3
关于流程控制语句的记忆要点 2.6 总结 希望现在读者对构成Java程序的很多基础结构有好的感觉。虽然本章包括的东西非常多,但是C++程序员应当能够很快地抓住两种语言之间的异同点,其他的程序员,除了语法可能是潜在的障碍之外,也应当熟悉本章列出的概念。 试着做下面的练习,它们会解开读者对本章内容的迷惑。在第3章中,我们将通过设计和使用面向对象的类来进一步地研究Java语言。 2.7 练习 1.Java import语句的目的是什么? 2.下面的哪个类可以在文件Gunship.java中定义? 3.下面哪个是声明java中main方法的正确方法? 4.为下面的变量提出合适的原始数据类型 5.根据用C++的经验,描述Java不允许从布尔值到任何整数类型进行转换的优势。 在C中,由于不存在布尔值,所以,它是以0代表假,非0代表真。于是在下面的两循环中就会发生完全不同的效果。 (1)while(i==1){}(当i的值为1时才循环) 两者的不同在于:在(1)中,计算机首先计算逻辑表达式i==1的值,之后判断这个值是0还是1,显而易见,只有当i为1时,逻辑表达式i==1才会返回1,循环才会进行。 而(2)中的,计算机同样首先计算i=0的值,而i=1是一个赋值语句,这样,不论之前i的值是多少,第一:i会被修改为1,第二:表达式i=1将返回i的值,也就是整数1,计算机将1转换为逻辑值“真”看待,那么就将出现一个死循环。 而在java中,因为有了布尔值,并且布尔不能转换为逻辑值,于是(2)将会报数据类型错误,这样,可以大大避免我们程序员(特别是初学者)犯下无意中写出死循环的情况。 6.(稍难)写一个程序,使之创建一个“无规则”数组,包含帕斯卡三角形前5行的所有值,并把它打印到屏幕上。你可以很努力地编出这些值,但是对于奖励分值,试着从算法中得到。输出应当如下所示,不是必须居中。 7.请解释比较两个String对象为什么与比较同一原始数据类型的两个值不同。写一个比较两个String对象并打印出结果的小测试程序。
8.如果熟悉如DirectX的图形包,试着写一个用移位操作构造32位颜色的程序。颜色以ARGB规则显示,也就是说,每个alpha、红、绿、蓝均为8位(值为0~255)。使用Integer.toHexString方法把颜色值的结果以16进制输出。 9.下面的程序用种子21创建一个随机对象,它会把产生器的下一个在[0,1000000)范围内的整数值保存到n。 import java.io.*; import java.util.*; public class RandomExercise { public static void main(String[] args) { Random r = new Random(21); int n = r.nextInt(1000000); System.out.println("number to generate is " + n); //your code goes here } }完成上面的程序,使之对用同一个随机数产生器、同一个传送到nextInt方法的参数而再次生成相同数字的n的次数进行计数,并把结果打印到屏幕上。(提示:程序每运行122963次总会再次找到相同的数字,为什么?) 10.声明一个关于Point对象的二维数组(不要忘记引入java.awt.Point),如下: Point[][] points=new Point[10][10]; 现在写一个循环来填充每个Point元素,用下标(i,j)以及i和j的值。这里需要两个循环,一个为行一个为列。实际创建每个Point对象的代码应当如下所示: points=new point(i,j); 11.讨论从无限循环中跳出的一些方法,如下: while(true) { //program code here } 这种结构的固有的危险是什么?能否做防护使这种结构不会总是危险的? 12.这章中没有讨论的主题之一是递归。递归算法用分解成更简单的一些问题的方法来解决复杂的问题。 递归方法的工作方式是在到达一个基本状态之前多次调用自己。在找到基本状态后,向上返回到每个调用方法。这里不研究递归如何工作的“奇妙”,不过可以看一个简单的例子。 任何给定数字n的阶乘,如下定义: n!=n*(n-1)*(n-2)*…*1 所以,5=5×4×3×2×1=120。读者可以写一个递归计算阶乘的方法,如下: public int factorial(int n) { if(n==0||n==1) { return n; } return n*factorial(n-1); } 注意这个方法在找到基本状态,即n是0或1之前,是如何重复调用自己的。每一个对factorial的调用能够把自己的答案传送给调用它的相应的factorial。最终,过程返回到最初的调用并得到正确的值。 试着写一个程序,使用上面的方法,看看是否清楚它的工作过程。打印出每一个对facorial的调用的值可能会使情况变得清晰。接下来试着用非递归(重复)的方式写相同的程序。进一步地,解释在哪种情况下,上面的代码会失败以及如何来修复它。 13.设想你准备写一个计算器程序,可以计算普通的算法表达。下面是这个程序的运行例子,用户想对两个数进行除运算: Enter the numerator: 67 Enter the denominator: 13 67/13=5.1538463 解释什么样的条件可能会引起要抛出的异常,假设用户的输入都是有效的数字。对于处理算术异常而言,可能比try-catch块更好的方法是什么? 14.描述整数左移和右移与乘法和除法在对相同数字的操作上有怎样的关联。假设移位操作比乘除法快,描述移位运算可能派上用场的一些情况。 答:左移相当于乘二,右移相当于除二。能派上用场的地方很多,不过我一时想不起来了。 更多阅读: |
|
| 最近更新 ( 2008-11-29 ) |
尚无评论发表