大二实训(二)问答题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cbb944131226/article/details/80025791

大二实训(二)问答题
author: SYSUcarey
date: 2018-04-15
[本人学院][(http://sdcs.sysu.edu.cn/)]
目录:

Part2

问题1.What is the role of the instance variable sideLength?

The instance variable sideLength set the maximum steps of the BoxBug from a turn to next turn.
When after a new turn:
1.the BoxBug will go forward if it can move to the location in front of it and the recomputed steps is smaller than sideLength.

//@file: project/boxBug/BoxBug.java
//@line: 45~49
if (steps < sideLength && canMove())
        {
            move();
            steps++;
        }

2.the BoxBug will turn right of 90 degrees when it can’t go to the location in front of it or the steps is not smaller than the sideLength.

//@file: project/boxBug/BoxBug.java
//@line: 52~54
turn();
turn();
steps = 0;

2.What is the role of the instance variable steps?

The instance variable steps plays a role of counting the steps of the BoxBug moving after a new turn.

//@file: project/boxBug/BoxBug.java
//@line: 47~48
move();
steps++;

3.Why is the turn method called twice when steps becomes equal to sideLength?

When the BoxBug can’t go to the location in front of it or the steps is not smaller than the sideLength, it will turn right for 90 degrees to go to the next side of its box.
But one turn method only make the BoxBug turn 45 degrees, so the turn method must be called twice.

//@file: framework/info/gridworld/actor/Bug.java
//@line: 64
setDirection(getDirection() + Location.HALF_RIGHT);

4.Why can the move method be called in the BoxBug class when there is no move method in the BoxBug code?

The BoxBug class extends the Bug class, which means BoxBug class is a subclass of the Bug class.

//@file: project/boxBug/BoxBug.java
//@line: 25
public class BoxBug extends Bug

And the Bug class has a public move method.

//@file: framework/info/gridworld/actor/Bug.java
//@line: 71
public void move()

According to the explain of “Class Inheritance”, the BoxBug class inherits the move method from its parent class—Bug class.

5.After a BoxBug is constructed, will the size of its square pattern always be the same? Why or why not?

Yes.
Because after a BoxBug is constructed, the instance variable sideLength which decides the side length of its square is determined and can’t be changed.

//@file: project/boxBug/BoxBug.java
//@line: 34~38
public BoxBug(int length)
    {
        steps = 0;
        sideLength = length;
    }

6.Can the path a BoxBug travels ever change? Why or why not?

Yes.
If there is an Actor at the location in front of a BoxBug, it will turn and may start a new box path.

//@file: framework/info/gridworld/actor/Bug.java
//@line: 101
return (neighbor == null) || (neighbor instanceof Flower);

7.When will the value of steps be zero?

In Two cases:
1.The BoxBug is first constructed.

//@file: project/boxBug/BoxBug.java
//@line: 34~38
public BoxBug(int length)
    {
        steps = 0;
        sideLength = length;
    }

2.The BoxBug just did a new 90 degrees turn.

//@file: project/boxBug/BoxBug.java
//@line: 52~54
turn();
turn();
steps = 0;

Part3

Set3

Assume the following statements when answering the following questions.
Location loc1 = new Location(4, 3);
Location loc2 = new Location(3, 4);
问题1:How would you access the row value for loc1?
Answer:
Using the method getRow() in Location class.

//@file: framework/info/gridworld/grid/Location.java
//@line: 110~113
public int getRow()
{
  return row;
}

问题2:
What is the value of b after the following statement is executed?
boolean b = loc1.equals(loc2);
Answer:
b = false,
Because, loc1’s position is (4,3), which is different from loc2’s position, (3,4).
More specificly, loc1’s row and column are both different from those of loc2.
So, the method equals() return false.

//@file: 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();
}

问题3:
What is the value of loc3 after the following statement is executed?
Location loc3 = loc2.getAdjacentLocation(Location.SOUTH);
Answer:
loc3 is in the Location (4,4).
Because the loc2 is in the Location(3,4), which is in row 3 and column 4.
loc2.getAdjacentLocation(Location.SOUTH)return the adjacent location of (3,4) in the direction of South. So it returns the location (4,4).

//@file: framework/info/gridworld/grid/Location.java
//@line: 130~139、147~148、168~169

  //@line: 130~139
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;

  //@line: 147~148
  else if (adjustedDirection == SOUTH)
    dr = 1;

  //@line 168~169
  return new Location(getRow() + dr, getCol() + dc);
}

问题4:
What is the value of dir after the following statement is executed?
int dir = loc1.getDirectionToward(new Location(6, 5));

Answer:
135 or SouthEast

//@file: 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;
}

问题5:
How does the getAdjacentLocation method know which adjacent location to return?

Answer:
the method getAdjacentLocation(int direction)has a parameter “direction(int)”, which tells the method to return the adjacent location in this direction.

//@file: 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);
}

Set4

问题1: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?

Answer:
(1)
Both the BoundedGrid class and UnboundedGrid class have the method getOccupiedLocations(), which return an ArrayList of the occupied locations in the grid.
We can use getOccupiedLocations().size() to get the size of this ArrayList, so that we can obtain a count of the objects in a grid.

