2016-02-13 144 views
-1

我有一个类称为单元并在它我有一个运行这段代码的更新方法:如果语句忽略返回方法,其他解决方案?

if(goalReached){ 
    if(returnNearestCell() > -1 && isTarget && this.checkCollide(cells.get(returnNearestCell()).x, cells.get(returnNearestCell()).y, cells.get(returnNearestCell()).mass)){ 
    addMass(cells.get(returnNearestCell()).mass); 
    cells.get(returnNearestCell()).mass = 20; 
    cells.get(returnNearestCell()).x = (int) Math.floor(Math.random() * 1001); 
    cells.get(returnNearestCell()).y = (int) Math.floor(Math.random() * 701); 
    isTarget = false; 
    } 
    if(returnNearestCell() > -1 && !isTarget){ 
    goalX = cells.get(returnNearestCell()).x; 
    goalY = cells.get(returnNearestCell()).y; 
    target = cells.indexOf(returnNearestCell()); 
    isTarget = true; 

    }else if(returnNearestCell() == -1){ 
    goalX = (int) Math.floor(Math.random() * 1001); 
    goalY = (int) Math.floor(Math.random() * 701); 
    isTarget = false; 
    } 
    if(!isTarget){ 
    addMass(5); 
    } 
    goalReached = false; 
} 

基本上概括起来讲,每个小区查找与一更小的质量,并且如果最近的细胞细胞,然后将goalX和goalY设置为该细胞的位置。如果没有发现具有相同标准的这样的单元格,则只需转到随机位置。代码工作正常,直到由于某种原因,第一个if语句被忽略:

returnNearestCell() > -1 

然后我得到一个ArrayIndexOutOfBoundsException。

我returnNearestCell方法进行如下:

public int returnNearestCell(){ 

int x = 0; 
int distance = 9999999; 
int min = distance; 

for(Cell cell : cells){ 
    if(this != cell){ 
    distance = (int)Math.sqrt((this.x - cell.x)*(this.x - cell.x) + (cell.y - this.y)*(cell.y - this.y)); 
    if(distance < min && this.mass > cell.mass + 10){ 
     min = distance; 
     x = cells.indexOf(cell); 
    }else if(distance < min && this.mass < cell.mass + 10 && cell.cellCount == cells.size()){ 
     x = -1; 
    } 
    } 
} 

return x; 
} 

此方法返回小区的索引与标准或-1。我的问题是:有什么办法可以避免这种OutofBoundsException?我已经尝试了多种方法,例如重复检查,但我仍然遇到同样的问题。

+0

我建议你做适当的诊断工作,这样你就可以缩小成一个[mcve]。考虑到你不明白的行为(假设“忽略”if语句),我会试着首先解决这个问题。 –

+2

我也建议在你的方法中调用'returnNearestCell' *一次*,并在整个方法中使用该结果。你为什么要多次打电话?我可能实际上会让它返回'Cell'(或者如果没有找到,则返回null),而不是索引,它会使你的代码变得更简单,我怀疑... –

+1

它可以帮助知道它在什么位置抛出异常 –

回答

1
cells.get(returnNearestCell()).mass = 20; 
cells.get(returnNearestCell()).x = (int) Math.floor(Math.random() * 1001); 
cells.get(returnNearestCell()).y = (int) Math.floor(Math.random() * 701); 

在这里,您正在突变单元格,然后再次调用returnNearestCell()。由于该方法现在使用更改的参数运行,所以返回值可能不同。最重要的是,您沿着坐标系移动单元格,然后在通过下一个returnNearestCell()调用进行评估时位于不同的位置。

您可能想查看非原子更新并发修改了解更多关于此主题的信息。

是否有任何方法将对象存储到变量中并通过该变量访问它?

是和它的解决问题的方法:

if (goalReached) { 
    // retrieve nearest cell once before modification 
    final int nearestCellIndex = returnNearestCell(); 
    if (nearestCellIndex > -1 && isTarget) { 
     // save cell. 
     final Cell nearestCell = cells.get(nearestCellIndex); 

     if (this.checkCollide(nearestCell.x, nearestCell.y, nearestCell.mass)) { 

      // remainder of your code 
     } 
    } 
} 

注意,它可能是最好有returnNearestCell()回报Optional<Cell>或至少Cell直接对象。 checkCollide()也是一样,只需要一个Cell对象作为参数。

+0

如果没有找到单元格(如果我直接返回单元格),我的方法会返回什么? – BruceTheGoose

+1

@BruceTheGoose如果返回类型是'Cell',你唯一的理智选择是返回'null'。如果使用Java 8,您可能需要考虑使用['Optional'](https://docs.oracle。com/javase/8/docs/api/java/util/Optional.html)并返回'Optional.empty()'。 – dhke