Как преобразовать этот метод в логическое значение - PullRequest
0 голосов
/ 10 ноября 2018

Я сейчас пытаюсь реализовать игру в шахматы. Я структурировал его так, чтобы возможные ходы генерировались для каждого типа фигуры и сохранялись в списке массивов. Моя доска - это двумерный массив. Я задавался вопросом, как написать, что если xTo yTo (координаты точки хотели переместиться) было возможным движением, то это движение могло быть сделано, но оно не позволило бы мне использовать массив list.contains(), любые предложения очень ценятся! Вот пример того, что у меня есть. (Пользователь вводит координаты xFrom, yFrom, затем xTo yTo через терминал) Теперь мне интересно, было бы проще преобразовать это в логическое значение? и избавиться от списка массивов?

public Board() {
    this.boardsize = DEFAULT_SIZE;

    board = new char[boardsize][boardsize];

    // Clear all playable fields
    for (int x = 0; x < boardsize; x++)
        for (int y = 0; y < boardsize; y++)
            board[x][y] = FREE;

    board[0][7] = BLACKROOK;
    board[2][7] = BLACKBISHOP;
    board[5][7] = BLACKBISHOP;
    board[7][7] = BLACKROOK;
    board[0][0] = WHITEROOK;
    board[2][0] = WHITEBISHOP;
    board[5][0] = WHITEBISHOP;
    board[7][0] = WHITEROOK;

Для Ладьи ....

public ArrayList<int[]> possibleMoves = new ArrayList<int[]>();


public ArrayList<int[]> generatePossibleMoves(char[][] gameBoard, int xFrom, int yFrom) {
    for (int i = 1; xFrom + i < gameBoard.length; i++) {
        if (getPieceColour(gameBoard, xFrom + i, yFrom) != getPieceColour(gameBoard, xFrom, yFrom)) {
            if (gameBoard[xFrom + i][yFrom] != FREE) {
                int[] move = {xFrom + i, yFrom};
                possibleMoves.add(move);
                break;                              //stops iterating here since a rook is not allowed to jump over other pieces
            } else
                {
                int[] move = {xFrom + i, yFrom};
                possibleMoves.add(move);
            }
        }
    }
    for (int i = 1; xFrom - i < gameBoard.length; i++) {
        if (getPieceColour(gameBoard, xFrom - i, yFrom) != getPieceColour(gameBoard, xFrom, yFrom)) {
            if (gameBoard[xFrom - i][yFrom] != FREE) {
                int[] move = {xFrom - i, yFrom};
                possibleMoves.add(move);
                break;
            }
            else
                {
                int[] move = {xFrom - i, yFrom};
                possibleMoves.add(move);
            }
        }
    }
    for (int i = 1; yFrom + i < gameBoard.length+1; i++) {       //makes sure the place to be moved is on the board
        if (getPieceColour(gameBoard, xFrom + i, yFrom) != getPieceColour(gameBoard, xFrom, yFrom)) {
            if (gameBoard[xFrom][yFrom+i] != FREE) {
                int[] move = {xFrom, yFrom+i};
                possibleMoves.add(move);
                break;
            }
            else
                {
                int[] move = {xFrom, yFrom+i};
                possibleMoves.add(move);
            }
        }
    }
    for (int i = 1; yFrom- i < gameBoard.length+1; i++)
        if (getPieceColour(gameBoard, xFrom, yFrom - 1) != getPieceColour(gameBoard, xFrom, yFrom)) {
            if (gameBoard[xFrom][yFrom - 1] != FREE) {
                int[] move = {xFrom, yFrom - 1};
                possibleMoves.add(move);
                break;
            } else {
                int[] move = {xFrom, yFrom - 1};
                possibleMoves.add(move);
            }
        }
    return possibleMoves;
}




public boolean moveLegal(char[][] gameBoard, int xFrom, int yFrom, int xTo, int yTo){
    generatePossibleMoves(gameBoard, xFrom,yFrom);

    if(possibleMoves.contains(xTo,yTo){
        //this is where I'm stuck
    }

}

Ответы [ 3 ]

0 голосов
/ 10 ноября 2018

Я бы создал другой класс Coordinates, который правильно реализует метод equals

public class Coordinates {
    int x = 0;
    int y = 0;

    public Coordinates(int x, int y) {
        super();
        this.x = x;
        this.y = y;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + x;
        result = prime * result + y;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Coordinates other = (Coordinates) obj;
        if (x != other.x)
            return false;
        if (y != other.y)
            return false;
        return true;
    }


}

и затем использовать этот класс для типа ArrayList

Так например

public List<Coordinates> possibleMoves = new ArrayList<Coordinates>();

тогда функция становится

public boolean moveLegal(char[][] gameBoard, int xFrom, int yFrom, int xTo, int yTo){
    generatePossibleMoves(gameBoard, xFrom,yFrom);
    Coordinates checkCoordinates = new Coordinates (xTo,yTo);
    if(possibleMoves.contains(xTo,yTo){
      ...
    }
}
0 голосов
/ 10 ноября 2018

Основная причина в том, что вы сохраняете в массиве possibleMoves, но пытаетесь проверить , а не массив. Как описано в документации , List.contains() принимает только 1 параметр. Поскольку вы помещаете массив в List, вы можете проверить массив: if(possibleMoves.contains({xTo,yTo})

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

Оффтоп : Я бы посоветовал вам использовать больше подходов в стиле ООП: использовать меньше необработанных массивов и больше объектов, отражающих фрагменты. Например

enum Side { 
   White; Black; 
   public Side opposite() {
      if (this==White) return Black;
      else return White;
   }
}
// in separate file
class Pawn {
  private ChessSquare currentPosition;
  private final Side color;
  public boolean couldMoveTo(ChessSquare another) {
     if (currentPosition.x == another.x) {
       return another.y - currentPosition.y == 1; //TODO check for first move in two sruares
     } else if (another.hasPiece(this.color.opposite())) {
        // TODO allow to take enemy piece in diagonal
     }
  }
 public List<ChessField> possibleMoves() { 
   List<ChessField> result = new ArrayList<>();
   for (currentSquare in ALL_SQUARES) {
     if (couldMoveTo(currentSquare)) result.add(currentSquare)
   }
   return result;
}

Мой пример неэффективен и может быть улучшен разными способами. Также есть много других вариантов организации структуры кода. Я полагаю, это продемонстрировало, как вы можете проверить, может ли фигура сделать ход с точки зрения этой фигуры . Также вы можете скрыть много деталей (например, en passant rule) внутри класса Pawn и в то же время иметь четкий код на верхних уровнях. Вы могли видеть, что possibleMoves() очень маленький и фактически может быть общим для всех частей.

P.S. Шахматы - отличная игра, и я хотел бы, чтобы вы могли изучать и шахматы, и Java при создании игры.

0 голосов
/ 10 ноября 2018

Чтобы проверить, возможно ли перемещение, можно сравнить пару {xTo, yTo} со всеми допустимыми ходами, которые вы рассчитываете с помощью функции generatePossibleMoves:

public boolean moveLegal(char[][] gameBoard, int xFrom, int yFrom, int xTo, int 
yTo){
       int[] wantedMove = new int[] {xTo, yTo};
       ArrayList<int[]> possibleMoves = generatePossibleMoves(gameBoard, xFrom,yFrom);
       boolean isMoveLegal = possibleMoves.stream().anyMatch(possibleMove -> 
           Arrays.equals(wantedMove, possibleMove));
       return isMoveLegal;
}
...