diff --git a/README.md b/README.md index 9775dda0ae..12c30d96a5 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,84 @@ # java-janggi 장기 미션 저장소 + +**주요 기능** + +- [x] 플레이어는 ‘상 차림’을 결정할 수 있다. +- [x] 기물은 자동으로 배치된다. +- [x] 현재 장기판의 현황을 볼 수 있다. +- [x] 초나라(선)/한나라(후) 번갈아가며 플레이한다. +- [x] 플레이어는 기물의 이동 규칙에 따라 이동시킬 수 있다. +- [x] 상대 플레이어의 기물을 잡을 수 있다. +- [ ] 상대 플레이어의 왕을 잡으면 승리하고, 게임은 종료된다. + +### **실행 예시** + +``` +초나라 상 차림을 결정해주세요. +1. [마 상 마 상] +2. [마 상 상 마] +3. [상 마 상 마] +4. [상 마 마 상] + +2 + +한나라 상 차림을 결정해주세요. +1. [마 상 마 상] +2. [마 상 상 마] +3. [상 마 상 마] +4. [상 마 마 상] + +3 + +기물이 배치 되었습니다. + 0 1 2 3 4 5 6 7 8 + 0 車 馬 象 士 · 士 馬 象 車 + 1 · · · · 漢 · · · · + 2 · 砲 · · · · · 砲 · + 3 兵 · 兵 · 兵 · 兵 · 兵 + 4 · · · · · · · · · + 5 · · · · · · · · · + 6 卒 · 卒 · 卒 · 卒 · 卒 + 7 · 炮 · · · · · 炮 · + 8 · · · · 楚 · · · · + 9 車 馬 相 士 · 士 相 馬 車 + +초나라 플레이어는 말을 선택해주세요.(입력예시 좌표: 0, 9) +좌표: 0, 9 + +초나라 플레이어는 선택한 말을 움직일 위치를 입력해 주세요.(입력예시 좌표: 0, 7) +좌표: 0, 7 + +이동되었습니다. + 0 1 2 3 4 5 6 7 8 + 0 車 馬 象 士 · 士 馬 象 車 + 1 · · · · 漢 · · · · + 2 · 砲 · · · · · 砲 · + 3 兵 · 兵 · 兵 · 兵 · 兵 + 4 · · · · · · · · · + 5 · · · · · · · · · + 6 卒 · 卒 · 卒 · 卒 · 卒 + 7 車 炮 · · · · · 炮 · + 8 · · · · 楚 · · · · + 9 · 馬 相 士 · 士 相 馬 車 +``` + +**입력** + +- [x] ‘상 차림’ 배치 타입 입력받는다. +- [x] 선택할 기물의 좌표를 입력받는다. + - [x] `[ERROR]` 해당 좌표에 기물이 없을 때 + - [x] `[ERROR]` 선택한 기물이 플레이어의 기물이 아닐 때 +- [x] 이동할 좌표를 입력받는다. + - [x] `[ERROR]` 이동할 좌표가 보드 크기 내에 유효하지 않을 때 + - [x] `[ERROR]` 해당 좌표에 플레이어의 팀 기물이 있을 때 + - [x] `[ERROR]` 이동 규칙에 따라 이동할 수 없을 때 + +**출력** + +- [x] 4 종류의 ‘상 차림’ 배치를 출력한다. +- [x] 기물이 배치된 보드를 출력한다. +- [x] 현재 턴을 출력한다. +- [x] 턴이 끝나고 기물 이동이 된 보드를 출력한다. +- [ ] 최종 승패를 출력한다. diff --git a/src/main/java/Application.java b/src/main/java/Application.java new file mode 100644 index 0000000000..d4c180750a --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,13 @@ +import view.InputView; +import view.OutputView; + +public class Application { + + public static void main(String[] args) { + InputView inputView = new InputView(); + OutputView outputView = new OutputView(); + + JanggiController janggiController = new JanggiController(inputView, outputView); + janggiController.run(); + } +} diff --git a/src/main/java/JanggiController.java b/src/main/java/JanggiController.java new file mode 100644 index 0000000000..3e4ab1d37f --- /dev/null +++ b/src/main/java/JanggiController.java @@ -0,0 +1,80 @@ +import domain.Board; +import domain.Camp; +import domain.ElephantFormation; +import domain.Position; +import dto.BoardStatusDto; +import view.InputView; +import view.OutputView; + +public class JanggiController { + + InputView inputView; + OutputView outputView; + + + JanggiController(InputView inputView, OutputView outputView) { + this.inputView = inputView; + this.outputView = outputView; + } + + public void run() { + Board board = generateBoard(); + printBoard(board); + + playJanggi(board); + } + + private Board generateBoard() { + Board board = new Board(); + int choElephantFormation = inputView.askElephantFormation(Camp.CHO); + int hanElephantFormation = inputView.askElephantFormation(Camp.HAN); + board.generatePiecesBy(Camp.CHO, mappingElephantFormation(choElephantFormation)); + board.generatePiecesBy(Camp.HAN, mappingElephantFormation(hanElephantFormation)); + return board; + } + + private void playJanggi(Board board) { + Camp camp = Camp.CHO; + while (true) { + try{ + Position fromPosition = askFromPosition(camp, board); + Position toPosition = inputView.askToPosition(camp); + board.move(fromPosition, toPosition); + } catch (IllegalArgumentException e) { + outputView.printErrorMessage(e); + continue; + } + printBoard(board); + camp = turnCamp(camp); + + //Todo: 사이클2 왕이 잡히면, 게임이 종료 + } + } + + private Camp turnCamp(Camp camp) { + if (camp.equals(Camp.CHO)) { + return Camp.HAN; + } + return Camp.CHO; + } + + private Position askFromPosition(Camp camp, Board board) { + while (true) { + Position fromPosition = inputView.askFromPosition(camp); + if (!board.isPieceOfCamp(fromPosition, camp)) { + outputView.printWrongChoice(); + continue; + } + return fromPosition; + } + } + + private void printBoard(Board board) { + BoardStatusDto boardStatus = board.getBoardStatus(); + outputView.printBoardStatus(boardStatus); + } + + private ElephantFormation mappingElephantFormation(int userInput) { + return ElephantFormation.getFormationType(userInput); + } +} diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java new file mode 100644 index 0000000000..8d011b2c60 --- /dev/null +++ b/src/main/java/domain/Board.java @@ -0,0 +1,102 @@ +package domain; + +import domain.pieces.Piece; +import dto.BoardStatusDto; +import dto.PositionStatusDto; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Board implements ExistBoard { + + private final Map board = new HashMap<>(); + + public void generatePiecesBy(Camp camp, ElephantFormation elephantFormation) { + PieceGenerator pieceGenerator = new PieceGenerator(); + Map pieces = pieceGenerator.generatePieces(camp, elephantFormation); + + board.putAll(pieces); + } + + public void locatePiece(Position position, Piece piece) { + if (!isExist(position)) { + board.put(position, piece); + return; + } + + if (getPieceFrom(position).isSameCamp(piece)) { + throw new IllegalArgumentException("[ERROR] 같은 팀은 잡을 수 없습니다!"); + } + + board.put(position, piece); + } + + public Piece getPieceFrom(Position position) { + return board.get(position); + } + + @Override + public boolean isExist(Position position) { + return board.containsKey(position); + } + + public void move(Position fromPosition, Position toPosition) { + if (fromPosition.equals(toPosition)) { + throw new IllegalArgumentException("[ERROR] 제자리 이동은 불가능합니다."); + } + + Piece piece = board.get(fromPosition); + boolean canMove = piece.canMove(fromPosition, toPosition, this); + if (canMove) { + locatePiece(toPosition, piece); + board.remove(fromPosition); + return; + } + + throw new IllegalArgumentException("[ERROR] 이동할 수 없습니다"); + } + + @Override + public boolean isDifferentPieceType(Position position, Piece piece) { + if (!board.containsKey(position)) { + return true; + } + + return board.get(position).isDifferentPieceType(piece); + } + + public BoardStatusDto getBoardStatus() { + List> boardStatusDto = new ArrayList<>(); + for (int y = Position.MIN_Y_VALUE; y <= Position.MAX_Y_VALUE; y++) { + List xPositionStatus = new ArrayList<>(); + for (int x = Position.MIN_X_VALUE; x <= Position.MAX_X_VALUE; x++) { + Position position = new Position(x, y); + + PositionStatusDto positionStatusDto = getPositionStatusDto(position); + xPositionStatus.add(positionStatusDto); + } + boardStatusDto.add(xPositionStatus); + } + return new BoardStatusDto(boardStatusDto); + } + + private PositionStatusDto getPositionStatusDto(Position position) { + if (!board.containsKey(position)) { + return new PositionStatusDto(position, PieceType.NONE, Camp.CHO); + } + + Piece piece = board.get(position); + PieceType pieceType = piece.getPieceType(); + Camp camp = piece.getCamp(); + return new PositionStatusDto(position, pieceType, camp); + } + + public boolean isPieceOfCamp(Position position, Camp camp) { + if (!board.containsKey(position)) { + return false; + } + + return board.get(position).isSameCamp(camp); + } +} diff --git a/src/main/java/domain/Camp.java b/src/main/java/domain/Camp.java new file mode 100644 index 0000000000..33abb85b49 --- /dev/null +++ b/src/main/java/domain/Camp.java @@ -0,0 +1,17 @@ +package domain; + +public enum Camp { + HAN("한나라"), + CHO("초나라"); + + private final String campName; + + Camp(String campName) { + this.campName = campName; + } + + public String getCampName() { + return campName; + } +} + diff --git a/src/main/java/domain/ElephantFormation.java b/src/main/java/domain/ElephantFormation.java new file mode 100644 index 0000000000..94af1c4ddc --- /dev/null +++ b/src/main/java/domain/ElephantFormation.java @@ -0,0 +1,156 @@ +package domain; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public enum ElephantFormation { + RIGHT(1, initRight()), + INNER(2, initInner()), + LEFT(3, initLeft()), + OUTER(4, initOuter()); + + private final int formationNumber; + private final Map>> positions; + + ElephantFormation(int formationNumber, Map>> positions) { + this.formationNumber = formationNumber; + this.positions = positions; + } + + private static Map>> initRight() { + Map>> position = new HashMap<>(); + Map> horseRightPosition = new HashMap<>(); + horseRightPosition.put(Camp.HAN, List.of( + new Position(2, 0), + new Position(7, 0) + )); + + horseRightPosition.put(Camp.CHO, List.of( + new Position(1, 9), + new Position(6, 9) + )); + + position.put(PieceLocation.HORSE, horseRightPosition); + + Map> elephantRightPosition = new HashMap<>(); + elephantRightPosition.put(Camp.HAN, List.of( + new Position(1, 0), + new Position(6, 0) + )); + + elephantRightPosition.put(Camp.CHO, List.of( + new Position(2, 9), + new Position(7, 9) + )); + + position.put(PieceLocation.ELEPHANT, elephantRightPosition); + + return position; + } + + private static Map>> initInner() { + Map>> position = new HashMap<>(); + Map> horseInnerPosition = new HashMap<>(); + horseInnerPosition.put(Camp.HAN, List.of( + new Position(1, 0), + new Position(7, 0) + )); + + horseInnerPosition.put(Camp.CHO, List.of( + new Position(1, 9), + new Position(7, 9) + )); + + position.put(PieceLocation.HORSE, horseInnerPosition); + + Map> elephantInnerPosition = new HashMap<>(); + elephantInnerPosition.put(Camp.HAN, List.of( + new Position(2, 0), + new Position(6, 0) + )); + + elephantInnerPosition.put(Camp.CHO, List.of( + new Position(2, 9), + new Position(6, 9) + )); + + position.put(PieceLocation.ELEPHANT, elephantInnerPosition); + + return position; + } + + private static Map>> initLeft() { + Map>> position = new HashMap<>(); + Map> horseLeftPosition = new HashMap<>(); + horseLeftPosition.put(Camp.HAN, List.of( + new Position(1, 0), + new Position(6, 0) + )); + + horseLeftPosition.put(Camp.CHO, List.of( + new Position(2, 9), + new Position(7, 9) + )); + + position.put(PieceLocation.HORSE, horseLeftPosition); + + Map> elephantLeftPosition = new HashMap<>(); + elephantLeftPosition.put(Camp.HAN, List.of( + new Position(2, 0), + new Position(7, 0) + )); + + elephantLeftPosition.put(Camp.CHO, List.of( + new Position(1, 9), + new Position(6, 9) + )); + + position.put(PieceLocation.ELEPHANT, elephantLeftPosition); + + return position; + } + + private static Map>> initOuter() { + Map>> position = new HashMap<>(); + Map> horseOuterPosition = new HashMap<>(); + horseOuterPosition.put(Camp.HAN, List.of( + new Position(2, 0), + new Position(6, 0) + )); + + horseOuterPosition.put(Camp.CHO, List.of( + new Position(2, 9), + new Position(6, 9) + )); + + position.put(PieceLocation.HORSE, horseOuterPosition); + + Map> elephantOuterPosition = new HashMap<>(); + elephantOuterPosition.put(Camp.HAN, List.of( + new Position(1, 0), + new Position(7, 0) + )); + + elephantOuterPosition.put(Camp.CHO, List.of( + new Position(1, 9), + new Position(7, 9) + )); + + position.put(PieceLocation.ELEPHANT, elephantOuterPosition); + + return position; + } + + public static ElephantFormation getFormationType(int formationNumber) { + return Arrays.stream(ElephantFormation.values()) + .filter(n -> n.formationNumber == formationNumber) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("잘못된 타입 번호입니다." + formationNumber)); + } + + public List getPositions(PieceLocation pieceLocation, Camp camp) { + return positions.get(pieceLocation).get(camp); + } +} diff --git a/src/main/java/domain/ExistBoard.java b/src/main/java/domain/ExistBoard.java new file mode 100644 index 0000000000..b2bb3f8d01 --- /dev/null +++ b/src/main/java/domain/ExistBoard.java @@ -0,0 +1,10 @@ +package domain; + +import domain.pieces.Piece; + +public interface ExistBoard { + + boolean isExist(Position position); + + boolean isDifferentPieceType(Position position, Piece piece); +} diff --git a/src/main/java/domain/PieceGenerator.java b/src/main/java/domain/PieceGenerator.java new file mode 100644 index 0000000000..8329d1527e --- /dev/null +++ b/src/main/java/domain/PieceGenerator.java @@ -0,0 +1,86 @@ +package domain; + +import domain.pieces.Cannon; +import domain.pieces.Chariot; +import domain.pieces.Elephant; +import domain.pieces.General; +import domain.pieces.Guard; +import domain.pieces.Horse; +import domain.pieces.Piece; +import domain.pieces.Soldier; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class PieceGenerator { + + public Map generatePieces(Camp camp, ElephantFormation elephantFormation) { + Map board = new HashMap<>(); + board.putAll(generateGeneral(camp)); + board.putAll(generateSoldier(camp)); + board.putAll(generateGuard(camp)); + board.putAll(generateHorse(camp, elephantFormation)); + board.putAll(generateElephant(camp, elephantFormation)); + board.putAll(generateCannon(camp)); + board.putAll(generateChariot(camp)); + + return board; + } + + private Map generateGeneral(Camp camp) { + Map generalPosition = new HashMap<>(); + + List positions = PieceLocation.GENERAL.getPositions(camp); + positions.forEach(position -> generalPosition.put(position, new General(camp))); + + return generalPosition; + } + + private Map generateSoldier(Camp camp) { + Map soldierPosition = new HashMap<>(); + List positions = PieceLocation.SOLDIER.getPositions(camp); + positions.forEach(position -> soldierPosition.put(position, new Soldier(camp))); + + return soldierPosition; + } + + private Map generateGuard(Camp camp) { + Map guardPosition = new HashMap<>(); + List positions = PieceLocation.GUARD.getPositions(camp); + positions.forEach(position -> guardPosition.put(position, new Guard(camp))); + + return guardPosition; + } + + private Map generateHorse(Camp camp, ElephantFormation elephantFormation) { + Map horsePosition = new HashMap<>(); + List positions = PieceLocation.HORSE.getPositions(camp, elephantFormation); + positions.forEach(position -> horsePosition.put(position, new Horse(camp))); + + return horsePosition; + } + + private Map generateCannon(Camp camp) { + Map cannonPosition = new HashMap<>(); + List positions = PieceLocation.CANNON.getPositions(camp); + positions.forEach(position -> cannonPosition.put(position, new Cannon(camp))); + + return cannonPosition; + } + + private Map generateElephant(Camp camp, ElephantFormation elephantFormation) { + Map elephantPosition = new HashMap<>(); + List positions = PieceLocation.ELEPHANT.getPositions(camp, elephantFormation); + positions.forEach(position -> elephantPosition.put(position, new Elephant(camp))); + + return elephantPosition; + } + + private Map generateChariot(Camp camp) { + Map chariotPosition = new HashMap<>(); + List positions = PieceLocation.CHARIOT.getPositions(camp); + positions.forEach(position -> chariotPosition.put(position, new Chariot(camp))); + + return chariotPosition; + } +} diff --git a/src/main/java/domain/PieceLocation.java b/src/main/java/domain/PieceLocation.java new file mode 100644 index 0000000000..4defdfcb92 --- /dev/null +++ b/src/main/java/domain/PieceLocation.java @@ -0,0 +1,139 @@ +package domain; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public enum PieceLocation { + GENERAL(initGeneralPosition()), + GUARD(initGuardPosition()), + HORSE(initHorsePosition()), + CANNON(initCannonPosition()), + ELEPHANT(initElephantPosition()), + SOLDIER(initSoldierPosition()), + CHARIOT(initChariotPosition()); + + private final Map> positions; + + PieceLocation(Map> positions) { + this.positions = positions; + } + + private static Map> initGeneralPosition() { + Map> generalPosition = new HashMap<>(); + generalPosition.put(Camp.HAN, List.of( + new Position(4, 1) + )); + + generalPosition.put(Camp.CHO, List.of( + new Position(4, 8) + )); + + return generalPosition; + } + + private static Map> initGuardPosition() { + Map> guardPosition = new HashMap<>(); + guardPosition.put(Camp.HAN, List.of( + new Position(3, 0), + new Position(5, 0) + )); + + guardPosition.put(Camp.CHO, List.of( + new Position(3, 9), + new Position(5, 9) + )); + + return guardPosition; + } + + private static Map> initHorsePosition() { + Map> horsePosition = new HashMap<>(); + + horsePosition.put(Camp.HAN, List.of( + new Position(2, 0), + new Position(7, 0) + )); + + horsePosition.put(Camp.CHO, List.of( + new Position(1, 9), + new Position(7, 9) + )); + + return horsePosition; + } + + private static Map> initCannonPosition() { + Map> cannonPosition = new HashMap<>(); + + cannonPosition.put(Camp.HAN, List.of( + new Position(1, 2), + new Position(7, 2) + )); + cannonPosition.put(Camp.CHO, List.of( + new Position(1, 7), + new Position(7, 7) + )); + + return cannonPosition; + } + + private static Map> initElephantPosition() { + Map> elephantPosition = new HashMap<>(); + + elephantPosition.put(Camp.HAN, List.of( + new Position(1, 0), + new Position(6, 0) + )); + elephantPosition.put(Camp.CHO, List.of( + new Position(2, 9), + new Position(6, 9) + )); + + return elephantPosition; + } + + private static Map> initSoldierPosition() { + Map> soldierPosition = new HashMap<>(); + + soldierPosition.put(Camp.HAN, List.of( + new Position(0, 3), + new Position(2, 3), + new Position(4, 3), + new Position(6, 3), + new Position(8, 3) + )); + soldierPosition.put(Camp.CHO, List.of( + new Position(0, 6), + new Position(2, 6), + new Position(4, 6), + new Position(6, 6), + new Position(8, 6) + )); + + return soldierPosition; + } + + private static Map> initChariotPosition() { + Map> chariotPosition = new HashMap<>(); + + chariotPosition.put(Camp.HAN, List.of( + new Position(0, 0), + new Position(8, 0)) + ); + chariotPosition.put(Camp.CHO, List.of( + new Position(0, 9), + new Position(8, 9)) + ); + + return chariotPosition; + } + + public List getPositions(Camp camp) { + return positions.get(camp); + } + + public List getPositions(Camp camp, ElephantFormation formation) { + return formation.getPositions(this, camp); + } +} diff --git a/src/main/java/domain/PieceType.java b/src/main/java/domain/PieceType.java new file mode 100644 index 0000000000..ac82b86860 --- /dev/null +++ b/src/main/java/domain/PieceType.java @@ -0,0 +1,12 @@ +package domain; + +public enum PieceType { + GENERAL, + GUARD, + HORSE, + CANNON, + ELEPHANT, + SOLDIER, + CHARIOT, + NONE +} diff --git a/src/main/java/domain/Position.java b/src/main/java/domain/Position.java new file mode 100644 index 0000000000..c52ac1225b --- /dev/null +++ b/src/main/java/domain/Position.java @@ -0,0 +1,58 @@ +package domain; + +import java.util.Objects; + +public class Position { + + public static int MAX_X_VALUE = 8; + public static int MIN_X_VALUE = 0; + public static int MAX_Y_VALUE = 9; + public static int MIN_Y_VALUE = 0; + + private final int x; + private final int y; + + public Position(int x, int y) { + validatePosX(x); + validatePosY(y); + this.x = x; + this.y = y; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + private void validatePosX(int x) { + if (x < MIN_X_VALUE || x > MAX_X_VALUE) { + throw new IllegalArgumentException("[ERROR] x 좌표는 " + MIN_X_VALUE + "~" + MAX_X_VALUE + "사이어야합니다."); + } + } + + private void validatePosY(int y) { + if (y < MIN_Y_VALUE || y > MAX_Y_VALUE) { + throw new IllegalArgumentException("[ERROR] y 좌표는 " + MIN_Y_VALUE + "~" + MAX_Y_VALUE + "사이어야합니다."); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Position position = (Position) o; + return x == position.x && y == position.y; + } + + @Override + public int hashCode() { + return Objects.hash(x, y); + } +} diff --git a/src/main/java/domain/pieces/Cannon.java b/src/main/java/domain/pieces/Cannon.java new file mode 100644 index 0000000000..626638d5f7 --- /dev/null +++ b/src/main/java/domain/pieces/Cannon.java @@ -0,0 +1,146 @@ +package domain.pieces; + +import domain.Camp; +import domain.ExistBoard; +import domain.PieceType; +import domain.Position; +import java.util.HashSet; +import java.util.Set; + +public class Cannon extends Piece { + + private final PieceType pieceType = PieceType.CANNON; + + public Cannon(Camp camp) { + super(camp); + } + + @Override + public boolean canMove(Position from, Position to, ExistBoard existBoard) { + Set movablePositions = new HashSet<>(); + + movablePositions.addAll(moveUp(from, existBoard)); + movablePositions.addAll(moveLeft(from, existBoard)); + movablePositions.addAll(moveRight(from, existBoard)); + movablePositions.addAll(moveDown(from, existBoard)); + + return movablePositions.contains(to); + } + + private Set moveRight(Position position, ExistBoard existBoard) { + Set movablePositions = new HashSet<>(); + boolean jumping = false; + + try { + while (!jumping) { + position = right(position); + jumping = checkCannonJumping(position, existBoard); + } + } catch (IllegalArgumentException e) { + + } + + try { + do { + position = right(position); + if (existBoard.isDifferentPieceType(position, this)) { + movablePositions.add(position); + } + } while (!existBoard.isExist(position)); + } catch (IllegalArgumentException e) { + + } + + return movablePositions; + } + + private Set moveLeft(Position position, ExistBoard existBoard) { + Set movablePositions = new HashSet<>(); + boolean jumping = false; + + try { + while (!jumping) { + position = left(position); + jumping = checkCannonJumping(position, existBoard); + } + } catch (IllegalArgumentException e) { + + } + + try { + do { + position = left(position); + if (existBoard.isDifferentPieceType(position, this)) { + movablePositions.add(position); + } + } while (!existBoard.isExist(position)); + } catch (IllegalArgumentException e) { + + } + + return movablePositions; + } + + private Set moveUp(Position position, ExistBoard existBoard) { + Set movablePositions = new HashSet<>(); + boolean jumping = false; + + try { + while (!jumping) { + position = up(position); + jumping = checkCannonJumping(position, existBoard); + } + } catch (IllegalArgumentException e) { + + } + + try { + do { + position = up(position); + if (existBoard.isDifferentPieceType(position, this)) { + movablePositions.add(position); + } + } while (!existBoard.isExist(position)); + } catch (IllegalArgumentException e) { + + } + + return movablePositions; + } + + private Set moveDown(Position position, ExistBoard existBoard) { + Set movablePositions = new HashSet<>(); + boolean jumping = false; + + try { + while (!jumping) { + position = down(position); + jumping = checkCannonJumping(position, existBoard); + } + } catch (IllegalArgumentException e) { + + } + + try { + do { + position = down(position); + if (existBoard.isDifferentPieceType(position, this)) { + movablePositions.add(position); + } + } while (!existBoard.isExist(position)); + } catch (IllegalArgumentException e) { + + } + + return movablePositions; + } + + private boolean checkCannonJumping(Position position, ExistBoard existBoard) { + return existBoard.isExist(position) && existBoard.isDifferentPieceType(position, this); + } + + @Override + public PieceType getPieceType() { + return this.pieceType; + } +} diff --git a/src/main/java/domain/pieces/Chariot.java b/src/main/java/domain/pieces/Chariot.java new file mode 100644 index 0000000000..79d92ef633 --- /dev/null +++ b/src/main/java/domain/pieces/Chariot.java @@ -0,0 +1,86 @@ +package domain.pieces; + +import domain.Camp; +import domain.ExistBoard; +import domain.PieceType; +import domain.Position; +import java.util.HashSet; +import java.util.Set; + +public class Chariot extends Piece { + + private final PieceType pieceType = PieceType.CHARIOT; + + public Chariot(Camp camp) { + super(camp); + } + + @Override + public boolean canMove(Position from, Position to, ExistBoard existBoard) { + Set movablePositions = new HashSet<>(); + + movablePositions.addAll(moveUp(from, existBoard)); + movablePositions.addAll(moveDown(from, existBoard)); + movablePositions.addAll(moveLeft(from, existBoard)); + movablePositions.addAll(moveRight(from, existBoard)); + + return movablePositions.contains(to); + } + + private Set moveUp(Position position, ExistBoard existBoard) { + Set movablePositions = new HashSet<>(); + try { + do { + position = up(position); + movablePositions.add(position); + } while (!existBoard.isExist(position)); + } catch (IllegalArgumentException e) { + + } + return movablePositions; + } + + private Set moveLeft(Position position, ExistBoard existBoard) { + Set movablePositions = new HashSet<>(); + try { + do { + position = left(position); + movablePositions.add(position); + } while (!existBoard.isExist(position)); + } catch (IllegalArgumentException e) { + + } + return movablePositions; + } + + private Set moveRight(Position position, ExistBoard existBoard) { + Set movablePositions = new HashSet<>(); + try { + do { + position = right(position); + movablePositions.add(position); + } while (!existBoard.isExist(position)); + } catch (IllegalArgumentException e) { + + } + return movablePositions; + } + + private Set moveDown(Position position, ExistBoard existBoard) { + Set movablePositions = new HashSet<>(); + try { + do { + position = down(position); + movablePositions.add(position); + } while (!existBoard.isExist(position)); + } catch (IllegalArgumentException e) { + + } + return movablePositions; + } + + @Override + public PieceType getPieceType() { + return this.pieceType; + } +} diff --git a/src/main/java/domain/pieces/Elephant.java b/src/main/java/domain/pieces/Elephant.java new file mode 100644 index 0000000000..030cd2777f --- /dev/null +++ b/src/main/java/domain/pieces/Elephant.java @@ -0,0 +1,209 @@ +package domain.pieces; + +import domain.Camp; +import domain.ExistBoard; +import domain.PieceType; +import domain.Position; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Elephant extends Piece { + + private final PieceType pieceType = PieceType.ELEPHANT; + + public Elephant(Camp camp) { + super(camp); + } + + @Override + public boolean canMove(Position from, Position to, ExistBoard existBoard) { + Map> routeOfDestination = new HashMap<>(); + + routeOfDestination.putAll(move_U_RU(from)); + routeOfDestination.putAll(move_U_LU(from)); + routeOfDestination.putAll(move_D_RD(from)); + routeOfDestination.putAll(move_D_LD(from)); + routeOfDestination.putAll(move_R_RU(from)); + routeOfDestination.putAll(move_R_RD(from)); + routeOfDestination.putAll(move_L_LU(from)); + routeOfDestination.putAll(move_L_LD(from)); + + if (!routeOfDestination.containsKey(to)) { + return false; + } + + List route = routeOfDestination.get(to); + for (Position position : route) { + if (existBoard.isExist(position)) { + return false; + } + } + + return true; + } + + private Map> move_U_RU(Position position) { + Map> routeOfDestination = new HashMap<>(); + List route = new ArrayList<>(); + try { + position = up(position); + route.add(position); + + position = rightUpDiagonal(position); + route.add(position); + + position = rightUpDiagonal(position); + + routeOfDestination.put(position, route); + } catch (IllegalArgumentException e) { + // 생성할 수 없는 Position이면 무시 + } + return routeOfDestination; + } + + private Map> move_U_LU(Position position) { + Map> routeOfDestination = new HashMap<>(); + List route = new ArrayList<>(); + try { + position = up(position); + route.add(position); + + position = leftUpDiagonal(position); + route.add(position); + + position = leftUpDiagonal(position); + + routeOfDestination.put(position, route); + } catch (IllegalArgumentException e) { + // 생성할 수 없는 Position이면 무시 + } + + return routeOfDestination; + } + + private Map> move_D_RD(Position position) { + Map> routeOfDestination = new HashMap<>(); + List route = new ArrayList<>(); + try { + position = down(position); + route.add(position); + + position = rightDownDiagonal(position); + route.add(position); + + position = rightDownDiagonal(position); + + routeOfDestination.put(position, route); + } catch (IllegalArgumentException e) { + // 생성할 수 없는 Position이면 무시 + } + return routeOfDestination; + } + + private Map> move_D_LD(Position position) { + Map> routeOfDestination = new HashMap<>(); + List route = new ArrayList<>(); + try { + position = down(position); + route.add(position); + + position = leftDownDiagonal(position); + route.add(position); + + position = leftDownDiagonal(position); + + routeOfDestination.put(position, route); + } catch (IllegalArgumentException e) { + // 생성할 수 없는 Position이면 무시 + } + + return routeOfDestination; + } + + private Map> move_R_RU(Position position) { + Map> routeOfDestination = new HashMap<>(); + List route = new ArrayList<>(); + try { + position = right(position); + route.add(position); + + position = rightUpDiagonal(position); + route.add(position); + + position = rightUpDiagonal(position); + + routeOfDestination.put(position, route); + } catch (IllegalArgumentException e) { + // 생성할 수 없는 Position이면 무시 + } + + return routeOfDestination; + } + + private Map> move_R_RD(Position position) { + Map> routeOfDestination = new HashMap<>(); + List route = new ArrayList<>(); + try { + position = right(position); + route.add(position); + + position = rightDownDiagonal(position); + route.add(position); + + position = rightDownDiagonal(position); + + routeOfDestination.put(position, route); + } catch (IllegalArgumentException e) { + // 생성할 수 없는 Position이면 무시 + } + + return routeOfDestination; + } + + private Map> move_L_LU(Position position) { + Map> routeOfDestination = new HashMap<>(); + List route = new ArrayList<>(); + try { + position = left(position); + route.add(position); + + position = leftUpDiagonal(position); + route.add(position); + + position = leftUpDiagonal(position); + + routeOfDestination.put(position, route); + } catch (IllegalArgumentException e) { + // 생성할 수 없는 Position이면 무시 + } + + return routeOfDestination; + } + + private Map> move_L_LD(Position position) { + Map> routeOfDestination = new HashMap<>(); + List route = new ArrayList<>(); + try { + position = left(position); + route.add(position); + + position = leftDownDiagonal(position); + route.add(position); + + position = leftDownDiagonal(position); + + routeOfDestination.put(position, route); + } catch (IllegalArgumentException e) { + // 생성할 수 없는 Position이면 무시 + } + + return routeOfDestination; + } + + @Override + public PieceType getPieceType() { + return this.pieceType; + } +} diff --git a/src/main/java/domain/pieces/General.java b/src/main/java/domain/pieces/General.java new file mode 100644 index 0000000000..e7281fa6e6 --- /dev/null +++ b/src/main/java/domain/pieces/General.java @@ -0,0 +1,103 @@ +package domain.pieces; + +import domain.Camp; +import domain.ExistBoard; +import domain.PieceType; +import domain.Position; +import java.util.HashSet; +import java.util.Set; + +public class General extends Piece { + + private final PieceType pieceType = PieceType.GENERAL; + + public General(Camp camp) { + super(camp); + } + + @Override + public boolean canMove(Position from, Position to, ExistBoard existBoard) { + + Set destination = new HashSet<>(); + + destination.add(move_L(from)); + destination.add(move_R(from)); + destination.add(move_D(from)); + destination.add(move_U(from)); + destination.add(move_RU(from)); + destination.add(move_RD(from)); + destination.add(move_LU(from)); + destination.add(move_LD(from)); + + return destination.contains(to); + } + + private Position move_U(Position position) { + try { + return up(position); + } catch (IllegalArgumentException e) { + return position; + } + } + + private Position move_L(Position position) { + try { + return left(position); + } catch (IllegalArgumentException e) { + return position; + } + } + + private Position move_R(Position position) { + try { + return right(position); + } catch (IllegalArgumentException e) { + return position; + } + } + + private Position move_D(Position position) { + try { + return down(position); + } catch (IllegalArgumentException e) { + return position; + } + } + + private Position move_RU(Position position) { + try { + return rightUpDiagonal(position); + } catch (IllegalArgumentException e) { + return position; + } + } + + private Position move_RD(Position position) { + try { + return rightDownDiagonal(position); + } catch (IllegalArgumentException e) { + return position; + } + } + + private Position move_LU(Position position) { + try { + return leftUpDiagonal(position); + } catch (IllegalArgumentException e) { + return position; + } + } + + private Position move_LD(Position position) { + try { + return leftDownDiagonal(position); + } catch (IllegalArgumentException e) { + return position; + } + } + + @Override + public PieceType getPieceType() { + return this.pieceType; + } +} diff --git a/src/main/java/domain/pieces/Guard.java b/src/main/java/domain/pieces/Guard.java new file mode 100644 index 0000000000..5e26149a6f --- /dev/null +++ b/src/main/java/domain/pieces/Guard.java @@ -0,0 +1,103 @@ +package domain.pieces; + +import domain.Camp; +import domain.ExistBoard; +import domain.PieceType; +import domain.Position; +import java.util.HashSet; +import java.util.Set; + +public class Guard extends Piece { + + private final PieceType pieceType = PieceType.GUARD; + + public Guard(Camp camp) { + super(camp); + } + + @Override + public boolean canMove(Position from, Position to, ExistBoard existBoard) { + + Set destination = new HashSet<>(); + + destination.add(move_L(from)); + destination.add(move_R(from)); + destination.add(move_D(from)); + destination.add(move_U(from)); + destination.add(move_RU(from)); + destination.add(move_RD(from)); + destination.add(move_LU(from)); + destination.add(move_LD(from)); + + return destination.contains(to); + } + + private Position move_U(Position position) { + try { + return up(position); + } catch (IllegalArgumentException e) { + return position; + } + } + + private Position move_L(Position position) { + try { + return left(position); + } catch (IllegalArgumentException e) { + return position; + } + } + + private Position move_R(Position position) { + try { + return right(position); + } catch (IllegalArgumentException e) { + return position; + } + } + + private Position move_D(Position position) { + try { + return down(position); + } catch (IllegalArgumentException e) { + return position; + } + } + + private Position move_RU(Position position) { + try { + return rightUpDiagonal(position); + } catch (IllegalArgumentException e) { + return position; + } + } + + private Position move_RD(Position position) { + try { + return rightDownDiagonal(position); + } catch (IllegalArgumentException e) { + return position; + } + } + + private Position move_LU(Position position) { + try { + return leftUpDiagonal(position); + } catch (IllegalArgumentException e) { + return position; + } + } + + private Position move_LD(Position position) { + try { + return leftDownDiagonal(position); + } catch (IllegalArgumentException e) { + return position; + } + } + + @Override + public PieceType getPieceType() { + return this.pieceType; + } +} diff --git a/src/main/java/domain/pieces/Horse.java b/src/main/java/domain/pieces/Horse.java new file mode 100644 index 0000000000..c10fce8065 --- /dev/null +++ b/src/main/java/domain/pieces/Horse.java @@ -0,0 +1,180 @@ +package domain.pieces; + +import domain.Camp; +import domain.ExistBoard; +import domain.PieceType; +import domain.Position; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Horse extends Piece { + + private final PieceType pieceType = PieceType.HORSE; + + public Horse(Camp camp) { + super(camp); + } + + @Override + public boolean canMove(Position from, Position to, ExistBoard existBoard) { + Map> routeOfDestination = new HashMap<>(); + + routeOfDestination.putAll(move_U_RU(from)); + routeOfDestination.putAll(move_U_LU(from)); + routeOfDestination.putAll(move_R_RU(from)); + routeOfDestination.putAll(move_R_RD(from)); + routeOfDestination.putAll(move_L_LU(from)); + routeOfDestination.putAll(move_L_LD(from)); + routeOfDestination.putAll(move_D_RD(from)); + routeOfDestination.putAll(move_D_LD(from)); + + if (!routeOfDestination.containsKey(to)) { + return false; + } + + List route = routeOfDestination.get(to); + for (Position position : route) { + if (existBoard.isExist(position)) { + return false; + } + } + + return true; + } + + private Map> move_U_RU(Position position) { + Map> routeOfDestination = new HashMap<>(); + List route = new ArrayList<>(); + try { + position = up(position); + route.add(position); + + position = rightUpDiagonal(position); + + routeOfDestination.put(position, route); + } catch (IllegalArgumentException e) { + // 생성할 수 없는 Position이면 무시 + } + + return routeOfDestination; + } + + private Map> move_U_LU(Position position) { + Map> routeOfDestination = new HashMap<>(); + List route = new ArrayList<>(); + try { + position = up(position); + route.add(position); + + position = leftUpDiagonal(position); + + routeOfDestination.put(position, route); + } catch (IllegalArgumentException e) { + // 생성할 수 없는 Position이면 무시 + } + return routeOfDestination; + } + + private Map> move_R_RU(Position position) { + Map> routeOfDestination = new HashMap<>(); + List route = new ArrayList<>(); + try { + position = right(position); + route.add(position); + + position = rightUpDiagonal(position); + + routeOfDestination.put(position, route); + } catch (IllegalArgumentException e) { + // 생성할 수 없는 Position이면 무시 + } + return routeOfDestination; + } + + private Map> move_R_RD(Position position) { + Map> routeOfDestination = new HashMap<>(); + List route = new ArrayList<>(); + try { + position = right(position); + route.add(position); + + position = rightDownDiagonal(position); + + routeOfDestination.put(position, route); + } catch (IllegalArgumentException e) { + // 생성할 수 없는 Position이면 무시 + } + return routeOfDestination; + } + + private Map> move_L_LU(Position position) { + Map> routeOfDestination = new HashMap<>(); + List route = new ArrayList<>(); + try { + position = left(position); + route.add(position); + + position = leftUpDiagonal(position); + + routeOfDestination.put(position, route); + } catch (IllegalArgumentException e) { + // 생성할 수 없는 Position이면 무시 + } + return routeOfDestination; + } + + private Map> move_L_LD(Position position) { + Map> routeOfDestination = new HashMap<>(); + List route = new ArrayList<>(); + try { + position = left(position); + route.add(position); + + position = leftDownDiagonal(position); + + routeOfDestination.put(position, route); + } catch (IllegalArgumentException e) { + // 생성할 수 없는 Position이면 무시 + } + return routeOfDestination; + } + + private Map> move_D_RD(Position position) { + Map> routeOfDestination = new HashMap<>(); + List route = new ArrayList<>(); + try { + position = down(position); + route.add(position); + + position = rightDownDiagonal(position); + + routeOfDestination.put(position, route); + } catch (IllegalArgumentException e) { + // 생성할 수 없는 Position이면 무시 + } + return routeOfDestination; + } + + private Map> move_D_LD(Position position) { + Map> routeOfDestination = new HashMap<>(); + List route = new ArrayList<>(); + try { + position = down(position); + route.add(position); + + position = leftDownDiagonal(position); + + routeOfDestination.put(position, route); + } catch (IllegalArgumentException e) { + // 생성할 수 없는 Position이면 무시 + } + return routeOfDestination; + } + + @Override + public PieceType getPieceType() { + return this.pieceType; + } +} diff --git a/src/main/java/domain/pieces/Piece.java b/src/main/java/domain/pieces/Piece.java new file mode 100644 index 0000000000..1f1fbb32df --- /dev/null +++ b/src/main/java/domain/pieces/Piece.java @@ -0,0 +1,88 @@ +package domain.pieces; + +import domain.Camp; +import domain.ExistBoard; +import domain.PieceType; +import domain.Position; + +public class Piece { + + private final PieceType pieceType = PieceType.NONE; + private final Camp camp; + + public Piece(Camp camp) { + this.camp = camp; + } + + public boolean isSameCamp(Piece comparedPiece) { + return this.camp == comparedPiece.camp; + } + + public boolean isSameCamp(Camp camp) { + return this.camp == camp; + } + + public boolean isDifferentPieceType(Piece piece) { + return this.getClass() != piece.getClass(); + } + + Position up(Position position) { + int x = position.getX(); + int y = position.getY(); + return new Position(x, --y); + } + + Position down(Position position) { + int x = position.getX(); + int y = position.getY(); + return new Position(x, ++y); + } + + Position left(Position position) { + int x = position.getX(); + int y = position.getY(); + return new Position(--x, y); + } + + Position right(Position position) { + int x = position.getX(); + int y = position.getY(); + return new Position(++x, y); + } + + Position leftUpDiagonal(Position position) { + int x = position.getX(); + int y = position.getY(); + return new Position(--x, --y); + } + + Position rightUpDiagonal(Position position) { + int x = position.getX(); + int y = position.getY(); + return new Position(++x, --y); + } + + Position leftDownDiagonal(Position position) { + int x = position.getX(); + int y = position.getY(); + return new Position(--x, ++y); + } + + Position rightDownDiagonal(Position position) { + int x = position.getX(); + int y = position.getY(); + return new Position(++x, ++y); + } + + public boolean canMove(Position from, Position to, ExistBoard existBoard) { + return true; + } + + public PieceType getPieceType() { + return this.pieceType; + } + + public Camp getCamp() { + return this.camp; + } +} diff --git a/src/main/java/domain/pieces/Soldier.java b/src/main/java/domain/pieces/Soldier.java new file mode 100644 index 0000000000..6fc0c8da5c --- /dev/null +++ b/src/main/java/domain/pieces/Soldier.java @@ -0,0 +1,73 @@ +package domain.pieces; + +import domain.Camp; +import domain.ExistBoard; +import domain.PieceType; +import domain.Position; +import java.util.HashSet; +import java.util.Set; + +public class Soldier extends Piece { + + private final PieceType pieceType = PieceType.SOLDIER; + + public Soldier(Camp camp) { + super(camp); + } + + @Override + public boolean canMove(Position from, Position to, ExistBoard existBoard) { + + Set destination = new HashSet<>(); + + destination.add(move_L(from)); + destination.add(move_R(from)); + + if (this.isSameCamp(Camp.HAN)) { + destination.add(move_D(from)); + } + + if (this.isSameCamp(Camp.CHO)) { + destination.add(move_U(from)); + } + + return destination.contains(to); + } + + private Position move_U(Position position) { + try { + return up(position); + } catch (IllegalArgumentException e) { + return position; + } + } + + private Position move_L(Position position) { + try { + return left(position); + } catch (IllegalArgumentException e) { + return position; + } + } + + private Position move_R(Position position) { + try { + return right(position); + } catch (IllegalArgumentException e) { + return position; + } + } + + private Position move_D(Position position) { + try { + return down(position); + } catch (IllegalArgumentException e) { + return position; + } + } + + @Override + public PieceType getPieceType() { + return this.pieceType; + } +} diff --git a/src/main/java/dto/BoardStatusDto.java b/src/main/java/dto/BoardStatusDto.java new file mode 100644 index 0000000000..b99a1c8916 --- /dev/null +++ b/src/main/java/dto/BoardStatusDto.java @@ -0,0 +1,9 @@ +package dto; + +import java.util.List; + +public record BoardStatusDto( + List> positionStatusDtos +) { + +} diff --git a/src/main/java/dto/PositionStatusDto.java b/src/main/java/dto/PositionStatusDto.java new file mode 100644 index 0000000000..bbe48d746e --- /dev/null +++ b/src/main/java/dto/PositionStatusDto.java @@ -0,0 +1,13 @@ +package dto; + +import domain.Camp; +import domain.PieceType; +import domain.Position; + +public record PositionStatusDto( + Position position, + PieceType pieceType, + Camp camp +) { + +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 0000000000..46d80fd834 --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,80 @@ +package view; + +import domain.Camp; +import domain.Position; +import java.util.Arrays; +import java.util.Scanner; + +public class InputView { + + private final Scanner sc = new Scanner(System.in); + + public int askElephantFormation(Camp camp) { + return readElephantFormation(camp); + } + + public Position askFromPosition(Camp camp) { + while (true) { + try { + System.out.println(camp.getCampName() + " 플레이어는 말을 선택해주세요. (입력좌표 예시: 2, 1)"); + return readPosition(); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + } + + public Position askToPosition(Camp camp) { + while (true) { + try { + System.out.println( + camp.getCampName() + " 플레이어는 선택한 말을 움직일 위치를 입력해 주세요.(입력좌표 예시: 2, 3)"); + return readPosition(); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + } + + private int readElephantFormation(Camp camp) { + while (true) { + try { + System.out.println(camp.getCampName() + " 상 차림을 결정해주세요."); + System.out.println("1. [마 상 마 상]"); + System.out.println("2. [마 상 상 마]"); + System.out.println("3. [상 마 상 마]"); + System.out.println("4. [상 마 마 상]"); + return Integer.parseInt(sc.nextLine()); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + } + + private Position readPosition() { + System.out.print("좌표: "); + String[] input = Arrays.stream(sc.nextLine().split(",")) + .map(String::trim) + .toArray(String[]::new); + + validateInputSize(input); + int x = parseInt(input[0]); + int y = parseInt(input[1]); + System.out.println(); + return new Position(x, y); + } + + private int parseInt(String input) { + try { + return Integer.parseInt(input); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("[ERROR] 숫자를 입력해 주세요"); + } + } + + private void validateInputSize(String[] input) { + if (input.length != 2) { + throw new IllegalArgumentException("[ERROR] 좌표는 숫자 2개 입니다."); + } + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 0000000000..a48d4dce9e --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,84 @@ +package view; + +import domain.Camp; +import domain.PieceType; +import dto.BoardStatusDto; +import dto.PositionStatusDto; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +public class OutputView { + + private static final String ANSI_RESET = "\u001B[0m"; + private static final String ANSI_GREEN = "\u001B[32m"; + private static final String ANSI_RED = "\u001B[31m"; + + // 전각 문자 통일을 위한 설정 + private static final String EMPTY_SPACE = "."; // 전각 마침표 (U+FF0E) + private static final String[] FULL_WIDTH_NUMBERS = { + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" + }; + + private static final Map CHO_SYMBOLS = new EnumMap<>(PieceType.class); + private static final Map HAN_SYMBOLS = new EnumMap<>(PieceType.class); + + static { + CHO_SYMBOLS.put(PieceType.GENERAL, "楚"); + CHO_SYMBOLS.put(PieceType.CHARIOT, "車"); + CHO_SYMBOLS.put(PieceType.CANNON, "包"); + CHO_SYMBOLS.put(PieceType.HORSE, "馬"); + CHO_SYMBOLS.put(PieceType.ELEPHANT, "象"); + CHO_SYMBOLS.put(PieceType.GUARD, "士"); + CHO_SYMBOLS.put(PieceType.SOLDIER, "卒"); + + HAN_SYMBOLS.put(PieceType.GENERAL, "漢"); + HAN_SYMBOLS.put(PieceType.CHARIOT, "車"); + HAN_SYMBOLS.put(PieceType.CANNON, "砲"); + HAN_SYMBOLS.put(PieceType.HORSE, "馬"); + HAN_SYMBOLS.put(PieceType.ELEPHANT, "相"); + HAN_SYMBOLS.put(PieceType.GUARD, "士"); + HAN_SYMBOLS.put(PieceType.SOLDIER, "兵"); + } + + public void printBoardStatus(BoardStatusDto boardStatusDto) { + List> rows = boardStatusDto.positionStatusDtos(); + + // 1. 상단 열 인덱스 출력 (전각 숫자 사용, 앞부분 공백 2칸으로 시작점 정렬) + System.out.println("\n 0 1 2 3 4 5 6 7 8"); + + for (int i = 0; i < rows.size(); i++) { + // 2. 좌측 행 인덱스 출력 (전각 숫자 사용) + System.out.print(FULL_WIDTH_NUMBERS[i] + " "); + + List row = rows.get(i); + for (PositionStatusDto cell : row) { + // 3. 기물 출력 및 띄어쓰기 1칸 + System.out.print(formatPiece(cell) + " "); + } + System.out.println(); + } + } + + public void printWrongChoice() { + System.out.println("잘못된 말 선택입니다."); + } + + public void printErrorMessage(Exception e) { + System.out.println(e.getMessage()); + } + + private String formatPiece(PositionStatusDto cell) { + if (cell.pieceType() == PieceType.NONE) { + return EMPTY_SPACE; // 전각 마침표 반환 + } + + String symbol = (cell.camp() == Camp.CHO) + ? CHO_SYMBOLS.get(cell.pieceType()) + : HAN_SYMBOLS.get(cell.pieceType()); + + String color = (cell.camp() == Camp.CHO) ? ANSI_GREEN : ANSI_RED; + + return color + symbol + ANSI_RESET; + } +} diff --git a/src/test/java/BoardTest.java b/src/test/java/BoardTest.java new file mode 100644 index 0000000000..62c4aba964 --- /dev/null +++ b/src/test/java/BoardTest.java @@ -0,0 +1,48 @@ +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import domain.Board; +import domain.Camp; +import domain.Position; +import domain.pieces.Piece; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class BoardTest { + + @Test + void 특정_위치에_기물을_놓을_수_있다() { + Board board = new Board(); + Position position = new Position(1, 2); + Piece piece = new Piece(Camp.HAN); + board.locatePiece(position, piece); + + Assertions.assertEquals(board.getPieceFrom(position), piece); + } + + @Test + void 같은_팀_기물은_잡을_수_없다() { + Board board = new Board(); + Position position = new Position(1, 2); + Piece locatedPiece = new Piece(Camp.HAN); + Piece anotherPiece = new Piece(Camp.HAN); + board.locatePiece(position, locatedPiece); + + assertThatThrownBy(() -> board.locatePiece(position, anotherPiece)).isInstanceOf( + IllegalArgumentException.class).hasMessageContaining("[ERROR]", "같은 팀"); + } + + @Test + void 기물을_이동시킬_수_있다() { + Board board = new Board(); + Position fromPosition = new Position(1, 2); + Position toPosition = new Position(1, 3); + + Piece piece = new Piece(Camp.HAN); + board.locatePiece(fromPosition, piece); //초기 배치 + + board.move(fromPosition, toPosition); // A위치의 기물을 B로 옮긴다. + + Assertions.assertFalse(board.isExist(fromPosition)); + Assertions.assertEquals(board.getPieceFrom(toPosition).getClass(), piece.getClass()); + } +} diff --git a/src/test/java/PieceGeneratorTest.java b/src/test/java/PieceGeneratorTest.java new file mode 100644 index 0000000000..4719dda3c6 --- /dev/null +++ b/src/test/java/PieceGeneratorTest.java @@ -0,0 +1,138 @@ +import domain.Camp; +import domain.ElephantFormation; +import domain.PieceGenerator; +import domain.Position; +import domain.pieces.Elephant; +import domain.pieces.Horse; +import domain.pieces.Piece; +import java.util.Map; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class PieceGeneratorTest { + + @Test + void 한나라_말_16개_생성() { + PieceGenerator pieceGenerator = new PieceGenerator(); + + Map board = pieceGenerator.generatePieces(Camp.HAN, + ElephantFormation.RIGHT); + + Assertions.assertEquals(board.size(), 16); + } + + @Test + void 초나라_말_16개_생성() { + PieceGenerator pieceGenerator = new PieceGenerator(); + + Map board = pieceGenerator.generatePieces(Camp.CHO, + ElephantFormation.RIGHT); + + Assertions.assertEquals(board.size(), 16); + } + + @Test + void 한나라_오른상차림() { + PieceGenerator pieceGenerator = new PieceGenerator(); + + Map board = pieceGenerator.generatePieces(Camp.HAN, + ElephantFormation.RIGHT); + + Assertions.assertEquals(board.get(new Position(1, 0)).getClass(), Elephant.class); + Assertions.assertEquals(board.get(new Position(2, 0)).getClass(), Horse.class); + Assertions.assertEquals(board.get(new Position(6, 0)).getClass(), Elephant.class); + Assertions.assertEquals(board.get(new Position(7, 0)).getClass(), Horse.class); + } + + @Test + void 한나라_왼상차림() { + PieceGenerator pieceGenerator = new PieceGenerator(); + + Map board = pieceGenerator.generatePieces(Camp.HAN, + ElephantFormation.LEFT); + + Assertions.assertEquals(board.get(new Position(1, 0)).getClass(), Horse.class); + Assertions.assertEquals(board.get(new Position(2, 0)).getClass(), Elephant.class); + Assertions.assertEquals(board.get(new Position(6, 0)).getClass(), Horse.class); + Assertions.assertEquals(board.get(new Position(7, 0)).getClass(), Elephant.class); + } + + @Test + void 한나라_안상차림() { + PieceGenerator pieceGenerator = new PieceGenerator(); + + Map board = pieceGenerator.generatePieces(Camp.HAN, + ElephantFormation.INNER); + + Assertions.assertEquals(board.get(new Position(1, 0)).getClass(), Horse.class); + Assertions.assertEquals(board.get(new Position(2, 0)).getClass(), Elephant.class); + Assertions.assertEquals(board.get(new Position(6, 0)).getClass(), Elephant.class); + Assertions.assertEquals(board.get(new Position(7, 0)).getClass(), Horse.class); + } + + @Test + void 한나라_바깥상차림() { + PieceGenerator pieceGenerator = new PieceGenerator(); + + Map board = pieceGenerator.generatePieces(Camp.HAN, + ElephantFormation.OUTER); + + Assertions.assertEquals(board.get(new Position(1, 0)).getClass(), Elephant.class); + Assertions.assertEquals(board.get(new Position(2, 0)).getClass(), Horse.class); + Assertions.assertEquals(board.get(new Position(6, 0)).getClass(), Horse.class); + Assertions.assertEquals(board.get(new Position(7, 0)).getClass(), Elephant.class); + } + + + @Test + void 초나라_오른상차림() { + PieceGenerator pieceGenerator = new PieceGenerator(); + + Map board = pieceGenerator.generatePieces(Camp.CHO, + ElephantFormation.RIGHT); + + Assertions.assertEquals(board.get(new Position(1, 9)).getClass(), Horse.class); + Assertions.assertEquals(board.get(new Position(2, 9)).getClass(), Elephant.class); + Assertions.assertEquals(board.get(new Position(6, 9)).getClass(), Horse.class); + Assertions.assertEquals(board.get(new Position(7, 9)).getClass(), Elephant.class); + } + + @Test + void 초나라_왼상차림() { + PieceGenerator pieceGenerator = new PieceGenerator(); + + Map board = pieceGenerator.generatePieces(Camp.CHO, + ElephantFormation.LEFT); + + Assertions.assertEquals(board.get(new Position(1, 9)).getClass(), Elephant.class); + Assertions.assertEquals(board.get(new Position(2, 9)).getClass(), Horse.class); + Assertions.assertEquals(board.get(new Position(6, 9)).getClass(), Elephant.class); + Assertions.assertEquals(board.get(new Position(7, 9)).getClass(), Horse.class); + } + + @Test + void 초나라_안상차림() { + PieceGenerator pieceGenerator = new PieceGenerator(); + + Map board = pieceGenerator.generatePieces(Camp.CHO, + ElephantFormation.INNER); + + Assertions.assertEquals(board.get(new Position(1, 9)).getClass(), Horse.class); + Assertions.assertEquals(board.get(new Position(2, 9)).getClass(), Elephant.class); + Assertions.assertEquals(board.get(new Position(6, 9)).getClass(), Elephant.class); + Assertions.assertEquals(board.get(new Position(7, 9)).getClass(), Horse.class); + } + + @Test + void 초나라_바깥상차림() { + PieceGenerator pieceGenerator = new PieceGenerator(); + + Map board = pieceGenerator.generatePieces(Camp.CHO, + ElephantFormation.OUTER); + + Assertions.assertEquals(board.get(new Position(1, 9)).getClass(), Elephant.class); + Assertions.assertEquals(board.get(new Position(2, 9)).getClass(), Horse.class); + Assertions.assertEquals(board.get(new Position(6, 9)).getClass(), Horse.class); + Assertions.assertEquals(board.get(new Position(7, 9)).getClass(), Elephant.class); + } +} diff --git a/src/test/java/domain/PositionTest.java b/src/test/java/domain/PositionTest.java new file mode 100644 index 0000000000..6fa1492629 --- /dev/null +++ b/src/test/java/domain/PositionTest.java @@ -0,0 +1,39 @@ +package domain; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +class PositionTest { + + @ParameterizedTest + @CsvSource({ + "0, 9", + "0, 8", + "8, 9", + "8, 8", + "2, 3" + }) + void 정상_생성_테스트(int x, int y) { + Assertions.assertThat(new Position(x, y)).isInstanceOf(Position.class); + } + + @ParameterizedTest + @ValueSource(ints = {-1, 9, 12}) + void X_예외_값_입력_오류_검증(int x) { + assertThatThrownBy(() -> new Position(x, 4)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("[ERROR]", "x 좌표는"); + } + + @ParameterizedTest + @ValueSource(ints = {-5, -1, 10, 12, 1000}) + void Y_예외_값_입력_오류_검증(int y) { + assertThatThrownBy(() -> new Position(1, y)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("[ERROR]", "y좌표"); + } +} diff --git a/src/test/java/domain/pieces/CannonTest.java b/src/test/java/domain/pieces/CannonTest.java new file mode 100644 index 0000000000..2b7b753ee1 --- /dev/null +++ b/src/test/java/domain/pieces/CannonTest.java @@ -0,0 +1,96 @@ +package domain.pieces; + +import domain.Board; +import domain.Camp; +import domain.Position; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class CannonTest { + + @Test + void 다른_기물을_넘고_이동_가능() { + Board board = new Board(); + Cannon cannon = new Cannon(Camp.HAN); + Piece piece = new Piece(Camp.HAN); + + Position fromPosition = new Position(3, 5); + Position anotherPiecePosition = new Position(5, 5); + + board.locatePiece(fromPosition, cannon); + board.locatePiece(anotherPiecePosition, piece); + + Assertions.assertFalse(cannon.canMove(fromPosition, new Position(3, 5), board)); + Assertions.assertFalse(cannon.canMove(fromPosition, new Position(4, 5), board)); + Assertions.assertFalse(cannon.canMove(fromPosition, new Position(5, 5), board)); + Assertions.assertTrue(cannon.canMove(fromPosition, new Position(6, 5), board)); + Assertions.assertTrue(cannon.canMove(fromPosition, new Position(7, 5), board)); + Assertions.assertTrue(cannon.canMove(fromPosition, new Position(8, 5), board)); + } + + @Test + void 포에_막혀_이동_불가() { + Board board = new Board(); + Cannon cannon = new Cannon(Camp.HAN); + Cannon cannonForBlock = new Cannon(Camp.HAN); + + Position fromPosition = new Position(3, 5); + Position anotherPiecePosition = new Position(5, 5); + + board.locatePiece(fromPosition, cannon); + board.locatePiece(anotherPiecePosition, cannonForBlock); + + Assertions.assertFalse(cannon.canMove(fromPosition, new Position(3, 5), board)); + Assertions.assertFalse(cannon.canMove(fromPosition, new Position(4, 5), board)); + Assertions.assertFalse(cannon.canMove(fromPosition, new Position(5, 5), board)); + Assertions.assertFalse(cannon.canMove(fromPosition, new Position(6, 5), board)); + Assertions.assertFalse(cannon.canMove(fromPosition, new Position(7, 5), board)); + Assertions.assertFalse(cannon.canMove(fromPosition, new Position(8, 5), board)); + } + + @Test + void 기물을_넘고_다른_기물을_만나기_전까지_이동_가능() { + Board board = new Board(); + Cannon cannon = new Cannon(Camp.HAN); + Piece pieceA = new Piece(Camp.HAN); + Piece pieceB = new Piece(Camp.HAN); + + Position fromPosition = new Position(3, 5); + Position anotherPieceAPosition = new Position(5, 5); + Position anotherPieceBPosition = new Position(7, 5); + + board.locatePiece(fromPosition, cannon); + board.locatePiece(anotherPieceAPosition, pieceA); + board.locatePiece(anotherPieceBPosition, pieceB); + + Assertions.assertFalse(cannon.canMove(fromPosition, new Position(3, 5), board)); + Assertions.assertFalse(cannon.canMove(fromPosition, new Position(4, 5), board)); + Assertions.assertFalse(cannon.canMove(fromPosition, new Position(5, 5), board)); + Assertions.assertTrue(cannon.canMove(fromPosition, new Position(6, 5), board)); + Assertions.assertTrue(cannon.canMove(fromPosition, new Position(7, 5), board)); + Assertions.assertFalse(cannon.canMove(fromPosition, new Position(8, 5), board)); + } + + @Test + void 기물을_넘고_다른_기물을_만나기_전까지_이동_가능_포는_못잡음() { + Board board = new Board(); + Cannon cannon = new Cannon(Camp.HAN); + Piece pieceA = new Piece(Camp.CHO); + Cannon pieceB = new Cannon(Camp.CHO); + + Position fromPosition = new Position(3, 5); + Position anotherPieceAPosition = new Position(5, 5); + Position anotherPieceBPosition = new Position(7, 5); + + board.locatePiece(fromPosition, cannon); + board.locatePiece(anotherPieceAPosition, pieceA); + board.locatePiece(anotherPieceBPosition, pieceB); + + Assertions.assertFalse(cannon.canMove(fromPosition, new Position(3, 5), board)); + Assertions.assertFalse(cannon.canMove(fromPosition, new Position(4, 5), board)); + Assertions.assertFalse(cannon.canMove(fromPosition, new Position(5, 5), board)); + Assertions.assertTrue(cannon.canMove(fromPosition, new Position(6, 5), board)); + Assertions.assertFalse(cannon.canMove(fromPosition, new Position(7, 5), board)); + Assertions.assertFalse(cannon.canMove(fromPosition, new Position(8, 5), board)); + } +} diff --git a/src/test/java/domain/pieces/ChariotTest.java b/src/test/java/domain/pieces/ChariotTest.java new file mode 100644 index 0000000000..4f08b0ed8d --- /dev/null +++ b/src/test/java/domain/pieces/ChariotTest.java @@ -0,0 +1,30 @@ +package domain.pieces; + +import domain.Board; +import domain.Camp; +import domain.Position; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class ChariotTest { + + @Test + void 다른_기물_뒤로는_이동할_수_없다() { + Board board = new Board(); + Chariot chariot = new Chariot(Camp.HAN); + Piece piece = new Piece(Camp.HAN); + + Position fromPosition = new Position(3, 5); + Position anotherPiecePosition = new Position(6, 5); + + board.locatePiece(fromPosition, chariot); + board.locatePiece(anotherPiecePosition, piece); + + Assertions.assertFalse(chariot.canMove(fromPosition, new Position(3, 5), board)); + Assertions.assertTrue(chariot.canMove(fromPosition, new Position(4, 5), board)); + Assertions.assertTrue(chariot.canMove(fromPosition, new Position(5, 5), board)); + Assertions.assertTrue(chariot.canMove(fromPosition, new Position(6, 5), board)); + Assertions.assertFalse(chariot.canMove(fromPosition, new Position(7, 5), board)); + Assertions.assertFalse(chariot.canMove(fromPosition, new Position(8, 5), board)); + } +} diff --git a/src/test/java/domain/pieces/ElephantTest.java b/src/test/java/domain/pieces/ElephantTest.java new file mode 100644 index 0000000000..5351afb2de --- /dev/null +++ b/src/test/java/domain/pieces/ElephantTest.java @@ -0,0 +1,61 @@ +package domain.pieces; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import domain.Board; +import domain.Camp; +import domain.Position; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class ElephantTest { + + @Test + void 위로_오른대각선_이동_가능() { + Board board = new Board(); + Elephant elephant = new Elephant(Camp.HAN); + Position fromPosition = new Position(2, 9); + Position toPosition = new Position(4, 6); + + Assertions.assertTrue(elephant.canMove(fromPosition, toPosition, board)); + } + + @Test + void 위로_오른대각선_이동() { + Board board = new Board(); + Elephant elephant = new Elephant(Camp.HAN); + Position fromPosition = new Position(2, 9); + Position toPosition = new Position(4, 6); + + board.locatePiece(fromPosition, elephant); + board.move(fromPosition, toPosition); + + Assertions.assertFalse(board.isExist(fromPosition)); + Assertions.assertEquals(board.getPieceFrom(toPosition), elephant); + } + + @Test + void 위로_오른대각선_경로_막힘() { + Board board = new Board(); + Elephant elephant = new Elephant(Camp.HAN); + Piece piece = new Piece(Camp.HAN); + Position fromPosition = new Position(2, 9); + Position toPosition = new Position(4, 6); + + board.locatePiece(fromPosition, elephant); + board.locatePiece(new Position(2, 8), piece); + + assertThatThrownBy(() -> board.move(fromPosition, toPosition)).isInstanceOf( + IllegalArgumentException.class).hasMessageContaining("[ERROR]", "이동할"); + } + + @Test + void 이동_불가_좌표_이동_불가() { + Board board = new Board(); + Elephant elephant = new Elephant(Camp.HAN); + Position fromPosition = new Position(2, 9); + Position toPosition = new Position(0, 0); + + Assertions.assertFalse(elephant.canMove(fromPosition, toPosition, board)); + } +} diff --git a/src/test/java/domain/pieces/GeneralTest.java b/src/test/java/domain/pieces/GeneralTest.java new file mode 100644 index 0000000000..916b733cf4 --- /dev/null +++ b/src/test/java/domain/pieces/GeneralTest.java @@ -0,0 +1,61 @@ +package domain.pieces; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import domain.Board; +import domain.Camp; +import domain.Position; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class GeneralTest { + + @Test + void 아래로_오른대각선_이동_가능() { + Board board = new Board(); + General general = new General(Camp.HAN); + Position fromPosition = new Position(4, 1); + Position toPosition = new Position(5, 2); + + Assertions.assertTrue(general.canMove(fromPosition, toPosition, board)); + } + + @Test + void 아래로_오른대각선_이동() { + Board board = new Board(); + General general = new General(Camp.HAN); + Position fromPosition = new Position(4, 1); + Position toPosition = new Position(5, 2); + + board.locatePiece(fromPosition, general); + board.move(fromPosition, toPosition); + + Assertions.assertFalse(board.isExist(fromPosition)); + Assertions.assertEquals(board.getPieceFrom(toPosition), general); + } + + @Test + void 아래로_오른대각선_경로_막힘() { + Board board = new Board(); + General general = new General(Camp.HAN); + Piece piece = new Piece(Camp.HAN); + Position fromPosition = new Position(4, 1); + Position toPosition = new Position(5, 2); + + board.locatePiece(fromPosition, general); + board.locatePiece(toPosition, piece); + + assertThatThrownBy(() -> board.move(fromPosition, toPosition)).isInstanceOf( + IllegalArgumentException.class).hasMessageContaining("[ERROR]", "이동할"); + } + + @Test + void 이동_불가_좌표_이동_불가() { + Board board = new Board(); + General general = new General(Camp.HAN); + Position fromPosition = new Position(3, 0); + Position toPosition = new Position(0, 0); + + Assertions.assertFalse(general.canMove(fromPosition, toPosition, board)); + } +} diff --git a/src/test/java/domain/pieces/GuardTest.java b/src/test/java/domain/pieces/GuardTest.java new file mode 100644 index 0000000000..e3f1a499d9 --- /dev/null +++ b/src/test/java/domain/pieces/GuardTest.java @@ -0,0 +1,61 @@ +package domain.pieces; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import domain.Board; +import domain.Camp; +import domain.Position; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class GuardTest { + + @Test + void 아래로_오른대각선_이동_가능() { + Board board = new Board(); + Guard guard = new Guard(Camp.HAN); + Position fromPosition = new Position(3, 0); + Position toPosition = new Position(4, 1); + + Assertions.assertTrue(guard.canMove(fromPosition, toPosition, board)); + } + + @Test + void 아래로_오른대각선_이동() { + Board board = new Board(); + Guard guard = new Guard(Camp.HAN); + Position fromPosition = new Position(3, 0); + Position toPosition = new Position(4, 1); + + board.locatePiece(fromPosition, guard); + board.move(fromPosition, toPosition); + + Assertions.assertFalse(board.isExist(fromPosition)); + Assertions.assertEquals(board.getPieceFrom(toPosition), guard); + } + + @Test + void 아래로_오른대각선_경로_막힘() { + Board board = new Board(); + Guard guard = new Guard(Camp.HAN); + Piece piece = new Piece(Camp.HAN); + Position fromPosition = new Position(3, 0); + Position toPosition = new Position(4, 1); + + board.locatePiece(fromPosition, guard); + board.locatePiece(toPosition, piece); + + assertThatThrownBy(() -> board.move(fromPosition, toPosition)).isInstanceOf( + IllegalArgumentException.class).hasMessageContaining("[ERROR]", "이동할"); + } + + @Test + void 이동_불가_좌표_이동_불가() { + Board board = new Board(); + Guard guard = new Guard(Camp.HAN); + Position fromPosition = new Position(3, 0); + Position toPosition = new Position(0, 0); + + Assertions.assertFalse(guard.canMove(fromPosition, toPosition, board)); + } +} diff --git a/src/test/java/domain/pieces/HorseTest.java b/src/test/java/domain/pieces/HorseTest.java new file mode 100644 index 0000000000..e253c223f3 --- /dev/null +++ b/src/test/java/domain/pieces/HorseTest.java @@ -0,0 +1,61 @@ +package domain.pieces; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import domain.Board; +import domain.Camp; +import domain.Position; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class HorseTest { + + @Test + void 위로_오른대각선_이동_가능() { + Board board = new Board(); + Horse horse = new Horse(Camp.HAN); + Position fromPosition = new Position(2, 9); + Position toPosition = new Position(3, 7); + + Assertions.assertTrue(horse.canMove(fromPosition, toPosition, board)); + } + + @Test + void 위로_오른대각선_이동() { + Board board = new Board(); + Horse horse = new Horse(Camp.HAN); + Position fromPosition = new Position(2, 9); + Position toPosition = new Position(3, 7); + + board.locatePiece(fromPosition, horse); + board.move(fromPosition, toPosition); + + Assertions.assertFalse(board.isExist(fromPosition)); + Assertions.assertEquals(board.getPieceFrom(toPosition), horse); + } + + @Test + void 위로_오른대각선_경로_막힘() { + Board board = new Board(); + Horse horse = new Horse(Camp.HAN); + Piece piece = new Piece(Camp.HAN); + Position fromPosition = new Position(2, 9); + Position toPosition = new Position(3, 7); + + board.locatePiece(fromPosition, horse); + board.locatePiece(new Position(2, 8), piece); + + assertThatThrownBy(() -> board.move(fromPosition, toPosition)).isInstanceOf( + IllegalArgumentException.class).hasMessageContaining("[ERROR]", "이동할"); + } + + @Test + void 이동_불가_좌표_이동_불가() { + Board board = new Board(); + Horse horse = new Horse(Camp.HAN); + Position fromPosition = new Position(2, 9); + Position toPosition = new Position(0, 0); + + Assertions.assertFalse(horse.canMove(fromPosition, toPosition, board)); + } +} diff --git a/src/test/java/domain/pieces/SoldierTest.java b/src/test/java/domain/pieces/SoldierTest.java new file mode 100644 index 0000000000..af4724b874 --- /dev/null +++ b/src/test/java/domain/pieces/SoldierTest.java @@ -0,0 +1,105 @@ +package domain.pieces; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import domain.Board; +import domain.Camp; +import domain.Position; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class SoldierTest { + + @Test + void 한나라_기준_앞으로_한_칸_전진_가능() { + Board board = new Board(); + Soldier soldier = new Soldier(Camp.HAN); + Position fromPosition = new Position(0, 3); + Position toPosition = new Position(0, 4); + + Assertions.assertTrue(soldier.canMove(fromPosition, toPosition, board)); + } + + @Test + void 한나라_기준_왼쪽으로_한_칸_전진_가능() { + Board board = new Board(); + Soldier soldier = new Soldier(Camp.HAN); + Position fromPosition = new Position(0, 3); + Position toPosition = new Position(1, 3); + + Assertions.assertTrue(soldier.canMove(fromPosition, toPosition, board)); + } + + @Test + void 한나라_기준_뒤로_한_칸_후진_불가() { + Board board = new Board(); + Soldier soldier = new Soldier(Camp.HAN); + Position fromPosition = new Position(0, 3); + Position toPosition = new Position(0, 2); + + Assertions.assertFalse(soldier.canMove(fromPosition, toPosition, board)); + } + + @Test + void 같은_팀_기물_막힘으로_앞으로_한_칸_전진_불가() { + Board board = new Board(); + Soldier soldier = new Soldier(Camp.HAN); + Piece piece = new Piece(Camp.HAN); + + Position fromPosition = new Position(0, 3); + Position toPosition = new Position(0, 4); + + board.locatePiece(fromPosition, soldier); + board.locatePiece(toPosition, piece); + + assertThatThrownBy(() -> board.move(fromPosition, toPosition)).isInstanceOf( + IllegalArgumentException.class).hasMessageContaining("[ERROR]", "같은 팀"); + } + + @Test + void 상대_팀_기물_잡고_앞으로_한_칸_전진_가능() { + Board board = new Board(); + Soldier soldier = new Soldier(Camp.HAN); + Piece piece = new Piece(Camp.CHO); + + Position fromPosition = new Position(0, 3); + Position toPosition = new Position(0, 4); + + board.locatePiece(fromPosition, soldier); + board.locatePiece(toPosition, piece); + + board.move(fromPosition, toPosition); + + Assertions.assertEquals(board.getPieceFrom(toPosition), soldier); + } + + @Test + void 초나라_기준_앞으로_한_칸_전진_가능() { + Board board = new Board(); + Soldier soldier = new Soldier(Camp.CHO); + Position fromPosition = new Position(0, 6); + Position toPosition = new Position(0, 5); + + Assertions.assertTrue(soldier.canMove(fromPosition, toPosition, board)); + } + + @Test + void 초나라_기준_오른쪽으로_한_칸_전진_가능() { + Board board = new Board(); + Soldier soldier = new Soldier(Camp.CHO); + Position fromPosition = new Position(0, 6); + Position toPosition = new Position(1, 6); + + Assertions.assertTrue(soldier.canMove(fromPosition, toPosition, board)); + } + + @Test + void 초나라_기준_뒤로_한_칸_후진_불가() { + Board board = new Board(); + Soldier soldier = new Soldier(Camp.CHO); + Position fromPosition = new Position(0, 6); + Position toPosition = new Position(0, 7); + + Assertions.assertFalse(soldier.canMove(fromPosition, toPosition, board)); + } +}