二维数组中的搜索函数崩溃(Java)

二维数组中的搜索函数崩溃(Java),java,arrays,multidimensional-array,jbutton,Java,Arrays,Multidimensional Array,Jbutton,我正在为我的入门CS课程制作一个reversi游戏 我在SearchN()中发现了一个错误,该错误会导致它给出错误的playableN标志,并创建了isSame()作为解决方法 现在,当我尝试移动时,游戏正在崩溃 我已将错误隔离到isPlayable(),这会导致程序停止运行,而不会显示错误消息 我认为这是因为程序在搜索范围之外;但是,当我运行.isPlayable(0,0)时,它会返回一个NullPointerException(我也不太知道如何摆脱它) 因此,在处理未播放的空间时一定会出现一

我正在为我的入门CS课程制作一个reversi游戏

我在SearchN()中发现了一个错误,该错误会导致它给出错误的playableN标志,并创建了isSame()作为解决方法

现在,当我尝试移动时,游戏正在崩溃

我已将错误隔离到isPlayable(),这会导致程序停止运行,而不会显示错误消息

我认为这是因为程序在搜索范围之外;但是,当我运行.isPlayable(0,0)时,它会返回一个NullPointerException(我也不太知道如何摆脱它)

因此,在处理未播放的空间时一定会出现一些错误

有人有什么想法吗

/**
 * a method to return the color of a tile
 *@params    x    y    tile coordinates 
 */
public Color getColor(int x, int y){
  try{
    return buttons[x][y].getBackground();
  }
  catch(ArrayIndexOutOfBoundsException e){
    return null;
  }
}

/**
 * a method to determine whether a tile has been played
 *@params    x    y    tile coordinates 
 */
public boolean isPlayed(int x, int y){
  if(this.isBlack(x,y) || this.isWhite(x,y)){
    return true;
  }else{ 
    return false;
  }
}


/**
 * a method to determine whether a tile has a color opposite to a given color
 *@params    x    y    c    tile coordinates and color to compare
 */
  public boolean isOpposite(int x, int y, Color c){
    if(this.isPlayed(x,y)){
      return(!(this.getColor(x,y).equals(c)));
    } else
      return false;                                    // this was giving the false playableN flag
  }

/**
 * a method to determine weather a tile has the same color as the one given
 *@params    x    y    c    tile coordinates and color to compare
 */
  public boolean isSame(int x, int y, Color c){
    if(this.isPlayed(x,y)){
      return(this.getColor(x,y).equals(c));
    }else{
      return false;
    }
  }

/**
 * a method used to check tiles north of an attempted play to verify legal moves
 *@params    x    y    c    tile coordinates and comparing color
 */
  public void searchN(int x, int y, int increment, Color c){
    if(increment>1 && (this.isSame(x-increment,y, c))){
      playableN = true;
      leadN = false;
    } else {
      if(this.isOpposite(x-increment,y,c)){
        leadN=true;
      }
    }
  }

/**
 * a method used to determine if a tile is playable
 *@params    x    y    tile coordinates
 */
  public boolean isPlayable(int x, int y){
    this.searchN(x,y,1,turnColor);
    // search 7 other directions
    while(leadN||leadNE||leadE||leadSE||leadS||leadSW||leadW||leadNW){ 
      int i = 2;
      if(leadN)
        this.searchN(x,y,i,turnColor);
        // search 7 other directions
      i++;
    }
    if(playableN||playableNE||playableE||playableSE||playableS||playableSW||playableW||playableNW)
      return true;
    else
      return false;
  }

**所有磁贴都是黑色、白色或默认的磁贴颜色(绿色),并且在gridLayout()中显示的JButton的2D数组中。

我发现有两种方式会发生
NullPointerException

您在
getColor
中获得了一个
ArrayIndexOutOfBoundsException
。在这种情况下,您将捕获异常并返回
null

getBackground
正在返回
null

在这两种情况下,
getColor
都将返回
null
,这将导致在调用
时抛出
null点异常


