SimpleDotCom类中的checkYourself()方法中的for循环有问题
每当玩家猜中某一格时,就将计数器加数,而不管之前是否就已经被猜中。需要一种机制来判别之前是否已经被猜中。
虚拟的行占有7个各自,而DotCom会占有其中连续的3格。下面的虚拟列展示出占领4,5,6三格的DotCom
DotCom有个实例变量——一个int数组来保存DotCom对象的位置
方案一
使用第二个数组,每当玩家猜中某一格时,就把相对的那一格设定称true,之后每次猜中都要检查是否在之前就已经被猜过了
方案二
可以只动用原来的数组,将任何命中的格子改为-1,这样只需要维护与检查一个数组
方案三
在命中某个格子时就把它删除掉,因此格子就会越来越少,但是数组无法改变大小,因此我们必须作出新的数组并拷贝旧数组的值
如果数组能够缩小的话,方案三会更好,如此就不用拷贝并重新赋值引用
Java SE函数库的一个类ArrayList的部分:
add(Object elem) 向list中加入对象参数
remove(int index) 在索引参数中移除对象
remove(Object elem) 移除该对象
contains(Object elem) 若和对象参数匹配返回“true”
isEmpty() 若list中没有元素返回“true”
indexOf(Object elem) 返回对象参数的索引或-1
size() 返回list中元素的一个数
get(int index) 返回当前索引参数的对象
1.创建
ArrayList
2.加入元素
Egg s = new Egg();
myList.add(s);
3.再加入元素
Egg b = new Egg();
myList.add(b);
4.查询大小
int theSize = myList.size();
5.查询特定元素
boolean isIn = myList.contains(s);
6.查询特定元素的位置
int idx = myList.indexOf(b);
7.判断集合是否为空
boolean empty = myList.isEmpty();
8.删除元素
myLIst.remove(s);
ArrayList与数组的比较
比较ArrayList与一般数组
但对于ArrayList来说,只需要创建出此类型的对象就行。它不需要指定大小,因为它会在加入或删除元素时自动地调整大小。
若索引值超越了数组的限制,程序会在执行期出现错误
使用ArrayList时,可以用add(Int, Object)这个形式的方法来指定索引值,或者使用add(Object)的形式来给他自行管理大小
但ArrayList是个普通对象,所以不会有特殊的语法
全新配方的DotCom类
import java.util.ArrayList;
public class DotCom {
private ArrayList locationCells;
public void setLocationCells(ArrayList loc) {
locationCells = loc;
}
public String checkYourself(String userInput) {
String result = "miss";
int index = locationCells.indexOf(userInput);
if (index >= 0) {
locationCells.remove(index);
if (locationCells.isEmpty()) {
result = "kill";
} else {
result = "hit";
}
}
return result;
}
}
开发真正的“Sink a Dot Com”游戏
游戏目标:以最少的猜测次数打掉计算机所安排的达康公司(Dot Com)网站。计算机会根据你的表现来评分。
初始设置:程序启动后,计算机会在虚拟的7×7方格上安排3个达康网站。安排完成后,游戏会要求你开始猜坐标。
进行游戏:因为我们还没有学到图形接口的程序设计,所以这一版会在命令行上进行。计算机会提示你输入所猜测的位置(格子),你会输入“A3”或“C5”等。计算机会回给你命中“Hit”、没中“Miss”或击沉“sunk”等回应。当你清光所有的达康时,游戏会列出你的分数并结束。
A.DotCom类
用来保存DotCom的名字,例如说“Pet.com”与“Go2.com”这样就可以在它们被击沉是列出名字
B.DotComBust类(the game)
对每个DotCom的setter调用以设定name这个实例变量
比简单版更复杂,因为要考虑到重叠等问题。把指定DotCom位置的算法放在GameHelper这个已经写好的辅助性类中
DotComBust类的main()方法会初始化DotComButs对象
DotComBust对象会初始化GameHelper的实例来帮助执行某些功能
DotComBust对象会初始化1个ArrayList来保存3个DotCom对象
DotComBust对象创建出3个DotCom对象放到ArrayList中
DotComBust对象询问helper对象来设定DotCom对象的位置
DotComBust对象赋值DotCom对象的位置,而DotCom对象则会把自己的3格放在独立的ArrayList中
DotComBust对象从helper对象取得玩家的猜测值
DotComBust对象逐个要求DotCom检查猜测值是否有命中。DotCom会检查ArrayList并返回结果
游戏会持续进行直到所有的DotCom都被击沉为止
DotComBust这个类有3个主要的任务:启动游戏,进行游戏直到所有的Dot-Com都被击沉为止,以及结束游戏。虽然我们可以将这3个任务直接用3个方法来对应,但我们还是将进行游戏的工作分割成两个方法以便保持较小的功能模块。较小的方法比较好测试、除错与修改。
“与”和“或”运算符(&&,||)
“不等于”运算符(!=和!)
短运算符(&&,||)
像&&与||,这些我们已经看过的运算符都称为短运算符。在&&表达式中,左右两边都为true这个表达式才会为true,若Java虚拟机发现左方的表达式为false,则它不需要也不会去计算右方的算式才知道要返回false,||也有相同的特点。
所以我们可以用以下这种方式来避免调用内容为null的指针变量的方法:
if (refVar != null && refVar.iaValidType()) {
//执行有效变量的工作
}
长运算符(&,|)
&与|运算符使用boolean表达式时会强制Java虚拟机一定要计算运算符两边的算式,但这两个运算符通常是用来作位的运算。
在Java的API中,类是被包装在包中
要使用API中的类,必须知道它被放在哪个包中
在Java函数库中的每个类都属于某个包。这些包都有个名字,像是javax.swing(里面带有很快就会遇到的Swing接口类)。ArrayList是放在java.util这个包中。顾名思义,java.util放了很多工具类。第16章会讨论有关包的细节,包括如何自制包。
使用来自API的类是很简单的。只要把它们当作是自己写的就好,但是其中还有一个很大的不同:在程序的某个地方你必须要指明函数库类的完整名称,也就是包的名称加上类的名称。
也许你还不清楚,但是实际上已经到了好几个来自API的类。像是System(System.out.println)、String与Math(Math.Random())都是属于java.lang这个包。
必须指明程序代码中所使用到的类的完整名称
ArrayList并不是它的全名,如同“Mike”也不是全名一样(除非是Madonna或Cher这种)。完整的名称是这样的:
你必须告诉Java想要使用的是哪一个ArrayList。有两种方法可以指定:
A.IMPORT
放一个import述句在程序源文件的最前面:
import java.util.ArrayList;
public class MyClass {... }
或
B.TYPE
或者在程序代码中打出全名。不管在哪里,只要有使用到就打出全名。
声明的时候:
java.util.ArrayList
用在参数的时候:
public void go(java.util.ArrayList
作为返回类型的时候:
public java.util.ArrayList
*除非是来自于java.lang 这个包中
查阅参考书和HTML API文档