软工中级实训Stage2-Part3:GridWorld Classes and Interfaces

The Location Class

Set 3

回答以下问题时,请假定以下陈述。

Location loc1 = new Location(4, 3);
Location loc2 = new Location(3, 4);

如何访问loc1的行值?

  • 回答:使用getRow()函数,即可访问。
  • 代码:
//@file: GridWorldCode\framework\info\gridworld\grid\Location.java
// @line: 110~112
public int getRow()
    {
        return row;
    }

执行以下语句后,b的值是什么?

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();
    }

执行以下语句后,loc3的值是什么?

Location loc3 = loc2.getAdjacentLocation(Location.SOUTH);
  • 回答:loc3的坐标为(4,4);
  • 代码:
//@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);
    }   

执行以下语句后,dir的值是什么?

int dir = loc1.getDirectionToward(new Location(6, 5);
  • 回答:dir=135° ;从坐标图可以直观看出,(6,5)位于(4,3)的东南方(坐标系向下建立)。
  • 代码:
//@file:GridWorldCode\framework\info\gridworld\grid\Location.java
//@line: 178~190
 public int getDirectionToward(Location target)
    {
        int dx = target.getCol() - getCol(); //2
        int dy = target.getRow() - getRow(); //-2
        int angle = (int) Math.toDegrees(Math.atan2(-dy, dx));
        int compassAngle = RIGHT - angle;
        compassAngle += HALF_RIGHT / 2;
        if (compassAngle < 0)
            compassAngle += FULL_CIRCLE;
        return (compassAngle / HALF_RIGHT) * HALF_RIGHT;
    }   

getAdjacentLocation方法如何知道要返回哪个相邻位置?

  • 回答:由代码可知,该函数传入的参数是一个角度值,因此方向已经被确定了。由参数direction确定位置,随后找到在给定方向相对位置为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);
    }   

The Grid Interface

Set 4

如何获得网格中对象的数量?如何获得有界网格中的空位置计数?

  • 回答:使用grid.getOccupiedLocations()函数,可以找到所有被占有的单元格的位置,再用size()函数计算出函数返回数组中元素的准确个数,这样一来就可以获得网格中对象的数量。 而空位置数量 = 总单元格数(grid的长的数目(grid.getNumRows()) * grid的宽的数目(grid.getNumCols()) ) - 已经被占用的单元格数(grid.getOccupiedLocation.size())
  • 代码:
 // @file: GridWorldCode\framework\info\gridworld\grid\BoundedGrid.java
 //@line: 66-83 
public ArrayList<Location> getOccupiedLocations()
    {
        ArrayList<Location> theLocations = new ArrayList<Location>();
        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;
    }

如何检查位置(10,10)是否在网格中?

  • 回答:isValid(Location loc)函数,如果一个点在grid内返回true,否则返回false;可以通过判断isValid((10,10))的返回值是true还是false来判断是不是在grid内
  • 代码:
// @file: GridWorldCode\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();
    }

Grid包含函数声明,但函数中未提供任何代码。为什么?在哪里可以找到这些函数的实现?

  • 回答:(1)从Grid文件的定义中,可以发现,Grid并不是一个完整的类,而是一个接口,所以Grid并不会提供相应具体的方法来让我们使用,而是只提供了一个方法模型;(2)而其他的类可以通过对这个接口的继承,来实现对方法的调用;同时在不同的类中,不同的继承,可能来自同一个借口的函数的功能也是不一样的。 从 AbstractGrid类, BoundedGrid类和 UnboundedGrid类中找到Grid对应方法的实现
  • 代码:
// @file: GridWorldCode\framework\info\gridworld\grid\BoundedGrid.java
 // @line: 29
  public class BoundedGrid<E> extends AbstractGrid<E>
// @file: GridWorldCode\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
    }

所有返回多个对象的函数都将它们返回到ArrayList中。您认为将对象返回到数组中会更好吗?解释你的答案。

  • 回答:我认为用数组不会更好。因为ArrayList是动态的,没有固定的大小,可以在需要时候增加或者减少来降低内存空间的使用;而array不可以,array是静态的,只能固定长度,不方便进行数据的删减,同时也可能会造成大量内存空间的浪费或者泄露。
  • 代码:
// @file: GridWorldCode\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);
                //实现ArrayList的动态加长
                if (get(loc) != null)
                    theLocations.add(loc);
            }
        }

        return theLocations;
    }

The Actor Class

Set 5

列出每个actor的三个属性。

  • 回答:三个属性分别是location、direction、color 。
  • 代码:
// @file: GridWorldCode\framework\info\gridworld\actor\Actor.java
// @line: 31-34
	 private Grid<Actor> grid;
    private Location location;
    private int direction;
    private Color color;

构造一个actor时,它的方向和颜色是什么?

  • 回答:当构造一个新的actor类型的对象时候,方向会被默认置为:**North,**颜色会被默认置为:**Blue **
  • 代码:
// @file: GridWorldCode\framework\info\gridworld\actor\Actor.java
// @line: 37-45
public Actor()
    {
        color = Color.BLUE;
        direction = Location.NORTH;
        grid = null;
        location = null;
    }

为什么认为Actor类是作为类而不是接口创建的?

  • 回答:因为actor这个类中,不仅定义了方法,而且还对方法进行了具体的实现,所以这个actor是一个类,如果actor是以一个接口的话,那么定义的这些方法再进行实现是不允许被实现的。
  • 代码:
// @file: GridWorldCode\framework\info\gridworld\actor\Actor.java
该文件中的函数都有具体实现,因此我认为此题不需要贴上代码。