//@file: framework/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;
}
//@file: framework/info/gridworld/grid/UnboundedGrid.java
//@line: 58~64
public ArrayList<Location> getOccupiedLocations()
{
    ArrayList<Location> a = new ArrayList<Location>();
    for (Location loc : occupantMap.keySet())
        a.add(loc);
    return a;
}

(2)
We can first get the whole number of all the locations in a BoundedGrid using getNumRows() * getNumCols() for the BoundedGrid is a rectangle。
Then, getNumRows() * getNumCols() - getOccupiedLocations().size()will get the result.

//@file: framework/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;
}

问题2:How can you check if location (10,10) is in a grid?

Answer:
Both the BoundedGrid class and UnboundedGrid class have the method isValid(Location loc) to tell us whether the Location loc is in the grid.
In the BoundedGrid, it depends on whether (10,10)’s row and column are out of the BoundedGrid.
In the UnboundedGrid, it all return true.

//@file: framework/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();
    }
//@file: framework/info/gridworld/grid/UnboundedGrid.java
//@line: 53~56
    public boolean isValid(Location loc)
    {
        return true;
    }

问题3:Grid contains method declarations, but no code is supplied in the methods. Why? Where can you find the implementations of these methods?

Answer:
Because Grid is only an interface in Java. it only contains method declarations.
We can find the implementations of these methods in class AbstractGridBoundedGridUnboundedGrid. And the AbstractGrid is an abstract class which BoundedGrid and UnboundedGrid inherit from.
Take the method IsValid() and getValidAdjacentLocations() for example:

//@file: framework/info/gridworld/grid/Grid.java
//@line: 50、96

boolean isValid(Location loc);

ArrayList<Location> getValidAdjacentLocations(Location loc);
//@file: framework/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();
    }
//@file: framework/info/gridworld/grid/UnboundedGrid.java
//@line: 53~56
    public boolean isValid(Location loc)
    {
        return true;
    }
//@file: framework/info/gridworld/grid/AbstractGrid.java
//@line: 36~49
    public ArrayList<Location> getValidAdjacentLocations(Location loc)
    {
        ArrayList<Location> locs = new ArrayList<Location>();

        int d = Location.NORTH;
        for (int i = 0; i < Location.FULL_CIRCLE / Location.HALF_RIGHT; i++)
        {
            Location neighborLoc = loc.getAdjacentLocation(d);
            if (isValid(neighborLoc))
                locs.add(neighborLoc);
            d = d + Location.HALF_RIGHT;
        }
        return locs;
    }

问题4: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.
Answer:
For the users, using with the [] notation may be easier to get the objects. But it required the users must know the size, because it may cause the IndexOutOfBoundsException.
And More important is that we must init the size of array by using the [] notation fuction. This is difficult because we hardly know the number of the multiple objects result.
But, by using the ArrayList, we can easily add the objects into it.

//@file: jdk-9.0.1/lib/src/java.base/java/util/ArrayList.java

//@line: 108~109
public class ArrayList<E> extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable

//@line: 166~168
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

//@line: 478~482
public boolean add(E e) {
    modCount++;
    add(e, elementData, size);
    return true;
}

Set5

问题1:Name three properties of every actor.
Answer:
Color、direction and location.
Also it has a reference grid.

//@file: framework/info/gridworld/actor/Actor.java
//@line: 39~45
    public Actor()
    {
        color = Color.BLUE;
        direction = Location.NORTH;
        grid = null;
        location = null;
    }

问题2:When an actor is constructed, what is its direction and color?
Answer:

Color is Blue and direction is North.

//@file: framework/info/gridworld/actor/Actor.java
//@line: 39~45
    public Actor()
    {
        color = Color.BLUE;
        direction = Location.NORTH;
        grid = null;
        location = null;
    }

问题3:Why do you think that the Actor class was created as a class instead of an interface?
Answer:

Because, we can also put an Actor into the grid, it also has its behavior like bug and rock. So, it should be a class but an interface.

//@file: framework/info/gridworld/actor/Actor.java
//@line: 182~185
    public void act()
    {
        setDirection(getDirection() + Location.HALF_CIRCLE);
    }

问题4: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?
Answer:
(1)
No.
An actor can put itself into a grid once until removing itself.
If we put itself into a grid twice without first removing itself, it will throw an IllegalStateException.

//@file: framework/info/gridworld/actor/Actor.java
//@line: 117~119
        if (grid != null)
            throw new IllegalStateException(
                    "This actor is already contained in a grid.");

(2)
No.
An actor can remove itself from a grid once.
If we remove itself twice, it will throw an IllegalStateException.

//@file: framework/info/gridworld/actor/Actor.java
//@line: 135~137
        if (grid == null)
            throw new IllegalStateException(
                    "This actor is not contained in a grid.");

(3)
Yes.
An actor can put it into the grid, and them remove it, and put it into the grid again.

//@file: 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;
    }

//@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;
    }

问题5:How can an actor turn 90 degrees to the right?
Answer:

