Part 01
Set 1
不会,当虫子的附近八个格子都有rock时无法移动,它会原地转圈。
虫子只会向这自身的正前方前进,当它遇到障碍或者边界时会顺时针旋转45°,直至正前方无障碍才停止旋转。
顺时针旋转45°。
当虫子移动到新单元格时,会在旧单元格中留下一朵花。花和虫子的颜色一样。
当虫子在网格边缘若时,若它不是面对边缘,会继续向前移动一格;若它面对边缘,则会顺时针旋转两个45°走向下一个单元格。
碰到障碍顺时针旋转45°,直至正前方无障碍。
花不会移动。
花会随着时间颜色逐渐变深,直到它变成深灰色。
没有
不能,不网格中的一个位置一次只能包含一个参与者。
Part 02
Set 2
sideLength作用是移动轨迹正方形的边长的。
steps作用是记录在该边已经走的长度,并与sideLength进行比较,当小于时继续前进,当等于时连续两次turn旋转90°走下一边,同时steps清零。
因为BoxBug需要走正方形轨迹,当前步数steps等于正方形边长sideLength时需要转弯。
因为BoxBug继承了Bug类,可以使用Bug类中的“move()”方法。
不一定,因为当BoxBug遇到障碍时,轨迹会被改变,如果障碍放在四个角的特定位置,可以走出任意边长的正方形轨迹。
会,比如BoxBug碰到障碍就会改变其路径。
当BoxBug刚被构造时steps = 0 ;当steps >= sideLength 或者遇到障碍canMove() = 0时,BoxBug会执行两次turn(),并使steps = 0 。
Part 03
Set 3
int row1 = loc1.getRow();
False
row 4, column 4
135 (degrees)
八个方向正好对应于周围相邻的八个格子,对于Location的row和col进行特定的加减1,比如NORTH方向row-1,NORTHEAST方向row-1,col+1。
Set 4
调用getOccupiedLocations() 获得所有已占用位置的数组列表,其长度即为网格中的对象的计数。 调用getNumRows()和getNumCols()获得有界网格的行数和列数,相乘后减去已占用位置的数组列表长度即为空位置的计数。
调用isVaild(new Location(10,10)),返回true则在网格内,返回false则不在。
因为Grid是一个interface,只申明方法但不实现。我们可以在AbstractGrid、BoundedGrid和UnboundedGrid中找到方法的实现。
我认为返回ArrayLisr更好,ArrayList可以动态扩充长度,而数组不行。
Set 5
location direction color
方向是Location.NORTH, 颜色是Color.BLUE
因为Actor类中有成员变量,并且包含方法的申明与实现,很明显不是interface。
①一个演员能在不去掉自己的情况下把自己放两次网格吗?
不能,因为在putSelfInGrid中会首先检查gird是否为空,放入一次后grid已经不为空,第二次会报错”This actor is already contained in a grid.”。
②一个演员能把自己从网格中移除两次吗?
不能,因为在removeSelfFromGrid中会首先检查gird是否为空,移除一次后grid已经为空,第二次会报错”This actor is not contained in a grid.”。
③一个演员能被放入一个网格中,移除自己,然后再把自己放回去吗?
可以。
- actor.setDirection(actor.getDirection() + 90);
Set 6
if (!gr.isValid(next)) return false;
return (neighbor == null) || (neighbor instanceof Flower);
①boolean isValid(Location loc) -> 用来判断Actor下一步loc是否超出grid边界。
②E get(Location loc)-> 获得下一步loc里面的类,判断Bug是否能走上去。
public Location getAdjacentLocation(int direction)-> 用于获得下一步移动到的Location。
①getGrid() -> 获得Bug所在的网格gird
②getLocation() -> 获得Bug所在的位置Location
“if (gr.isValid(next)) moveTo(next); else removeSelfFromGrid();” Bug会将自己移出网格。
需要loc变量,因为在Bug移动后需要在原位置放置flower,原位置用loc存储。
可以更好的判断不同颜色的Bug的轨迹。
当使用Actor类中的removeSelfFromGrid()方法或者其他Actor类使用moveTo(Location newLocation)将其移出时不会放置花在原来位置;当其自身因为使用move()方法时到达的新位置在grid边界外而被移除时,会在原位置留下花。
Flower flower = new Flower(getColor());
flower.putSelfInGrid(gr, loc);
- 4次
Part 04
Set 7
- 在Critter中实现了以下方法
·public void act()
·public ArrayList getActors()
·public void processActors(ArrayList actors)
·public ArrayList getMoveLocations()
·public Location selectMoveLocation(ArrayList locs)
·public void makeMove(Location loc)
- Critter共有的是
public ArrayList getActors()
public void processActors(ArrayList actors)
public ArrayList getMoveLocations()
public Location selectMoveLocation(ArrayList locs)
public void makeMove(Location loc)
可以,因为有些critter只选择部分而不是周围所有actor进行操作
吃掉周围的花、清除附近的石头、将前面不为空的对象移至后面
getMoveLocations()、selectMoveLocation(ArrayList locs)、makeMove(Location loc)
因为 Critter extend了Actor类,Java会自动构造一个默认的构造函数去调用 super() 进而调用Actor的构造函数。
Set8
因为 Critter 中的act方法调用了public void processActors(ArrayList<Actor> actors)和public void makeMove(Location loc)而 ChamelonCritter 重写了这两个方法。
因为 ChameleonCritter 中需要更改方向在进行移动,而调用 super.makeMove(loc) 方法是表示调用 Critter 中的而不是自身的,如果没用super 会进入递归导致死循环。
public void makeMove(Location loc)
{
Location location = getLocation(); //在移动前获取当前位置
setDirection(getLocation().getDirectionToward(loc));
super.makeMove(loc);
if(!location.equals(loc)) { //若移动到了新位置
Flower flower = new Flower(getColor());
flower.putSelfInGrid(getGrid(), location);
}
}
因为 ChameleonCritter 本身就是需要获取周围的Actor与 Critter 中的一样,又因为继承了 Critter 所以不需要override了。
Actor中实现了该方法,则其子类都可以使用该方法。
因为 Critter 是 Actor 的子类,则可以直接使用public Grid<Actor> getGrid()方法。
Set9
CrabCritter 的该方法是吃掉rock和critter以外的actor与Critter类一样,所以不需要override。
CrabCritter 使用 public ArrayList<Actor> getActors() 查找其前面、左前方和右前方的Actor,然后使用 public void processActors(ArrayList<Actor> actors) 将不为rock或者critter吃掉。
CrabCritter 使用public ArrayList<Location> getLocationsInDirections(int[] directions) 并传入前面、左前方和右前方三个方向的数组参数可以获得该三个方向的位置列表。
(4, 3) (4, 4) (4, 6)
CrabCritter 和 Critter 都是随机选取一个位置移动; CrabCritter只能左右两个方向随机选取移动, Critter 从八个方向随机选取,当不能移动时 CrabCritter 能转向,而 Critter 不能。
if (loc.equals(getLocation())) 当要移动到的位置,即makeMove中参数loc与当前位置相同则转向。
CrabCritter 继承了 Critter 的processActors方法,该方法使得他们不会吃同类。
Part5
set10
BoundedGrid 类 和 UnboundedGrid 类
getValidAdjacentLocations(Location loc)调用了isVaild方法,因为其他方法都会直接或间接调用该方法来获取location。
getOccupiedAdjacentLocations(Location loc), BoundedGrid 类和UnboundedGrid类提供了这些方法的实现。
因为getEmptyAdjacentLocations方法需要返回的是没有object的网格位置,通过 get 可以判断该位置有无object。
致其相邻位置从八个变为四个,分别为东南西北四个方向的邻近位置
set11
- BoundedGrid类的构造函数规定:如果grid的行数或者列数小于或等于0就会抛出异常,这确保了grid中至少有一个有效位置。
if (rows <= 0)
throw new IllegalArgumentException("rows <= 0");
if (cols <= 0)
throw new IllegalArgumentException("cols <= 0");occupantArray = new Object[rows][cols];
-
①通过occupantArray[0].length确定网格列数。
②“有界网格具有固定数量的行和列。”
被判断的location行的值大于或等于0且小于BoundGrid行数,列的值大于或等于0且小于BoundGrid列数。
ArrayList<Location>方法返回ArrayList<Location>类型。时间复杂度为O(row*col)。
Get方法返回occupantArray中存储的类型。需要参数类型为Location。时间复杂度为O(1)。
要在网格添加物体的位置超出网格范围或者要添加的物体为空会抛出异常;时间复杂度为O(1)。
①Remove方法返回occupantArray中存储的类型。
②当尝试去删去没有物体的空位置时返回值为空。
③O(1)
- 我认为这是一个高效率的实现,567都已经做到了最高效,4可以使用HashMap优化。
set12
- ①Location类必须实现equals(Object other)和 hashCode( )方法。
②如果使用TreeMap代替,不需要再实现其他方法,已经满足条件。
在 UnboundedGrid中用位置作为key键存储相应位置的物体,而null不是一个有效位置,则需要判断location是否为null。在BoundedGrid中,数据存储在二维数组中。在使用位置访问BoundedGrid中的occupantArray方法之前都会先调用isValid方法,一旦位置是null就会直接产生异常,所以在编写其他get和put和remove方法时并不需要重复实现。
O(1)、O(logn)。
因为存储结构的改变会导致返回的对象列表顺序发生变化。存储结构的的变化还会导致数据访问方式的变化。
①map可以用来实现bounded grid。
②相比于使用map实现,使用二维数组实现的优势:在Bounded grid中如果存储的数据对象很多,几乎占满了整个Bounded Grid的话,使用二维空间会更省内存。因为使用Map不仅要存储数据元素还要存储元素的位置,而二维数组只存储数据元素。