Как предотвратить StackOverflowError? - PullRequest
0 голосов
/ 22 сентября 2018

Я давно занимаюсь шахматной программой.Я сделал класс под названием Checkmate, чтобы обнаружить чеки, незаконные ходы, мат и пат.На данный момент я только что реализовал проверки и незаконные ходы.Но всякий раз, когда я запускаю программу, она вызывает ошибку StackOverflowError.

/**
 * <code>String player</code> contains the constant of the currently playing player.
 * This method will first find out the position of the opponent's King and store it in <code>Point opponentKing</code>.
 * After that, it will find all the currently playing player's pieces. It will find the possible moves of each of the piece.
 * If the <code>opponentKing</code> is found within the possible moves of any piece, it will return "true, else it will return "false".
 * @return "true" if it is check. "false" if it is not a check.
 */
public boolean getIsCheck(String[][] board) {
    boolean isCheck = false;
    Point opponentKing = new Point(0,0);
    outer: for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
            if(!board[i][j].substring(1).equals(player) && board[i][j].substring(0,1).equals(Board.KING)) {
                opponentKing = new Point(i, j);
                break outer;
            }
        }
    }
    List<Point> friendlyPieces = new ArrayList<>();
    for (int i = 0; i < 8; i++)
        for (int j = 0; j < 8; j++)
            if (board[i][j].substring(1).equals(player)
                    && !board[i][j].equals(Board.EMPTY))
                friendlyPieces.add(new Point(i, j));

    outer: for(Point p : friendlyPieces) {
        List<Point> availableMoves = new ArrayList<>();
        switch (board[p.x][p.y].substring(0,1)){
            case Board.PAWN: availableMoves = new Pawn(player).getCheckMoves(p); break;
            case Board.ROOK: availableMoves = new Rook(player).getAvailableMoves(p); break;
            case Board.KNIGHT: availableMoves = new Knight(player).getAvailableMoves(p); break;
            case Board.BISHOP: availableMoves = new Bishop(player).getAvailableMoves(p); break;
            case Board.KING: availableMoves = new King(player).getAvailableMoves(p); break;
            case Board.QUEEN: availableMoves = new Queen(player).getAvailableMoves(p); break;
        }
        for (Point point: availableMoves) {
            if(point.equals(opponentKing)) {
                isCheck = true;
                break outer;
            }
        }
    }
    return isCheck;
}

Это код для определения, находится ли текущая позиция фигур на доске в состоянии проверки для короля.

public boolean getIsIllegal(Point start, Point end, Pieces piece){
    String[][] board = Board.board;
    board[start.x][start.y] = Board.EMPTY;
    board[end.x][end.y] = piece.getPiece() + piece.getPlayer();
    return getIsCheck(board);
}

Это getIsIllegal () того же класса Checkmate.

Всякий раз, когда я выбираю пешку на доске.Это дает мне следующую ошибку: -

Exception in thread "main" java.lang.StackOverflowError
    at Pieces.Pawn.getCheckMoves(Pawn.java:56)
    at Win.Checkmate.getIsCheck(Checkmate.java:60)
    at Win.Checkmate.getIsIllegal(Checkmate.java:81)
    at Pieces.Knight.getAvailableMoves(Knight.java:30)
    at Win.Checkmate.getIsCheck(Checkmate.java:62)
    at Win.Checkmate.getIsIllegal(Checkmate.java:81)
    at Pieces.Knight.getAvailableMoves(Knight.java:34)
    at Win.Checkmate.getIsCheck(Checkmate.java:62)
    at Win.Checkmate.getIsIllegal(Checkmate.java:81)

И так далее.

if (x<7 && y<6 && isEmpty(x + 1, y + 2) && !check.getIsIllegal(point, new Point(x, y), this)) availableMoves.add(new Point(x + 1, y + 2));
    if (x>0 && y<6 && isEmpty(x - 1, y + 2) && !check.getIsIllegal(point, new Point(x, y), this)) availableMoves.add(new Point(x - 1, y + 2));
    if (x<6 && y>0 && isEmpty(x + 2, y - 1) && !check.getIsIllegal(point, new Point(x, y), this)) availableMoves.add(new Point(x + 2, y - 1));
    if (x<6 && y<7 && isEmpty(x + 2, y + 1) && !check.getIsIllegal(point, new Point(x, y), this)) availableMoves.add(new Point(x + 2, y + 1));
    if (x<7 && y>1 && isEmpty(x + 1, y - 2) && !check.getIsIllegal(point, new Point(x, y), this)) availableMoves.add(new Point(x + 1, y - 2));
    if (x>0 && y>1 && isEmpty(x - 1, y - 2) && !check.getIsIllegal(point, new Point(x, y), this)) availableMoves.add(new Point(x - 1, y - 2));
    if (x>1 && y>0 && isEmpty(x - 2, y - 1) && !check.getIsIllegal(point, new Point(x, y), this)) availableMoves.add(new Point(x - 2, y - 1));
    if (x>1 && y<7 && isEmpty(x - 2, y + 1) && !check.getIsIllegal(point, new Point(x, y), this)) availableMoves.add(new Point(x - 2, y + 1));

Приведенный выше код - это строки, которые я написал, чтобы получить доступные ходы для Рыцаря на текущей доске.Вот где находится постоянный цикл между getIsCheck () и getIsIllegal ().Пожалуйста, обратитесь к Исключению для дальнейших разъяснений.

1 Ответ

0 голосов
/ 18 октября 2018

Часть проверяет короля, хотя ход части не разрешен!Например: белый Kc2, Rb2 - черный Kh2, Ba3:

enter image description here

После хода Kc2-c1 Rb2 дает чек, хотя Rb2 не можетход.

Изменить определение доступного и недопустимого хода: доступный ход может быть незаконным.Так что getAvailableMoves () не вызывает getIsIllegal ().Таким образом, Rb2-h2 является доступным ходом, и метод isCheck () работает.

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

...
Pieces piece;
switch (board[p.x][p.y].substring(0,1)){
    case Board.PAWN: piece = new Pawn(player); break;
    case Board.ROOK: piece = new Rook(player); break;
    case Board.KNIGHT: piece = new Knight(player); break;
    case Board.BISHOP: piece = new Bishop(player); break;
    case Board.KING: piece = new King(player); break;
    case Board.QUEEN: piece = new Queen(player); break;
} 

List<Point> availableMoves = piece.getAvailableMoves(p);
List<Point> legalMoves = new ArrayList<>();

for (Point point : availableMoves ) {
    if (!getIsIllegal(p, point, piece))
        legalMoves.add(point);
}
...
...