By using the setDirection()method and getDirection():
way1: setDirection(getDirection() + 90)
wat2: setDirection(getDirection() + Location.RIGHT)

//@file: framework/info/gridworld/actor/Actor.java

//@line: 69~72
    public int getDirection()
    {
        return direction;
    }

//@line: 80~85
    public void setDirection(int newDirection)
    {
        direction = newDirection % Location.FULL_CIRCLE;
        if (direction < 0)
            direction += Location.FULL_CIRCLE;
    }

Set6

问题1:Which statement(s) in the canMove method ensures that a bug does not try to move out of its grid?
Answer:

In the method canMove(), the statement that judge whether the next location is valid in the grid.

//@file: framework/info/gridworld/actor/Bug.java
//@line: 98~99
if (!gr.isValid(next))
    return false;

问题2:Which statement(s) in the canMove method determines that a bug will not walk into a rock?
Answer:
In the method canMove(), the statement that judge whether the next location is NULL or flower.
If yes, it can move.
If no, like a rock there, it can not move.

//@file: framework/info/gridworld/actor/Bug.java
//@line: 100~101
Actor neighbor = gr.get(next);
return (neighbor == null) || (neighbor instanceof Flower);

问题3:Which methods of the Grid interface are invoked by the canMove method and why?
Answer:
IsValid() and get().
The first one is used in judging whether the next location is valid.
The second one is used to get the Actor in the next Location.

//@file: framework/info/gridworld/actor/Bug.java
//@line: 98~100
if (!gr.isValid(next))
    return false;
Actor neighbor = gr.get(next);

问题4:Which method of the Location class is invoked by the canMove method and why?
Answer:

getAdjacentLocation().
It used to get the next location.

//@file: framework/info/gridworld/actor/Bug.java
//@line: 97
Location next = loc.getAdjacentLocation(getDirection());

问题5:Which methods inherited from the Actor class are invoked in the canMove method?
Answer:
getLocation()getDirection()getGrid()

//@file: framework/info/gridworld/actor/Bug.java
//@line: 93~97
Grid<Actor> gr = getGrid();
    if (gr == null)
        return false;
    Location loc = getLocation();
    Location next = loc.getAdjacentLocation(getDirection());

问题6:What happens in the move method when the location immediately in front of the bug is out of the grid?
Answer:

The bug will remove itself frome the grid.

//@file: framework/info/gridworld/actor/Bug.java
//@line: 78~81
if (gr.isValid(next))
    moveTo(next);
else
    removeSelfFromGrid();

问题7:Is the variable loc needed in the move method, or could it be avoided by calling getLocation() multiple times?
Answer:
Yes.
We are supposed to store the location before the bug’s moving. Because, we need to put a flower into this location after the bug’s moving.

//@file: framework/info/gridworld/actor/Bug.java

//@line: 76
Location loc = getLocation();

//@line: 82~83
Flower flower = new Flower(getColor());
flower.putSelfInGrid(gr, loc);

问题8:Why do you think the flowers that are dropped by a bug have the same color as the bug?
Answer:
When we run the program, we can easily know that which bug leaves the flower in the location by the color. Because, the color of the flower and the bug is the same.

//@file: framework/info/gridworld/actor/Bug.java
//@line: 82
Flower flower = new Flower(getColor());

问题9:When a bug removes itself from the grid, will it place a flower into its previous location?
Answer:

It depends on which method you call:
If you call the method removeSelfFromGrid() immediately, no flowers will be left.
If you call the method move() and leads the bug removing, it will left a flower.

//@file: framework/info/gridworld/actor/Actor.java
//@line: 143~145
grid.remove(location);
grid = null;
location = null;
//@file: framework/info/gridworld/actor/Bug.java
//@line: 82~83
Flower flower = new Flower(getColor());
flower.putSelfInGrid(gr, loc);

问题10:Which statement(s) in the move method places the flower into the grid at the bug’s previous location?
Answer:
At the last in the move() method, it will places the flower into the grid at the bug’s previous location.

//@file: framework/info/gridworld/actor/Bug.java
//@line: 82~83
Flower flower = new Flower(getColor());
flower.putSelfInGrid(gr, loc);

问题11: If a bug needs to turn 180 degrees, how many times should it call the turn method?
Answer:

It should call the turn() method four times.
One time for 45 degress, and four times for 180 degress.

//@file: framework/info/gridworld/actor/Bug.java
//@line: 62~65
    public void turn()
    {
        setDirection(getDirection() + Location.HALF_RIGHT);
    }

Part4

Set7

问题1:What methods are implemented in Critter?
Answer:

Six methods : act()getActors()processActors()getMoveLocations()selectMoveLocation()makeMove()

//@file: framework/info/gridworld/actor/Critter.java

//@line: 38
public void act()
//@line: 56
public ArrayList<Actor> getActors()
//@line: 71
public void processActors(ArrayList<Actor> actors)
//@line: 88
public ArrayList<Location> getMoveLocations()
//@line: 104
public Location selectMoveLocation(ArrayList<Location> locs)
//@line: 125
public void makeMove(Location loc)

