Interacting Objects
The Critter Class
Set 7
The source code for the Critter class is in the critters directory
-
What methods are implemented in Critter?
浏览我们的
Crittel类,我们看里面实现的函数有:public void act(); public ArrayList<Actor> getActors(); public void processActors(ArrayList<Actor> actors); public ArrayList<Location> getMoveLocations; public Location selectMoveLocation(ArrayList<Location> locs); public void makeMove(Location loc); -
What are the five basic actions common to all critters when they act?
act函数包含的五个基本的子函数就是每个对象在行动的时候应该考虑的行为:public ArrayList<Actor> getActors();//获得对象 public void processActors(ArrayList<Actor> actors);//Critter的行为函数 public ArrayList<Location> getMoveLocations;//获得可能的移动位置 public Location selectMoveLocation(ArrayList<Location> locs);//选择移动的位置 public void makeMove(Location loc);//移动 -
Should subclasses of Critter override the getActors method? Explain.
我们知道,这个函数的原型是:
public ArrayList<Actor> getActors() { return getGrid().getNeighbors(getLocation()); }那么当一个新的类(继承类)在不同于
Critter的位置选择一个生物的时候,当然需要以不同的方式重载该函数,就像之前重载act()函数一样。 -
Describe the way that a critter could process actors.
行为方式很多:
- 获得对象,让他们移动
- 改变他们的颜色
- 吃掉他们
-
What three methods must be invoked to make a critter move? Explain each of these methods.
看看
act()函数,我们可以大致了解,在移动的时候需要以下步骤:-
获得可能的移动位置
-
选择移动的位置
-
执行向移动命令
这几个行为的执行依次依赖于以下的函数:
getMoveLocations(); selectMoveLocation(); makeMove(loc);第一个方法就是获得一个可以移动的位置的表,第二个方法就是在第一个方法的基础上得到一个、或者说选择一个位置执行为目标移动点,最后一个方法执行移动。
-
-
Why is there no Critter constructor?
这个跟
C++的情况类似,但是不完全一样,我们看看:public class Critter extends Actor目标类继承了
Actor,所以在没有写一个构造函数的时候,java语言一样的,编译器会执行一个默认的构造函数,但是由于这里有继承关系,所以Critter调用的构造函数会是它的父类的构造函数,也就是:public Actor() { color = Color.BLUE; direction = Location.NORTH; grid = null; location = null; }生成一个
对象,颜色蓝色,面朝北方。
Extending the Critter Class
Set 8
The source code for the ChameleonCritter class is in the critters directory
-
Why does act cause a ChameleonCritter to act differently from a Critter even though ChameleonCritter does not override act?
因为行为不同所以一定有函数是重载了的,但是由于
act()函数是最终调用上面\(7\)提到过四种方法的函数,所以也可以不用重载,看看ChameleonCritter类,重载了以下函数:processActors(); makeMove();第一个函数的重载加入了不同的功能,也就是变成选中的角色的颜色,第二个函数重载加入了转弯儿。
-
Why does the makeMove method of ChameleonCritter call super.makeMove?
ChameleonCritter类的行动的函数,首先确定了生物应该朝向的方向,在接下来的过程当中(也就是转向完成之后)需要按照原来的方式进行移动,所以它调用了父类的方法,也就是:public void makeMove(Location loc) { setDirection(getLocation().getDirectionToward(loc)); super.makeMove(loc); } -
How would you make the ChameleonCritter drop flowers in its old location when it moves?
这个就像是之前
Part3设计Jumper的时候一样,不过那个是去除掉原来的位置的花朵,模仿之前的Bug的行为,我们需要确定一个临时变量来完成对于对象行动之前的位置的记录工作,在完成移动之后我们应当在原来的位置声明定义一个与之前的对象一样的颜色的花朵Flower。具体可以对函数做如下的修改:public void makeMove(Location loc) { Location loc_prv = getLocation(); setDirection(getLocation().getDirectionToward(loc)); super.makeMove(loc); if(!loc_prv.equals(loc)) //转弯的时候不要出现花儿。 { Flower flower = new Flower(getColor()); flower.putSelfInGrid(getGrid(), loc_prv); } }与之前不同的是,这个对象是要寻找一个目标,而之前的bug是要寻找一个空的或者合理的位置而已。需要增加一个判断条件,在转弯儿的时候不能够让花儿出现在原来的位置,因为这样会造成对象的重叠。
-
Why doesn’t ChameleonCritter override the getActors method?
因为我们当前的继承类处理Actor对象的时候,处理的那个
Actor的队列获取方式跟它的父类的获取没有区别,所以不需要重载。 -
Which class contains the getLocation method?
Location方法需要确定对象的具体位置,在移动或者行动的函数当中必不可少,第一次出现在是在Actor类,所以对于所有的Actor继承类,都包含Location方法。 -
How can a Critter access its own grid?
调用在父类
Actor当中继承的方法getGrid()就可以了:public Grid<Actor> getGrid()//函数定义 { return grid; } //调用 super.getGeid();
Another Critter
Set 9
The source code for the CrabCritter class is reproduced at the end of this part of GridWorld.
-
Why doesn’t CrabCritter override the processActors method?
我们的
CrabCritte类的行为是,吃掉所有可能出现在目标范围的合理对象,这个跟之前的父类的行为是一样的,所以我们没有必要重载该函数。 -
Describe the process a CrabCritter uses to find and eat other actors. Does it always eat all neighboring actors? Explain.
我们首先看一下该类的
getActor()方法:public ArrayList<Actor> getActors() { ArrayList<Actor> actors = new ArrayList<Actor>(); int[] dirs = { Location.AHEAD, Location.HALF_LEFT, Location.HALF_RIGHT }; for (Location loc : getLocationsInDirections(dirs)) { Actor a = getGrid().get(loc); if (a != null) actors.add(a); } return actors; }第五行,它会获得方向是:前、西北、东北(相对于此时的位置),在这些地方出现的可能的生物都会被吃掉,而在其他的地方出现的东西不会受到影响。
-
Why is the getLocationsInDirections method used in CrabCritter?
这个方法首先获得一个可能的方向的数组,包含的是
CrabCritter的邻居,getLocationsInDirections方法通过这个数组来来确定可能的对象的具体位置,并返回:for (int d : directions) { Location neighborLoc = loc.getAdjacentLocation(getDirection() + d); if (gr.isValid(neighborLoc)) locs.add(neighborLoc); } return locs; -
If a CrabCritter has location (3, 4) and faces south, what are the possible locations for actors that are returned by a call to the getActors method?
我们之前说过,可能的方向就是前、西北、东北,当然是相对于它此时的位置而言的。所以在笛卡尔坐标系对应的位置可能是:\((4,3)\), \((4,4)\), \((4,5)\) 。
-
What are the similarities and differences between the movements of a CrabCritter and a Critter?
-
相似点:
当它们移动的时候,都不会朝着格子移动的方向转向,都是在可能的下一个位置当中选择一个随机移动。
-
不同点:
- CrabCritter移动的方向就只有左和右,而Critter的移动方向可能是八个坐标位置当中的任何一个。
- CrabCritter不能移动的时候,会随机左右转向,而Critter不会转动。
-
-
How does a CrabCritter determine when it turns instead of moving?
看代码:
if (loc.equals(getLocation())){ //turns } else super.makeMove(loc);这段代码里面的
loc是函数参数,也就是说,当我们的参数位置等于我们CrabCritter的当前位置的时候执行转向,否则移动。 -
Why don’t the CrabCritter objects eat each other?
该类继承了之前类的方法:
public void processActors(ArrayList<Actor> actors) { for (Actor a : actors) { if (!(a instanceof Rock) && !(a instanceof Critter)) a.removeSelfFromGrid(); } }我们看到:只有不是
Rock也不是Critter的时候,才会删除(吃掉)对象,可是CrabCritter是一个Critter,相互之间不会吃掉。

浙公网安备 33010602011771号