2014-08-29 3 views
1

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

int count = 0; 
       if(model.get(i-1, j-1) == MinerGridCo.UNTURNED_MINE){ count++;} 
       if(model.get(i, j-1) == MinerGridCo.UNTURNED_MINE){ count++;} 
       if(model.get(i-1, j) == MinerGridCo.UNTURNED_MINE){ count++;} 
       if(model.get(i+1, j) == MinerGridCo.UNTURNED_MINE){ count++;} 
       if(model.get(i, j+1) == MinerGridCo.UNTURNED_MINE){ count++;} 
       if(model.get(i-1, j+1) == MinerGridCo.UNTURNED_MINE){ count++;} 
       if(model.get(i+1, j-1) == MinerGridCo.UNTURNED_MINE){ count++;} 
       if(model.get(i+1, j+1) == MinerGridCo.UNTURNED_MINE){ count++;} 
       String mineNum = String.valueOf(count); 
       cell[i][j].setText(mineNum); 

однако, это приводит к ошибкам, когда стремятся получить номер шахты по краям доски. Какие-нибудь полезные методы, чтобы избежать этого?

После попытки предложения ниже. Я все еще получаю ошибки за пределами границ. Кто-нибудь есть какие-либо советы, вот репо, если кто-то хочет, чтобы собрать его сами https://github.com/phillolivercomp/MineSweeper.git

+0

Какой тип данных «модель»? – Zyerah

+7

Игнорирование исключений - это всегда плохая идея. Вместо этого напишите свой код, чтобы обрабатывать граничные (в данном случае) условия. Например, напишите метод с подписями «Список getNeighbors (Cell cell)», который, учитывая ячейку, возвращает список действительных соседей для проверки. Затем исследуйте только тех соседей. –

+0

Ну, модель является образцовым элементом графического интерфейса, и это всего лишь экземпляр класса «MinerGridCo», в котором есть эти элементы UNTURNED_MINE, которые являются целыми числами, которые специально объявлены. –

ответ

1

Используйте короткие закодировать и написать функцию isInGrid(int x, int y), которая проверяет, находится ли позиция в сетке.

public boolean isInGrid(int x, int y) { 
    //Check if a position is valid in the grid 
    if(i < 0 || j < 0) return false; 
    if(i >= WIDTH || j >= HEIGHT) return false; 
    return true; 
} 

... 

if(isInGrid(i-1, j-1) && model.get(i-1, j-1) == MinerGridCo.UNTURNED_MINE) count++; 
if(isInGrid(i+1, j+1) && model.get(i+1, j+1) == MinerGridCo.UNTURNED_MINE) count++; 
//Repeat for each location you want to check 

Если первое условие, isInGrid(i-1, j-1) это не так, то условие будет выходить без запуска [condition] заявления. Таким образом, вы предотвращаете выполнение [condition], если он в противном случае завершится с ошибкой.

Это называется «короткое замыкание» - это оптимизация, которая приводит к завершению проверки условий для выхода, если уже известно, что код не будет запущен. Вы можете поместить одну из этих isInGrid проверок перед каждым оператором, который хотите оценить, и если местоположение не находится в сетке, оно не будет выполнено get.

+0

Только проблема состоит в том, что некоторые из утверждений if, которые я включил, должны быть вызваны. Если объект, который я ищу проверить, находится в левом верхнем углу, он должен проверить объект справа и внизу и по диагонали внизу и справа если этот объект находится в правом нижнем углу. –

+0

@Phill Вы можете создать как многие из этих заявлений, как вам хотелось бы. Поместите условие 'isInGrid()' перед каждым оператором, а 'get' не будет выполняться, если местоположение не находится в сетке. – Zyerah

+0

Извините, я понимаю, что вы имеете в виду. Хорошая идея. Будет реализовывать это. Так же, как сторона примечания, ваш код в приведенном выше примере имеет имена переменных, отличающиеся от тех, которые вы передаете ему, и те, которые вы используете. –

0

Создать функцию в одну строку:

boolean checkBounds(int i, int j) { //TODO }

Затем убедитесь, что прежде чем делать модели поиск

+0

Я думал об этом, но единственная проблема заключается в том, что я должен делать контрольные оценки для каждого отдельного случая. Например, нижний правый регистр должен находиться внутри 2D-массива и должен быть меньше максимального высота и ширина для того, чтобы счет был действительным, а верхний левый должен быть больше 0 –

+0

. Я не уверен, в чем проблема: проверка границ не ограничивается только закрытием всего лишь одного углового футляра. – coffeeaddict

+0

@PhillOliver да, вам нужно для проверки каждого случая – ControlAltDel

2

Сделай себе одолжение и создай model.countUnturnedMinesAround(i,j). Тогда внутри модели у вас есть несколько вариантов.

Вы можете создавать дополнительные строки/столбцы, которые не видны, чтобы вы могли обрабатывать индексы «один за другим».

Или вы можете написать функцию private Cell getCell(i,j), которая вернет пустую ячейку по умолчанию, когда i и j не связаны.

Или вы можете иметь boolean hasUnturnedMine(i,j), который возвращает false, когда i или j находятся вне сетки.

2

Вы можете избежать дублирования с петлями:

for (int iOffset = -1; iOffset <= 1; iOffset++) { 
    for (int jOffset = -1; jOffset <= 1; jOffset++) { 
     if (iOffset != 0 || jOffset != 0) { 
      if (isInGrid(i + iOffset, j + jOffset) && 
       model.get(i + iOffset, j + jOffset) == MinerGridCo.UNTURNED_MINE) { 
        count++; 
      } 
     } 
    } 
} 

с помощью функции isInGrid предложенный @ ответ Эмракул в (я бы на самом деле совместить проверку диапазона и UNTURNED_MINE проверку в одной hasUnturnedMine функции, как упомянуто в @ Arkadiy-х ответ).

+0

Я реализовал это, и значение, кажется, достигает ошибки за пределами, когда она добирается до 12 по какой-то причине, которая меня действительно сбивает с толку. 12 - максимальная высота и ширина, которые я указал для платы. –

+0

Я добавил свое github-репо к заголовку, так как не могу понять, почему код все еще бросает эти исключения. –

+0

@PhillOliver Я заметил, что ответ @ Emrakul говорит 'if (i> WIDTH || j> HEIGHT)' .. вероятно, должно быть 'if (i> = WIDTH || j> = HEIGHT)'. Постскриптум еще не посмотрели на ваше репо. – ajb

0

Альтернативным подходом может быть метод isBorder (int i, int j), который позволяет узнать, находитесь ли вы на границах. Если это не граница, вы знаете, что можете безопасно проверять все квадраты вокруг (i, j). Если он находится на границе, вы можете рассчитать, будет ли это левая/правая/верхняя/нижняя граница или некоторая комбинация из 4 (не более 2), а затем установите соответствующие флажки.

отказ: я предполагаю, что вы уже делаете чек, чтобы убедиться, что (i, j) является допустимым местоположением на сетке.Вы должны делать проверку на это независимо от вашей реализации.

0

Есть более эффективные способы сделать это, структурируя код немного лучше. Однако вот ответ на ваш конкретный вопрос:

То, как вы игнорируете исключение в Java, имеет блок try-catch. Это позволяет вам попытаться запустить блок кода, уловить любые исключения, которые будут выбрасываться, а затем решить, что делать с ними (в том числе игнорировать их).

Предполагая, что ваш из исключения ограничивающих исходят из model.get() вызовов, которые вы могли бы игнорировать их, как это:

int count = 0; 
try 
{ 
    if(model.get(i-1, j-1) == MinerGridCo.UNTURNED_MINE){ count++;} 
    if(model.get(i, j-1) == MinerGridCo.UNTURNED_MINE){ count++;} 
    if(model.get(i-1, j) == MinerGridCo.UNTURNED_MINE){ count++;} 
    if(model.get(i+1, j) == MinerGridCo.UNTURNED_MINE){ count++;} 
    if(model.get(i, j+1) == MinerGridCo.UNTURNED_MINE){ count++;} 
    if(model.get(i-1, j+1) == MinerGridCo.UNTURNED_MINE){ count++;} 
    if(model.get(i+1, j-1) == MinerGridCo.UNTURNED_MINE){ count++;} 
    if(model.get(i+1, j+1) == MinerGridCo.UNTURNED_MINE){ count++;} 
} 
catch (IndexOutOfBoundsException ex) 
{ 
    // Do nothing 
} 
String mineNum = String.valueOf(count); 
cell[i][j].setText(mineNum); 

Однако, когда исключение встречается весь последующий код в блоке Ьги будет пропустить. И это определенно не то, что вы хотите, потому что вы пропустите проверку некоторых примыканий. Вместо этого вам нужно будет выполнить try-catch для каждого вызова модели.get(). Это лучше всего реализуется путем создания булевой функции, как:

// Change method visibility and signature accordingly to match your code 
public static boolean tileHasMine(int x, int y) 
{ 
    try 
    { 
     if (model.get(x, y) == MinerGridCo.UNTURNED_MINE) 
     { 
      return true; 
     } 
    } 
    catch (IndexOutOfBoundsException ex) 
    { 
     // Do Nothing 
    } 
    return false; 
} 

Тогда ваши чеки будут выглядеть следующим образом:

int count = 0; 
if(tileHasMine(i-1, j-1)){ count++;} 
if(tileHasMine(i, j-1)){ count++;} 
if(tileHasMine(i-1, j)){ count++;} 
if(tileHasMine(i+1, j)){ count++;} 
if(tileHasMine(i, j+1)){ count++;} 
if(tileHasMine(i-1, j+1)){ count++;} 
if(tileHasMine(i+1, j-1)){ count++;} 
if(tileHasMine(i+1, j+1)){ count++;} 
String mineNum = String.valueOf(count); 
cell[i][j].setText(mineNum); 

В качестве альтернативы, вы можете написать булеву функцию, которая сначала проверяет, если блок находится вне ограничивает модель до того, как даже пытается ее прочитать, что может быть лучшим подходом. Но я думаю, что это то, о чем вы спрашивали.

Смежные вопросы