问题2:What are the five basic actions common to all critters when they act?
Answer:
getActors()processActors()getMoveLocations()selectMoveLocation()makeMove()

//@file: framework/info/gridworld/actor/Critter.java
//@line: 38~47
    public void act()
    {
        if (getGrid() == null)
            return;
        ArrayList<Actor> actors = getActors();
        processActors(actors);
        ArrayList<Location> moveLocs = getMoveLocations();
        Location loc = selectMoveLocation(moveLocs);
        makeMove(loc);
    }

问题3:Should subclasses of Critter override the getActors method? Explain.
Answer:

It depends on the subclasses of Critter.

If we want it select its Actors in the same way as the Critter class, then we can easily not override.

If we want it select its Actors in the different way, we must override the getActors() method.

Take the CrabCritter class for an example :

//@file: project/Part4/CrabCritter/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:Describe the way that a critter could process actors.
Answer:

If the actors are not Rock or another Critter, the Actors will be moved from the grid.

//@file: 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();
        }
    }

问题5:What three methods must be invoked to make a critter move? Explain each of these methods.
Answer:

getMoveLocations()selectMoveLocation()makeMove()

getMoveLocations() return the empty locations near by.

selectMoveLocation() chose one of the empty locations by using Math.random()

makeMove() execute the move operation to the chosen location.

//@file: framework/info/gridworld/actor/Critter.java
//@line: 104~111
    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);
    }

问题6:Why is there no Critter constructor?
Answer:

Because the Critter class inherits the Actor class.

The Actor class has its constructor, so the constructor in Critter class is
unnecessary.

Because Java will help us call the super() ‘s default constructor.

//@file: framework/info/gridworld/actor/Critter.java
//@line: 31
public class Critter extends Actor

Set8

问题1:Why does act cause a ChameleonCritter to act differently from a Critter even though ChameleonCritter does not override act?
Answer:

Though we does’t override the act() method.

But the act() calls other five method: getActors()processActors()getMoveLocations()selectMoveLocation()makeMove(), two of which we have overridden. ( processActors() and makeMove() )

So, the act() method causes a ChameleonCritter to act differently from a Critter.

//@file: project/Part4/ChameleonCritter/ChameleonCritter.java

//@line: 45~56
    public void processActors(ArrayList<Actor> actors)
    {
        int n = actors.size();
        if (n == 0) {
            darken();
            return;
        }
        int r = (int) (Math.random() * n);

        Actor other = actors.get(r);
        setColor(other.getColor());
    }
//@line: 61~65
    public void makeMove(Location loc)
    {
        setDirection(getLocation().getDirectionToward(loc));
        super.makeMove(loc);
    }

问题2:Why does the makeMove method of ChameleonCritter call super.makeMove?
Answer:

The difference of the makeMove() methods of ChameleonCritter and Critter is that before super.makeMove(), the ChameleonCritter will first change its direction.

After changing the direction, the ChameleonCritter moves as the Critter does, so it calls super.makeMove().

//@file: project/Part4/ChameleonCritter/ChameleonCritter.java
//@line: 61~65
    public void makeMove(Location loc)
    {
        setDirection(getLocation().getDirectionToward(loc));
        super.makeMove(loc);
    }

问题3:How would you make the ChameleonCritter drop flowers in its old location when it moves?
Answer:

By changing the makeMove() of ChameleonCritter.

Adding some codes to implement the demand, it requires us to store the old location and add the flower into it after the ChameleonCritter moves to an another place.

After changing:
//@file: project/Part4/ChameleonCritter/ChameleonCritter.java
//@line: 61~69
public void makeMove(Location loc) {
  Location old_loc = this.getLocation();
  setDirection(getLocation().getDirectionToward(loc));
  super.makeMove(loc);
  if(!old_loc.equals(loc)) {
    Flower flo = new Flower(getColor());
    flo.putSelfInGrid(getGrid(), old_loc); 
  }
}

问题4:Why doesn’t ChameleonCritter override the getActors method?
Answer:

Because the way to get Actors for ChameleonCritter is the same as Critter.

And the ChameleonCritter class inherits Critter class, Java will help us to call super.getActors() for ChameleonCritter.

//@file: project/Part4/ChameleonCritter/ChameleonCritter.java
//@line: 31
public class ChameleonCritter extends Critter

问题5:Which class contains the getLocation method?
Answer:

Actor class and all of its subclasses like BugRock and so on.

//@file: framework/info/gridworld/actor/Actor.java
//@line: 102~105
    public Location getLocation()
    {
        return location;
    }

问题6:How can a Critter access its own grid?
Answer:

Because Critter inherits Actor, so it can access its own grid by calling the method getGrid(), which is implemented in class Actor and Critter inherits this method.

//@file: framework/info/gridworld/actor/Actor.java
//@line: 92~95
    public Grid<Actor> getGrid()
    {
        return grid;
    }

//@file: framework/info/gridworld/actor/Critter.java
//@line: 31
public class Critter extends Actor

Set9

问题1:Why doesn’t CrabCritter override the processActors method?
Answer:

Because the way to process Actors for CrabCritter is the same as Critter.

And the CrabCritter class inherits Critter class, Java will help us to call super.processActors() for CrabCritter.

//@file: project/Part4/CrabCritter/CrabCritter.java
//@line: 32
public class CrabCritter extends Critter

//@file: 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:Describe the process a CrabCritter uses to find and eat other actors. Does it always eat all neighboring actors? Explain.
Answer:

(1)find the Actors near by:

Different from Critter class, CrabCritter override the getActor() method, the method return the list of Actors which is only in the Location of its AHEADHALF_LEFTHALF_RIGHT.

//@file: project/Part4/CrabCritter/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;
    }

(2) eat the Actors near by:

The same as Critter class, if the actor is not rock or other critter, it will eat them.

So, it is unnecessary to override this method.

//@file: 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();
        }
    }

问题3:Why is the getLocationsInDirections method used in CrabCritter?
Answer:

It calls getLocationsInDirections() in the method getActors() to help find the three next Location in the direction of CrabCritter’s AHEADHALF_LEFTHALF_RIGHT.

In fact, the parameter of getLocationsInDirections() method is a array of direction(int).

It returns all the next Locations in these direction in the form of ArrayList

//@file: project/Part4/CrabCritter/CrabCritter.java
//@line: 49
for (Location loc : getLocationsInDirections(dirs))

//@file: project/Part4/CrabCritter/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: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?
Answer:

(4,3)、(4,4)、(4,5)

AHEAD for (4,4)、HALF_LEFT for (4,5)、HALF_RIGHT for (4,3).

//@file: project/Part4/CrabCritter/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;
    }

//@file: project/Part4/CrabCritter/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;
}    

问题5:What are the similarities and differences between the movements of a CrabCritter and a Critter?
Answer:

(1)Similarities:

They both chose a random location from the ArrayList of locations which they can move to.

(2)Differences:

They chose the location into the ArrayList in two different ways.

Critter chose all of the empty locations near by while CrabCritter only chose the empty locations near by in the direction of its LEFTand RIGHT.

//@file: project/Part4/CrabCritter/CrabCritter.java
//@line: 62~72
    public ArrayList<Location> getMoveLocations()
    {
        ArrayList<Location> locs = new ArrayList<Location>();
        int[] dirs =
            { Location.LEFT, Location.RIGHT };
        for (Location loc : getLocationsInDirections(dirs))
            if (getGrid().get(loc) == null)
                locs.add(loc);

        return locs;
    }

//@file: framework/info/gridworld/actor/Critter.java
//@line: 88~91
    public ArrayList<Location> getMoveLocations()
    {
        return getGrid().getEmptyAdjacentLocations(getLocation());
    }

//@file: framework/info/gridworld/actor/Critter.java
//@line: 104~111
    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);
    }

问题6:How does a CrabCritter determine when it turns instead of moving?
Answer:

In the method makeMove(Location loc), it tells us if the loc is equal to CrabCritter ‘s current location, which means it can’t move to both the next location of its LEFT and RIGHT.

Then, the CrabCritter turns left or right for 90 degrees instead of moving.

//@file: project/Part4/CrabCritter/CrabCritter.java
//@line: 77~91
    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: Why don’t the CrabCritter objects eat each other?

Because the CrabCritter class inherits Critter class, so it also inherits the method processActors().
In the super.processActors(), it defined that if the Actors are Rock or other Critter, the CrabCritter does nothing.

//@file: project/Part4/CrabCritter/CrabCritter.java
//@line: 32
public class CrabCritter extends Critter

//@file: 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();
        }
    }

Part5

Set10

问题1:Where is the isValid method specified? Which classes provide an implementation of this method?
Answer:

The isValid method is specified in interface Grid.

Classes BoundedGrid and UnboundedGrid implement this method.

//@file: framework/info/gridworld/grid/Grid.java
//@line: 50
    boolean isValid(Location loc);
//@file: framework/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();
    }
//@file: framework/info/gridworld/grid/UnboundedGrid.java
//@line: 53~56
    public boolean isValid(Location loc)
    {
        return true;
    }

问题2:Which AbstractGrid methods call the isValid method? Why don’t the other methods need to call it?
Answer:

(1)

getValidAdjacentLocations() method calls this isValid() method while others do not.

//@file: framework/info/gridworld/grid/AbstractGrid.java
//@line: 44~45
if (isValid(neighborLoc))
    locs.add(neighborLoc);

(2)

Because, other methods like getEmptyAdjacentLocations() and getOccupiedAdjacentLocations can call method getValidAdjacentLocations() to get the valid and adjacent locations which means it is unnecessary for them to call isValid() method immediately.

Take getEmptyAdjacentLocations() for an example:

//@file: framework/info/gridworld/grid/AbstractGrid.java
//@line: 54~58
for (Location neighborLoc : getValidAdjacentLocations(loc))
{
    if (get(neighborLoc) == null)
        locs.add(neighborLoc);
}

问题3:Which methods of the Grid interface are called in the getNeighbors method? Which classes provide implementations of these methods?
Answer:

