Сбой функции поиска в 2D-массивах (Java) - PullRequest
1 голос
/ 26 ноября 2011

Я создаю игру реверси для моего вступительного класса CS.

Я обнаружил ошибку в 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;
  }

** все плитки имеют черный, белый или цвет плитки по умолчанию (зеленый) и в двумерном массиве кнопок J, отображаемых в gridLayout ().

Ответы [ 2 ]

3 голосов
/ 26 ноября 2011

Поскольку @ goto10 уже дал направление, в котором вам нужно искать, вот некоторые другие заметки:

  • Вам нужно научиться лучше разделять проблемы.В частности, вы смешиваете свой код дисплея с кодом правил игры.При правильном дизайне почти все программы должны запускаться из командной строки - графический интерфейс исключительно , чтобы помочь конечному пользователю.

  • Когда у вас есть два(или более) связанных параметров, у вас действительно есть один - составной класс, содержащий их.Например, параметры x и y для поиска в вашем массиве действительно представляют один экземпляр CoordinatePair, Location или Point.Хотя вероятность здесь небольшая, это поможет избежать проблем в будущем - что произойдет, если кто-нибудь случайно поменяет параметры y и increment в searchN(), например?Запишите неизменный класс Point и используйте его - это полностью устранит эту проблему:

    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), но в остальном не является «частью» метода.Побочные эффекты чрезвычайно затрудняют «рассуждение» (выяснение того, что происходит) о состоянии объекта, и делают хорошее тестирование фактическим кошмаром .Написание методов, которые зависят исключительно от (мы надеемся, неизменного) состояния передаваемых объектов и неизменного состояния объекта 'host' (this), может быть несколько сложнее, но намного прощерассуждать о;о системах, которые почти все (или, возможно, полностью) неизменяемы, гораздо проще думать, и вы получаете потоковое / параллельное выполнение бесплатно.

  • Ваши методы .isSame() и .isOpposite() немного взломаны вместе, потому что единственное различие между игровым / неиграемым квадратом - это его цвет.Соответствующий код на стороне правила не должен знать о коде на стороне дисплея - не существует такого понятия, как кусок с зеленой стороной (технически здесь нет ни белого, ни черного элемента - есть кусок для игрока 1 и кусок дляигрок 2. Даже в физическом мире это эффект , отображающий только , и правила, которые гласят: «белые получают 4,5 дополнительных очка», действительно означают, что «игрок, занявший второе место, получает 4,5 дополнительных очка»).Кроме того, эти два метода не возвращают обратные результаты для не сыгранных квадратов (.isSame() возвращает false), что не логично.

  • Всякий раз, когда у вас есть длинный список похожихэлементы (наборы переменных leadX и playableX), попробуйте переформатировать их в фактический список.Это также очень поможет, если вы хотите сделать 3D-версию ... Кроме того, есть способ использовать так называемый шаблон стратегии (вместе с хэш-картой или списком массивов) для перемещения / поискав разные стороны гораздо проще.

3 голосов
/ 26 ноября 2011

Я вижу два способа, которыми NullPointerException может произойти:

Вы получаете ArrayIndexOutOfBoundsException в getColor.В этом случае вы перехватываете исключение и возвращаете null.

или

getBackground возвращает null.

В любом случае getColor вернетnull, который вызывает NullPointerException, когда вы вызываете .equals в isOpposite или isSame.

. Вы должны проверить результат getColor, прежде чем пытаться вызвать .equals на нем.,Затем вы должны выяснить, почему getBackground возвращается null или ArrayIndexOutOfBoundsException выбрасывается.

...