Как логика этого фрагмента может быть абстрагирована? - PullRequest
2 голосов
/ 03 марта 2012

Следующий метод используется, чтобы определить, заблокирована ли шахматная фигура для выполнения определенного хода.В тот момент, когда этот метод вызывается, само движение (т. Е. Способность епископа двигаться по диагонали) уже было проверено - этот метод затем будет смотреть на «путь», по которому должна идти фигура.

Какбольно ясно, этот метод полон избыточности.На самом деле существует 6 почти идентичных циклов for, различия в которых: 1) какие переменные контролируют итерацию, 2) увеличивается или уменьшается переменная, и 3) в случае диагонального движения включениеоператор для увеличения / уменьшения обеих переменных x и y одновременно.

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

Итак, мой вопрос таков: какие инструменты может предоставить Java для абстрагирования этой логики и уменьшения или устранения избыточности в этом методе?Я укажу, что я довольно плохо знаком с языком, поэтому, пожалуйста, не воспринимайте мое пренебрежение общими идиомами как намеренное или просто тупое;Я учусь!

Спасибо.

private static boolean notBlocked(Piece[][] board, int xfrom, int yfrom, int xto, int yto) {

    int x = xfrom;
    int xstop = xto;
    int y = yfrom;
    int ystop = yto;

    int xinc = (x < xstop) ? 1 : -1;
    int yinc = (y < ystop) ? 1 : -1;

    Piece to = board[yto][xto];
    Piece from = board[yfrom][xfrom];

    if (xfrom == xto) {
        // x is constant, check in y direction
        if (y <= ystop) {
            for (; y <= ystop; y += yinc) {
                if (board[y][x] != null && board[y][x] != to && board[y][x] != from) {
                    return false;
                }
            }
        } else {
            for (; y >= ystop; y += yinc) {
                if (board[y][x] != null && board[y][x] != to && board[y][x] != from) {
                    return false;
                }
            }
        }
    } else if (yfrom == yto) {
        // y is constant, check in x direction
        if (x <= xstop) {
            for (; x <= xstop; x += xinc) {
                if (board[y][x] != null && board[y][x] != to && board[y][x] != from) {
                    return false;
                }
            }
        } else {
            for (; x >= xstop; x += xinc) {
                if (board[y][x] != null && board[y][x] != to && board[y][x] != from) {
                    return false;
                }
            }
        }
    } else if (Math.abs(xfrom - xto) == Math.abs(yfrom - yto)){
        // the move is diagonal
        if (y <= ystop) {
            for (; y <= ystop; y += yinc) {
                if (board[y][x] != null && board[y][x] != to && board[y][x] != from) {
                    return false;
                }
                x += xinc;
            }
        } else {
            for (; y >= ystop; y += yinc) {
                if (board[y][x] != null && board[y][x] != to && board[y][x] != from) {
                    return false;
                }
                x += xinc;
            }
        }
    }
    return true;
}

РЕДАКТИРОВАТЬ:

Ого ... теперь намного лучше!

private static boolean notBlocked(Piece[][] board, int xfrom, int yfrom, int xto, int yto) {

    Piece from = board[yfrom][xfrom];
    Piece to = board[yto][xto];

    // Determine the direction (if any) of x and y movement
    int dx = (xfrom < xto) ? 1 : ((xfrom == xto) ? 0 : -1);
    int dy = (yfrom < yto) ? 1 : ((yfrom == yto) ? 0 : -1);

    // Determine the number of times we must iterate
    int steps = Math.max(Math.abs(xfrom - xto), Math.abs(yfrom - yto));

    if (xfrom == xto || yfrom == yto || Math.abs(xfrom - xto) == Math.abs(yfrom - yto)) {
        for (int i = 1; i < steps; i++) {
            int x = xfrom + i * dx;
            int y = yfrom + i * dy;
            if (isBlocked(board, from, to, x, y)) {
                return false;
            }
        }
    }
    return true;
}

1 Ответ

2 голосов
/ 03 марта 2012

Подумайте о написании этой функции в виде одного шага в правильном направлении. Предположим, что вы можете заполнить две переменные dx и dy, которые представляют, сколько вы двигаетесь в направлениях x и y на каждом шаге. Вы можете вычислить это, посмотрев на разницу между начальной и конечной точками x и y. Получив это, вы можете написать отдельный цикл for, который пытается двигаться в этом направлении, проверяя каждый шаг. Например:

for (int i = 1; i < numStepsRequired; i++) {
    int currX = x + i * dx;
    int currY = y + i * dy;
    if (board[currY][currX] != null) {
        return false;
    }
}

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

Надеюсь, это поможет!

...