(1)Two methods: getOccupiedAdjacentLocations() and get() are called.

//@file: framework/info/gridworld/grid/AbstractGrid.java
//@line: 28~34
    public ArrayList<E> getNeighbors(Location loc)
    {
        ArrayList<E> neighbors = new ArrayList<E>();
        for (Location neighborLoc : getOccupiedAdjacentLocations(loc))
            neighbors.add(get(neighborLoc));
        return neighbors;
    }

(2)

Class AbstractGrid provides the implementation of getOccupiedAdjacentLocations() .

//@file: framework/info/gridworld/grid/AbstractGrid.java
//@line: 62~71
    public ArrayList<Location> getOccupiedAdjacentLocations(Location loc)
    {
        ArrayList<Location> locs = new ArrayList<Location>();
        for (Location neighborLoc : getValidAdjacentLocations(loc))
        {
            if (get(neighborLoc) != null)
                locs.add(neighborLoc);
        }
        return locs;
    }

Class BoundedGrid and UnboundedGrid provide the implementation of get().

//@file: framework/info/gridworld/grid/BoundedGrid.java
//@line: 85~91
public E get(Location loc)
{
    if (!isValid(loc))
        throw new IllegalArgumentException("Location " + loc
                + " is not valid");
    return (E) occupantArray[loc.getRow()][loc.getCol()]; 
    // unavoidable warning
}
//@file: framework/info/gridworld/grid/UnboundedGrid.java
//@line: 66~71
    public E get(Location loc)
    {
        if (loc == null)
            throw new NullPointerException("loc == null");
        return occupantMap.get(loc);
    }

问题4:Why must the get method, which returns an object of type E, be used in the getEmptyAdjacentLocations method when this method returns locations, not objects of type E?
Answer:

The get(Location loc) method is used to get the Object in the loc Location in method getEmptyAdjacentLocations().

If there is nothing in the loc Location, method get(Location loc) will return null.

So it can used to judge whether there is an object in the loc Location.

And then we can add this empty Location into the ArrayList which is the result of the method getEmptyAdjacentLocations().

//@file: framework/info/gridworld/grid/AbstractGrid.java
//@line: 51~60
public ArrayList<Location> getEmptyAdjacentLocations(Location loc)
    {
        ArrayList<Location> locs = new ArrayList<Location>();
        for (Location neighborLoc : getValidAdjacentLocations(loc))
        {
            if (get(neighborLoc) == null)
                locs.add(neighborLoc);
        }
        return locs;
    }

问题5:What would be the effect of replacing the constant Location.HALF_RIGHT with Location.RIGHT in the two places where it occurs in the getValidAdjacentLocations method?
Answer:

If we replaced the constant Location.HALF_RIGHT to Location.RIGHT:

Normally, the size of the result ArrayList will decrease from 8 to 4 if the Locations nearby are all valid.

The four locations in the ArrayList will be the next locations in the direction of its NORTHEASTSOUTHWEST

After changing:
//@file: framework/info/gridworld/grid/AbstractGrid.java
//@line: 36~49
public ArrayList<Location> getValidAdjacentLocations(Location loc)
    {
        ArrayList<Location> locs = new ArrayList<Location>();

        int d = Location.NORTH;
        for (int i = 0; i < Location.FULL_CIRCLE / Location.HALF_RIGHT; i++)
        {
            Location neighborLoc = loc.getAdjacentLocation(d);
            if (isValid(neighborLoc))
                locs.add(neighborLoc);
            d = d + Location.RIGHT;
        }
        return locs;
    }

Set11

问题一:The source code for the BoundedGrid class is in Appendix D.
1.What ensures that a grid has at least one valid location?
Answer:

In the constructor of BoundedGrid: BoundedGrid(int rows, int cols), it first judges the value of rows and cols.

If rows <=0 or cols <= 0, the constructor will throw an IllegalArgumentException().

So, this decides that the grid has at least one valid location.

//@file: framework/info/gridworld/grid/BoundedGrid.java
//@line: 39~46
    public BoundedGrid(int rows, int cols)
    {
        if (rows <= 0)
            throw new IllegalArgumentException("rows <= 0");
        if (cols <= 0)
            throw new IllegalArgumentException("cols <= 0");
        occupantArray = new Object[rows][cols];
    }

2.How is the number of columns in the grid determined by the getNumCols method? What assumption about the grid makes this possible?
Answer:

(1)

The number of columns is decided by the value of occupantArray[0].length.

(2)

The constructor of BoundedGrid make a grid with at least one row and one column.

So, occupantArray[0] must exist, and occupantArray[0].length is just the number of columns.

//@file: framework/info/gridworld/grid/BoundedGrid.java

//@line: 39~46
    public BoundedGrid(int rows, int cols)
    {
        if (rows <= 0)
            throw new IllegalArgumentException("rows <= 0");
        if (cols <= 0)
            throw new IllegalArgumentException("cols <= 0");
        occupantArray = new Object[rows][cols];
    }

//@line: 53~58
    public int getNumCols()
    {
        // Note: according to the constructor precondition, numRows() > 0, so
        // theGrid[0] is non-null.
        return occupantArray[0].length;
    }

