Более эффективный способ проверки соседей в двумерном массиве в Java - PullRequest
6 голосов
/ 08 ноября 2010

Привет всем, для нескольких моих заданий в колледже я обнаружил необходимость проверять соседние ячейки в двумерных массивах (сетках). Решением, которое я использовал, является хакерское использование исключений, и я ищу способ очистить его, не загружая операторы if, как некоторые из моих одноклассников. Мое текущее решение -

for ( int row = 0; row < grid.length; row++ ) {
    for ( int col = 0; col < grid.length; col++ ) {
        // this section will usually be in a function
        // checks neighbours of the current "cell"
        try {
            for ( int rowMod = -1; rowMod <= 1; rowMod++ ) {
                for ( int colMod = -1; colMod <= 1; colMod++ ) {
                    if ( someVar == grid[row+rowMod][col+colMod] ) {
                        // do something
                    }
                }
            }
        } catch ( ArrayIndexOutOfBoundsException e ) {
            // do nothing, continue
        }
        // end checking neighbours
    }
}

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

Ответы [ 7 ]

21 голосов
/ 27 апреля 2011

Вы можете попробовать это.Сначала определитесь с размером сетки. Давайте скажем, что она 8 × 8 и присваиваем MIN_X = 0, MIN_Y = 0, MAX_X = 7, MAX_Y = 7

Ваша текущая позиция представлена ​​thisPosX, thisPosY, затем попробуйте это

int startPosX = (thisPosX - 1 < MIN_X) ? thisPosX : thisPosX-1;
int startPosY = (thisPosY - 1 < MIN_Y) ? thisPosY : thisPosY-1;
int endPosX =   (thisPosX + 1 > MAX_X) ? thisPosX : thisPosX+1;
int endPosY =   (thisPosY + 1 > MAX_Y) ? thisPosY : thisPosY+1;


// See how many are alive
for (int rowNum=startPosX; rowNum<=endPosX; rowNum++) {
    for (int colNum=startPosY; colNum<=endPosY; colNum++) {
        // All the neighbors will be grid[rowNum][colNum]
    }
}

Вы можете закончить его в 2 цикла.

6 голосов
/ 28 апреля 2011

Итак, row и col в настоящее время содержат координаты ячейки, в которой я хочу проверить соседейТак что, если у меня есть переменная класса с именем START_OF_GRID, которая содержит 0, мое решение будет следующим:

3 голосов
/ 08 ноября 2010

почему вы не можете проверить правильность строк + rowMod и col + colMod перед доступом к массиву?

что-то вроде:

 r=row+rowMod;
 c=col+colMod;
 if (r < 0 || c < 0 || r >= grid.length || c >= grid.length) continue;

в качестве альтернативы (нет продолжить ):

 if (r >= 0 && c >= 0 && r < grid.length && c < grid.length && 
     someVar == grid[r][c]) { /* do something */ }
1 голос
/ 08 ноября 2010

Если я правильно понимаю ваш код и правильно угадываю ваши опасения, вы пытаетесь не проверять несуществующего соседа, когда интересующая ячейка находится на одном краю сетки. Один из подходов, который может подходить или не подходить вашему приложению, - это поместить рамку шириной в 1 ячейку по всей вашей сетке. Затем вы проводите свои циклы по внутренней части этой расширенной сетки, и у всех проверяемых ячеек есть 4 соседа (или 8, если вы считаете соседние по диагонали ячейки).

1 голос
/ 08 ноября 2010

Основной принцип не состоит в том, чтобы получить доступ к вещам, которые находятся за пределами границ - поэтому либо защищайте границы, либо не выходите за пределы в первую очередь. То есть начните с того места, где вы сразу не выйдете за пределы и остановитесь до того, как выйдете за пределы.

for ( int row = 1; row < grid.length - 1; row++ ) {
    for ( int col = 1; col < grid.length - 1; col++ ) {
        // this section will usually be in a function
        // checks neighbours of the current "cell"
        for ( int rowMod = -1; rowMod <= 1; rowMod++ ) {
            for ( int colMod = -1; colMod <= 1; colMod++ ) {
                if ( someVar == grid[row+rowMod][col+colMod] ) {
                    // do something
                }
            }
        }
        // end checking neighbours
    }
}

Как и ваш текущий код, это не обязательно имеет дело с граничными условиями - то есть он применяет сетку 3x3 везде, где сетка 3x3 вписывается в матрицу, но не уменьшает сетку до 2x2, 2x3 или Сетка 3х2, когда на краю матрицы. Это, однако, позволит методу в основной части проверять сетку 3x3 для наблюдения каждой ячейки в матрице.

0 голосов
/ 01 августа 2017
private void fun(char[][] mat, int i, int j){
    int[] ith = { 0, 1, 1, -1, 0, -1 ,-1, 1};
    int[] jth = { 1, 0, 1, 0, -1, -1 ,1,-1};
     // All neighbours of cell
     for (int k = 0; k < 8; k++) {
            if (isValid(i + ith[k], j + jth[k], mat.length)) {
                //do something here 
            }
        }
}

private boolean isValid(int i, int j, int l) {
        if (i < 0 || j < 0 || i >= l || j >= l)
            return false;
        return true;
}
0 голосов
/ 16 мая 2015

Как насчет этого:

private static void printNeighbours(int row, int col, int[][] Data, int rowLen, int colLen)
{
    for(int nextR=row-1; nextR<=row+1; nextR++)
    {
        if(nextR<0 || nextR>=rowLen)
            continue;  //row out of bound
        for(int nextC=col-1; nextC<=col+1; nextC++)
        {
            if(nextC<0 || nextC>=colLen)
                continue;  //col out of bound
            if(nextR==row && nextC==col)
                continue;    //current cell
            System.out.println(Data[nextR][nextC]);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...