diff --git a/.gitignore b/.gitignore index fc7ea37..a38acda 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,7 @@ .idea #Ignore output directory -bin \ No newline at end of file +bin + +# Ignore test lib +lib \ No newline at end of file diff --git a/uebung02/chess/Board.java b/uebung02/chess/Board.java new file mode 100644 index 0000000..74818a1 --- /dev/null +++ b/uebung02/chess/Board.java @@ -0,0 +1,52 @@ +import java.io.PrintStream; +import java.util.ArrayList; + +class Board { + ArrayList Pieces; + + Board() { + this.Pieces = new ArrayList(); + } + + void add(Piece piece) { + if (piece.board != this) + throw new IllegalArgumentException("wrong board"); + if (piece.board.pieceAt(piece.row, piece.col) != null) + throw new IllegalArgumentException("field is occupied"); + Pieces.add(piece); + } + + void printBoard(PrintStream out) { + out.println(" 1 2 3 4 5 6 7 8"); + out.println(" +---+---+---+---+---+---+---+---+"); + for (int Row = 1; Row <= 8; Row++) { + out.print("" + Row + " "); + for (int Col = 1; Col <= 8; Col++) { + final Piece p = pieceAt(Row, Col); + final char c = p == null ? ' ' : p.charRep(); + out.print("| " + c + " "); + } + out.println("|"); + out.println(" +---+---+---+---+---+---+---+---+"); + } + } + + Piece pieceAt(int col, int row) { + for (Piece p : Pieces) + if (p.row == row && p.col == col) + return p; + return null; + } + + void check(PrintStream out) { + for (Piece P1 : Pieces) { + out.println(P1.showPiece()); + for (Piece P2 : Pieces) + if (P1 != P2) + if (P1.canCapture(P2)) + out.println(" can capture " + P2.showPiece()); + else + out.println(" cannot capture " + P2.showPiece()); + } + } +} diff --git a/uebung02/chess/ChessApp.java b/uebung02/chess/ChessApp.java new file mode 100644 index 0000000..6ab4d38 --- /dev/null +++ b/uebung02/chess/ChessApp.java @@ -0,0 +1,11 @@ +public class ChessApp { + public static void main(String[] args) { + final Board board = new Board(); + final Piece p1 = new Piece(Kind.QUEEN, Color.BLACK, board, 4, 1); + final Piece p2 = new Piece(Kind.QUEEN, Color.WHITE, board, 4, 8); + final Piece p3 = new Piece(Kind.KNIGHT, Color.WHITE, board, 3, 3); + final Piece p4 = new Piece(Kind.KNIGHT, Color.BLACK, board, 4, 6); + board.printBoard(System.out); + board.check(System.out); + } +} diff --git a/uebung02/chess/ChessTest.java b/uebung02/chess/ChessTest.java new file mode 100644 index 0000000..808176c --- /dev/null +++ b/uebung02/chess/ChessTest.java @@ -0,0 +1,162 @@ +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class ChessTest { + // Das Zeilenende wird auf Windows-Systemen anders codiert als auf Nicht-Windows-Systemen. + // Die folgende Zeile ermittelt die aktuelle Codierung. + // EOL = "End of Line" + private static final String LS = System.lineSeparator(); + private static final String HE = " 1 2 3 4 5 6 7 8" + LS; + private static final String LI = " +---+---+---+---+---+---+---+---+" + LS; + private static final String EMP = " | | | | | | | | |" + LS; + private static final String WK1 = " | n | | | | | | | |" + LS; + private static final String WQ3 = " | | | q | | | | | |" + LS; + private static final String CO1 = " | | | n | | N | Q | | |" + LS; + private static final String INIT_BOARD = board(EMP, EMP, EMP, EMP, EMP, EMP, EMP, EMP); + private static final String WK61_BOARD = board(EMP, EMP, EMP, EMP, EMP, WK1, EMP, EMP); + private static final String APP1_BOARD = board(EMP, EMP, EMP, EMP, WQ3, CO1, EMP, EMP); + private static final String CHECK_TEXT1 = "white queen at (4, 2)" + LS + + " cannot capture black queen at (8, 6)" + LS + + " cannot capture white knight at (6, 4)" + LS + + "black queen at (8, 6)" + LS + + " cannot capture white queen at (4, 2)" + LS + + " can capture white knight at (6, 4)" + LS + + "white knight at (6, 4)" + LS + + " cannot capture white queen at (4, 2)" + LS + + " cannot capture black queen at (8, 6)" + LS; + private static final String CHECK_TEXT2 = "white knight at (6, 3)" + LS + + " cannot capture black knight at (6, 5)" + LS + + " cannot capture black queen at (6, 6)" + LS + + " cannot capture white queen at (5, 3)" + LS + + "black knight at (6, 5)" + LS + + " cannot capture white knight at (6, 3)" + LS + + " cannot capture black queen at (6, 6)" + LS + + " can capture white queen at (5, 3)" + LS + + "black queen at (6, 6)" + LS + + " cannot capture white knight at (6, 3)" + LS + + " cannot capture black knight at (6, 5)" + LS + + " cannot capture white queen at (5, 3)" + LS + + "white queen at (5, 3)" + LS + + " cannot capture white knight at (6, 3)" + LS + + " cannot capture black knight at (6, 5)" + LS + + " cannot capture black queen at (6, 6)" + LS; + + private static String board(String... s) { + if (s.length != 8) + throw new IllegalArgumentException("Expected 8, but got " + s.length + " arguments"); + StringBuilder sb = new StringBuilder(); + sb.append(HE).append(LI); + for (int i = 1; i <= 8; i++) + sb.append(i).append(s[i - 1]).append(LI); + return sb.toString(); + } + + private Board board; + private PrintStream printStream; + private ByteArrayOutputStream printed; + + @Before + public void setup() { + board = new Board(); + printed = new ByteArrayOutputStream(); + printStream = new PrintStream(printed, true); + } + + @After + public void tearDown() { + printStream.close(); + } + + @Test + public void testEmpty() { + board.printBoard(printStream); + assertEquals(INIT_BOARD, printed.toString()); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidPos1() { + new Piece(Kind.KNIGHT, Color.WHITE, board, 0, 4); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidPos2() { + new Piece(Kind.QUEEN, Color.WHITE, board, 0, 4); + } + + @Test + public void testWhiteknight() { + final Piece knight = new Piece(Kind.KNIGHT, Color.WHITE, board, 6, 1); + checkPieces(1); + assertEquals(knight, board.pieceAt(6, 1)); + board.printBoard(printStream); + assertEquals(WK61_BOARD, printed.toString()); + } + + @Test + public void test3Pieces() { + final Piece queen1 = new Piece(Kind.QUEEN, Color.WHITE, board, 4, 2); + final Piece queen2 = new Piece(Kind.QUEEN, Color.BLACK, board, 8, 6); + final Piece knight = new Piece(Kind.KNIGHT, Color.WHITE, board, 6, 4); + assertFalse(queen1.canCapture(queen2)); + assertFalse(queen1.canCapture(knight)); + assertFalse(queen2.canCapture(queen1)); + assertTrue(queen2.canCapture(knight)); + assertFalse(knight.canCapture(queen1)); + assertFalse(knight.canCapture(queen2)); + checkPieces(3); + assertEquals(queen1, board.pieceAt(4, 2)); + assertEquals(queen2, board.pieceAt(8, 6)); + assertEquals(knight, board.pieceAt(6, 4)); + printed.reset(); + board.check(printStream); + assertEquals(CHECK_TEXT1, printed.toString()); + } + + @Test + public void test4Pieces() { + final Piece knight1 = new Piece(Kind.KNIGHT, Color.WHITE, board, 6, 3); + final Piece knight2 = new Piece(Kind.KNIGHT, Color.BLACK, board, 6, 5); + final Piece queen1 = new Piece(Kind.QUEEN, Color.BLACK, board, 6, 6); + final Piece queen2 = new Piece(Kind.QUEEN, Color.WHITE, board, 5, 3); + checkPieces(4); + assertEquals(knight1, board.pieceAt(6, 3)); + assertEquals(knight2, board.pieceAt(6, 5)); + assertEquals(queen1, board.pieceAt(6, 6)); + assertEquals(queen2, board.pieceAt(5, 3)); + printed.reset(); + board.printBoard(printStream); + assertEquals(APP1_BOARD, printed.toString()); + assertFalse(knight1.canCapture(knight2)); + assertFalse(knight1.canCapture(queen1)); + assertFalse(knight1.canCapture(queen2)); + assertFalse(knight2.canCapture(knight1)); + assertFalse(knight2.canCapture(queen1)); + assertTrue(knight2.canCapture(queen2)); + assertFalse(queen1.canCapture(knight1)); + assertFalse(queen1.canCapture(knight2)); + assertFalse(queen1.canCapture(queen2)); + assertFalse(queen2.canCapture(knight1)); + assertFalse(queen2.canCapture(knight2)); + assertFalse(queen2.canCapture(queen1)); + printed.reset(); + board.check(printStream); + assertEquals(CHECK_TEXT2, printed.toString()); + } + + private void checkPieces(int expectedNumPieces) { + int numPieces = 0; + for (int row = 0; row < 9; row++) + for (int col = 0; col < 9; col++) + if (board.pieceAt(row, col) != null) + numPieces++; + assertEquals(expectedNumPieces, numPieces); + } +} \ No newline at end of file diff --git a/uebung02/chess/Color.java b/uebung02/chess/Color.java new file mode 100644 index 0000000..c29738d --- /dev/null +++ b/uebung02/chess/Color.java @@ -0,0 +1,3 @@ +public enum Color { + BLACK, WHITE +} diff --git a/uebung02/chess/Kind.java b/uebung02/chess/Kind.java new file mode 100644 index 0000000..8bb73c3 --- /dev/null +++ b/uebung02/chess/Kind.java @@ -0,0 +1,3 @@ +public enum Kind { + QUEEN, KNIGHT +} diff --git a/uebung02/chess/Piece.java b/uebung02/chess/Piece.java new file mode 100644 index 0000000..98da724 --- /dev/null +++ b/uebung02/chess/Piece.java @@ -0,0 +1,100 @@ +import static java.lang.Integer.signum; +import static java.lang.Math.abs; + +class Piece { + Kind kind; + Color color; + Board board; + int row; + int col; + + Piece(Kind kind, Color color, Board board, int row, int col) { + if (row < 1 || row > 8 || col < 1 || col > 8) + throw new IllegalArgumentException("Invalid pos " + row + "/" + col); + this.kind = kind; + this.color = color; + this.board = board; + this.row = row; + this.col = col; + board.add(this); + } + + char charRep() { + switch (kind) { + case QUEEN: + return queenCharRep(); + case KNIGHT: + return knightCharRep(); + } + throw new IllegalArgumentException("Unknown piece " + kind); + } + + String showPiece() { + switch (kind) { + case QUEEN: + return queenShowPiece(); + case KNIGHT: + return knightShowPiece(); + } + throw new IllegalArgumentException("Unknown piece " + kind); + } + + boolean canCapture(Piece other) { + switch (kind) { + case QUEEN: + return queenCanCapture(other); + case KNIGHT: + return knightCanCapture(other); + } + throw new IllegalArgumentException("Unknown piece " + kind); + } + + char queenCharRep() { + if (color == Color.WHITE) + return 'q'; + else + return 'Q'; + } + + char knightCharRep() { + if (color == Color.WHITE) + return 'n'; + else + return 'N'; + } + + String queenShowPiece() { + return "" + color.toString().toLowerCase() + " queen at (" + row + ", " + col + ")"; + } + + String knightShowPiece() { + return "" + color.toString().toLowerCase() + " knight at (" + row + ", " + col + ")"; + } + + boolean queenCanCapture(Piece other) { + if (board != other.board || color == other.color) + return false; + if (other.row != row && + other.col != col && + abs(other.row - row) != abs(other.col - col)) + return false; + final int dr = signum(other.row - row); + final int dc = signum(other.col - col); + int r = row + dr; + int c = col + dc; + while (r != other.row || c != other.col) { + if (board.pieceAt(r, c) != null) return false; + r += dr; + c += dc; + } + return true; + } + + boolean knightCanCapture(Piece other) { + if (board != other.board || color == other.color) + return false; + final int dr = abs(row - other.row); + final int dc = abs(col - other.col); + return dr == 2 && dc == 1 || dr == 1 && dc == 2; + } +}