diff --git a/src/main/java/.gitkeep b/src/main/java/.gitkeep deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/main/java/chess/Application.java b/src/main/java/chess/Application.java new file mode 100644 index 00000000000..18249b115cb --- /dev/null +++ b/src/main/java/chess/Application.java @@ -0,0 +1,25 @@ +package chess; + +import chess.model.BoardFactory; +import chess.model.ChessBoard; +import chess.model.element.Color; +import chess.model.position.Position; +import chess.view.InputView; +import chess.view.OutputView; + +import java.util.List; + +public class Application { + + public static void main(String[] args) { + BoardFactory boardFactory = new BoardFactory(); + ChessBoard board = boardFactory.generateBoard(); + Color color = Color.WHITE; + while (true) { + color = color.opposite(); + OutputView.printChessBoard(board); + List inputPositions = InputView.readMovePositions(); + board.updatePosition(inputPositions.get(0), inputPositions.get(1), color); + } + } +} diff --git a/src/main/java/chess/model/BoardFactory.java b/src/main/java/chess/model/BoardFactory.java new file mode 100644 index 00000000000..881ee9d75ce --- /dev/null +++ b/src/main/java/chess/model/BoardFactory.java @@ -0,0 +1,27 @@ +package chess.model; + +import chess.model.element.Color; +import chess.model.piece.Piece; +import chess.model.piece.PieceType; +import chess.model.position.Position; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +public class BoardFactory { + + public ChessBoard generateBoard() { + Map positionByPieceData = new HashMap<>(); + for (PieceType pieceType : PieceType.values()) { + for (Color color : Color.values()) { + List initPositionsByColor = pieceType.getInitPositionsByColor(color); + for (Position position : initPositionsByColor) { + positionByPieceData.put(position, pieceType.getPieceByColor(color)); + } + } + } + return new ChessBoard(positionByPieceData); + } +} diff --git a/src/main/java/chess/model/ChessBoard.java b/src/main/java/chess/model/ChessBoard.java new file mode 100644 index 00000000000..b12f36dcc03 --- /dev/null +++ b/src/main/java/chess/model/ChessBoard.java @@ -0,0 +1,56 @@ +package chess.model; + +import chess.model.element.Color; +import chess.model.piece.Piece; +import chess.model.position.Position; + +import java.util.Map; +import java.util.Optional; + +public class ChessBoard { + + Map positionByPieceBoard; + + public ChessBoard(Map boardData) { + this.positionByPieceBoard = boardData; + } + + public void updatePosition(final Position source, final Position destination, final Color teamType) { + validatePositionAndTeam(source, teamType); + validatePieceCanMove(source, destination); + + movePieceToDestination(source, destination); + } + + private void validatePositionAndTeam(final Position source, final Color color) { + if (!positionByPieceBoard.containsKey(source) || !positionByPieceBoard.get(source).getColor().equals(color)) { + throw new IllegalArgumentException("scr 좌표에 기물이 존재하지 않거나, 해당 팀의 기물이 아닙니다."); + } + } + + private void validatePieceCanMove(final Position source, final Position destination) { + final Piece piece = positionByPieceBoard.get(source); + + if (!piece.canMove(source, destination, this)) { + throw new IllegalArgumentException("해당 기물은 해당 위치로 이동할 수 없습니다."); + } + } + + private void movePieceToDestination(final Position source, final Position destination) { + positionByPieceBoard.put(destination, positionByPieceBoard.get(source)); + positionByPieceBoard.remove(source); + } + + + public boolean isExistPosition(Position position) { + return positionByPieceBoard.containsKey(position); + } + + public Optional findPieceByPosition(final Position position) { + return Optional.ofNullable(positionByPieceBoard.get(position)); + } + + public Map getPositionByPieceBoard() { + return positionByPieceBoard; + } +} diff --git a/src/main/java/chess/Color.java b/src/main/java/chess/model/element/Color.java similarity index 72% rename from src/main/java/chess/Color.java rename to src/main/java/chess/model/element/Color.java index 55cd020b681..0d6fc8b403f 100644 --- a/src/main/java/chess/Color.java +++ b/src/main/java/chess/model/element/Color.java @@ -1,10 +1,11 @@ -package chess; +package chess.model.element; public enum Color { BLACK, WHITE, - EMPTY; + ; +// EMPTY; public boolean isWhite() { return this == WHITE; @@ -14,15 +15,14 @@ public boolean isBlack() { return this == BLACK; } - public boolean isEmpty() { - return this == EMPTY; - } +// public boolean isEmpty() { +// return this == EMPTY; +// } public Color opposite() { return switch (this) { case BLACK -> WHITE; case WHITE -> BLACK; - default -> EMPTY; }; } } diff --git a/src/main/java/chess/Movement.java b/src/main/java/chess/model/element/Movement.java similarity index 97% rename from src/main/java/chess/Movement.java rename to src/main/java/chess/model/element/Movement.java index e57c6e91bb9..fd4bdba359f 100644 --- a/src/main/java/chess/Movement.java +++ b/src/main/java/chess/model/element/Movement.java @@ -1,4 +1,4 @@ -package chess; +package chess.model.element; public enum Movement { UP(0, 1), diff --git a/src/main/java/chess/model/piece/Piece.java b/src/main/java/chess/model/piece/Piece.java new file mode 100644 index 00000000000..e4e5c8eee10 --- /dev/null +++ b/src/main/java/chess/model/piece/Piece.java @@ -0,0 +1,78 @@ +package chess.model.piece; + +import chess.model.ChessBoard; +import chess.model.element.Color; +import chess.model.position.Position; + +public abstract class Piece { + + protected final Color color; + + public Piece(Color color) { + this.color = color; + } + + public boolean canMove(Position src, Position dest, ChessBoard board) { + double distanceByPositions = calculateDistanceBy(src, dest); + + if (!isNotWithInDirection(src, dest)) { + return false; + } + if (!isWithInRangeByMovement(distanceByPositions)) { + return false; + } + if (!passFilter(src, dest, board)) { + return false; + } + return true; + } + + protected abstract boolean isNotWithInDirection(Position src, Position dest); + + private double calculateDistanceBy(Position src, Position dest) { + int[] srcNumber = findNumberByPosition(src); + int[] destNumber = findNumberByPosition(dest); + + int xx = calculateSquare(srcNumber[0], destNumber[0]); + int yy = calculateSquare(srcNumber[1], destNumber[1]); + + return Math.sqrt(xx + yy); + } + + protected static int[] findNumberByPosition(Position position) { + int columnNumber = position.column().ordinal(); + int rowNumber = position.row().ordinal(); + return new int[]{rowNumber, columnNumber}; + } + + private static int calculateSquare(int rowNumber, int destNumber) { + return (int) Math.pow(calculateAbs(rowNumber, destNumber), 2); + } + + protected static int calculateAbs(int rowNumber, int destNumber) { + return Math.abs(rowNumber - destNumber); + } + + protected abstract boolean isWithInRangeByMovement(double distance); + + + protected abstract boolean passFilter(Position src, Position dest, ChessBoard board); + + protected boolean isVertical(Position src, Position dest) { // 수직 + int[] srcNumber = findNumberByPosition(src); + int[] destNumber = findNumberByPosition(dest); + + return srcNumber[0] == destNumber[0] && srcNumber[1] != destNumber[1]; + } + + protected boolean isHorizontal(Position src, Position dest) { // 수평 + int[] srcNumber = findNumberByPosition(src); + int[] destNumber = findNumberByPosition(dest); + + return srcNumber[0] != destNumber[0] && srcNumber[1] == destNumber[1]; + } + + public Color getColor() { + return color; + } +} diff --git a/src/main/java/chess/model/piece/PieceType.java b/src/main/java/chess/model/piece/PieceType.java new file mode 100644 index 00000000000..6b5b23268d7 --- /dev/null +++ b/src/main/java/chess/model/piece/PieceType.java @@ -0,0 +1,89 @@ +package chess.model.piece; + +import chess.model.element.Color; +import chess.model.piece.types.*; +import chess.model.position.Position; + +import java.util.List; + +import static chess.model.position.Column.*; + +import static chess.model.position.Row.*; + +public enum PieceType { + + BISHOP(List.of(new Position(C, ONE), new Position(F, ONE)), + List.of(new Position(C, EIGHT), new Position(F, EIGHT)), + new Bishop(Color.BLACK), + new Bishop(Color.WHITE)), + KING(new Position(D, ONE), + new Position(D, EIGHT), + new King(Color.BLACK), + new King(Color.WHITE)), + KNIGHT(List.of(new Position(B, ONE), new Position(G, ONE)), + List.of(new Position(B, EIGHT), new Position(G, EIGHT)), + new Knight(Color.BLACK), + new Knight(Color.WHITE)), + PAWN(List.of(new Position(A, TWO), new Position(B, TWO), new Position(C, TWO), new Position(D, TWO), new Position(E, TWO), new Position(F, TWO), new Position(G, TWO), new Position(H, TWO)), + List.of(new Position(A, SEVEN), new Position(B, SEVEN), new Position(C, SEVEN), new Position(D, SEVEN), new Position(E, SEVEN), new Position(F, SEVEN), new Position(G, SEVEN), new Position(H, SEVEN)), + new Pawn(Color.BLACK), + new Pawn(Color.WHITE)), + QUEEN(new Position(E, ONE), + new Position(E, EIGHT), + new Queen(Color.BLACK), + new Queen(Color.WHITE)), + ROOK(List.of(new Position(A, ONE), new Position(H, ONE)), + List.of(new Position(A, EIGHT), new Position(H, EIGHT)), + new Rook(Color.BLACK), + new Rook(Color.WHITE)), + ; + + private final List whiteInitPositions; + private final List blackInitPositions; + private final Piece pieceByBlack; + private final Piece pieceByWhite; + + PieceType(List whiteInitPositions, List blackInitPositions, Piece pieceByBlack, Piece pieceByWhite) { + this.whiteInitPositions = whiteInitPositions; + this.blackInitPositions = blackInitPositions; + this.pieceByBlack = pieceByBlack; + this.pieceByWhite = pieceByWhite; + } + + PieceType(Position whiteInitPosition, Position blackInitPosition, Piece pieceByBlack, Piece pieceByWhite) { + this.whiteInitPositions = List.of(whiteInitPosition); + this.blackInitPositions = List.of(blackInitPosition); + this.pieceByBlack = pieceByBlack; + this.pieceByWhite = pieceByWhite; + } + + public List getInitPositionsByColor(final Color color) { + if (color.isWhite()) { + return getWhiteInitPositions(); + } + return getBlackInitPositions(); + } + + private List getWhiteInitPositions() { + return whiteInitPositions; + } + + private List getBlackInitPositions() { + return blackInitPositions; + } + + public Piece getPieceByColor(Color color) { + if (color.isWhite()) { + return getPieceByWhite(); + } + return getPieceByBlack(); + } + + public Piece getPieceByBlack() { + return pieceByBlack; + } + + public Piece getPieceByWhite() { + return pieceByWhite; + } +} diff --git a/src/main/java/chess/model/piece/types/Bishop.java b/src/main/java/chess/model/piece/types/Bishop.java new file mode 100644 index 00000000000..f032c82ee63 --- /dev/null +++ b/src/main/java/chess/model/piece/types/Bishop.java @@ -0,0 +1,50 @@ +package chess.model.piece.types; + +import chess.model.ChessBoard; +import chess.model.element.Color; +import chess.model.piece.Piece; +import chess.model.position.Column; +import chess.model.position.Position; +import chess.model.position.Row; + +public class Bishop extends Piece { + + public Bishop(Color color) { + super(color); + } + + @Override + protected boolean isNotWithInDirection(Position src, Position dest) { + // x들 차의 절대값과 y들 차의 절대값이 동일하면 4대각선 내에 존재 + int[] srcNumber = findNumberByPosition(src); + int[] destNumber = findNumberByPosition(dest); + int absX = calculateAbs(srcNumber[0], destNumber[0]); + int absY = calculateAbs(srcNumber[1], destNumber[1]); + return absX == absY; + } + + @Override + protected boolean isWithInRangeByMovement(double distance) { + return true; + } + + + @Override + protected boolean passFilter(Position src, Position dest, ChessBoard board) { + // 4방향 중 어느 방향인지 파악할 것 + int[] srcNumber = findNumberByPosition(src); + int[] destNumber = findNumberByPosition(dest); + int DX = srcNumber[0] - destNumber[0] < 0 ? +1 : -1; + int DY = srcNumber[1] - destNumber[1] < 0 ? +1 : -1; + + // dest까지 어떠한 장애물도 없어야 함 + for (int loop = srcNumber[0], x = srcNumber[0], y = srcNumber[1]; loop < destNumber[0]; loop++, x = x + DX, y = y + DY) { + Row row = Row.findByNumber(x); + Column column = Column.findByNumber(y); + if (board.isExistPosition(new Position(row, column))) { + return false; + } + } + return true; + } +} diff --git a/src/main/java/chess/model/piece/types/King.java b/src/main/java/chess/model/piece/types/King.java new file mode 100644 index 00000000000..38630fb8622 --- /dev/null +++ b/src/main/java/chess/model/piece/types/King.java @@ -0,0 +1,34 @@ +package chess.model.piece.types; + +import chess.model.ChessBoard; +import chess.model.element.Color; +import chess.model.piece.Piece; +import chess.model.position.Position; + +public class King extends Piece { + + public King(Color color) { + super(color); + } + + @Override + protected boolean isNotWithInDirection(Position src, Position dest) { + return true; + } + + @Override + protected boolean isWithInRangeByMovement(double distance) { + if (distance == 1) { + return true; + } + if (distance == Math.sqrt(2)) { + return true; + } + return false; + } + + @Override + protected boolean passFilter(Position src, Position dest, ChessBoard board) { + return true; + } +} diff --git a/src/main/java/chess/model/piece/types/Knight.java b/src/main/java/chess/model/piece/types/Knight.java new file mode 100644 index 00000000000..c32698da469 --- /dev/null +++ b/src/main/java/chess/model/piece/types/Knight.java @@ -0,0 +1,31 @@ +package chess.model.piece.types; + +import chess.model.ChessBoard; +import chess.model.element.Color; +import chess.model.piece.Piece; +import chess.model.position.Position; + +public class Knight extends Piece { + + public Knight(Color color) { + super(color); + } + + @Override + protected boolean isNotWithInDirection(Position src, Position dest) { + return true; + } + + @Override + protected boolean isWithInRangeByMovement(double distance) { + if (distance == Math.sqrt(5)) { + return true; + } + return false; + } + + @Override + protected boolean passFilter(Position src, Position dest, ChessBoard board) { + return true; + } +} diff --git a/src/main/java/chess/model/piece/types/Pawn.java b/src/main/java/chess/model/piece/types/Pawn.java new file mode 100644 index 00000000000..ee8bb0cc4a3 --- /dev/null +++ b/src/main/java/chess/model/piece/types/Pawn.java @@ -0,0 +1,45 @@ +package chess.model.piece.types; + +import chess.model.ChessBoard; +import chess.model.element.Color; +import chess.model.piece.Piece; +import chess.model.position.Position; + +public class Pawn extends Piece { + + public Pawn(Color color) { + super(color); + } + + @Override + protected boolean isNotWithInDirection(Position src, Position dest) { + int[] srcNumber = findNumberByPosition(src); + int[] destNumber = findNumberByPosition(dest); + + if (color.isBlack()) { + if (destNumber[0] != srcNumber[0] - 1) { // 아래 방향 3개 + return false; + } + } + if (destNumber[0] != srcNumber[0] + 1) { // 윗 방향 3개 + return false; + } + return true; + } + + @Override + protected boolean isWithInRangeByMovement(double distance) { + if (distance == 1) { + return true; + } + if (distance == Math.sqrt(2)) { + return true; + } + return false; + } + + @Override + protected boolean passFilter(Position src, Position dest, ChessBoard board) { + return true; + } +} diff --git a/src/main/java/chess/model/piece/types/Queen.java b/src/main/java/chess/model/piece/types/Queen.java new file mode 100644 index 00000000000..507fea65230 --- /dev/null +++ b/src/main/java/chess/model/piece/types/Queen.java @@ -0,0 +1,74 @@ +package chess.model.piece.types; + +import chess.model.ChessBoard; +import chess.model.element.Color; +import chess.model.piece.Piece; +import chess.model.position.Column; +import chess.model.position.Position; +import chess.model.position.Row; + +public class Queen extends Piece { + + public Queen(Color color) { + super(color); + } + + @Override + protected boolean isNotWithInDirection(Position src, Position dest) { + return true; + } + + @Override + protected boolean isWithInRangeByMovement(double distance) { + return true; + } + + @Override + protected boolean passFilter(Position src, Position dest, ChessBoard board) { + /* + 8방향 중 대각선, 동서남북 분리하여 작성 + */ + + int[] srcNumber = findNumberByPosition(src); + int[] destNumber = findNumberByPosition(dest); + + if (isHorizontal(src, dest)) { // 수평 column 다름 + int rowN = srcNumber[0]; + for (int cNum = Math.min(srcNumber[1], destNumber[1]); cNum < Math.max(srcNumber[1], destNumber[1]); cNum++) { + Row row = Row.findByNumber(rowN); + Column column = Column.findByNumber(cNum); + if (board.isExistPosition(new Position(row, column))) { + return false; + } + } + return true; + } + + if (isVertical(src, dest)) { // 수직 row 다름 + int colN = srcNumber[1]; + for (int sNum = Math.min(srcNumber[0], destNumber[0]); sNum < Math.max(srcNumber[0], destNumber[0]); sNum++) { + Row row = Row.findByNumber(sNum); + Column column = Column.findByNumber(colN); + if (board.isExistPosition(new Position(row, column))) { + return false; + } + } + return true; + } + + // 4방향 중 어느 방향인지 파악할 것 + + int DX = srcNumber[0] - destNumber[0] < 0 ? +1 : -1; + int DY = srcNumber[1] - destNumber[1] < 0 ? +1 : -1; + + // dest까지 어떠한 장애물도 없어야 함 + for (int loop = srcNumber[0], x = srcNumber[0], y = srcNumber[1]; loop < destNumber[0]; loop++, x = x + DX, y = y + DY) { + Row row = Row.findByNumber(x); + Column column = Column.findByNumber(y); + if (board.isExistPosition(new Position(row, column))) { + return false; + } + } + return true; + } +} diff --git a/src/main/java/chess/model/piece/types/Rook.java b/src/main/java/chess/model/piece/types/Rook.java new file mode 100644 index 00000000000..7b89789e228 --- /dev/null +++ b/src/main/java/chess/model/piece/types/Rook.java @@ -0,0 +1,62 @@ +package chess.model.piece.types; + +import chess.model.ChessBoard; +import chess.model.element.Color; +import chess.model.piece.Piece; +import chess.model.position.Column; +import chess.model.position.Position; +import chess.model.position.Row; + +public class Rook extends Piece { + + public Rook(Color color) { + super(color); + } + + @Override + protected boolean isNotWithInDirection(Position src, Position dest) { + if (!isHorizontal(src, dest)) { + return false; + } + if (!isVertical(src, dest)) { + return false; + } + return true; + } + + @Override + protected boolean isWithInRangeByMovement(double distance) { + return true; + } + + @Override + protected boolean passFilter(Position src, Position dest, ChessBoard board) { + // 중간에 장애물이 없어야 함 + + int[] srcNumber = findNumberByPosition(src); + int[] destNumber = findNumberByPosition(dest); + + if (isHorizontal(src, dest)) { // 수평 column 다름 + int rowN = srcNumber[0]; + for (int cNum = Math.min(srcNumber[1], destNumber[1]); cNum < Math.max(srcNumber[1], destNumber[1]); cNum++) { + Row row = Row.findByNumber(rowN); + Column column = Column.findByNumber(cNum); + if (board.isExistPosition(new Position(row, column))) { + return false; + } + } + return true; + } + + + int colN = srcNumber[1]; + for (int sNum = Math.min(srcNumber[0], destNumber[0]); sNum < Math.max(srcNumber[0], destNumber[0]); sNum++) { + Row row = Row.findByNumber(sNum); + Column column = Column.findByNumber(colN); + if (board.isExistPosition(new Position(row, column))) { + return false; + } + } + return true; + } +} diff --git a/src/main/java/chess/Column.java b/src/main/java/chess/model/position/Column.java similarity index 72% rename from src/main/java/chess/Column.java rename to src/main/java/chess/model/position/Column.java index b64b4dc77a3..e5927c9dc0d 100644 --- a/src/main/java/chess/Column.java +++ b/src/main/java/chess/model/position/Column.java @@ -1,4 +1,6 @@ -package chess; +package chess.model.position; + +import java.util.Arrays; public enum Column { @@ -50,4 +52,11 @@ public Column moveRight(final int step) { throw new IllegalStateException("움직일 수 없는 위치입니다."); } + + public static Column findByNumber(int number) { + return Arrays.stream(Column.values()) + .filter(o -> o.ordinal() == 8 - number) + .findFirst() + .orElseThrow(() -> new IllegalStateException("존재하지 않는 number로 Column를 찾으려 하고 있습니다")); + } } diff --git a/src/main/java/chess/Position.java b/src/main/java/chess/model/position/Position.java similarity index 94% rename from src/main/java/chess/Position.java rename to src/main/java/chess/model/position/Position.java index 3ebeb0ea185..489e1b88401 100644 --- a/src/main/java/chess/Position.java +++ b/src/main/java/chess/model/position/Position.java @@ -1,4 +1,6 @@ -package chess; +package chess.model.position; + +import chess.model.element.Movement; public record Position( Column column, @@ -167,4 +169,14 @@ public Position moveHorizontal(final int step) { } return this; } + + @Override + public Column column() { + return column; + } + + @Override + public Row row() { + return row; + } } diff --git a/src/main/java/chess/Row.java b/src/main/java/chess/model/position/Row.java similarity index 73% rename from src/main/java/chess/Row.java rename to src/main/java/chess/model/position/Row.java index 126ed048daa..5067840bf5b 100644 --- a/src/main/java/chess/Row.java +++ b/src/main/java/chess/model/position/Row.java @@ -1,4 +1,6 @@ -package chess; +package chess.model.position; + +import java.util.Arrays; public enum Row { @@ -50,4 +52,11 @@ public Row moveDown(final int step) { throw new IllegalStateException("움직일 수 없는 위치입니다."); } + + public static Row findByNumber(int number) { + return Arrays.stream(Row.values()) + .filter(o -> o.ordinal() == 8 - number) + .findFirst() + .orElseThrow(() -> new IllegalStateException("존재하지 않는 number로 Row를 찾으려 하고 있습니다")); + } } diff --git a/src/main/java/chess/piece/Bishop.java b/src/main/java/chess/piece/Bishop.java deleted file mode 100644 index b14ab70f981..00000000000 --- a/src/main/java/chess/piece/Bishop.java +++ /dev/null @@ -1,5 +0,0 @@ -package chess.piece; - -public class Bishop { - -} diff --git a/src/main/java/chess/piece/King.java b/src/main/java/chess/piece/King.java deleted file mode 100644 index d64210cad13..00000000000 --- a/src/main/java/chess/piece/King.java +++ /dev/null @@ -1,5 +0,0 @@ -package chess.piece; - -public class King { - -} diff --git a/src/main/java/chess/piece/Knight.java b/src/main/java/chess/piece/Knight.java deleted file mode 100644 index 2ee7c47a3bc..00000000000 --- a/src/main/java/chess/piece/Knight.java +++ /dev/null @@ -1,5 +0,0 @@ -package chess.piece; - -public class Knight { - -} diff --git a/src/main/java/chess/piece/Pawn.java b/src/main/java/chess/piece/Pawn.java deleted file mode 100644 index c8b6cafa51e..00000000000 --- a/src/main/java/chess/piece/Pawn.java +++ /dev/null @@ -1,5 +0,0 @@ -package chess.piece; - -public class Pawn { - -} diff --git a/src/main/java/chess/piece/Queen.java b/src/main/java/chess/piece/Queen.java deleted file mode 100644 index 9b547261c4b..00000000000 --- a/src/main/java/chess/piece/Queen.java +++ /dev/null @@ -1,5 +0,0 @@ -package chess.piece; - -public class Queen { - -} diff --git a/src/main/java/chess/piece/Rook.java b/src/main/java/chess/piece/Rook.java deleted file mode 100644 index 7ed4d08bf03..00000000000 --- a/src/main/java/chess/piece/Rook.java +++ /dev/null @@ -1,5 +0,0 @@ -package chess.piece; - -public class Rook { - -} diff --git a/src/main/java/chess/view/InputView.java b/src/main/java/chess/view/InputView.java new file mode 100644 index 00000000000..7fcadabfeee --- /dev/null +++ b/src/main/java/chess/view/InputView.java @@ -0,0 +1,29 @@ +package chess.view; + +import chess.model.position.Column; +import chess.model.position.Position; +import chess.model.position.Row; + +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +public class InputView { + + private static final Scanner sc = new Scanner(System.in); + + public static List readMovePositions() { + System.out.println(" 형태로 입력해주세요"); + System.out.println("ex) 1,2 3,5"); + + String input = sc.nextLine(); + String[] parsedInput = input.split(" ", -1); + List positions = new ArrayList<>(); + for (String text : parsedInput) { + Row row = Row.findByNumber(Integer.parseInt(text.charAt(0) + "")); + Column column = Column.findByNumber(Integer.parseInt(text.charAt(2) + "")); + positions.add(new Position(row, column)); + } + return positions; + } +} diff --git a/src/main/java/chess/view/OutputView.java b/src/main/java/chess/view/OutputView.java new file mode 100644 index 00000000000..8af574f4126 --- /dev/null +++ b/src/main/java/chess/view/OutputView.java @@ -0,0 +1,69 @@ +package chess.view; + +import chess.model.ChessBoard; +import chess.model.piece.Piece; +import chess.model.piece.types.*; +import chess.model.position.Column; +import chess.model.position.Position; +import chess.model.position.Row; + +import java.util.Arrays; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; + +public class OutputView { + + private static final Map ROW_FORMAT = Map.of( + Row.ONE, "1", + Row.TWO, "2", + Row.THREE, "3", + Row.FOUR, "4", + Row.FIVE, "5", + Row.SIX, "6", + Row.SEVEN, "7", + Row.EIGHT, "8" + ); + + private static final Map, String> PIECE_FORMAT = Map.of( + Bishop.class, "B", + King.class, "K", + Knight.class, "N", + Pawn.class, "P", + Queen.class, "Q", + Rook.class, "R" + ); + + public static void printChessBoard(ChessBoard board) { + System.out.println("체스 게임을 시작합니다."); + System.out.println("----------------------"); + System.out.println("아래는 현재 체스판 입니다."); + + StringBuffer sb = new StringBuffer(); + sb.append(" "); + Arrays.stream(Column.values()).forEach(column -> sb.append(column).append(" ")); + sb.append("\n"); + + for (Row row : Row.values()) { + sb.append(ROW_FORMAT.get(row) + " "); + for (Column column : Column.values()) { + sb.append(findPieceFormat(board, row, column) + " "); + } + sb.append("\n"); + } + System.out.println(sb); + } + + private static String findPieceFormat(ChessBoard board, Row row, Column column) { + Optional optionalPiece = board.findPieceByPosition(new Position(column, row)); + if (optionalPiece.isEmpty()) { + return "-"; + } + Piece piece = optionalPiece.get(); + String pieceText = PIECE_FORMAT.get(piece.getClass()); + if (piece.getColor().isBlack()) { + return pieceText; + } + return pieceText.toLowerCase(Locale.ROOT); + } +} diff --git a/src/test/java/chess/ChessBoardTest.java b/src/test/java/chess/ChessBoardTest.java new file mode 100644 index 00000000000..31a82881ead --- /dev/null +++ b/src/test/java/chess/ChessBoardTest.java @@ -0,0 +1,30 @@ +package chess; + +import chess.model.BoardFactory; +import chess.model.ChessBoard; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + + +class ChessBoardTest { + + @Nested + @DisplayName("체스판 관련 테스트") + class Construct { + + @DisplayName("체스판 생성 시, 포지션들이 잘 주입되었는 지") + @Test + void createBoard() { + // given + final int initBoardSize = 32; + // when + BoardFactory boardFactory = new BoardFactory(); + ChessBoard board = boardFactory.generateBoard(); + + // then + Assertions.assertThat(board.getPositionByPieceBoard()).hasSize(initBoardSize); + } + } +} diff --git a/src/test/java/chess/ColumnTest.java b/src/test/java/chess/ColumnTest.java index e43523240f7..360243de63e 100644 --- a/src/test/java/chess/ColumnTest.java +++ b/src/test/java/chess/ColumnTest.java @@ -1,5 +1,6 @@ package chess; +import chess.model.position.Column; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/chess/Fixtures.java b/src/test/java/chess/Fixtures.java index f940ab37137..2400d7f8239 100644 --- a/src/test/java/chess/Fixtures.java +++ b/src/test/java/chess/Fixtures.java @@ -1,5 +1,10 @@ package chess; + +import chess.model.position.Column; +import chess.model.position.Position; +import chess.model.position.Row; + @SuppressWarnings("unused") public final class Fixtures { diff --git a/src/test/java/chess/PositionTest.java b/src/test/java/chess/PositionTest.java index 3ad7cc64084..19028a33e98 100644 --- a/src/test/java/chess/PositionTest.java +++ b/src/test/java/chess/PositionTest.java @@ -1,5 +1,7 @@ package chess; +import chess.model.element.Movement; +import chess.model.position.Position; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; diff --git a/src/test/java/chess/RowTest.java b/src/test/java/chess/RowTest.java index fcb65485410..a1f7a17ab1c 100644 --- a/src/test/java/chess/RowTest.java +++ b/src/test/java/chess/RowTest.java @@ -1,5 +1,6 @@ package chess; +import chess.model.position.Row; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/chess/model/piece/types/BishopTest.java b/src/test/java/chess/model/piece/types/BishopTest.java new file mode 100644 index 00000000000..4f8fb2a22bf --- /dev/null +++ b/src/test/java/chess/model/piece/types/BishopTest.java @@ -0,0 +1,106 @@ +package chess.model.piece.types; + +import chess.model.ChessBoard; +import chess.model.element.Color; +import chess.model.piece.Piece; +import chess.model.position.Column; +import chess.model.position.Position; +import chess.model.position.Row; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +class BishopTest { + + @Test + @DisplayName("비숍의 방향 내에 존재하는 지 확인: 4대각선") + void isNotWithInDirection() { + + // given + Color anyColor = Color.WHITE; + Bishop bishop = new Bishop(anyColor); + + Row srcRow = Row.findByNumber(2); + Column srcCol = Column.findByNumber(3); + Position src = new Position(srcRow, srcCol); + + Row dest1Row = Row.findByNumber(3); + Column dest1Col = Column.findByNumber(4); + Position dest1 = new Position(dest1Row, dest1Col); + + Row dest2Row = Row.findByNumber(1); + Column dest2Col = Column.findByNumber(4); + Position dest2 = new Position(dest2Row, dest2Col); + + Row dest3Row = Row.findByNumber(3); + Column dest3Col = Column.findByNumber(2); + Position dest3 = new Position(dest3Row, dest3Col); + + Row dest4Row = Row.findByNumber(1); + Column dest4Col = Column.findByNumber(2); + Position dest4 = new Position(dest4Row, dest4Col); + + Row dest5Row = Row.findByNumber(2); + Column dest5Col = Column.findByNumber(5); + Position dest5 = new Position(dest5Row, dest5Col); + + // when + + boolean able1Result = bishop.isNotWithInDirection(src, dest1); + boolean able2Result = bishop.isNotWithInDirection(src, dest2); + boolean able3Result = bishop.isNotWithInDirection(src, dest3); + boolean able4Result = bishop.isNotWithInDirection(src, dest4); + boolean unableResult = bishop.isNotWithInDirection(src, dest5); + + // then + Assertions.assertAll( + () -> org.assertj.core.api.Assertions.assertThat(able1Result).isTrue(), + () -> org.assertj.core.api.Assertions.assertThat(able2Result).isTrue(), + () -> org.assertj.core.api.Assertions.assertThat(able3Result).isTrue(), + () -> org.assertj.core.api.Assertions.assertThat(able4Result).isTrue(), + () -> org.assertj.core.api.Assertions.assertThat(unableResult).isFalse() + ); + + } + + @Test + void isWithInRangeByMovement() { + } + + @Test + @DisplayName("비숍의 이동 방향 에 장애물이 있는 지: 없어야 함") + void passFilter() { + + // given + Row obstacleRow = Row.findByNumber(3); + Column obstacleCol = Column.findByNumber(4); + Position obstaclePosition = new Position(obstacleRow, obstacleCol); + + Map board = new HashMap<>(); + Color anyColor = Color.BLACK; + Knight anyPiece = new Knight(anyColor); + board.put(obstaclePosition, anyPiece); + + ChessBoard chessBoard = new ChessBoard(board); + + +// Color anyColor = Color.WHITE; +// Bishop bishop = new Bishop(anyColor); + + Row srcRow = Row.findByNumber(2); + Column srcCol = Column.findByNumber(3); + Position src = new Position(srcRow, srcCol); + + Row dest1Row = Row.findByNumber(4); + Column dest1Col = Column.findByNumber(5); + Position dest1 = new Position(dest1Row, dest1Col); + + // when + + + // then + } +}