diff --git a/.idea/material_theme_project_new.xml b/.idea/material_theme_project_new.xml new file mode 100644 index 0000000..73c9d30 --- /dev/null +++ b/.idea/material_theme_project_new.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 8f86b33..807cb65 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -4,7 +4,7 @@ - + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/Ladder.java b/src/main/java/Ladder.java deleted file mode 100644 index 0d2b070..0000000 --- a/src/main/java/Ladder.java +++ /dev/null @@ -1,8 +0,0 @@ -public class Ladder { - - private final int[][] rows; - - public Ladder(int row, int numberOfPerson) { - rows = new int[row][numberOfPerson]; - } -} diff --git a/src/main/java/ladder/Direction.java b/src/main/java/ladder/Direction.java new file mode 100644 index 0000000..1d1d1f2 --- /dev/null +++ b/src/main/java/ladder/Direction.java @@ -0,0 +1,20 @@ +package ladder; + +public enum Direction { + + LEFT(-1), RIGHT(1), NONE(0); + + private final int value; + + Direction(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public String getStringValue() { + return Integer.toString(value); + } +} diff --git a/src/main/java/ladder/ExceptionMessage.java b/src/main/java/ladder/ExceptionMessage.java new file mode 100644 index 0000000..10fea54 --- /dev/null +++ b/src/main/java/ladder/ExceptionMessage.java @@ -0,0 +1,19 @@ +package ladder; + +public enum ExceptionMessage { + + INVALID_LADDER_POSITION("사다리 위치는 1이상 자연수입니다."), + INVALID_LADDER_NUMBER("사다리의 행과 열은 2 이상이여야 합니다."), + INVALID_POSITION("유효하지 않은 위치입니다."), + INVALID_DRAW_POSITION("사다리를 그릴 수 없는 위치입니다."); + + private final String message; + + ExceptionMessage(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } +} diff --git a/src/main/java/ladder/GreaterThanOne.java b/src/main/java/ladder/GreaterThanOne.java new file mode 100644 index 0000000..940c76e --- /dev/null +++ b/src/main/java/ladder/GreaterThanOne.java @@ -0,0 +1,27 @@ +package ladder; + +// 1보다 큰지 검증하는 클래스 +public class GreaterThanOne { + + private final int number; + + private GreaterThanOne(int number) { + this.number = number; + } + + public static GreaterThanOne from(int number) { + if (! isGreaterThanOne(number)) { // 팩토리 메소드로 검증 (1보다 큰지) + throw new IllegalArgumentException(ExceptionMessage.INVALID_LADDER_NUMBER.getMessage()); + } + return new GreaterThanOne(number); + } + + // opt + cmd + m : 드래그 한 부분 새로운 method 생성 + private static boolean isGreaterThanOne(int number) { + return number > 1; + } + + public int getNumber() { + return number; + } +} diff --git a/src/main/java/ladder/LadderGame.java b/src/main/java/ladder/LadderGame.java new file mode 100644 index 0000000..754d7b2 --- /dev/null +++ b/src/main/java/ladder/LadderGame.java @@ -0,0 +1,31 @@ +package ladder; + +import ladder.creator.LadderCreator; +import ladder.creator.LadderRandomCreator; + +// todo Ladder 클래스가 많은 책임 (사다리 생성 / 사다리 그리기 / 사다리 게임 진행) +// 마지막으로 Ladder는 전체를 관장하는 클래스가 되었으므로 +// LadderGame으로 변경 +// todo LadderGame에 의존성주입을 통해 LadderCreator를 변경해보기 +// todo LadderGame클래스 자체도 정적메소드 패턴을 이용하여 생성 +public class LadderGame { + + private final LadderCreator ladderCreator; + // private final LadderRandomCreator ladderRandomCreator; + + public LadderGame(LadderCreator ladderCreator) { + this.ladderCreator = ladderCreator; + } + + + + // todo 포지션 wrapper 클래스 필요 + // todo LadderRunner로 분리 (Ladder 클래스 책임분산) + // LadderRunner를 통해 돌리자 (사다리를 타는것을 관리하는 클래스) + public int run(Position position) { + LadderRunner ladderRunner = new LadderRunner(ladderCreator.getRows()); // 이미 만들어 둔 ladderCreator의 사다리를 인수로 넘긴다.. + ladderRunner.run(position); + + return position.getPosition(); // 최종 인덱스(세로 번 째) 반환 + } +} diff --git a/src/main/java/ladder/LadderPosition.java b/src/main/java/ladder/LadderPosition.java new file mode 100644 index 0000000..c2fe9b7 --- /dev/null +++ b/src/main/java/ladder/LadderPosition.java @@ -0,0 +1,30 @@ +package ladder; + +// 사다리 출력을 위해, (x,y)좌표를 동시에 다루는 클래스 +// 어디에 점을 찍을 지 알 수 있다...? +public class LadderPosition { + Position x, y; + + public LadderPosition(Position x, Position y) { + this.x = x; + this.y = y; + } + + public Position getX() { + return x; + } + + public Position getY() { + return y; + } + + public int getIntX() { + return x.getPosition(); + } + + public int getIntY() { + return y.getPosition(); + } + + +} diff --git a/src/main/java/ladder/LadderRunner.java b/src/main/java/ladder/LadderRunner.java new file mode 100644 index 0000000..933e2cf --- /dev/null +++ b/src/main/java/ladder/LadderRunner.java @@ -0,0 +1,62 @@ +package ladder; + +public class LadderRunner { + + private final Row[] rows; // 사다리의 한 행을 빼놓았다. + private StringBuilder ladder = new StringBuilder(); + + public LadderRunner(Row[] rows) { + this.rows = rows; + } + + // todo 포지션 wrapper 클래스 필요 + // 매개변수 : 시작 x좌표 / 반복문 : y좌표 + public int run(Position position) { + // position (x)좌표는 마지막 위치에 있고 + // for문의 반복으로 y좌표가 움직이면 좌표 다룰 수 있음 + + for (int i = 0; i < rows.length; i++) { + // 사다리 (*포함) 세팅 + // todo 매개변수로 넘기는 값이 x,y인지 구별될 수 있도록 + setStringLadder(new LadderPosition(position, Position.from(i))); + printLadder(); + rows[i].nextPosition(position); + setStringLadder(new LadderPosition(position, Position.from(i))); + printLadder(); + } + + System.out.println("-".repeat(10)); + + return position.getPosition(); + } + + public void setStringLadder(LadderPosition xy) { + // 점을 한번 찍으면 특정 변수에 변화를 주어서, 다음 줄에서는 *을 찍지 않도록 조치..? + + for (int i = 0; i < rows.length; i++) { // 높이만큼 순환 + // todo 여기서 xy의 y좌표랑 반복문 인자 i랑 같은지 확인하고 + // 같을 때 만 *을 찍을 수 있도록 인자를 넘긴다. + if (xy.getIntY() == i) { + ladder.append(rows[i].setStringStarLadder(xy)); // *을 붙이는 라인 + ladder.append(System.lineSeparator()); + continue; + } + ladder.append(rows[i].setStringLadder(xy)); // 일반 사다리 붙이는 라인 + ladder.append(System.lineSeparator()); + } + } + + public void printLadder() { + System.out.println(ladder); + // System.out.println(); + clearStringLadder(); + } + + public void clearStringLadder() { + ladder.setLength(0); // 전체 사다리 초기화 + +// for (int i = 0; i < rows.length; i++) { // 만들었던 사다리 줄 하나씩 초기화 +// rows[i].rowLadder.setLength(0); +// } + } +} diff --git a/src/main/java/ladder/LadderSize.java b/src/main/java/ladder/LadderSize.java new file mode 100644 index 0000000..9f4ef33 --- /dev/null +++ b/src/main/java/ladder/LadderSize.java @@ -0,0 +1,32 @@ +package ladder; + +public class LadderSize { + GreaterThanOne row, numberOfPerson; + + public LadderSize(GreaterThanOne row, GreaterThanOne numberOfPerson) { + this.row = row; + this.numberOfPerson = numberOfPerson; + } + + public GreaterThanOne getRow() { + return row; + } + + public GreaterThanOne getNumberOfPerson() { + return numberOfPerson; + } + + public int getIntRow() { + return row.getNumber(); + } + + public int getIntNumberOfPerson() { + return numberOfPerson.getNumber(); + } + + // 생성해야 할 라인 개수 반환 + public int getLadderLineNum() { + return (int) Math.floor(numberOfPerson.getNumber() * row.getNumber() * 0.3); + } + +} diff --git a/src/main/java/ladder/Node.java b/src/main/java/ladder/Node.java new file mode 100644 index 0000000..2de93fe --- /dev/null +++ b/src/main/java/ladder/Node.java @@ -0,0 +1,58 @@ +package ladder; +import static ladder.Direction.*; + +// 사다리의 세로줄 (열), numberOFPerson +// 사다리의 실제 값 (방향)을 지정하는 클래스 +public class Node { + private Direction direction; // 사다리의 실제 값 + + private Node(Direction direction) { + this.direction = direction; + } + + public static Node from(Direction direction) { + return new Node(direction); + } + + public void setRightNode(Position position) { + direction = RIGHT; + } + + public void setLeftNode(Position position) { + direction = LEFT; + } + + // 밖에서 안쓰므로 private으로 만들기 + private boolean isRight() { + return direction == RIGHT; + } + + private boolean isLeft() { + return direction == LEFT; + } + + public boolean isAlreadySetDirection() { + return isNone(); + } + + private boolean isNone() { + return direction == NONE; + } + + // 노드값을 보고 하는 것이므로 node의 책임 (from Row클래스) + public void move(Position position) { + if (isRight()) { + position.next(); // position (인덱스값 ++) + return; + } + if (isLeft()) { + position.prev(); + return; + } + } + + public String getDirection() { + return direction.getStringValue(); + } + +} diff --git a/src/main/java/ladder/Position.java b/src/main/java/ladder/Position.java new file mode 100644 index 0000000..9951904 --- /dev/null +++ b/src/main/java/ladder/Position.java @@ -0,0 +1,52 @@ +package ladder; + +// 사다리의 인덱스(위치)를 나타내는 클래스 +public class Position { + + private int position; + + private Position(int position) { + this.position = position; + } + + public int getPosition() { + return position; + } + + public static Position from(int position) { + validatePosition(position); // 1-1. 검증로직 + return new Position(position); + } + + private static void validatePosition(int position) { + if (!isPosition(position)) { + throw new IllegalArgumentException(ExceptionMessage.INVALID_LADDER_POSITION.getMessage()); + } + + } + + private static boolean isPosition(int position) { + return position >= 0; + } + + public boolean isBiggerThan(int position) { + return this.position > position; + } + + public boolean isSmallerThan(int position) { + return this.position < position; + } + + public void next() { + // return Position.from(position + 1); (1) + position++; + } + // 3번째 강의 11:04 + // 1. Position을 생성해서 넘겨주고 있음 (next, prev) + // 1-3. Position을 생성해서 로직을 돌리는 것 보다, 본인 스스로 관리하도록 + + public void prev() { + // return Position.from(position - 1); + position--; + } +} diff --git a/src/main/java/ladder/Row.java b/src/main/java/ladder/Row.java new file mode 100644 index 0000000..0b94ccf --- /dev/null +++ b/src/main/java/ladder/Row.java @@ -0,0 +1,104 @@ +package ladder; +// 문제점 +// drawLine, nextPosition 등의 하드코딩 (+1 or -1) + +import static ladder.Direction.*; + +// 사다리의 하나의 가로줄 (행) +public class Row { + // todo Node 클래스로 분리(row 배열에서 값을 하나씩 꺼내서 볼 필요가 없다..?) + Node[] nodes; + + public Row(GreaterThanOne numberOfPerson) { + nodes = new Node[numberOfPerson.getNumber()]; // 노드 배열개수할당 + for (int i = 0; i < numberOfPerson.getNumber(); i++) { + nodes[i] = Node.from(NONE); + } + } + + public StringBuilder setStringLadder(LadderPosition xy) { + StringBuilder rowLadder = new StringBuilder(); // 호출 될 때 마다 새로운 StringBuilder + + for (int i = 0; i < nodes.length; i++) { // 사람 수 만큼 순환 + + rowLadder.append(nodes[i].getDirection());// 받는 로직 추가 + rowLadder.append(" "); + } + return rowLadder; + + } + // *이 포함되게 찍히는 메소드 + public StringBuilder setStringStarLadder(LadderPosition xy) { + StringBuilder rowLadder = new StringBuilder(); // 호출 될 때 마다 새로운 StringBuilder + + for (int i = 0; i < nodes.length; i++) { // 사람 수 만큼 순환 + // y좌표를 고려하여 *을 찍을 수 있는지 없는지 판단한다. + + rowLadder.append(nodes[i].getDirection());// 받는 로직 추가 + if (i == xy.getIntX()) { // x좌표에 무조건 점을 찍게된다 + rowLadder.append("*"); + } + rowLadder.append(" "); + } + return rowLadder; + + } + + // todo : 상수 리팩토링 (1,-1, 0) + public void drawLine(Position startPosition) { + validateDrawLinePosition(startPosition); // 선 그리기 유효성 검사 통합 + + setDirectionBetweenNextPosition(startPosition); + } + + private void setDirectionBetweenNextPosition(Position position) { + nodes[position.getPosition()].setRightNode(position); // 현재 노드에 1대입 (오른쪽 이동) + position.next(); + nodes[position.getPosition()].setLeftNode(position); // 그 다음 노드에 -1대입 (왼쪽 이동) + } + + // run 메소드의 다음 상태 + // 시작점이 될 수 있는지 판단하고 + // Node 클래스의 move메소드로 넘겨서 실제 움직임을 동작한다 + public void nextPosition(Position position) { + // Position클래스 자체에서는 사다리의 크기를 모르므로 Row클래스에서 검증해야 함 + validatePosition(position); // 1-2. next, prev 이전에 다시 position 검증 + + nodes[position.getPosition()].move(position); // 검증이 완료된 position을 넘긴다. + } + + // Todo 상수 하드코딩도 enum으로 클래스단위로 관리하자 + + private void validatePosition(Position position) { + if (position.isBiggerThan(nodes.length - 1)) { // 위치값과 실제 인덱스값 동일시 + throw new IllegalArgumentException(ExceptionMessage.INVALID_POSITION.getMessage()); + } + } + + // 선그리기 유효성 검사 통합 + private void validateDrawLinePosition(Position startPosition) { + if (isInvalidPosition(startPosition) || isLineAtPosition(startPosition) || isLineAtNextPosition(startPosition)) { + throw new IllegalArgumentException(ExceptionMessage.INVALID_DRAW_POSITION.getMessage()); + } + } + + // 선그리기 유효성 검사 + // 1. 숫자가 사다리 크기보다 커서 실패하는 경우 + private boolean isInvalidPosition(Position startPosition) { + return startPosition.isBiggerThan(nodes.length - 1); // startPosition.getPosition() < 0 -> position 만들때 이미 검증했던 logic + } + + // 2. 이미 그려진 경우 + private boolean isLineAtPosition(Position startPosition) { + return ! nodes[startPosition.getPosition()].isAlreadySetDirection(); // none이 아니면 + // return nodes[startPosition.getPosition()] == RIGHT.getValue() || row[startPosition.getPosition()] == LEFT.getValue(); + } + + // 3. 옆에 이미 그려진 경우 + private boolean isLineAtNextPosition(Position startPosition) { + startPosition.next(); + boolean IsLineAtPosition = !nodes[startPosition.getPosition()].isAlreadySetDirection(); + startPosition.prev(); + return IsLineAtPosition; + } +} \ No newline at end of file diff --git a/src/main/java/ladder/creator/LadderCreation.java b/src/main/java/ladder/creator/LadderCreation.java new file mode 100644 index 0000000..092ce92 --- /dev/null +++ b/src/main/java/ladder/creator/LadderCreation.java @@ -0,0 +1,10 @@ +package ladder.creator; + +import ladder.Position; +import ladder.Row; + +public interface LadderCreation { + void drawLine(Position row, Position col); + + Row[] getRows(); +} diff --git a/src/main/java/ladder/creator/LadderCreator.java b/src/main/java/ladder/creator/LadderCreator.java new file mode 100644 index 0000000..6d88d1a --- /dev/null +++ b/src/main/java/ladder/creator/LadderCreator.java @@ -0,0 +1,31 @@ +package ladder.creator; + +import ladder.GreaterThanOne; +import ladder.Position; +import ladder.Row; + +public class LadderCreator implements LadderCreation{ + + private final Row[] rows; // 사다리의 한 행을 빼놓았다. + + // todo 생성자 wrapper 클래스 필요 ㅇㅋ (-> GreaterThanOne) + // Greaterthanone 클래스 필요 : 사다리 게임을 1명이서 하지는 않으니 (사다리 높이 및 인원수는 최소 1이상) + public LadderCreator(GreaterThanOne numberOfRow, GreaterThanOne numberOfPerson) { + rows = new Row[numberOfRow.getNumber()]; // 가로줄 몇개 만들건지 + for (int i = 0; i < numberOfRow.getNumber(); i++) { + rows[i] = new Row(numberOfPerson); // 하나의 가로줄에 실제 세로줄 개수 할당 + } + } + + // 사다리의 가로 줄 긋기 + // todo LadderCreator로 분리 (Ladder 클래스 책임분산) + // todo 파라미터 Position wrapper 클래스 (0부터 입력가능한) + // Position으로 인덱스 접근하여 rows에 실제 사다리 방향(선)을 그린다 + public void drawLine(Position row, Position col) { + rows[row.getPosition()].drawLine(col); + } + + public Row[] getRows() { + return rows; + } +} diff --git a/src/main/java/ladder/creator/LadderRandomCreator.java b/src/main/java/ladder/creator/LadderRandomCreator.java new file mode 100644 index 0000000..962b669 --- /dev/null +++ b/src/main/java/ladder/creator/LadderRandomCreator.java @@ -0,0 +1,46 @@ +package ladder.creator; + +import ladder.*; + +import java.util.HashSet; + +public class LadderRandomCreator implements LadderCreation { + + private final LadderCreator ladderCreator; + private final LadderSize ladderSize; + private final int lineNumber; // 몇개 생성할 건지 개수 + HashSet startPosition; + + // 우선 drawLine으로 x좌표 넘겨주고, 그 다음에 y좌표까지 같은지 반복문으로 판단 + public LadderRandomCreator(LadderSize ladderSize) { + this.ladderSize = ladderSize; + ladderCreator = new LadderCreator(ladderSize.getRow(), ladderSize.getNumberOfPerson()); + this.lineNumber = ladderSize.getLadderLineNum(); + } + + public void makeRandomLine() { + startPosition = new HashSet<>(); // HashSet<>초기화 + + while (startPosition.size() < lineNumber) { // hashset 개수가 lineNumber 안 넘는 동안 + int xValue = (int) (Math.random() * (ladderSize.getIntNumberOfPerson() - 1)); // 제일 오른쪽은 그릴 수 없으므로 + int yValue = (int) (Math.random() * ladderSize.getIntRow()); + Position x = Position.from(xValue); + Position y = Position.from(yValue); + + LadderPosition currentPosition = new LadderPosition(x,y); // 추가하려는 임시 LadderPosition 객체 + + if (!startPosition.contains(currentPosition)) { + startPosition.add(currentPosition); + drawLine(currentPosition.getY(), currentPosition.getX()); + } + } + } + + public void drawLine(Position row, Position col) { + ladderCreator.getRows()[row.getPosition()].drawLine(col); + } + + public Row[] getRows() { + return ladderCreator.getRows(); + } +} diff --git a/src/test/java/LadderTest.java b/src/test/java/LadderTest.java deleted file mode 100644 index 741a915..0000000 --- a/src/test/java/LadderTest.java +++ /dev/null @@ -1,5 +0,0 @@ -import static org.junit.jupiter.api.Assertions.*; - -class LadderTest { - -} \ No newline at end of file diff --git a/src/test/java/ladder/LadderGameTest.java b/src/test/java/ladder/LadderGameTest.java new file mode 100644 index 0000000..1a9ae38 --- /dev/null +++ b/src/test/java/ladder/LadderGameTest.java @@ -0,0 +1,69 @@ +package ladder; + +import ladder.creator.LadderCreator; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.*; +// Ladder 클래스와 Row 클래스의 테스트를 분리하는게 좋다. +class LadderGameTest { + + @Test + void 사다리_생성_확인() { + //given + GreaterThanOne numberOfRow = GreaterThanOne.from(3); + GreaterThanOne numberOfPerson = GreaterThanOne.from(5); + + //when + LadderCreator ladderCreator = new LadderCreator(numberOfRow, numberOfPerson); + + //then + assertThat(ladderCreator).isNotNull(); + } + + @Test + void 사다리_사람_예외_처리_확인() { + //when + GreaterThanOne row = GreaterThanOne.from(2); + GreaterThanOne numberOfPerson = GreaterThanOne.from(3); + LadderCreator ladderCreator = new LadderCreator(row, numberOfPerson); + LadderRunner ladderRunner = new LadderRunner(ladderCreator.getRows()); + + //given + Position nthOfPerson = Position.from(4); + + //then + assertThatThrownBy(() -> ladderRunner.run(nthOfPerson)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 사다리_결과_확인() { // 출력결과 포함 + //when + GreaterThanOne numberOfPerson = GreaterThanOne.from(4); + GreaterThanOne row = GreaterThanOne.from(3); + LadderCreator ladderCreator = new LadderCreator(row, numberOfPerson); + LadderRunner ladderRunner = new LadderRunner(ladderCreator.getRows()); + + ladderCreator.drawLine(Position.from(0),Position.from(0)); + ladderCreator.drawLine(Position.from(1),Position.from(1)); + // ladderCreator.drawLine(Position.from(2),Position.from(0)); + + //given + Position nthOfPerson = Position.from(0); + + //then + assertThat(ladderRunner.run(nthOfPerson)).isEqualTo(2); + + //given + nthOfPerson = Position.from(1); + + //then + assertThat(ladderRunner.run(nthOfPerson)).isEqualTo(0); + + //given + nthOfPerson = Position.from(2); + + //then + assertThat(ladderRunner.run(nthOfPerson)).isEqualTo(1); + } +} \ No newline at end of file diff --git a/src/test/java/ladder/LadderRandomTest.java b/src/test/java/ladder/LadderRandomTest.java new file mode 100644 index 0000000..ec51584 --- /dev/null +++ b/src/test/java/ladder/LadderRandomTest.java @@ -0,0 +1,68 @@ +package ladder; + +import ladder.creator.LadderRandomCreator; +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.*; + +public class LadderRandomTest { + @Test + void 사다리_자동_생성_확인() { + // given + GreaterThanOne numberOfRow = GreaterThanOne.from(3); + GreaterThanOne numberOfPerson = GreaterThanOne.from(4); + + // when + LadderRandomCreator ladderRandomCreator = new LadderRandomCreator(new LadderSize(numberOfRow, numberOfPerson)); + + // then + assertThat(ladderRandomCreator).isNotNull(); + } + + @Test + void 사다리_사람_예외_처리_확인() { + //when + GreaterThanOne numberOfRow = GreaterThanOne.from(2); + GreaterThanOne numberOfPerson = GreaterThanOne.from(3); + LadderRandomCreator ladderRandomCreator = new LadderRandomCreator(new LadderSize(numberOfRow, numberOfPerson)); + LadderRunner ladderRunner = new LadderRunner(ladderRandomCreator.getRows()); + + + //given + Position nthOfPerson = Position.from(4); + + //then + assertThatThrownBy(() -> ladderRunner.run(nthOfPerson)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + // todo test통과할 때가 있고 안될때가 있다... + void 사다리_결과_확인() { // 출력결과 포함 + //when + GreaterThanOne numberOfPerson = GreaterThanOne.from(4); + GreaterThanOne numberOfRow = GreaterThanOne.from(3); + LadderRandomCreator ladderRandomCreator = new LadderRandomCreator(new LadderSize(numberOfRow, numberOfPerson)); + LadderRunner ladderRunner = new LadderRunner(ladderRandomCreator.getRows()); + + ladderRandomCreator.makeRandomLine(); + + //given + Position nthOfPerson = Position.from(0); + + //then + // 눈으로 테스트하는게 제일 직관적이겠지만, numberOfPerson 사이에 결과가 있어야하는 건 자명하니, isBetween 메소드 사용 + assertThat(ladderRunner.run(nthOfPerson)).isBetween(0,3); + + //given + nthOfPerson = Position.from(1); + + //then + assertThat(ladderRunner.run(nthOfPerson)).isBetween(0,3); + + //given + nthOfPerson = Position.from(2); + + //then + assertThat(ladderRunner.run(nthOfPerson)).isBetween(0,3); + } +} diff --git a/src/test/java/ladder/NodesTest.java b/src/test/java/ladder/NodesTest.java new file mode 100644 index 0000000..319fc9b --- /dev/null +++ b/src/test/java/ladder/NodesTest.java @@ -0,0 +1,42 @@ +package ladder; + + +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.*; +import static ladder.Direction.*; + +public class NodesTest { + + @Test + void 오른쪽_방향_위치_이동_확인() { + Node node = Node.from(RIGHT); + + Position position = Position.from(0); + + node.move(position); + + assertThat(position.getPosition()).isEqualTo(1); + } + + @Test + void NONE_방향_위치_이동_확인() { + Node node = Node.from(NONE); + + Position position = Position.from(0); + + node.move(position); + + assertThat(position.getPosition()).isEqualTo(0); + } + + @Test + void 왼쪽_방향_위치_이동_확인() { + Node node = Node.from(LEFT); + + Position position = Position.from(1); + + node.move(position); + + assertThat(position.getPosition()).isEqualTo(0); + } +} diff --git a/src/test/java/ladder/RowTest.java b/src/test/java/ladder/RowTest.java new file mode 100644 index 0000000..b0745f6 --- /dev/null +++ b/src/test/java/ladder/RowTest.java @@ -0,0 +1,162 @@ +package ladder; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.*; + +class RowTest { + + // 유효성 처리 및 핵심 로직을 분리해두었다. + + @Test + void 한_칸_사다리_이동() { + //when + GreaterThanOne numberOfPerson = GreaterThanOne.from(2); + Row row = new Row(numberOfPerson); + + //given + Position position = Position.from(0); + row.nextPosition(position); + + //then + assertThat(position.getPosition()).isEqualTo(0); + } + + @Test + void 두_칸_사다리_선_이동() { + //when + GreaterThanOne numberOfPerson = GreaterThanOne.from(2); + Row row = new Row(numberOfPerson); + row.drawLine(Position.from(0)); + + //given + Position position = Position.from(0); + row.nextPosition(position); + + //then + assertThat(position.getPosition()).isEqualTo(1); + + //given + position = Position.from(1); + row.nextPosition(position); + + //then + assertThat(position.getPosition()).isEqualTo(0); + } + + @Test + void 세_칸_사다리_선_이동() { + //when + GreaterThanOne numberOfPerson = GreaterThanOne.from(3); + Row row = new Row(numberOfPerson); + row.drawLine(Position.from(0)); + + //given + Position position = Position.from(0); + row.nextPosition(position); + + //then + assertThat(position.getPosition()).isEqualTo(1); + + //given + position = Position.from(1); + row.nextPosition(position); + + //then + assertThat(position.getPosition()).isEqualTo(0); + + //given + position = Position.from(2); + row.nextPosition(position); + + //then + assertThat(position.getPosition()).isEqualTo(2); + } + + @Test + void 사다리_사람수_예외_처리() { + assertThatThrownBy(() -> new Row(GreaterThanOne.from(0))) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 사다리_최대_사람수_초과_예외() { + //when + GreaterThanOne numberOfPerson = GreaterThanOne.from(3); + Row row = new Row(numberOfPerson); + + //given + Position position = Position.from(3); + + //then + assertThatThrownBy(() -> row.nextPosition(Position.from(3))) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 사다리_최소_사람수_미만_예외() { + //when + GreaterThanOne numberOfPerson = GreaterThanOne.from(3); + Row row = new Row(numberOfPerson); + + //given + //Position position = Position.from(-1); + + //then + assertThatThrownBy(() -> row.nextPosition(Position.from(-1))) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 사다리_그리기_위치_초과_예외() { + //when + GreaterThanOne numberOfPerson = GreaterThanOne.from(3); + Row row = new Row(numberOfPerson); + + //given + Position position = Position.from(3); + + //then + assertThatThrownBy(() -> row.drawLine(position)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 사다리_그리기_위치_미만_예외() { + //when + GreaterThanOne numberOfPerson = GreaterThanOne.from(3); + Row row = new Row(numberOfPerson); + + //given + //Position position = Position.from(-1); + + //then + assertThatThrownBy(() -> row.drawLine(Position.from(-1))) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 사다리_그리기_좌측_선_중복_예외() { + //when + GreaterThanOne numberOfPerson = GreaterThanOne.from(3); + Row row = new Row(numberOfPerson); + row.drawLine(Position.from(0)); + + //then + assertThatThrownBy(() -> row.drawLine(Position.from(1))) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 사다리_그리기_우측_선_중복_예외() { + //when + GreaterThanOne numberOfPerson = GreaterThanOne.from(3); + Row row = new Row(numberOfPerson); + row.drawLine(Position.from(1)); + + //then + assertThatThrownBy(() -> row.drawLine(Position.from(0))) + .isInstanceOf(IllegalArgumentException.class); + + } +} \ No newline at end of file diff --git a/week02.md b/week02.md new file mode 100644 index 0000000..e69de29