From 321a924555bbd3502f24f779878e2acb694b2df1 Mon Sep 17 00:00:00 2001 From: happymeal2024 Date: Tue, 20 May 2025 09:23:13 +0200 Subject: [PATCH] update again --- chess/Main.java | 18 - chess/board/Board.java | 148 -------- chess/board/Field.java | 118 ------- chess/game/Game.java | 330 ------------------ chess/pieces/Color.java | 9 - chess/pieces/Piece.java | 70 ---- chess/pieces/Type.java | 23 -- chess/src/main/java/de/vivi/chess/Main.java | 6 + .../main/java/de/vivi/chess/board/Board.java | 73 +++- .../main/java/de/vivi/chess/board/Field.java | 83 ++++- .../main/java/de/vivi/chess/game/Game.java | 307 +++++++++++++++- .../java/de/vivi/chess}/pieces/Bishop.java | 0 .../main/java/de/vivi/chess/pieces/Color.java | 2 + .../main/java/de/vivi/chess}/pieces/King.java | 0 .../java/de/vivi/chess}/pieces/Knight.java | 0 .../main/java/de/vivi/chess}/pieces/Pawn.java | 0 .../main/java/de/vivi/chess/pieces/Piece.java | 37 +- .../java/de/vivi/chess}/pieces/Queen.java | 0 .../main/java/de/vivi/chess}/pieces/Rook.java | 0 .../main/java/de/vivi/chess/pieces/Type.java | 6 + 20 files changed, 499 insertions(+), 731 deletions(-) delete mode 100644 chess/Main.java delete mode 100644 chess/board/Board.java delete mode 100644 chess/board/Field.java delete mode 100644 chess/game/Game.java delete mode 100644 chess/pieces/Color.java delete mode 100644 chess/pieces/Piece.java delete mode 100644 chess/pieces/Type.java rename chess/{ => src/main/java/de/vivi/chess}/pieces/Bishop.java (100%) rename chess/{ => src/main/java/de/vivi/chess}/pieces/King.java (100%) rename chess/{ => src/main/java/de/vivi/chess}/pieces/Knight.java (100%) rename chess/{ => src/main/java/de/vivi/chess}/pieces/Pawn.java (100%) rename chess/{ => src/main/java/de/vivi/chess}/pieces/Queen.java (100%) rename chess/{ => src/main/java/de/vivi/chess}/pieces/Rook.java (100%) diff --git a/chess/Main.java b/chess/Main.java deleted file mode 100644 index 3f7628f..0000000 --- a/chess/Main.java +++ /dev/null @@ -1,18 +0,0 @@ -package de.vivi.chess; - -import de.vivi.chess.board.Board; -import de.vivi.chess.board.Field; -import de.vivi.chess.game.Game; -import de.vivi.chess.pieces.Piece; - -import java.util.Arrays; - -public class Main { - - public static void main(String[] args) { - Game game = new Game(); - - game.play(); - - } -} diff --git a/chess/board/Board.java b/chess/board/Board.java deleted file mode 100644 index 3abd3a5..0000000 --- a/chess/board/Board.java +++ /dev/null @@ -1,148 +0,0 @@ -package de.vivi.chess.board; - -import de.vivi.chess.pieces.*; -import de.vivi.chess.game.Game; - -public class Board { - - private static final int SIZE = 8; - private final Piece[/* column */][/* row */] grid; - - public Board() { - grid = new Piece[SIZE][SIZE]; - setup(); - } - - /** - * TODO: implement - *

- * This method should setup the board like it is common - * for a chess game. Black is in the top two rows, white - * in the bottom two rows. "White queen, white field, black - * queen, black field". - */ - - private void setup() { - grid[0][0] = new Rook(Color.BLACK, Type.ROOK, new Field(0, 0)); - grid[1][0] = new Knight(Color.BLACK, Type.KNIGHT, new Field(1, 0)); - grid[2][0] = new Bishop(Color.BLACK, Type.BISHOP, new Field(2, 0)); - grid[3][0] = new Queen(Color.BLACK, Type.QUEEN, new Field(3, 0)); - grid[4][0] = new King(Color.BLACK, Type.KING, new Field(4, 0)); - grid[5][0] = new Bishop(Color.BLACK, Type.BISHOP, new Field(5, 0)); - grid[6][0] = new Knight(Color.BLACK, Type.KNIGHT, new Field(6, 0)); - grid[7][0] = new Rook(Color.BLACK, Type.ROOK, new Field(7, 0)); - //grid[0][0] = new Rook(Color.BLACK, Type.ROOK); -// grid[1][0] = new Knight(Color.BLACK, Type.KNIGHT); -// grid[2][0] = new Bishop(Color.BLACK, Type.BISHOP); -// grid[3][0] = new Queen(Color.BLACK, Type.QUEEN); -// grid[4][0] = new King(Color.BLACK, Type.KING); -// grid[5][0] = new Bishop(Color.BLACK, Type.BISHOP); -// grid[6][0] = new Knight(Color.BLACK, Type.KNIGHT); -// grid[7][0] = new Rook(Color.BLACK, Type.ROOK); - - for (int i = 0; i < SIZE; i++) { - //grid[i][1] = new Pawn(Color.BLACK, Type.PAWN); - grid[i][1] = new Pawn(Color.BLACK, Type.PAWN, new Field(i, 0)); - } - - grid[0][7] = new Rook(Color.WHITE, Type.ROOK, new Field(0, 7)); - grid[1][7] = new Knight(Color.WHITE, Type.KNIGHT, new Field(1, 7)); - grid[2][7] = new Bishop(Color.WHITE, Type.BISHOP, new Field(2, 7)); - grid[3][7] = new Queen(Color.WHITE, Type.QUEEN, new Field(3, 7)); - grid[4][7] = new King(Color.WHITE, Type.KING, new Field(4, 7)); - grid[5][7] = new Bishop(Color.WHITE, Type.BISHOP, new Field(5, 7)); - grid[6][7] = new Knight(Color.WHITE, Type.KNIGHT, new Field(6, 7)); - grid[7][7] = new Rook(Color.WHITE, Type.ROOK, new Field(7, 7)); - -// grid[0][7] = new Rook(Color.WHITE, Type.ROOK); -// grid[1][7] = new Knight(Color.WHITE, Type.KNIGHT); -// grid[2][7] = new Bishop(Color.WHITE, Type.BISHOP); -// grid[3][7] = new Queen(Color.WHITE, Type.QUEEN); -// grid[4][7] = new King(Color.WHITE, Type.KING); -// grid[5][7] = new Bishop(Color.WHITE, Type.BISHOP); -// grid[6][7] = new Knight(Color.WHITE, Type.KNIGHT); -// grid[7][7] = new Rook(Color.WHITE, Type.ROOK); - - for (int i = 0; i < SIZE; i++) { - //grid[i][6] = new Pawn(Color.WHITE, Type.PAWN); - grid[i][6] = new Pawn(Color.WHITE, Type.PAWN, new Field(i, 6)); - } - } - - /** - * TODO: implement - *

- * Moves the piece at the from field to the to field. - * Doesn't check for validity, this has to be done somewhere - * else. If a piece is already at the to field, this piece is - * just getting replaced. - */ - public void move(Field from, Field to) { - if (grid[from.getColumn()][from.getRow()] != null) { - grid[to.getColumn()][to.getRow()] = grid[from.getColumn()][from.getRow()]; - grid[to.getColumn()][to.getRow()].setField(to); - grid[from.getColumn()][from.getRow()] = null; - } - } - - /** - * TODO: implement - *

- * Returns the piece at the given field. If no piece is - * present it just returns null. - */ - public Piece getPiece(Field field) { - return grid[field.getColumn()][field.getRow()]; - } - - public Piece[][] getBoard() { - return grid; - } - - public Piece getPiece(int column, int row) { - return grid[column][row]; - } - - public void setPiece(int column, int row, Piece piece) { - grid[column][row] = piece; - if (piece != null) { - piece.setField(new Field(column, row)); - } - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - boolean whiteField = true; - - result.append(" "); - - for (int column = 0; column < SIZE; column++) { - result.append((char) ('A' + column)).append(' '); - } - - result.append('\n'); - - for (int row = 0; row < SIZE; row++) { - result.append((char) ('1' + (char) row)).append(' '); - - for (int column = 0; column < SIZE; column++) { - Piece piece = grid[column][row]; - - if (piece == null) { - result.append(whiteField ? '\u25a0' : '\u25a1'); - } else { - result.append(piece.getSymbol()); - } - - result.append(' '); - whiteField = !whiteField; - } - - result.append('\n'); - whiteField = !whiteField; - } - - return result.toString(); - } -} diff --git a/chess/board/Field.java b/chess/board/Field.java deleted file mode 100644 index 3d5e3a6..0000000 --- a/chess/board/Field.java +++ /dev/null @@ -1,118 +0,0 @@ -package de.vivi.chess.board; - -import de.vivi.chess.pieces.Piece; - -/** - * TODO: implement fields and constructor - *

- * This class contains information to identify a single field - * on the board by its column and row. - */ -public class Field { - - private int column; - private int row; - - public Field(int column, int row) { - this.column = column; - this.row = row; - } - - /** - * TODO: implement - *

- * Returns a new field that represents the field at the - * column and row indices. - */ - public static Field from(int column, int row) { - return new Field(column, row); - } - - /** - * TODO: implement - *

- * Returns a new field that represents the field represented - * by the provided string (like "A5", "E7", ...). If the string - * is not valid, because it is garbage (like "hello", "world", ...) - * or the indices are out of bounds (like "K3", "B9", ...") - * it should throw an IllegalArgument exception. - */ - public static Field fromString(String value) throws IllegalArgumentException { - try { - char[] array = value.toCharArray(); - int column_ = 0; - int row_ = 0; - - switch (array[0]) { - case 'A': - column_ = 0; - break; - case 'B': - column_ = 1; - break; - case 'C': - column_ = 2; - break; - case 'D': - column_ = 3; - break; - case 'E': - column_ = 4; - break; - case 'F': - column_ = 5; - break; - case 'G': - column_ = 6; - break; - case 'H': - column_ = 7; - break; - default: - System.out.println("Wrong input"); - } - - switch (array[1]) { - case '1': - row_ = 0; - break; - case '2': - row_ = 1; - break; - case '3': - row_ = 2; - break; - case '4': - row_ = 3; - break; - case '5': - row_ = 4; - break; - case '6': - row_ = 5; - break; - case '7': - row_ = 6; - break; - case '8': - row_ = 7; - break; - default: - System.out.println("Wrong input"); - } - return from(column_, row_); - } catch (RuntimeException e) { - throw new RuntimeException(e); - } - } - - public int getColumn() { - // TODO: implement - return column; - } - - public int getRow() { - // TODO: implement - return row; - } -} diff --git a/chess/game/Game.java b/chess/game/Game.java deleted file mode 100644 index 671d3d4..0000000 --- a/chess/game/Game.java +++ /dev/null @@ -1,330 +0,0 @@ -package de.vivi.chess.game; - -import de.vivi.chess.board.Board; -import de.vivi.chess.board.Field; -import de.vivi.chess.pieces.Color; -import de.vivi.chess.pieces.King; -import de.vivi.chess.pieces.Piece; - -import java.util.ArrayList; -import java.util.List; -import java.util.Scanner; - -import static de.vivi.chess.pieces.Color.BLACK; -import static de.vivi.chess.pieces.Color.WHITE; - -public class Game { - - private Board board; - private Color player; - private int count = 0; - private boolean whiteTurn = true; - - /** - * TODO: implement - */ - public Game() { - this.board = new Board(); - player = null; - } - - /** - * TODO: implement - *

- * Starts the game and should process the game like it is - * specified inside example-output.txt. - */ - public void play() { - System.out.println("Welcome to Vivi's Chess Game!"); - System.out.println(board); - player = ((count % 2) == 0) ? WHITE : BLACK; - System.out.println("It is white's turn: [from:to]"); - - Scanner scanner = new Scanner(System.in); - - while (scanner.hasNext()) { - - scanner.useDelimiter(":\\s*"); - String fromString = scanner.nextLine(); - - char[] arrayInRange = fromString.toCharArray(); - - if ((arrayInRange[0] == 'A' || - arrayInRange[0] == 'B' || - arrayInRange[0] == 'C' || - arrayInRange[0] == 'D' || - arrayInRange[0] == 'E' || - arrayInRange[0] == 'F' || - arrayInRange[0] == 'G' || - arrayInRange[0] == 'H' ) && - (arrayInRange[1] == '0' || - arrayInRange[1] == '1' || - arrayInRange[1] == '2' || - arrayInRange[1] == '3' || - arrayInRange[1] == '4' || - arrayInRange[1] == '5' || - arrayInRange[1] == '6' || - arrayInRange[1] == '7' || - arrayInRange[1] == '8' )) { - - StringBuilder sb=new StringBuilder(fromString); - int l=sb.length(); - - if (l == 2) { - String toString = scanner.nextLine(); - Field from = Field.fromString(fromString); - Field to = Field.fromString(toString); - - System.out.println("player == WHITE && board.getPiece(from).getColor() == WHITE " + - (player == WHITE && board.getPiece(from).getColor() == WHITE)); - - - System.out.println("board.getPiece(from).isValidMove(board, from,to) " + - (board.getPiece(from).isValidMove(board, from,to))); - - if (player == WHITE && board.getPiece(from).getColor() == WHITE) { - if (board.getPiece(from).isValidMove(board, from,to)) { - count++; - board.move(from, to); - System.out.println("Moving white " + board.getPiece(to).getType() - + " from " + fromString + " to " + toString); - } - System.out.println(board); - } else if (player == BLACK && board.getPiece(from).getColor() == BLACK) { - if (board.getPiece(from).isValidMove(board, from,to)) { - count++; - board.move(from, to); - System.out.println("Moving black " + board.getPiece(to).getType() - + " from " + fromString + " to " + toString); - } - System.out.println(board); - } else { - System.err.println("Illegal move, try again: "); - } - - player = ((count % 2) == 0) ? WHITE : BLACK; - if (player == BLACK) { - System.out.println("It is black's turn: [from:to]"); - } else { - System.out.println("It is white's turn: [from:to]"); - } - } else { - System.err.println("Illegal move, try again: "); - } - } else - System.err.println("Illegal move, try again: "); - } - } - - public Board getBoard() { - return this.board; - } - - public void resetGame() { - this.board = new Board(); - this.whiteTurn = true; - } - - public Color getCurrentPlayerColor() { - return whiteTurn ? Color.WHITE : Color.BLACK; - } - - private Field selectedField; - - public boolean isPieceSelected() { - return selectedField != null; - } - - public boolean handleSquareSelection(int row, int col) { - if (selectedField == null) { - Piece selectedPiece = board.getPiece(row, col); - if (selectedPiece != null - && selectedPiece.getColor() == (whiteTurn ? Color.WHITE : Color.BLACK)) { - selectedField = new Field(row, col); - return false; - } - } else { - boolean moveMade = makeMove(selectedField, new Field(row, col)); - selectedField = null; - return moveMade; - } - return false; - } - - public boolean makeMove(Field from, Field to) { - Piece movingPiece = board.getPiece(Field.from(from.getRow(), from.getColumn())); - if (movingPiece == null || movingPiece.getColor() != (whiteTurn ? WHITE : BLACK)) { - return false; - } - - if (movingPiece.isValidMove(board, movingPiece.getField(), to)) { - board.move(from, to); - whiteTurn = !whiteTurn; - return true; - } - return false; - } - - public boolean isInCheck(Color kingColor) { - Field kingPosition = findKingPosition(kingColor); - for (int row = 0; row < 8; row++) { - for (int col = 0; col < 8; col++) { - Piece piece = board.getPiece(Field.from(row, col)); - if (piece != null && piece.getColor() != kingColor) { - if (piece.isValidMove(board, piece.getField(), kingPosition)) { - return true; - } - } - } - } - return false; - - } - - private Field findKingPosition(Color color) { - for (int row = 0; row < 8; row++) { - for (int col = 0; col < 8; col++) { - Piece piece = board.getPiece(Field.from(row, col)); - if (piece instanceof King && piece.getColor() == color) { - return new Field(row, col); - } - } - } - throw new RuntimeException("King not found, which should never happen."); - } - - public boolean isCheckmate(Color kingColor) { - if (!isInCheck(kingColor)) { - return false; - } - - Field kingPosition = findKingPosition(kingColor); - King king = (King) board.getPiece(Field.from(kingPosition.getRow(), kingPosition.getColumn())); - - for (int rowOffset = -1; rowOffset <= 1; rowOffset++) { - for (int colOffset = -1; colOffset <= 1; colOffset++) { - if (rowOffset == 0 && colOffset == 0) { - continue; - } - Field newPosition = new Field(kingPosition.getRow() + rowOffset, - kingPosition.getColumn() + colOffset); - if ( - isPositionOnBoard(newPosition) && - king.isValidMove(board, king.getField() , newPosition) - && !wouldBeInCheckAfterMove(kingColor, kingPosition, newPosition)) { - return false; - } - } - } - - return true; - - } - - private boolean isPositionOnBoard(Field field) { - return field.getRow() >= 0 && field.getRow() < 8 && - field.getColumn() >= 0 && field.getColumn() < 8; - - } - - private boolean wouldBeInCheckAfterMove(Color kingColor, Field from, Field to) { - Piece temp = board.getPiece(Field.from(to.getRow(), to.getColumn())); - board.setPiece(to.getRow(), to.getColumn(), board.getPiece(to)); - board.setPiece(from.getRow(), from.getColumn(), null); - - boolean inCheck = isInCheck(kingColor); - - board.setPiece(from.getRow(), from.getColumn(), board.getPiece(to.getRow(), to.getColumn())); - board.setPiece(to.getRow(), to.getColumn(), temp); - - return inCheck; - } - - public List getLegalMovesForPieceAt(Field field) { - Piece selectedPiece = board.getPiece(field.getRow(), field.getColumn()); - if (selectedPiece == null) - return new ArrayList<>(); - - List legalMoves = new ArrayList<>(); - switch (selectedPiece.getClass().getSimpleName()) { - case "Pawn": - addPawnMoves(field, selectedPiece.getColor(), legalMoves); - break; - case "Rook": - addLineMoves(field, new int[][] { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } }, legalMoves); - break; - case "Knight": - addSingleMoves(field, new int[][] { { 2, 1 }, { 2, -1 }, { -2, 1 }, { -2, -1 }, { 1, 2 }, { -1, 2 }, - { 1, -2 }, { -1, -2 } }, legalMoves); - break; - case "Bishop": - addLineMoves(field, new int[][] { { 1, 1 }, { -1, -1 }, { 1, -1 }, { -1, 1 } }, legalMoves); - break; - case "Queen": - addLineMoves(field, new int[][] { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 }, { 1, 1 }, { -1, -1 }, - { 1, -1 }, { -1, 1 } }, legalMoves); - break; - case "King": - addSingleMoves(field, new int[][] { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 }, { 1, 1 }, { -1, -1 }, - { 1, -1 }, { -1, 1 } }, legalMoves); - break; - } - return legalMoves; - } - - private void addLineMoves(Field field, int[][] directions, List legalMoves) { - for (int[] d : directions) { - Field newPos = new Field(field.getRow() + d[0], field.getColumn() + d[1]); - while (isPositionOnBoard(newPos)) { - if (board.getPiece(newPos.getRow(), newPos.getColumn()) == null) { - legalMoves.add(new Field(newPos.getRow(), newPos.getColumn())); - newPos = new Field(newPos.getRow() + d[0], newPos.getColumn() + d[1]); - } else { - if (board.getPiece(newPos.getRow(), newPos.getColumn()).getColor() != board - .getPiece(field.getRow(), field.getColumn()).getColor()) { - legalMoves.add(newPos); - } - break; - } - } - } - } - - private void addSingleMoves(Field field, int[][] moves, List legalMoves) { - for (int[] move : moves) { - Field newPos = new Field(field.getRow() + move[0], field.getColumn() + move[1]); - if (isPositionOnBoard(newPos) && (board.getPiece(newPos.getRow(), newPos.getColumn()) == null || - board.getPiece(newPos.getRow(), newPos.getColumn()).getColor() != board - .getPiece(field.getRow(), field.getColumn()).getColor())) { - legalMoves.add(newPos); - } - } - } - - private void addPawnMoves(Field field, Color color, List legalMoves) { - int direction = color == WHITE ? -1 : 1; - Field newPos = new Field(field.getRow() + direction, field.getColumn()); - if (isPositionOnBoard(newPos) && board.getPiece(newPos.getRow(), newPos.getColumn()) == null) { - legalMoves.add(newPos); - } - - if ((color == Color.WHITE && field.getRow() == 6) - || (color == Color.BLACK && field.getRow() == 1)) { - newPos = new Field(field.getRow() + 2 * direction, field.getColumn()); - Field intermediatePos = new Field(field.getRow() + direction, field.getColumn()); - if (isPositionOnBoard(newPos) && board.getPiece(newPos.getRow(), newPos.getColumn()) == null - && board.getPiece(intermediatePos.getRow(), intermediatePos.getColumn()) == null) { - legalMoves.add(newPos); - } - } - - int[] captureCols = { field.getColumn() - 1, field.getColumn() + 1 }; - for (int col : captureCols) { - newPos = new Field(field.getRow() + direction, col); - if (isPositionOnBoard(newPos) && board.getPiece(newPos.getRow(), newPos.getColumn()) != null && - board.getPiece(newPos.getRow(), newPos.getColumn()).getColor() != color) { - legalMoves.add(newPos); - } - } - } -} diff --git a/chess/pieces/Color.java b/chess/pieces/Color.java deleted file mode 100644 index b3cf8d7..0000000 --- a/chess/pieces/Color.java +++ /dev/null @@ -1,9 +0,0 @@ -package de.vivi.chess.pieces; - -/** - * TODO: add colors (white and black) - */ -public enum Color { - WHITE, - BLACK -} diff --git a/chess/pieces/Piece.java b/chess/pieces/Piece.java deleted file mode 100644 index 2234b52..0000000 --- a/chess/pieces/Piece.java +++ /dev/null @@ -1,70 +0,0 @@ -package de.vivi.chess.pieces; - -import de.vivi.chess.board.Board; -import de.vivi.chess.board.Field; - -public abstract class Piece { - - Color color; - private Type type; - protected char symbol; - protected Field field; - - protected Piece(Color color, Type type) { - this.color = color; - this.type = type; - symbol = '\u0000'; - } - - protected Piece(Color color, Field field) { - this.color = color; - this.field = field; - } - - protected Piece(Color color, Type type, Field field) { - this.color = color; - this.type = type; - this.field = field; - } - - /** - * TODO: implement - *

- * This method needs to be implemented in each piece by - * using inheritance. It returns true if the move from the - * from field to the to field is considered a valid move - * for the type of piece this method is called on. Otherwise - * it returns false. - */ - public abstract boolean isValidMove(Board board, Field from, Field to); - - - public Color getColor() { - // TODO: implement - return color; - } - - public Type getType() { - // TODO: implement - return type; - } - - /** - * TODO: implement - *

- * Use unicode symbols for the chess pieces. You can find - * them here: - * Unicode chess pieces - */ - public char getSymbol() { - return symbol; - } - - public Field getField() { - return field; - } - - public void setField(Field field) { - this.field = field; - } -} diff --git a/chess/pieces/Type.java b/chess/pieces/Type.java deleted file mode 100644 index 1b7f635..0000000 --- a/chess/pieces/Type.java +++ /dev/null @@ -1,23 +0,0 @@ -package de.vivi.chess.pieces; - -/** - * TODO: add types - *

- * This enum should contain all chess piece types. - * The types are: - * - * - king (König) - * - queen (Dame) - * - bishop (Läufer) - * - knight (Springer/Pferd) - * - rook (Turm) - * - pawn (Bauer) - */ -public enum Type { - KING, - QUEEN, - BISHOP, - KNIGHT, - ROOK, - PAWN -} diff --git a/chess/src/main/java/de/vivi/chess/Main.java b/chess/src/main/java/de/vivi/chess/Main.java index 8d2fb91..3f7628f 100644 --- a/chess/src/main/java/de/vivi/chess/Main.java +++ b/chess/src/main/java/de/vivi/chess/Main.java @@ -1,12 +1,18 @@ package de.vivi.chess; import de.vivi.chess.board.Board; +import de.vivi.chess.board.Field; import de.vivi.chess.game.Game; +import de.vivi.chess.pieces.Piece; + +import java.util.Arrays; public class Main { public static void main(String[] args) { Game game = new Game(); + game.play(); + } } diff --git a/chess/src/main/java/de/vivi/chess/board/Board.java b/chess/src/main/java/de/vivi/chess/board/Board.java index 7c7b246..3abd3a5 100644 --- a/chess/src/main/java/de/vivi/chess/board/Board.java +++ b/chess/src/main/java/de/vivi/chess/board/Board.java @@ -1,11 +1,11 @@ package de.vivi.chess.board; -import de.vivi.chess.pieces.Piece; +import de.vivi.chess.pieces.*; +import de.vivi.chess.game.Game; public class Board { private static final int SIZE = 8; - private final Piece[/* column */][/* row */] grid; public Board() { @@ -21,8 +21,52 @@ public class Board { * in the bottom two rows. "White queen, white field, black * queen, black field". */ - private void setup() { + private void setup() { + grid[0][0] = new Rook(Color.BLACK, Type.ROOK, new Field(0, 0)); + grid[1][0] = new Knight(Color.BLACK, Type.KNIGHT, new Field(1, 0)); + grid[2][0] = new Bishop(Color.BLACK, Type.BISHOP, new Field(2, 0)); + grid[3][0] = new Queen(Color.BLACK, Type.QUEEN, new Field(3, 0)); + grid[4][0] = new King(Color.BLACK, Type.KING, new Field(4, 0)); + grid[5][0] = new Bishop(Color.BLACK, Type.BISHOP, new Field(5, 0)); + grid[6][0] = new Knight(Color.BLACK, Type.KNIGHT, new Field(6, 0)); + grid[7][0] = new Rook(Color.BLACK, Type.ROOK, new Field(7, 0)); + //grid[0][0] = new Rook(Color.BLACK, Type.ROOK); +// grid[1][0] = new Knight(Color.BLACK, Type.KNIGHT); +// grid[2][0] = new Bishop(Color.BLACK, Type.BISHOP); +// grid[3][0] = new Queen(Color.BLACK, Type.QUEEN); +// grid[4][0] = new King(Color.BLACK, Type.KING); +// grid[5][0] = new Bishop(Color.BLACK, Type.BISHOP); +// grid[6][0] = new Knight(Color.BLACK, Type.KNIGHT); +// grid[7][0] = new Rook(Color.BLACK, Type.ROOK); + + for (int i = 0; i < SIZE; i++) { + //grid[i][1] = new Pawn(Color.BLACK, Type.PAWN); + grid[i][1] = new Pawn(Color.BLACK, Type.PAWN, new Field(i, 0)); + } + + grid[0][7] = new Rook(Color.WHITE, Type.ROOK, new Field(0, 7)); + grid[1][7] = new Knight(Color.WHITE, Type.KNIGHT, new Field(1, 7)); + grid[2][7] = new Bishop(Color.WHITE, Type.BISHOP, new Field(2, 7)); + grid[3][7] = new Queen(Color.WHITE, Type.QUEEN, new Field(3, 7)); + grid[4][7] = new King(Color.WHITE, Type.KING, new Field(4, 7)); + grid[5][7] = new Bishop(Color.WHITE, Type.BISHOP, new Field(5, 7)); + grid[6][7] = new Knight(Color.WHITE, Type.KNIGHT, new Field(6, 7)); + grid[7][7] = new Rook(Color.WHITE, Type.ROOK, new Field(7, 7)); + +// grid[0][7] = new Rook(Color.WHITE, Type.ROOK); +// grid[1][7] = new Knight(Color.WHITE, Type.KNIGHT); +// grid[2][7] = new Bishop(Color.WHITE, Type.BISHOP); +// grid[3][7] = new Queen(Color.WHITE, Type.QUEEN); +// grid[4][7] = new King(Color.WHITE, Type.KING); +// grid[5][7] = new Bishop(Color.WHITE, Type.BISHOP); +// grid[6][7] = new Knight(Color.WHITE, Type.KNIGHT); +// grid[7][7] = new Rook(Color.WHITE, Type.ROOK); + + for (int i = 0; i < SIZE; i++) { + //grid[i][6] = new Pawn(Color.WHITE, Type.PAWN); + grid[i][6] = new Pawn(Color.WHITE, Type.PAWN, new Field(i, 6)); + } } /** @@ -34,7 +78,11 @@ public class Board { * just getting replaced. */ public void move(Field from, Field to) { - + if (grid[from.getColumn()][from.getRow()] != null) { + grid[to.getColumn()][to.getRow()] = grid[from.getColumn()][from.getRow()]; + grid[to.getColumn()][to.getRow()].setField(to); + grid[from.getColumn()][from.getRow()] = null; + } } /** @@ -44,7 +92,22 @@ public class Board { * present it just returns null. */ public Piece getPiece(Field field) { - return null; + return grid[field.getColumn()][field.getRow()]; + } + + public Piece[][] getBoard() { + return grid; + } + + public Piece getPiece(int column, int row) { + return grid[column][row]; + } + + public void setPiece(int column, int row, Piece piece) { + grid[column][row] = piece; + if (piece != null) { + piece.setField(new Field(column, row)); + } } @Override diff --git a/chess/src/main/java/de/vivi/chess/board/Field.java b/chess/src/main/java/de/vivi/chess/board/Field.java index 735b06b..3d5e3a6 100644 --- a/chess/src/main/java/de/vivi/chess/board/Field.java +++ b/chess/src/main/java/de/vivi/chess/board/Field.java @@ -1,5 +1,7 @@ package de.vivi.chess.board; +import de.vivi.chess.pieces.Piece; + /** * TODO: implement fields and constructor *

@@ -8,6 +10,14 @@ package de.vivi.chess.board; */ public class Field { + private int column; + private int row; + + public Field(int column, int row) { + this.column = column; + this.row = row; + } + /** * TODO: implement *

@@ -15,7 +25,7 @@ public class Field { * column and row indices. */ public static Field from(int column, int row) { - return null; + return new Field(column, row); } /** @@ -28,16 +38,81 @@ public class Field { * it should throw an IllegalArgument exception. */ public static Field fromString(String value) throws IllegalArgumentException { - return null; + try { + char[] array = value.toCharArray(); + int column_ = 0; + int row_ = 0; + + switch (array[0]) { + case 'A': + column_ = 0; + break; + case 'B': + column_ = 1; + break; + case 'C': + column_ = 2; + break; + case 'D': + column_ = 3; + break; + case 'E': + column_ = 4; + break; + case 'F': + column_ = 5; + break; + case 'G': + column_ = 6; + break; + case 'H': + column_ = 7; + break; + default: + System.out.println("Wrong input"); + } + + switch (array[1]) { + case '1': + row_ = 0; + break; + case '2': + row_ = 1; + break; + case '3': + row_ = 2; + break; + case '4': + row_ = 3; + break; + case '5': + row_ = 4; + break; + case '6': + row_ = 5; + break; + case '7': + row_ = 6; + break; + case '8': + row_ = 7; + break; + default: + System.out.println("Wrong input"); + } + return from(column_, row_); + } catch (RuntimeException e) { + throw new RuntimeException(e); + } } public int getColumn() { // TODO: implement - return -1; + return column; } public int getRow() { // TODO: implement - return -1; + return row; } } diff --git a/chess/src/main/java/de/vivi/chess/game/Game.java b/chess/src/main/java/de/vivi/chess/game/Game.java index be43c30..671d3d4 100644 --- a/chess/src/main/java/de/vivi/chess/game/Game.java +++ b/chess/src/main/java/de/vivi/chess/game/Game.java @@ -1,19 +1,30 @@ package de.vivi.chess.game; import de.vivi.chess.board.Board; +import de.vivi.chess.board.Field; import de.vivi.chess.pieces.Color; +import de.vivi.chess.pieces.King; +import de.vivi.chess.pieces.Piece; + +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +import static de.vivi.chess.pieces.Color.BLACK; +import static de.vivi.chess.pieces.Color.WHITE; public class Game { - private final Board board; - + private Board board; private Color player; + private int count = 0; + private boolean whiteTurn = true; /** * TODO: implement */ public Game() { - board = null; + this.board = new Board(); player = null; } @@ -24,6 +35,296 @@ public class Game { * specified inside example-output.txt. */ public void play() { + System.out.println("Welcome to Vivi's Chess Game!"); + System.out.println(board); + player = ((count % 2) == 0) ? WHITE : BLACK; + System.out.println("It is white's turn: [from:to]"); + + Scanner scanner = new Scanner(System.in); + + while (scanner.hasNext()) { + + scanner.useDelimiter(":\\s*"); + String fromString = scanner.nextLine(); + + char[] arrayInRange = fromString.toCharArray(); + + if ((arrayInRange[0] == 'A' || + arrayInRange[0] == 'B' || + arrayInRange[0] == 'C' || + arrayInRange[0] == 'D' || + arrayInRange[0] == 'E' || + arrayInRange[0] == 'F' || + arrayInRange[0] == 'G' || + arrayInRange[0] == 'H' ) && + (arrayInRange[1] == '0' || + arrayInRange[1] == '1' || + arrayInRange[1] == '2' || + arrayInRange[1] == '3' || + arrayInRange[1] == '4' || + arrayInRange[1] == '5' || + arrayInRange[1] == '6' || + arrayInRange[1] == '7' || + arrayInRange[1] == '8' )) { + + StringBuilder sb=new StringBuilder(fromString); + int l=sb.length(); + + if (l == 2) { + String toString = scanner.nextLine(); + Field from = Field.fromString(fromString); + Field to = Field.fromString(toString); + + System.out.println("player == WHITE && board.getPiece(from).getColor() == WHITE " + + (player == WHITE && board.getPiece(from).getColor() == WHITE)); + + + System.out.println("board.getPiece(from).isValidMove(board, from,to) " + + (board.getPiece(from).isValidMove(board, from,to))); + + if (player == WHITE && board.getPiece(from).getColor() == WHITE) { + if (board.getPiece(from).isValidMove(board, from,to)) { + count++; + board.move(from, to); + System.out.println("Moving white " + board.getPiece(to).getType() + + " from " + fromString + " to " + toString); + } + System.out.println(board); + } else if (player == BLACK && board.getPiece(from).getColor() == BLACK) { + if (board.getPiece(from).isValidMove(board, from,to)) { + count++; + board.move(from, to); + System.out.println("Moving black " + board.getPiece(to).getType() + + " from " + fromString + " to " + toString); + } + System.out.println(board); + } else { + System.err.println("Illegal move, try again: "); + } + + player = ((count % 2) == 0) ? WHITE : BLACK; + if (player == BLACK) { + System.out.println("It is black's turn: [from:to]"); + } else { + System.out.println("It is white's turn: [from:to]"); + } + } else { + System.err.println("Illegal move, try again: "); + } + } else + System.err.println("Illegal move, try again: "); + } + } + + public Board getBoard() { + return this.board; + } + + public void resetGame() { + this.board = new Board(); + this.whiteTurn = true; + } + + public Color getCurrentPlayerColor() { + return whiteTurn ? Color.WHITE : Color.BLACK; + } + + private Field selectedField; + + public boolean isPieceSelected() { + return selectedField != null; + } + + public boolean handleSquareSelection(int row, int col) { + if (selectedField == null) { + Piece selectedPiece = board.getPiece(row, col); + if (selectedPiece != null + && selectedPiece.getColor() == (whiteTurn ? Color.WHITE : Color.BLACK)) { + selectedField = new Field(row, col); + return false; + } + } else { + boolean moveMade = makeMove(selectedField, new Field(row, col)); + selectedField = null; + return moveMade; + } + return false; + } + + public boolean makeMove(Field from, Field to) { + Piece movingPiece = board.getPiece(Field.from(from.getRow(), from.getColumn())); + if (movingPiece == null || movingPiece.getColor() != (whiteTurn ? WHITE : BLACK)) { + return false; + } + + if (movingPiece.isValidMove(board, movingPiece.getField(), to)) { + board.move(from, to); + whiteTurn = !whiteTurn; + return true; + } + return false; + } + + public boolean isInCheck(Color kingColor) { + Field kingPosition = findKingPosition(kingColor); + for (int row = 0; row < 8; row++) { + for (int col = 0; col < 8; col++) { + Piece piece = board.getPiece(Field.from(row, col)); + if (piece != null && piece.getColor() != kingColor) { + if (piece.isValidMove(board, piece.getField(), kingPosition)) { + return true; + } + } + } + } + return false; } + + private Field findKingPosition(Color color) { + for (int row = 0; row < 8; row++) { + for (int col = 0; col < 8; col++) { + Piece piece = board.getPiece(Field.from(row, col)); + if (piece instanceof King && piece.getColor() == color) { + return new Field(row, col); + } + } + } + throw new RuntimeException("King not found, which should never happen."); + } + + public boolean isCheckmate(Color kingColor) { + if (!isInCheck(kingColor)) { + return false; + } + + Field kingPosition = findKingPosition(kingColor); + King king = (King) board.getPiece(Field.from(kingPosition.getRow(), kingPosition.getColumn())); + + for (int rowOffset = -1; rowOffset <= 1; rowOffset++) { + for (int colOffset = -1; colOffset <= 1; colOffset++) { + if (rowOffset == 0 && colOffset == 0) { + continue; + } + Field newPosition = new Field(kingPosition.getRow() + rowOffset, + kingPosition.getColumn() + colOffset); + if ( + isPositionOnBoard(newPosition) && + king.isValidMove(board, king.getField() , newPosition) + && !wouldBeInCheckAfterMove(kingColor, kingPosition, newPosition)) { + return false; + } + } + } + + return true; + + } + + private boolean isPositionOnBoard(Field field) { + return field.getRow() >= 0 && field.getRow() < 8 && + field.getColumn() >= 0 && field.getColumn() < 8; + + } + + private boolean wouldBeInCheckAfterMove(Color kingColor, Field from, Field to) { + Piece temp = board.getPiece(Field.from(to.getRow(), to.getColumn())); + board.setPiece(to.getRow(), to.getColumn(), board.getPiece(to)); + board.setPiece(from.getRow(), from.getColumn(), null); + + boolean inCheck = isInCheck(kingColor); + + board.setPiece(from.getRow(), from.getColumn(), board.getPiece(to.getRow(), to.getColumn())); + board.setPiece(to.getRow(), to.getColumn(), temp); + + return inCheck; + } + + public List getLegalMovesForPieceAt(Field field) { + Piece selectedPiece = board.getPiece(field.getRow(), field.getColumn()); + if (selectedPiece == null) + return new ArrayList<>(); + + List legalMoves = new ArrayList<>(); + switch (selectedPiece.getClass().getSimpleName()) { + case "Pawn": + addPawnMoves(field, selectedPiece.getColor(), legalMoves); + break; + case "Rook": + addLineMoves(field, new int[][] { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } }, legalMoves); + break; + case "Knight": + addSingleMoves(field, new int[][] { { 2, 1 }, { 2, -1 }, { -2, 1 }, { -2, -1 }, { 1, 2 }, { -1, 2 }, + { 1, -2 }, { -1, -2 } }, legalMoves); + break; + case "Bishop": + addLineMoves(field, new int[][] { { 1, 1 }, { -1, -1 }, { 1, -1 }, { -1, 1 } }, legalMoves); + break; + case "Queen": + addLineMoves(field, new int[][] { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 }, { 1, 1 }, { -1, -1 }, + { 1, -1 }, { -1, 1 } }, legalMoves); + break; + case "King": + addSingleMoves(field, new int[][] { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 }, { 1, 1 }, { -1, -1 }, + { 1, -1 }, { -1, 1 } }, legalMoves); + break; + } + return legalMoves; + } + + private void addLineMoves(Field field, int[][] directions, List legalMoves) { + for (int[] d : directions) { + Field newPos = new Field(field.getRow() + d[0], field.getColumn() + d[1]); + while (isPositionOnBoard(newPos)) { + if (board.getPiece(newPos.getRow(), newPos.getColumn()) == null) { + legalMoves.add(new Field(newPos.getRow(), newPos.getColumn())); + newPos = new Field(newPos.getRow() + d[0], newPos.getColumn() + d[1]); + } else { + if (board.getPiece(newPos.getRow(), newPos.getColumn()).getColor() != board + .getPiece(field.getRow(), field.getColumn()).getColor()) { + legalMoves.add(newPos); + } + break; + } + } + } + } + + private void addSingleMoves(Field field, int[][] moves, List legalMoves) { + for (int[] move : moves) { + Field newPos = new Field(field.getRow() + move[0], field.getColumn() + move[1]); + if (isPositionOnBoard(newPos) && (board.getPiece(newPos.getRow(), newPos.getColumn()) == null || + board.getPiece(newPos.getRow(), newPos.getColumn()).getColor() != board + .getPiece(field.getRow(), field.getColumn()).getColor())) { + legalMoves.add(newPos); + } + } + } + + private void addPawnMoves(Field field, Color color, List legalMoves) { + int direction = color == WHITE ? -1 : 1; + Field newPos = new Field(field.getRow() + direction, field.getColumn()); + if (isPositionOnBoard(newPos) && board.getPiece(newPos.getRow(), newPos.getColumn()) == null) { + legalMoves.add(newPos); + } + + if ((color == Color.WHITE && field.getRow() == 6) + || (color == Color.BLACK && field.getRow() == 1)) { + newPos = new Field(field.getRow() + 2 * direction, field.getColumn()); + Field intermediatePos = new Field(field.getRow() + direction, field.getColumn()); + if (isPositionOnBoard(newPos) && board.getPiece(newPos.getRow(), newPos.getColumn()) == null + && board.getPiece(intermediatePos.getRow(), intermediatePos.getColumn()) == null) { + legalMoves.add(newPos); + } + } + + int[] captureCols = { field.getColumn() - 1, field.getColumn() + 1 }; + for (int col : captureCols) { + newPos = new Field(field.getRow() + direction, col); + if (isPositionOnBoard(newPos) && board.getPiece(newPos.getRow(), newPos.getColumn()) != null && + board.getPiece(newPos.getRow(), newPos.getColumn()).getColor() != color) { + legalMoves.add(newPos); + } + } + } } diff --git a/chess/pieces/Bishop.java b/chess/src/main/java/de/vivi/chess/pieces/Bishop.java similarity index 100% rename from chess/pieces/Bishop.java rename to chess/src/main/java/de/vivi/chess/pieces/Bishop.java diff --git a/chess/src/main/java/de/vivi/chess/pieces/Color.java b/chess/src/main/java/de/vivi/chess/pieces/Color.java index 6ff2949..b3cf8d7 100644 --- a/chess/src/main/java/de/vivi/chess/pieces/Color.java +++ b/chess/src/main/java/de/vivi/chess/pieces/Color.java @@ -4,4 +4,6 @@ package de.vivi.chess.pieces; * TODO: add colors (white and black) */ public enum Color { + WHITE, + BLACK } diff --git a/chess/pieces/King.java b/chess/src/main/java/de/vivi/chess/pieces/King.java similarity index 100% rename from chess/pieces/King.java rename to chess/src/main/java/de/vivi/chess/pieces/King.java diff --git a/chess/pieces/Knight.java b/chess/src/main/java/de/vivi/chess/pieces/Knight.java similarity index 100% rename from chess/pieces/Knight.java rename to chess/src/main/java/de/vivi/chess/pieces/Knight.java diff --git a/chess/pieces/Pawn.java b/chess/src/main/java/de/vivi/chess/pieces/Pawn.java similarity index 100% rename from chess/pieces/Pawn.java rename to chess/src/main/java/de/vivi/chess/pieces/Pawn.java diff --git a/chess/src/main/java/de/vivi/chess/pieces/Piece.java b/chess/src/main/java/de/vivi/chess/pieces/Piece.java index a685db8..2234b52 100644 --- a/chess/src/main/java/de/vivi/chess/pieces/Piece.java +++ b/chess/src/main/java/de/vivi/chess/pieces/Piece.java @@ -5,6 +5,28 @@ import de.vivi.chess.board.Field; public abstract class Piece { + Color color; + private Type type; + protected char symbol; + protected Field field; + + protected Piece(Color color, Type type) { + this.color = color; + this.type = type; + symbol = '\u0000'; + } + + protected Piece(Color color, Field field) { + this.color = color; + this.field = field; + } + + protected Piece(Color color, Type type, Field field) { + this.color = color; + this.type = type; + this.field = field; + } + /** * TODO: implement *

@@ -16,14 +38,15 @@ public abstract class Piece { */ public abstract boolean isValidMove(Board board, Field from, Field to); + public Color getColor() { // TODO: implement - return null; + return color; } public Type getType() { // TODO: implement - return null; + return type; } /** @@ -34,6 +57,14 @@ public abstract class Piece { * Unicode chess pieces */ public char getSymbol() { - return 0; + return symbol; + } + + public Field getField() { + return field; + } + + public void setField(Field field) { + this.field = field; } } diff --git a/chess/pieces/Queen.java b/chess/src/main/java/de/vivi/chess/pieces/Queen.java similarity index 100% rename from chess/pieces/Queen.java rename to chess/src/main/java/de/vivi/chess/pieces/Queen.java diff --git a/chess/pieces/Rook.java b/chess/src/main/java/de/vivi/chess/pieces/Rook.java similarity index 100% rename from chess/pieces/Rook.java rename to chess/src/main/java/de/vivi/chess/pieces/Rook.java diff --git a/chess/src/main/java/de/vivi/chess/pieces/Type.java b/chess/src/main/java/de/vivi/chess/pieces/Type.java index adeef34..1b7f635 100644 --- a/chess/src/main/java/de/vivi/chess/pieces/Type.java +++ b/chess/src/main/java/de/vivi/chess/pieces/Type.java @@ -14,4 +14,10 @@ package de.vivi.chess.pieces; * - pawn (Bauer) */ public enum Type { + KING, + QUEEN, + BISHOP, + KNIGHT, + ROOK, + PAWN }