Шахматы: дублированный код в валидации движения - Java - PullRequest
0 голосов
/ 02 января 2019

В настоящее время я изучаю Java и работаю над назначением класса.Мы должны сделать «странную версию» шахмат.Как и в оригинальных шахматах, фигуры не могут двигаться, если на их пути есть фигура, очевидным исключением является лошадь, которая может прыгать на все фигуры , кроме королей .

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

    public boolean freeWayHorizontally(int xO, int yO, int xD) {
    //RIGHT
    if (xO < xD) {
        for (int x = xO + 1; x < xD; x++) {
            CrazyPiece thereIsPiece = Simulador.checkIfTheresPiece(x, yO);
            if (thereIsPiece != null){
                return false;
            }
        }
    //LEFT
    } else if (xO > xD) {
        for (int x = xO - 1; x > xD; x--) {
            CrazyPiece thereIsPiece = Simulador.checkIfTheresPiece(x, yO);
            if (thereIsPiece != null){
                return false;
            }
        }
    }
    return true;
}

public boolean freeWayVertically(int xO, int yO, int yD) {
    //UP
    if (yO < yD) {
        for (int y = yO + 1; y < yD; y++) {
            CrazyPiece thereIsPiece = Simulador.checkIfTheresPiece(xO, y);
            if (thereIsPiece != null){
                return false;
            }
        }
    //DOWN
    } else if (yO > yD) {
        for (int y = yO - 1; y > yD; y--) {
            CrazyPiece thereIsPiece = Simulador.checkIfThereIsPiece(xO, y);
            if (thereIsPiece != null){
                return false;
            }
        }
    }
    return true;
}

thereIsPiece(int x, int y) - это функция из класса Chess Simulator, которая, учитывая позицию на доске,возвращает кусок в этой позиции.

Очевидно, что эти два получают одинаковые параметры (исходные координаты и координату назначения, где одна из координат назначения является одной из исходных координат фигуры), поэтому единственноечто действительно меняется, так называется thereIsPiece(). РЕДАКТИРОВАТЬ: И из-за этого они помечены как дубликаты, и, как мне сказали, это очень плохо!

Тем не менее, я не могу понять,способ решить эту проблему, используя только один из этих методов; ТАКЖЕ РЕДАКТИРОВАТЬ: Я пытался перегрузить его, но тогда он работал бы только вертикально или горизонтально (возможно, сделал это неправильно).

Дело в том, что мне нужно сделать это отдельно для реализации движения Лошади, которое переопределяет эти методы:

public boolean freeWayHorizontally(int xO, int yO, int xD) { //Overriden by the Horse class
    //RIGHT
    if (xO < xD) {
        for (int x = xO + 1; x <= xD; x++) {
            CrazyPiece thereIsPiece = Simulador.checkIfTheresPiece(x, yO);
            if (thereIsPiece != null && thereIsPiece.isKing){
                return false;
            }
        }
    //LEFT
    } else if (xO > xD) {
        for (int x = xO - 1; x >= xD; x--) {
            CrazyPiece thereIsPiece = Simulador.checkIfTheresPiece(x, yO);
            if (thereIsPiece != null && thereIsPiece.isKing){
                return false;
            }
        }
    }
    return true;
}

public boolean freeWayVertically(int xO, int yO, int yD) { //Overriden by the Horse class
    //UP
    if (yO < yD) {
        for (int y = yO + 1; y <= yD; y++) {
            CrazyPiece thereIsPiece = Simulador.checkIfTheresPiece(xO, y);
            if (thereIsPiece != null && thereIsPiece.isKing){
                return false;
            }
        }
    //DOWN
    } else if (yO > yD) {
        for (int y = yO - 1; y >= yD; y--) {
            CrazyPiece thereIsPiece = Simulador.checkIfThereIsPiece(xO, y);
            if (thereIsPiece != null && thereIsPiece.isKing){
                return false;
            }
        }
    }
    return true;
}

И затем вызывает свой собственный тип проверки движения, также определенный вPiece класс:

public boolean freeWayL(int xO, int yO, int xD, int yD) {
    boolean fH, fV;
    //Horizontal -> Vertical
    fH = this.freeWayHorizontally(xO, yO, xD);
    if (fH) {
        fV = this.freeWayVertically(xD, yO, yD);
        if (fV) {
            return true;
        }
    }
    //Vertical -> Horizontal
    fV = this.freeWayVertically(xO, yO, yD);
    if (dV) {
        fH = this.freeWayHorizontally(xO, yD, xD);
        if (fH) {
            return true;
        }
    }
    return false;
}

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

1 Ответ

0 голосов
/ 02 января 2019

Первая проблема с вашим кодом состоит в том, что у вас есть другой метод в классе Simulador для проверки позиций:

// When is checking horizontally
CrazyPiece thereIsPiece = Simulador.pegaPecaPorCoordenada(x, yO);

// When is checking vertically
CrazyPiece thereIsPiece = Simulador.checkIfThereIsPiece(xO, y);

Я не вижу причины, по которой это не должен быть один метод.

Здесь я вижу 2 различных улучшения:

  1. переписать начало и конец изменения цикла таким образом, чтобы был только один цикл.

КакНапример:

public boolean freeWayHorizontally(int xO, int yO, int xD) {
    int destination = xD;
    int origin = xO + 1;
    if (xO > xD) {
        destination = xO - 1;
        origin = xD;
    }

    for (int x = origin; x < destination; x++) {
        CrazyPiece thereIsPiece = Simulador.pegaPecaPorCoordenada(x, yO);
        if (thereIsPiece != null){
            return false;
        }
    }

    return true;
}

Если у вас есть источник, находящийся перед пунктом назначения, вы перемещаетесь от пункта отправления к пункту назначения вперед.

Когда пункт назначения находится перед источником, вы просто меняете местами и перемещаетеот пункта назначения до пункта отправления.

вторая точка - это условие проверки.

Я думаю, вам нужно просто добавить метод:

private boolean checkPositionIsFree(int x, int y) {
    return Simulador.pegaPecaPorCoordenada(x, y) != null;
}

Теперь вам нужно иметь один для горизонтали и один дляпо вертикали, пока вы не можете объединить 2 метода.

А затем вы можете переписать свой метод следующим образом:

public boolean freeWayHorizontally(int xO, int yO, int xD) {
    int destination = xD;
    int origin = xO + 1;
    if (xO > xD) {
        destination = xO - 1;
        origin = xD;
    }

    for (int x = origin; x < destination; x++) {
        if (checkPositionIsFree(x, yO)){
            return false;
        }
    }

    return true;
}

Для Лошади вы просто @Override checkPositionIsFree() метод с надлежащим условием (добавление проверки на короля), и все должно работать.

Обновление

Чтобы полностью покрыть случай лошади, у вас может быть методкоторые работают с входными данными:

@Override
public boolean freeWayHorizontally(int xO, int yO, int xD) {
    return super.freeWayHorizontally(xO, yO, xD + 1);
}

Таким образом, вы можете избежать переписать весь код.

Кстати, ваш код здесь имеет некоторые опечатки, может бытьВы переписываете это.Лучше проверять подобные вещи и иметь рабочий код (в вашем случае) или точный код не работает, чтобы избежать потери времени добровольцев из-за неправильной ошибки.

...