3.What are the requirements for a Location to be valid in a BoundedGrid?
Answer:

The value of this Location’s row must be equal or larger than 0 and smaller than the number of rows of the grid. ( grid.getNumRows() )

As for the value of this Location’s column, it is the same.

It must also be equal or larger than 0 and smaller than the number of columns of the grid. ( grid.getNumCols() )

//@file: framework/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();
    }

问题二:In the next four questions, let r = number of rows, c = number of columns, and n = number of occupied locations.

1.What type is returned by the getOccupiedLocations method? What is the time complexity (Big-Oh) for this method?
Answer:

(1) ArrayList<Location> is returned.

(2)complexity = O(r*c)

//@file: framework/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;
}

2.What type is returned by the get method? What parameter is needed? What is the time complexity (Big-Oh) for this method?
Answer:

(1) Type E is returned which is also the type of an defined grid’s object.

(2)A parameter in type Location is needed.

(3)complexity = O(1)

//@file: framework/info/gridworld/grid/BoundedGrid.java
//@line: 85~91
    public E get(Location loc)
    {
        if (!isValid(loc))
            throw new IllegalArgumentException("Location " + loc
                    + " is not valid");
        return (E) occupantArray[loc.getRow()][loc.getCol()]; 
        // unavoidable warning
    }

3.What conditions may cause an exception to be thrown by the put method? What is the time complexity (Big-Oh) for this method?
Answer:

(1)

If the parameter loc:Location is Invalid for the bounded grid, it will throw an IllegalArgumentException().

And if the parameter obj:E is null, it will throw a NullPointerException() .

(2) complexity = O(1) .

//@file: framework/info/gridworld/grid/BoundedGrid.java
//@line: 93~105
    public E put(Location loc, E obj)
    {
        if (!isValid(loc))
            throw new IllegalArgumentException("Location " + loc
                    + " is not valid");
        if (obj == null)
            throw new NullPointerException("obj == null");

        // Add the object to the grid.
        E oldOccupant = get(loc);
        occupantArray[loc.getRow()][loc.getCol()] = obj;
        return oldOccupant;
    }

4.What type is returned by the remove method? What happens when an attempt is made to remove an item from an empty location? What is the time complexity (Big-Oh) for this method?
Answer:

(1)Type E is returned which is also the type of an defined grid’s object.

(2)

Nothing special. It will also make the null be stored in the location.

The difference is that it will return null instead of an Actor .

(3) complexity = O(1) .

//@file: framework/info/gridworld/grid/BoundedGrid.java
//@line: 107~117
    public E remove(Location loc)
    {
        if (!isValid(loc))
            throw new IllegalArgumentException("Location " + loc
                    + " is not valid");

        // Remove the object from the grid.
        E r = get(loc);
        occupantArray[loc.getRow()][loc.getCol()] = null;
        return r;
    }

5.Based on the answers to questions 4, 5, 6, and 7, would you consider this an efficient implementation? Justify your answer.
Answer:
Yes.

Using HashMap<Location, E> for the grid can be more efficient.

Set x be the number of occupied locations in this grid of r rows and c columns.
then x <= r*c

In this way, the complexity of getOccupiedLocations() can be less.

It may be O(x) <= O(r * c) , which means it is more efficient.

The complexity of other methods are the same, all are O(1) .

//@file: project/info/Part5/2/SparseBoundedGrid.java
//@line: 70~76
    public ArrayList<Location> getOccupiedLocations() {
        ArrayList<Location> result = new ArrayList<Location>();
        for (Location loc : occMap.keySet()) {
            result.add(loc);
        }
        return result;
    }

Set12

The source code for the UnboundedGrid class is in Appendix D.

问题1:Which method must the Location class implement so that an instance of HashMap can be used for the map? What would be required of the Location class if a TreeMap were used instead? Does Location satisfy these requirements?
Answer:

(1) It must implement hashCode() and equals()

//@file: framework/info/gridworld/grid/Location.java
//@line: 205~221
public boolean equals(Object other)
{
    if (!(other instanceof Location))
        return false;

    Location otherLoc = (Location) other;
    return getRow() == otherLoc.getRow() && getCol() == otherLoc.getCol();
}

/**
 * Generates a hash code.
 * @return a hash code for this location
 */
public int hashCode()
{
    return getRow() * 3737 + getCol();
}

(2)

It’s required that we should implement the compareTo(Object other) method if we want to use TreeMap.

//@file: framework/info/gridworld/grid/Location.java
//@line: 234~246
    public int compareTo(Object other)
    {
        Location otherLoc = (Location) other;
        if (getRow() < otherLoc.getRow())
            return -1;
        if (getRow() > otherLoc.getRow())
            return 1;
        if (getCol() < otherLoc.getCol())
            return -1;
        if (getCol() > otherLoc.getCol())
            return 1;
        return 0;
    }

(3) Yes.

问题2:Why are the checks for null included in the get, put, and remove methods? Why are no such checks included in the corresponding methods for the BoundedGrid?
Answer:
(1)

