Set 3
-
How would you access the row value for loc1?
答:使用函数:loc1.getRow();
//@file: GridWorldCode/framework/info/gridworld/grid/Location.java //@line: 110~113 public int getRow() { return row; }
-
What is the value of b after the following statement is executed?
boolean b = loc1.equals(loc2);
答:该语句被执行完之后,b的值为false//@file: GridWorldCode/framework/info/gridworld/grid/Location.java //@line: 205~212 public boolean equals(Object other) { if (!(other instanceof Location)) return false; Location otherLoc = (Location) other; return getRow() == otherLoc.getRow() && getCol() == otherLoc.getCol(); }
-
What is the value of loc3 after the following statement is executed?
Location loc3 = loc2.getAdjacentLocation(Location.SOUTH);
答:因为loc2表示的坐标为(3,4),指向的方向为SOUTH,getAdjacentLocation()函数的作用是移动到所指方向上相邻的位置,所以loc3表示的坐标为(4,4)//@file: GridWorldCode/framework/info/gridworld/grid/Location.java //@line: 81 public static final int SOUTH = 180; //@file: GridWorldCode/framework/info/gridworld/grid/Location.java //@line: 130~169 public Location getAdjacentLocation(int direction) { // reduce mod 360 and round to closest multiple of 45 int adjustedDirection = (direction + HALF_RIGHT / 2) % FULL_CIRCLE; if (adjustedDirection < 0) adjustedDirection += FULL_CIRCLE; adjustedDirection = (adjustedDirection / HALF_RIGHT) * HALF_RIGHT; int dc = 0; int dr = 0; if (adjustedDirection == EAST) dc = 1; else if (adjustedDirection == SOUTHEAST) { dc = 1; dr = 1; } else if (adjustedDirection == SOUTH) dr = 1; else if (adjustedDirection == SOUTHWEST) { dc = -1; dr = 1; } else if (adjustedDirection == WEST) dc = -1; else if (adjustedDirection == NORTHWEST) { dc = -1; dr = -1; } else if (adjustedDirection == NORTH) dr = -1; else if (adjustedDirection == NORTHEAST) { dc = 1; dr = -1; } return new Location(getRow() + dr, getCol() + dc); }
-
What is the value of dir after the following statement is executed?
int dir = loc1.getDirectionToward(new Location(6, 5));
答:该语句执行之后dir的值为 135//@file: GridWorldCode/framework/info/gridworld/grid/Location.java //@line: 178~195 public int getDirectionToward(Location target) { int dx = target.getCol() - getCol(); int dy = target.getRow() - getRow(); // y axis points opposite to mathematical orientation int angle = (int) Math.toDegrees(Math.atan2(-dy, dx)); // mathematical angle is counterclockwise from x-axis, // compass angle is clockwise from y-axis int compassAngle = RIGHT - angle; // prepare for truncating division by 45 degrees compassAngle += HALF_RIGHT / 2; // wrap negative angles if (compassAngle < 0) compassAngle += FULL_CIRCLE; // round to nearest multiple of 45 return (compassAngle / HALF_RIGHT) * HALF_RIGHT; }
-
How does the getAdjacentLocation method know which adjacent location to return?
答:通过参数direction判断actor方向,然后根据该方向计算相邻位置,例如:但从东西方向上看,往东就将dc令为1,若往西则dc为1;单从南北方向同理,若actor往北则dr置为1,往南则置为-1;最后再跟初始坐标相加就得到了调用该方法之后该移动到的方向。//@file: GridWorldCode/framework/info/gridworld/grid/Location.java //@line: 130~169 public Location getAdjacentLocation(int direction) { // reduce mod 360 and round to closest multiple of 45 int adjustedDirection = (direction + HALF_RIGHT / 2) % FULL_CIRCLE; if (adjustedDirection < 0) adjustedDirection += FULL_CIRCLE; adjustedDirection = (adjustedDirection / HALF_RIGHT) * HALF_RIGHT; int dc = 0; int dr = 0; if (adjustedDirection == EAST) dc = 1; else if (adjustedDirection == SOUTHEAST) { dc = 1; dr = 1; } else if (adjustedDirection == SOUTH) dr = 1; else if (adjustedDirection == SOUTHWEST) { dc = -1; dr = 1; } else if (adjustedDirection == WEST) dc = -1; else if (adjustedDirection == NORTHWEST) { dc = -1; dr = -1; } else if (adjustedDirection == NORTH) dr = -1; else if (adjustedDirection == NORTHEAST) { dc = 1; dr = -1; } return new Location(getRow() + dr, getCol() + dc); }
Set 4
-
How can you obtain a count of the objects in a grid? How can you obtain a count of the empty locations in a bounded grid?
答:
(1) 使用方法getOccupiedLocation()
通过检查array list中的元组数即可获得网格中有多少网格已被占有也就是网格中有多少对象。
(2)上面的回答我们已知网格中被占用的网格的数目,所以网格中空的数目=所有网格的数目 - 问题一中的得到的已被占用的网格数量,即空网格数 = getNumRows() * getNumCols = getOccupiedLocation().size()//@file:GridWorldCode/famework/info/gridworld/grid/Grid.java //@line:85 ArrayList<Location> getOccupiedLocations(); //@file:GridWorldCode/famework/info/gridworld/grid/BoundedGrid.java //@line:48~58 public int getNumRows() { return occupantArray.length; } public int getNumCols() { // Note: according to the constructor precondition, numRows() > 0, so // theGrid[0] is non-null. return occupantArray[0].length; } //@file:GridWorldCode/famework/info/gridworld/grid/BoundedGrid.java //@line:66~83 public ArrayList<Location> getOccupiedLocations() { ArrayList<Location> theLocations = new ArrayList<Location>(); // Look at all grid locations. for (int r = 0; r < getNumRows(); r++) { for (int c = 0; c < getNumCols(); c++) { // If there's an object at this location, put it in the array. Location loc = new Location(r, c); if (get(loc) != null) theLocations.add(loc); } } return theLocations; }
-
How can you check if location (10,10) is in a grid?
答:如果是在Ubounded grid中的话(10,10)一直是valid,若在Bounded grid中则使用方法isvalid()
即可知道该位置是否为valid。//@file:GridWorldCode/famework/info/gridworld/grid/BoundedGrid.java //@line:60~64 public boolean isValid(Location loc) { return 0 <= loc.getRow() && loc.getRow() < getNumRows() && 0 <= loc.getCol() && loc.getCol() < getNumCols(); }
-
Grid contains method declarations, but no code is supplied in the methods. Why? Where can you find the implementations of these methods?
答:由Part3的介绍我们可以知道,Grid是一个接口,它只需要包含方法的声明并不需要将方法进行实现。在BoundedGrid
和UnbounddedGrid
类中实现了这些方法。//@file:GridWorldCode/famework/info/gridworld/grid/AbstractGrid.java //@line:26 public abstract class AbstractGrid<E> implements Grid<E> //@file:GridWorldCode/famework/info/gridworld/grid/BoundedGrid.java //@line:29 public class BoundedGrid<E> extends AbstractGrid<E> //@file:GridWorldCode/famework/info/gridworld/grid/UnboundedGrid.java //@line:31 public class UnboundedGrid<E> extends AbstractGrid<E>
-
All methods that return multiple objects return them in an ArrayList. Do you think it would be a better design to return the objects in an array? Explain your answer.
答:不。ArrayList比数组更适合。因为在我们调用该方法的时候,我们并不能具体直到调用该方法之后返回的对象数目,而数组在声明之后大小固定,所以使用数组可能会造成所申请的数组过小或者过大造成浪费等等,然而使用Arraylist却没有这个问题,因为ArrayList是动态添加对象的。// @file:GridWorldCode\framework\info\gridworld\grid\Grid.java // @line: 85,96,107,118,129 ArrayList<Location> getOccupiedLocations(); ArrayList<Location> getValidAdjacentLocations(Location loc); ArrayList<Location> getEmptyAdjacentLocations(Location loc); ArrayList<Location> getOccupiedAdjacentLocations(Location loc); ArrayList<E> getNeighbors(Location loc);
Set 5
-
Name three properties of every actor.
答:color,direction,location// @file:GridWorldCode\framework\info\gridworld\actor\Actor.java // @line: 32~34 private Location location; private int direction; private Color color;
-
When an actor is constructed, what is its direction and color?
答:一个actor刚创建时其方向为:北,颜色为蓝色。// @file:GridWorldCode\framework\info\gridworld\actor\Actor.java // @line: 39~45 public Actor() { color = Color.BLUE; direction = Location.NORTH; grid = null; location = null; }
-
Why do you think that the Actor class was created as a class instead of an interface?
答:因为Actor类定义并实现了方法,而接口类只是定义但并不实现类中的方法。// @file:GridWorldCode\framework\info\gridworld\actor\Actor.java // @line: 39~45 public Actor() { color = Color.BLUE; direction = Location.NORTH; grid = null; location = null; }
-
Can an actor put itself into a grid twice without first removing itself? Can an actor remove itself from a grid twice? Can an actor be placed into a grid, remove itself, and then put itself back? Try it out. What happens?
答:
(1) 不可以。重复将同一个actor放入grid中会抛出异常throw new IllegalStateException("This actor is already contained in a grid.");
// @file:GridWorldCode\framework\info\gridworld\actor\Actor.java // @line: 115~127 public void putSelfInGrid(Grid<Actor> gr, Location loc) { if (grid != null) throw new IllegalStateException( "This actor is already contained in a grid."); Actor actor = gr.get(loc); if (actor != null) actor.removeSelfFromGrid(); gr.put(loc, this); grid = gr; location = loc; }
尝试结果:
Exception in thread "main" java.lang.IllegalStateException: This actor is already contained in a grid. at info.gridworld.actor.Actor.putSelfInGrid(Actor.java:118) at BugRunner.main(BugRunner.java:36)
(2) 不可以。重复从grid中删除一个actor会抛出异常
throw new IllegalStateException("This actor is not contained in a grid.");
// @file:GridWorldCode\framework\info\gridworld\actor\Actor.java // @line: 133~146 public void removeSelfFromGrid() { if (grid == null) throw new IllegalStateException( "This actor is not contained in a grid."); if (grid.get(location) != this) throw new IllegalStateException( "The grid contains a different actor at location " + location + "."); grid.remove(location); grid = null; location = null; }
尝试结果:
Exception in thread "main" java.lang.IllegalStateException: This actor is not contained in a grid. at info.gridworld.actor.Actor.removeSelfFromGrid(Actor.java:136) at BugRunner.main(BugRunner.java:37)
(3) 可以。先将actor放入grid中,再将该actor移除,再将其放回并不会引发错误,不会有异常抛出。
-
How can an actor turn 90 degrees to the right?
答:通过调用setDirection(int newDirection)即可完成向右旋转90度:setDirection(getDirection() + Location.RIGHT)
// @file:GridWorldCode\framework\info\gridworld\actor\Actor.java // @line: 80~85 public void setDirection(int newDirection) { direction = newDirection % Location.FULL_CIRCLE; if (direction < 0) direction += Location.FULL_CIRCLE; } // @file:GridWorldCode\framework\info\gridworld\actor\Actor.java // @line: 69~72 public int getDirection() { return direction; }
Set 6
-
Which statement(s) in the canMove method ensures that a bug does not try to move out of its grid?
答:下面的语句保证bug不会移出grid界外。//@file:GridWorldCode\framework\info\gridworld\actor\Bug.java // @line: 97~99 Location next = loc.getAdjacentLocation(getDirection()); if (!gr.isValid(next)) return false;
-
Which statement(s) in the canMove method determines that a bug will not walk into a rock?
答:通过判断,保证下一个要移动到的地方不是空的就是花朵。//@file:GridWorldCode\framework\info\gridworld\actor\Bug.java // @line: 100~101 Actor neighbor = gr.get(next); return (neighbor == null) || (neighbor instanceof Flower);
-
Which methods of the Grid interface are invoked by the canMove method and why?
答:canMove方法调用了Grid接口中的isValid(Location loc)
和get(Location loc)
方法。调用isValid()
方法是为了检查下一个location是不是在grid中,再通过get()
可以知道是否可以移动到下一个location。//@file:GridWorldCode\framework\info\gridworld\actor\Bug.java // @line: 98~101 f (!gr.isValid(next)) return false; Actor neighbor = gr.get(next); return (neighbor == null) || (neighbor instanceof Flower); //@file:GridWorld/framework/info/gridworld/grid/Grid.java //@line: 50, 79 boolean isValid(Location loc); E get(Location loc)
-
Which method of the Location class is invoked by the canMove method and why?
答:Location getAdjacentLocation(int direction)
.该函数返回bug在当前方向上的下一个location,然后我们再对其加以判断,判断bug是不是可以移动到该location。// @file:GridWorldCode\framework\info\gridworld\grid\Location.java // @line: 130 public Location getAdjacentLocation(int direction); // @file:GridWorldCode\framework\info\gridworld\actor\Bug.java // @line: 97~101 Location next = loc.getAdjacentLocation(getDgetDirection()); if (!gr.isValid(next)) return false; Actor neighbor = gr.get(next); return (neighbor == null) || (neighbor instanceof Flower);
-
Which methods inherited from the Actor class are invoked in the canMove method?
答:Location getLocation()
和Grid<Actor> getGrid()
和int getDirection()
// @file:GridWorldCode\framework\info\gridworld\actor\Actor.java // @line: 69,92,102 public int getDirection() public Grid<Actor> getGrid() public Location getLocation() //@file:GridWorldCode\framework\info\gridworld\actor\Bug.java // @line: 91~104 public boolean canMove() { Grid<Actor> gr = getGrid(); if (gr == null) return false; Location loc = getLocation(); Location next = loc.getAdjacentLocation(getDirection()); if (!gr.isValid(next)) return false; Actor neighbor = gr.get(next); return (neighbor == null) || (neighbor instanceof Flower); // ok to move into empty location or onto flower // not ok to move onto any other actor }
-
What happens in the move method when the location immediately in front of the bug is out of the grid?
答:如果下一个location在网格外面的话,move()
方法会调用removeSelfFromGrid()
将自身从网格中消除掉。//@file:GridWorldCode\framework\info\gridworld\actor\Bug.java // @line: 78~81 if (gr.isValid(next)) moveTo(next); else removeSelfFromGrid();
-
Is the variable loc needed in the move method, or could it be avoided by calling getLocation() multiple times?
答:move方法中的loc变量是必须的,且无法通过多次调用getLocation()
来避免。原因是我们需要在bug走过的地方放置花朵,而且一旦调用moveTo()
或者removeSelfFromGrid()
之后bug位置会改变,所以我们需要记录一下bug走过的地方。// @file:GridWorldCode\framework\info\gridworld\actor\Bug.java // @line: 76~83 Location loc = getLocation(); Location next = loc.getAdjacentLocation(getDirection()); if (gr.isValid(next)) moveTo(next); else removeSelfFromGrid(); Flower flower = new Flower(getColor()); flower.putSelfInGrid(gr, loc);
-
Why do you think the flowers that are dropped by a bug have the same color as the bug?
答:由花产生的代码我们可以知道,在设置花的颜色的时候,我们直接将bug的颜色赋给了花的颜色,所以bug掉下的花和bug本身的颜色相同。// @file:GridWorldCode\framework\info\gridworld\actor\Bug.java // @line: 82~83 Flower flower = new Flower(getColot()); flower.putSelfInGrid(gr, loc);
-
When a bug removes itself from the grid, will it place a flower into its previous location?
答:bug移除自己时是否会留下花在其原来的位置这取决于其调用哪个方法,有两个方法用于移除bug自身:removeSelfFromGrid()
和move()
.
如果是调用removeSelfFromGrid,
,将不会留下花朵。
如果调用的是move()
,且bug的下一个location是invalid的话,就会留下一个花朵。// @file:GridWorldCode\framework\info\gridworld\actor\Actor.java // @line: 133~146 public void removeSelfFromGrid() { if (grid == null) throw new IllegalStateException( "This actor is not contained in a grid."); if (grid.get(location) != this) throw new IllegalStateException( "The grid contains a different actor at location " + location + "."); grid.remove(location); grid = null; location = null; } // @file:GridWorldCode/framework/info/gridwork/actor/Bug.java // @line: 79~83 if (gr.isValid(next)) moveTo(next); else removeSelfFromGrid(); Flower flower = new Flower(getColor()); flower.putSelfInGrid(gr, loc);
-
Which statement(s) in the move method places the flower into the grid at the bug’s previous location?
// @file:GridWorldCode\framework\info\gridworld\actor\Bug.java // @line: 82~83 Flower flower = new Flower(getColot()); flower.putSelfInGrid(gr, loc);
-
If a bug needs to turn 180 degrees, how many times should it call the turn method?
答:因为调用一次turn()
方法转动45度,所以想转动180度得调用四次turn方法。// @file:GridWorldCode\framework\info\gridworld\actor\Bug.java // @line:62~65 public void turn() { setDirection(getDirection() + Location.HALF_RIGHT); }