Part4:Interacting Objects
The Critter Class
set 7
1.在Critter中实现了哪些方法?
-
回答:Critter中实现的函数有六个函数
- act()
- getActors()
- processActors()
- getMoveLocations()
- selectMoveLocation()
- makeMove()
-
代码:
// @file: GridWorldCode\framework\info\gridworld\actor\Critter.java
// @line: 38、56、71、88、104、125
1. public void act()
2. public ArrayList<Actor> getActors()
3. public void processActors(ArrayList<Actor> actors)
4. public ArrayList<Location> getMoveLocations()
5. public Location selectMoveLocation(ArrayList<Location> locs)
6. public void makeMove(Location loc)
2.所有Critter采取行动时共有的五个基本动作是什么?
-
回答:这五个基本行为分别是:
- getActors()
- processActors()
- getMoveLocations()
- selectMoveLocation()
- makeMove()
-
代码:
// @file: GridWorldCode\framework\info\gridworld\actor\Critter.java
// @line: 56、71、88、104、125
1. public ArrayList<Actor> getActors()
2. public void processActors(ArrayList<Actor> actors)
3. public ArrayList<Location> getMoveLocations()
4. public Location selectMoveLocation(ArrayList<Location> locs)
5. public void makeMove(Location loc)
3.Critter的子类是否应该覆盖getActors方法?说明。
-
回答:需要重载,因为Critter的子类调用getActors()函数时候,得到的应该是子类对象类型,而非父类对象类型,同时满足条件要求的actors也是不一样的,所以需要重载。
-
代码
//Critter中的getActors()函数:
// @file: GridWorldCode\framework\info\gridworld\actor\Critter.java
// @line: 56-59
public ArrayList<Actor> getActors()
{
return getGrid().getNeighbors(getLocation());
}
//与
CrabCritter中的getActors()函数:
// @file: GridWorldCode\projects\critters\CrabCritter.java
// @line: 44-57
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;
}
//从两个函数的对比可以明显的发现,两个方法是完全不同的
4.描述critter处理actor的方式。
-
回答:
- 一个critter可以吃掉其他的actors
- 一个critter可以改变其他actors的颜色
- 一个critter让其他actors进行移动.
-
代码:
//Critter移动rock函数:
// @file: GridWorldCode\framework\info\gridworld\actor\Critter.java
// @line: 75-76
public void processActors(ArrayList<Actor> actors)
{
for (Actor a : actors)
{
if (!(a instanceof Rock) && !(a instanceof Critter))
a.removeSelfFromGrid();
}
}
5.1. 要激活Critter,必须调用哪种三种方法?说明每种方法。
-
回答:促使Critter移动的三个函数以及功能依次是:
- getMoveLocations()
功能:得到Critterz周围可以进行移动的空白区域 - selectMoveLocation(ArrayList locs)
功能:找到一个空白区域并返回位置 - makeMove(Location loc)
功能:移动Critter到第2步中找到的空白位置
- getMoveLocations()
-
代码:
//三个函数具体执行过程:
// @file: GridWorldCode\framework\info\gridworld\actor\Critter.java
// @line: 88-90、104-111、125-131
public ArrayList<Location> getMoveLocations()
{
return getGrid().getEmptyAdjacentLocations(getLocation());
}//先找到周围空白位置
public Location selectMoveLocation(ArrayList<Location> locs)
{
int n = locs.size();
if (n == 0)
return getLocation();
int r = (int) (Math.random() * n);
return locs.get(r);
}//确定某个空白位置
public void makeMove(Location loc)
{
if (loc == null)
removeSelfFromGrid();
else
moveTo(loc);
}//完成移动
6.为什么Critter没有构造函数?
- 回答:由于Critter从Actors继承而来,所以可以调用Actors的默认构造函数,进而实现在runner类中进行Critter实例的创建。
- 代码:
//Critter从Actors继承而来:
//@file: GridWorldCode\framework\info\gridworld\actor\Critter.java
//@file:GridWorldCode\framework\info\gridworld\actor\Actor.java
//@line: 37(Critter)和39-45(Actor)
public class Critter extends Actor
//和
public Actor()
{
color = Color.BLUE;
direction = Location.NORTH;
grid = null;
location = null;
}
Extending the Critter Class
set 8
1.为什么即使ChameleonCritter不忽略行为,行为也会导致ChameleonCritter与Critter的行为有所不同?
- 回答:由于ChameleonCritter继承了Critter类,也就继承了Critter类中的函数,所以可以使用Critter中的方法;但是由于ChameleonCritter对makeMove()函数以及processActors()函数进行了重载,这也就导致了ChameleonCritter对象的运动方式与Critter不同,比如随机的将自身的颜色更改为自己前方或者后方Aactor的颜色,同时还会在周围没有actors时候加深自身颜色。
*代码:
//ChameleonCritter中重载ProcessActors()函数:
//@file: GridWorldCode\projects\critters\ChameleonCritter.java
//@line:36-45(processActors)和50-54(maekMove)
public void processActors(ArrayList<Actor> actors)
{
int n = actors.size();
if (n == 0)
return;
int r = (int) (Math.random() * n);
Actor other = actors.get(r);
setColor(other.getColor());
}
public void makeMove(Location loc)
{
setDirection(getLocation().getDirectionToward(loc));
super.makeMove(loc);
}
2.为什么ChameleonCritter的makeMove方法调用super.makeMove?
- 回答:由于当ChameleonCritter调用makeMove()函数进行移动的时候,首先进行方向的改变,然后再调用父类的makeMove()函数移动到一个指定的位置。所以这里要使用super.makeMove()方法来调用父类方法。
*代码:
//子类makeMove()函数:
//@file: GridWorldCode\projects\critters\ChameleonCritter.java
//@line: 50-54
public void makeMove(Location loc)
{
setDirection(getLocation().getDirectionToward(loc));
super.makeMove(loc);
}
3.移动时,如何使ChameleonCritter在其旧位置放置花?
- 回答:首先需要设置一个变量loc记录原来的位置,随后在ChameleonCritter完成移动之后,在loc上放置花并设置这个花的颜色与ChameleonCritter颜色相同。
*代码:
//自定义ChameleonCritter对象生成花函数makeFlower(Location loc):
// @file: Desktop\makeFlower.java
// @line: all
public void makeFlower(Location loc)
{
Location Loc_old = getLocation(); //找到旧位置
setDirection(getLocation().getDirectionToward(loc)); //找到ChemoleonCritter对象新位置
super.makeMove(loc); //让ChemoleonCritter移动
if(!oldLoc.equals(loc))
Flower flower = new Flower(getColor()); //设置颜色
flower.putSelfInGrid(getGrid(), Loc_old);//把花放在旧位置上
}
}
4.为什么ChameleonCritter不覆盖getActors方法?
- 回答:因为ChameleonCritter继承Critter,Critter继承Actor,所以不管是Critter还是ChameleonCritter,在使用getActor()函数时候,都是为了得到地图上已经有的Actor类型实例对象,所以ChameleonCritter类没必要对getActor()函数进行重载。
*代码:
//Critter中getActor()函数
// @file: GridWorldCode\framework\info\gridworld\actor\Critter.java
// @line: 56-59
public ArrayList<Actor> getActors()
{
return getGrid().getNeighbors(getLocation());
}
5.哪个类包含getLocation方法?
- 回答:Actor类
*代码:
//Actor类中getLocation()函数
// @file: GridWorldCode\framework\info\gridworld\actor\Actor.java
// @line: 102-104
public Location getLocation()
{
return location;
}
6.小动物如何访问自己的网格?
- 回答:通过使用Actor类中getGrid()函数
- 代码:
//Actor类中getGrid()函数
// @file: GridWorldCode\framework\info\gridworld\actor\Actor.java
// @line: 92-95
public Grid<Actor> getGrid()
{
return grid;
}
Another Critter
set9
1.为什么CrabCritter不覆盖processActors方法?
- 回答:因为CrabCritter类从Critter类继承而来,并且二者吃东西的行为是一样的,都是去吃掉actors,所以并不需要对processActors()函数进行重载。
- 代码:
//Critter中的processActors()函数
//@file:GridWorldCode\framework\info\gridworld\actor\Critter.java
//@line: 71-78
public void processActors(ArrayList<Actor> actors)
{
for (Actor a : actors)
{
if (!(a instanceof Rock) && !(a instanceof Critter))
a.removeSelfFromGrid();
}
}
2.描述CrabCritter用于寻找和吃其他演员的过程。它是否总是吃掉所有邻近的演员?说明。
- 回答:首先CrabCritter先使用getActor()函数找到自己左前方前方右前方的actor对象,随后使用processActors()函数把他们吃掉。其余位置的actor对象并不会被吃掉。
*代码:
// CrabCritter中的getActor()函数
// @file:GridWorldCode\projects\critters\CrabCritter.java
// @line: 44-57
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;
}
3.为什么在CrabCritter中使用getLocationsInDirections方法?
- 回答:为了找到给定方向数组里面所给的对应方向上是否存在着可以吃的actors,如果存在就加入到actor实体集中,返回信息表示哪个方向上actors是有效的可以被吃掉的。
- 代码:
//CrabCritter中的getLocationsInDirections()函数
// @file:GridWorldCode\projects\critters\CrabCritter.java
// @line: 101-114
public ArrayList<Location> getLocationsInDirections(int[] directions)
{
ArrayList<Location> locs = new ArrayList<Location>();
Grid gr = getGrid();
Location loc = getLocation();
for (int d : directions)
{
Location neighborLoc = loc.getAdjacentLocation(getDirection() + d);
if (gr.isValid(neighborLoc))
locs.add(neighborLoc);
}
return locs;
}
4.如果CrabCritter的位置为(3,4)并且面朝南,则通过调用getActors方法返回的actor可能位于什么位置?
- 回答:(4,3)(4,4)(4,5)三个位置。
- 代码 :
//CrabCritter中的getActor()函数
// @file:GridWorldCode\projects\critters\CrabCritter.java
// @line: 44-57
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;
}
5.CrabCritter和Critter的运动之间有什么异同?
-
回答:
-
相似性:
- 二者均不可以在移动中改变方向
- 可以随机选择自己移动的位置
-
差异性:
- CrabCritter只可以左右移动,并且在不能移动时候可以改变运动方向
- Critter可以向八个方向移动
-
-
代码:
//CrabCritter中的makeMove()函数与Critter的makeMove()函数
// @file:GridWorldCode\projects\critters\CrabCritter.java和GridWorldCode\framework\info\gridworld\actor\Critter.java
// @line: 125-131(Critter)和77-91(CribCitter)
//Critter的makeMove()函数
public void makeMove(Location loc)
{
if (loc == null)
removeSelfFromGrid();
else
moveTo(loc);
}
//CrabCritter的makemMove()函数
public void makeMove(Location loc)
{
if (loc.equals(getLocation()))
{
double r = Math.random();
int angle;
if (r
}
6.CrabCritter如何确定何时转动而不是移动?
- 回答:当传入的参数loc == CrabCritter此时所处的位置时候。
- 代码:
//CrabCritter中的makeMove()函数
// @file:GridWorldCode\projects\critters\CrabCritter.java
// @line: 77-91(CribCitter)
//CrabCritter的makemMove()函数
public void makeMove(Location loc)
{
if (loc.equals(getLocation()))
{
double r = Math.random();
int angle;
if (r < 0.5)
angle = Location.LEFT;
else
angle = Location.RIGHT;
setDirection(getDirection() + angle);
}
else
super.makeMove(loc);
}
7.为什么CrabCritter对象不互相吃东西?
-
回答:CrabCritter类的processActor()函数从Critter继承而来,儿Critter中的processActor()函数定义了Critter不能吃掉rock与critter,所以一个CrabCritter对象也就不能吃掉另一个CrabCritter对象。
-
代码:
// Critter中的processActors()函数
// @file:GridWorldCode\framework\info\gridworld\actor\Critter.java
// @line: 71-78
public void processActors(ArrayList<Actor> actors)
{
for (Actor a : actors)
{
if (!(a instanceof Rock) && !(a instanceof Critter))
a.removeSelfFromGrid();
}
}