actor是否可以先将自己放入网格两次而不先将其自身移除?actor可以两次将自己从网格中移除吗?可以将actor放置到网格中,将其自身移除然后放回去吗?

  • 回答:
    (1)不可以,一个actor不可以连续添加两次 (2)不可以,一个actor只允许被删除一次(3)可以,一个actor先被加入,后被删除,随后再加入,自始至终都是这个actor实体在进行行动,同时也没有出现多次出现以及多次被删除的情况。
  • 代码:
//写一个ActRunner类对该问题进行检验
 public class ActorRunner 
    { 
        public static void main(String[] args) 
        { 
            ActorWorld world = new ActorWorld();
            Actor a = new Actor(); 
            //(1)test
            world.add(a);    
            //world.add(a);错误
            //(2) test
            a.removeSelfFromGrid(); 
            //a.removeSelfFromGrid(); 错误
            //(3) test
            world.add(a);//正确     
            world.add(new Rock()); 
            world.show(); 
        } 
    } 

actor如何向右旋转90度?

  • 回答:使用actor.setDirection(getDirection() + Location.RIGHT)方法进行实现右转90°
  • 代码:
// @file: GridWorldCode\framework\info\gridworld\actor\Actor.java
// @line: 80-86
public void setDirection(int newDirection)
//输入90就可以使actor右转九十度
    {
        direction = newDirection % Location.FULL_CIRCLE;
        if (direction < 0)
            direction += Location.FULL_CIRCLE;
    }

Extending the Actor Class

Set 6

canMove方法中的哪条语句可确保bug不会试图移出网格?

  • 回答:使用isValid()方法保证bug不出界。
// @file: GridWorldCode\framework\info\gridworld\actor\Bug.java
// @line: 98-99
if (!gr.isValid(next))
            return false;

canMove方法中的哪条语句确定bug不会进入岩石?

  • 代码:
 // @file: GridWorldCode\framework\info\gridworld\actor\Bug.java
 // @line: 101

       return (neighbor == null) || (neighbor instanceof Flower); 

return (neighbor == null) || (neighbor instanceof Flower); 

可以通过canMove方法调用Grid接口的哪些方法,为什么?

  • 回答:使用到的接口有isValid()函数和get()函数,这两个函数前者确保bug可以进行正常的移动,后者保证bug可以避开岩石或者再次走到花上面;
  • 代码:
// @file: GridWorldCode\framework\info\gridworld\actor\Bug.java
// @line: 78-79和101
if (gr.isValid(next)) 
	moveTo(next);
  // 和
 return (neighbor == null) || (neighbor instanceof Flower);

canMove方法调用Location类的哪个方法,为什么?

  • 回答:getAdjacentLocation()函数。调用这个函数作用是为了找到bug下一个可以移动的位置。
  • 代码:
// @file: GridWorldCode\framework\info\gridworld\actor\Bug.java
// @line: 97
 Location next = loc.getAdjacentLocation(getDirection()); 

在canMove方法中调用了从Actor类继承的哪些方法?

  • 回答:从Actor类中继承过来三个函数:getGrid()、getLocation()、getDirection()
  • 代码:
// @file: GridWorldCode\framework\info\gridworld\actor\Bug.java
// @line: 64、76、96

       setDirection(getDirection() + Location.HALF_RIGHT);
       Location loc = getLocation();
       Location loc = getLocation();

当bug正前方的位置不在网格中时,在move方法中会发生什么?

  • 回答:当bug前面的位置位于grid外面时候,使用move方法会让bug把自己从grid中移除
  • 代码:
// @file: GridWorldCode\framework\info\gridworld\actor\Bug.java
 // @line:78-81

       if (gr.isValid(next))
        moveTo(next);
    else
        removeSelfFromGrid();

是move方法中需要变量loc,还是可以通过多次调用getLocation()来避免变量loc?

  • 回答:move方法中需要变量loc,因为在bug移动过程中,bug的location会被多次改变,从而需要一个变量loc来标记每一次bug移动之前的位置,同时判断下一个位置是否可以进行移动;同时这个loc还可以用于放置一朵花 。
  • 代码:
// @file: GridWorldCode\framework\info\gridworld\actor\Bug.java
// @line:76-77
 Location loc = getLocation();
 Location next = loc.getAdjacentLocation(getDirection());

您为什么认为bug掉落的花朵与bug的颜色相同?

  • 回答:这个是由bug类定义的,bug移动之后会在bug移动之前那个位置放置一朵与自身颜色相同的花
  • 代码:
//@file: GridWorldCode\framework\info\gridworld\actor\Flower.java
//@fileGridWorldCode\framework\info\gridworld\actor\Bug.java
//@line:46-49(flower)和82-83(bug)
public Flower(Color initialColor)
    {
        setColor(initialColor);
    }
    Flower flower = new Flower(getColor());//设置花的颜色与bug相同
    flower.putSelfInGrid(gr, loc);//找到bug移动之前的位置放置花

当bug从网格中移出时,会否将花朵放到先前的位置?

  • 回答:不会,当bug调用从actor类中继承的removeSelfFromGrid()函数移除bug的时候,并未涉及到有产生花的方法;
  • 代码:
// @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;
    }

move方法中的哪条语句将花放到bug的先前位置的网格中?

  • 代码:
// @file:  
GridWorldCode\framework\info\gridworld\actor\Bug.java
 // @line:)82-83
  Flower flower = new Flower(getColor());//产生花并设置好花的颜色
   flower.putSelfInGrid(gr, loc);//将花放置到bug的上一个移动位置上

如果bug需要旋转180度,应该调用turn方法多少次?

  • 回答:共4次;由于turn一次就只能旋转45°,所以就需要进行4次旋转。
  • 代码:
// @file: GridWorldCode\framework\info\gridworld\actor\Actor.java
// @line:61-65
public void turn()
    {
        setDirection(getDirection() + Location.HALF_RIGHT);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值