在尝试调用getColor上的
.equals
之前,应该检查getColor的结果。然后你应该弄清楚为什么
getBackground
返回
null
或者
ArrayIndexOutOfBoundsException
被抛出。

我发现有两种方式可以发生
NullPointerException

您在
getColor
中获得了一个
ArrayIndexOutOfBoundsException
。在这种情况下,您将捕获异常并返回
null

getBackground
正在返回
null

在这两种情况下,
getColor
都将返回
null
,这将导致在调用
时抛出
null点异常


在尝试调用getColor上的
.equals
之前,应该检查getColor的结果。然后你应该弄清楚为什么
getBackground
返回
null
或者
ArrayIndexOutOfBoundsException
被抛出。

因为@goto10已经给出了你需要查看的方向,下面是一些其他注意事项:

  • 您需要更好地分离关注点。具体来说,您将显示代码与游戏规则代码混合在一起。如果设计得当,几乎所有的程序都应该可以从命令行运行——GUI只是用来帮助最终用户的

  • 当您有两个(或更多)相关参数时,实际上只有一个参数—一个包含它们的复合类。例如,用于搜索数组的
    x
    y
    参数实际上表示一个
    坐标点
    位置
    实例。尽管这种可能性很小,但这将有助于避免将来出现问题——例如,如果有人意外地交换了
    searchN()
    中的
    y
    increment
    参数,会发生什么情况?编写一个不可变的类并使用它-它将完全消除该问题:

    public final class Point {
       // Yes, public variables are almost universally frowned upon, with good reason.
       // Here, though, it's kind of the 'point'
       public final int x;
       public final int y; 
    
       // Note: private constructor - can't call this from outside.
       private Point(final int x, final int y) {
          this.x = x;
          this.y = y;
       }
    
       // Static factory method for construction instead.
       // It is left as an exercise for the reader to implement caching.
       public static Point fromCoordinates(final int x, final int y) {
          return new Point(x, y);
       }
    }
    
    您需要实现一个好的
    .hashCode()
    .equals()
    方法来实现这一点,但是Eclipse(或任何其他好工具)给出的应该是好的。使用不可变对象有一些性能方面的考虑,但对于您的需要,这不是问题

  • 努力使方法产生尽可能少的副作用;也就是说,尽量使它们修改尽可能少的外部状态(最好是NO)。这包括作为对象一部分的状态(例如
    leadN
    ),但不是方法的“一部分”。副作用使我们很难对一个对象的状态进行“推理”(弄清楚发生了什么),并使测试成为一场真正的噩梦。编写完全依赖于传入对象的(希望是不可变的)状态以及“主机”(
    )对象的不可变状态的方法可能有点困难,但更容易推理;几乎所有(或者可能完全)不可变的系统更容易思考,并且您可以免费获得线程安全/并行执行

  • 您的方法
    .isSame()
    .isoposite()
    有点混乱,因为播放/未播放的方块之间的唯一区别是颜色。相关的规则端代码应该不知道显示端代码-没有绿色边的代码(从技术上讲,也没有白色或黑色的棋子——有一个棋子是给玩家1的,一个棋子是给玩家2的。即使在现实世界中,这也是一种只显示的效果,而“白色获得4.5额外分数”的规则实际上意味着“第二名的玩家获得4.5额外分数”)。此外,这两种方法不会为未播放的方块返回相反的结果(
    .isSame()
    返回false),这是不符合逻辑的

  • 每当你有一个类似元素的长列表(leadX
和playableX
变量集)时,尝试将它们重新格式化为一个实际的列表。如果你想制作一个3D版本,这也会非常有帮助……此外,还有一种方法可以使用已知的(以及哈希映射或数组列表)使在不同方向移动/搜索更加容易


因为@goto10已经给出了您需要查看的方向,下面是一些其他注意事项:

  • 你需要学习如何更好地分离关注点。特别是,你将显示代码与游戏规则代码混合在一起。通过正确的设计,几乎所有的程序