In the UnboundedGrid class , if the Location is not null, then it must be valid.

Because the method isValid() always return true.

So, we can only checks for null in the get()put()remove() method to judge whether it is valid, or it will cause ArrayIndexOutOfBoundsException() .

//@file: framework/info/gridworld/grid/UnboundedGrid.java
//@line: 53~56
    public boolean isValid(Location loc)
    {
        return true;
    }

(2)

As for the BoundedGrid class,

The isValid() method is called before we use the location in class BoundedGrid.

And in this isValid() method, it will catch the NullPointerException() when comes to the getRow() method of Location class and will be thrown.

So, we are unnecessary to checks for null in the methods get()put()remove() .

//@file: framework/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();
    }

问题3:What is the average time complexity (Big-Oh) for the three methods: get, put, and remove? What would it be if a TreeMap were used instead of a HashMap?
Answer:

(1) They are all O(1) .

(2)

Let n be the number of occupied Location of the grid.

If we used TreeMap, the complexity will become O(log n) .

//@file: framework/info/gridworld/grid/UnboundedGrid.java
//@line: 66~87
    public E get(Location loc)
    {
        if (loc == null)
            throw new NullPointerException("loc == null");
        return occupantMap.get(loc);
    }

    public E put(Location loc, E obj)
    {
        if (loc == null)
            throw new NullPointerException("loc == null");
        if (obj == null)
            throw new NullPointerException("obj == null");
        return occupantMap.put(loc, obj);
    }

    public E remove(Location loc)
    {
        if (loc == null)
            throw new NullPointerException("loc == null");
        return occupantMap.remove(loc);
    }

问题4:How would the behavior of this class differ, aside from time complexity, if a TreeMap were used instead of a HashMap?
Answer:

The most different is that it returns an inorder ArrayList<> by using the TreeMap .

Because A TreeMap store the key in order in a binary tree and we visit the grid by key using the compareTo() method to compare the key.

//@file: framework/info/gridworld/grid/Location.java
//@line: 234~246
    public int compareTo(Object other)
    {
        Location otherLoc = (Location) other;
        if (getRow() < otherLoc.getRow())
            return -1;
        if (getRow() > otherLoc.getRow())
            return 1;
        if (getCol() < otherLoc.getCol())
            return -1;
        if (getCol() > otherLoc.getCol())
            return 1;
        return 0;
    }

问题5:Could a map implementation be used for a bounded grid? What advantage, if any, would the two-dimensional array implementation that is used by the BoundedGrid class have over a map implementation?
Answer:

Yes, we of course could use the map implementation.

One of the advantage is that we can save more memory by using the two-dimensional array implementation.

Because we should only store the object while the Hash-Map should store the location and object.

/*---IF USING HASH-MAP---*/
//@file: framework/info/gridworld/grid/BoundedGrid.java
//@line: 31
private Map<Location, E> occupantMap;
//@line: 45
occupantMap = new HashMap<Location, E>();

/*---IF USING two-dimensional ARRAY
//@file: framework/info/gridworld/grid/BoundedGrid.java
//@line: 31
private Object[][] occupantArray;
//@line: 45
occupantArray = new Object[rows][cols];

code exercise answer:

1.

Methods SparseGridNode version LinkedList version HashMap version TreeMap version
getNeighbors O(c) O(c) O(1) O(log n)
getEmptyAdjacentLocations O(c) O(c) O(1) O(log n)
getOccupiedAdjacentLocations O(c) O(c) O(1) O(log n)
getOccupiedLocation O(r+n) O(r+n) O(n) O(n)
get O(c) O(c) O(1) O(log n)
put O(c) O(c) O(1) O(log n)
remove O(c) O(c) O(1) O(log n)

这里写图片描述

2.

(1)The Big-Oh efficiency of the get() method is O(1)

//@file: project/Part5/3/UnboundedGrid2.java
//@line: 79~87
    public E get(Location loc) {
        if (!isValid(loc)) {
            throw new IllegalArgumentException("Error! Location: " + loc + " is InValid.");
        }
        if (loc.getRow() >= dim || loc.getCol() >= dim) {
            return null;
        }
        return (E)occArray[loc.getRow()][loc.getCol()];
    }

(2)The Big-Oh efficiency of the put() method is O(1) when the row and column index values are within the current array bounds.

(2)The Big-Oh efficiency of the put() method is O(dim*dim) when the array needs to be resized.

//@file: project/Part5/3/UnboundedGrid2.java
//@line: 95~111
    public E put(Location loc, E obj) {
        if (loc == null) {
            throw new IllegalArgumentException("Error! Location: " + loc + " is InValid.");
        }
        if (obj == null) {
            throw new IllegalArgumentException("Error! obj == null");
        }

        //resize the occArray using the method resize()
        if (loc.getRow() >= dim || loc.getCol() >= dim) {
            resize(loc);
        }
        //get the old , put the new, return the old
        E old = get(loc);
        occArray [loc.getRow()][loc.getCol()] = obj;
        return old;
    }

猜你喜欢

转载自blog.csdn.net/cbb944131226/article/details/80025791
今日推荐