Как мне отфильтровать заблокированные шахматные ходы? - PullRequest
0 голосов
/ 17 июня 2020

Как описано в заголовке, я хотел бы знать, как мне отфильтровать недопустимые ходы для шахматной фигуры.

Доска представлена ​​с Map<Position, BaseChessman> Где Position - это Enum с положением шахматной доски (A1 - H8), а BaseChessman - это абстрактный класс, к которому относятся конкретные классы, такие как Rook, Bishop, King et c. наследовать от.

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

На данный момент я пытаюсь собрать все правильные ходы для шахматной фигуры «Ладья». Допустим, ладья на «А1» каким-то образом теперь стоит там, где находится синий круг, я могу отфильтровать все недопустимые ходы, кроме черного ферзя на «D8». Мой вопрос в том, как отфильтровать ходы, которые блокируются другой шахматной фигурой, как в этом случае, когда «D7» блокирует «D8». Могу ли я добавить в перечисление поле сом, из которого я могу отфильтровать ходы, заблокированные другой фигурой? (См. Изображение ниже для пояснения)

PS: Я знаю, что моя реализация ошибочна, так как я в настоящий момент не проверяю, заблокирована ли фигура, которую я сейчас хочу переместить. enter image description here

Плата, представленная перечислением (хэш-карта создается из этого перечисления. Ключ: Позиция, Значение: BaseChessman)

(Что такое Ghost? Это предназначен как «фиктивный» класс, который действует как «None» вместо использования null)

public enum Position {

    A8(new Rook(BLACK)), B8(new Knight(BLACK)), C8(new Bishop(BLACK)), D8(new King(BLACK)), E8(new Queen(BLACK)), F8(new Bishop(BLACK)), G8(new Knight(BLACK)), H8(new Rook(BLACK)),
    A7(new Pawn(BLACK)), B7(new Pawn(BLACK)), C7(new Pawn(BLACK)), D7(new Pawn(BLACK)), E7(new Pawn(BLACK)), F7(new Pawn(BLACK)), G7(new Pawn(BLACK)), H7(new Pawn(BLACK)),
    A6(new Ghost(TRANSPARENT)), B6(new Ghost(TRANSPARENT)), C6(new Ghost(TRANSPARENT)), D6(new Ghost(TRANSPARENT)), E6(new Ghost(TRANSPARENT)), F6(new Ghost(TRANSPARENT)), G6(new Ghost(TRANSPARENT)), H6(new Ghost(TRANSPARENT)),
    A5(new Ghost(TRANSPARENT)), B5(new Ghost(TRANSPARENT)), C5(new Ghost(TRANSPARENT)), D5(new Ghost(TRANSPARENT)), E5(new Ghost(TRANSPARENT)), F5(new Ghost(TRANSPARENT)), G5(new Ghost(TRANSPARENT)), H5(new Ghost(TRANSPARENT)),
    A4(new Ghost(TRANSPARENT)), B4(new Ghost(TRANSPARENT)), C4(new Ghost(TRANSPARENT)), D4(new Ghost(TRANSPARENT)), E4(new Ghost(TRANSPARENT)), F4(new Ghost(TRANSPARENT)), G4(new Ghost(TRANSPARENT)), H4(new Ghost(TRANSPARENT)),
    A3(new Ghost(TRANSPARENT)), B3(new Ghost(TRANSPARENT)), C3(new Ghost(TRANSPARENT)), D3(new Ghost(TRANSPARENT)), E3(new Ghost(TRANSPARENT)), F3(new Ghost(TRANSPARENT)), G3(new Ghost(TRANSPARENT)), H3(new Ghost(TRANSPARENT)),
    A2(new Pawn(WHITE)), B2(new Pawn(WHITE)), C2(new Pawn(WHITE)), D2(new Pawn(WHITE)), E2(new Pawn(WHITE)), F2(new Pawn(WHITE)), G2(new Pawn(WHITE)), H2(new Pawn(WHITE)),
    A1(new Rook(WHITE)), B1(new Knight(WHITE)), C1(new Bishop(WHITE)), D1(new King(WHITE)), E1(new Queen(WHITE)), F1(new Bishop(WHITE)), G1(new Knight(WHITE)), H1(new Rook(WHITE));  

    private BaseChessman chessman;

    private Position(BaseChessman chessman) {
        this.chessman = chessman;
    }

    public BaseChessman getChessman(){
        return this.chessman;
    }
}

Моя функция, которая должна возвращать список возможных ходов для этой позиции. (nextPosition в настоящее время не используется)

private List<Position> getPossibleRookMoves(Color playerColor, Map<Position, BaseChessman> mapOfChessboard, Position currentPosition, Position nextPosition){
        String position = currentPosition.toString();
        String pos1 = position.substring(0, 1);
        String pos2 = position.substring(1, 2);

        return mapOfChessboard.keySet()
                .stream()
                .filter(pos -> (pos.toString().contains(pos1)) || pos.toString().contains(pos2))//Filter out any row and col that does not match "currentPosition"
                .filter(pos -> !(pos.toString().equals(position))) //Filter out the spot the piece stands on
                .filter(pos -> (pos.getChessman().getColor() != playerColor)) //Filter out spots where same color pieces stands on
                .sorted()
                .collect(Collectors.toList());

    }

Как бы вы это решили? Вы бы переключились на 2D-массив вместо перечисления и карты?

1 Ответ

2 голосов
/ 18 июня 2020

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

Я бы предложил следующую модель:

public enum Position {
    A1(1, 1), A2(2, 1) ....

    private final int column;
    private final int row;
}

public class Move {
    private final List<Position> path;
}

public enum PieceType {
    PAWN, KNIGHT, BISHOP ...

    private final Function<Position,Stream<Move>> moveGenerator;

    public Stream<Move> getMoves(Position origin) { 
        return moveGenerator.apply(origin); 
    }
}

public enum Colour {
    WHITE, BLACK;
}

public class Piece {
    private final PieceType type;
    private final Colour colour;
}

public class Board {
    private final EnumMap<Position,Piece> pieces;

    public Stream<Move> getLegalMoves() {
        return pieces.entrySet().stream()
            .flatMap(e -> e.getValue().getType().getMoves(e.getKey()))
            .filter(this::isLegal);
    }

    private boolean isLegal(Move move) {
        Piece piece = pieces.get(move.getOrigin());
        return (!pieces.containsKey(move.getDestination()) 
            || pieces.get(move.getDestination()).getColour() != piece.getColour()))
            && move.getIntermediatePositions().noneMatch(pieces::containsKey))
    }
}

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

...