diff --git a/src/main/java/ladder/Ladder.java b/src/main/java/ladder/Ladder.java deleted file mode 100644 index 503ae00..0000000 --- a/src/main/java/ladder/Ladder.java +++ /dev/null @@ -1,27 +0,0 @@ -package ladder; - -public class Ladder { - - private Row[] rows; - - public Ladder(int numberOfRows, int numberOfPerson) { - rows = new Row[numberOfPerson]; - - for(int i = 0; i < numberOfRows; i++) { - rows[i] = new Row(numberOfPerson); - } - } - - public void drawLine(int row, int col) { - rows[row].drawLine(col); - } - - public int run(int position) { - - for(int i = 0; i < rows.length; i++) { - position = rows[i].nextPosition(position); - } - - return position; - } -} diff --git a/src/main/java/ladder/Row.java b/src/main/java/ladder/Row.java deleted file mode 100644 index 722a9a6..0000000 --- a/src/main/java/ladder/Row.java +++ /dev/null @@ -1,60 +0,0 @@ -package ladder; - -public class Row { - private int[] row; - - public Row(int numberOfPerson) { - validateNumberOfPerson(numberOfPerson); - row = new int[numberOfPerson]; - } - - public void drawLine(int lineStartPosition) { - validateDrawLinePosition(lineStartPosition); - row[lineStartPosition] = 1; - row[lineStartPosition + 1] = -1; - } - - public int nextPosition(int position) { - - validatePosition(position); - - if (isLeft(position)) { - return position - 1; - } - if (isRight(position)) { - return position + 1; - } - - return position; - } - - private boolean isLeft(int position) { - return row[position] == -1; - } - - private boolean isRight(int position) { - return row[position] == 1; - } - - private void validateNumberOfPerson(int numberOfPerson) { - if(numberOfPerson < 1) { - throw new IllegalArgumentException("게임의 참여자 수는 1명 이상이어야 합니다."); - } - } - - private void validateDrawLinePosition(int lineStartPosition) { - if(lineStartPosition < 0 || lineStartPosition >= row.length - 1 || row[lineStartPosition] == -1 || row[lineStartPosition + 1] == 1) { - throw new IllegalArgumentException("라인 생성이 불가능한 위치 입니다."); - } - } - - private void validatePosition(int position) { - if(position >= row.length || position < 0 ) { - throw new IllegalArgumentException("유효하지 않은 위치 입니다."); - } - } - - - - -} diff --git a/src/main/java/ladder/application/LadderGame.java b/src/main/java/ladder/application/LadderGame.java new file mode 100644 index 0000000..a250993 --- /dev/null +++ b/src/main/java/ladder/application/LadderGame.java @@ -0,0 +1,19 @@ +package ladder.application; + +import ladder.application.creator.LadderCreator; +import ladder.domain.Position; + +public class LadderGame { + + private final LadderCreator ladder; + + public LadderGame(LadderCreator ladder) { + this.ladder = ladder; + } + + public int run(Position position){ + LadderRunner ladderRunner = new LadderRunner(ladder.getRows()); + return ladderRunner.run(position); + } + +} diff --git a/src/main/java/ladder/application/LadderRunner.java b/src/main/java/ladder/application/LadderRunner.java new file mode 100644 index 0000000..35538b7 --- /dev/null +++ b/src/main/java/ladder/application/LadderRunner.java @@ -0,0 +1,23 @@ +package ladder.application; + +import ladder.domain.Position; +import ladder.domain.Row; + +public class LadderRunner { + + private final Row[] rows; + + LadderRunner(Row[] rows) { + this.rows = rows; + } + + // 현재 포지션 입력하면 최종 포지션 출력 + public int run(Position position) { + + for(int i = 0; i < rows.length; i++) { + position = rows[i].nextPosition(position); + } + + return position.getValue(); + } +} \ No newline at end of file diff --git a/src/main/java/ladder/application/creator/LadderCreator.java b/src/main/java/ladder/application/creator/LadderCreator.java new file mode 100644 index 0000000..509e752 --- /dev/null +++ b/src/main/java/ladder/application/creator/LadderCreator.java @@ -0,0 +1,23 @@ +package ladder.application.creator; + +import ladder.domain.NaturalNumber; +import ladder.domain.Position; +import ladder.domain.Row; + +public interface LadderCreator { +// public Row[] rows; +// +// public LadderCreator(NaturalNumber numberOfRows, NaturalNumber numberOfPerson) { +// rows = new Row[numberOfRows.getNum()]; +// +// for(int i = 0; i < numberOfRows.getNum(); i++) { +// rows[i] = new Row(numberOfPerson); +// } +// } +// +// public void drawLine(Position row, Position col) { +// rows[row.getValue()].drawLine(col); +// } +// + public Row[] getRows(); +} diff --git a/src/main/java/ladder/application/creator/RandomLadderCreator.java b/src/main/java/ladder/application/creator/RandomLadderCreator.java new file mode 100644 index 0000000..124f8a6 --- /dev/null +++ b/src/main/java/ladder/application/creator/RandomLadderCreator.java @@ -0,0 +1,11 @@ +package ladder.application.creator; + +import ladder.domain.Row; + +public class RandomLadderCreator implements LadderCreator { + + @Override + public Row[] getRows() { + return new Row[0]; + } +} diff --git a/src/main/java/ladder/domain/Direction.java b/src/main/java/ladder/domain/Direction.java new file mode 100644 index 0000000..b1a1d64 --- /dev/null +++ b/src/main/java/ladder/domain/Direction.java @@ -0,0 +1,17 @@ +package ladder.domain; + +public enum Direction { + RIGHT(1), + LEFT(-1), + NONE(0); + + private final int value; + + Direction(int value) { + this.value = value; + } + + public int getValue() { + return this.value; + } +} diff --git a/src/main/java/ladder/domain/NaturalNumber.java b/src/main/java/ladder/domain/NaturalNumber.java new file mode 100644 index 0000000..2d849a3 --- /dev/null +++ b/src/main/java/ladder/domain/NaturalNumber.java @@ -0,0 +1,34 @@ +package ladder.domain; + +import static ladder.exception.ExceptionMessage.INVALID_NATURAL_NUMBER; + +public class NaturalNumber { + private final int num; + + private NaturalNumber(int num) { + validateNaturalNumber(num); + this.num = num; + } + + public static NaturalNumber of(int num){ + return new NaturalNumber(num); + } + + public int getNum() { + // 검증된 num 반환 + return num; + } + + // 유효성 검증 + private void validateNaturalNumber(int num){ + // num이 자연수인지 검증 + if (!isNaturalNumber((num))) { + throw new IllegalArgumentException(INVALID_NATURAL_NUMBER.getMessage()); + } + } + + private static boolean isNaturalNumber(int num){ + return num >= 1; + } + +} diff --git a/src/main/java/ladder/domain/Node.java b/src/main/java/ladder/domain/Node.java new file mode 100644 index 0000000..873d2a2 --- /dev/null +++ b/src/main/java/ladder/domain/Node.java @@ -0,0 +1,34 @@ +package ladder.domain; + +import ladder.domain.Direction; + +public class Node { + private final Direction nodeDirection; + + private Node(Direction nodeDirection){ + this.nodeDirection = nodeDirection; + } + + public Position move(Position position) { + if(isRight()) { + return position.nextPosition(); + } + if(isLeft()){ + return position.prevPosition(); + } + return position; + } + + public boolean isRight() { + return nodeDirection == Direction.RIGHT; + } + + public boolean isLeft() { + return nodeDirection == Direction.LEFT; + } + + // 정적 팩토리 메소드 + public static Node of(Direction direction) { + return new Node(direction); + } +} diff --git a/src/main/java/ladder/domain/Position.java b/src/main/java/ladder/domain/Position.java new file mode 100644 index 0000000..52114f8 --- /dev/null +++ b/src/main/java/ladder/domain/Position.java @@ -0,0 +1,48 @@ +package ladder.domain; + +import static ladder.exception.ExceptionMessage.INVALID_LADDER_POSITION; + +public class Position { + private int position; + + private Position(int position) { + validatePosition(position); + this.position = position; + } + + // 정적 팩토리 메소드 + public static Position of(int position){ + return new Position(position); + } + + public Position prevPosition(){ + return of(position - 1); + } + + public Position nextPosition() { + return of(position + 1); + } + + public int getValue(){ + return position; + } + + public boolean isBiggerThan(int position){ + return this.position > position; + } + + public boolean isSmallerThan(int position){ + return this.position < position; + } + + // 유효성 검증 + private void validatePosition(int position) { + if(!isPositionValid(position)) { + throw new IllegalArgumentException(INVALID_LADDER_POSITION.getMessage()); + } + } + + private static boolean isPositionValid(int position){ + return position >= 0; + } +} diff --git a/src/main/java/ladder/domain/Row.java b/src/main/java/ladder/domain/Row.java new file mode 100644 index 0000000..9f21693 --- /dev/null +++ b/src/main/java/ladder/domain/Row.java @@ -0,0 +1,66 @@ +package ladder.domain; + +import static ladder.exception.ExceptionMessage.*; + +public class Row { + + // Node들로 이루어진 한 행 + private Node[] row; + + // 사람 수만큼의 node를 가진 행 생성 + public Row(NaturalNumber numberOfPerson) { + row = new Node[numberOfPerson.getNum()]; + // 초기화 + for (int i = 0; i < numberOfPerson.getNum(); i++) { + row[i] = Node.of(Direction.NONE); + } + } + + // 사다리 그리기 + public void drawLine(Position lineStartPosition) { + validateDrawLinePosition(lineStartPosition); + + Position next = lineStartPosition.nextPosition(); + row[lineStartPosition.getValue()] = Node.of(Direction.RIGHT); + row[next.getValue()] = Node.of(Direction.LEFT); + } + + // 다음 position으로 이동 + public Position nextPosition(Position position) { + validatePosition(position); + Position newPosition = row[position.getValue()].move(position); + // 새로운 위치가 유효한지 검증 + validatePosition(newPosition); + return newPosition; + } + + + // 유효성 검증 + private void validateDrawLinePosition(Position position) { + if(isInvalidDrawPosition(position) && isSameLine(position)){ + throw new IllegalArgumentException(INVALID_ROW_POSITION.getMessage()); + } + } + + private boolean isInvalidDrawPosition(Position position){ + return position.isBiggerThan(row.length - 2) || position.isSmallerThan(0); + } + + // 중복 라인 체크 + private boolean isSameLine(Position position){ + return (row[position.getValue()].isLeft() + || row[position.nextPosition().getValue()].isRight() + || row[position.getValue()].isRight()); + } + + private void validatePosition(Position position){ + if(isInvalidPosition(position)) { + throw new IllegalArgumentException(INVALID_LADDER_POSITION.getMessage()); + } + } + + private boolean isInvalidPosition(Position position) { + return position.isBiggerThan(row.length - 1) || position.isSmallerThan(0); + } + +} diff --git a/src/main/java/ladder/exception/ExceptionMessage.java b/src/main/java/ladder/exception/ExceptionMessage.java new file mode 100644 index 0000000..8ab1f5f --- /dev/null +++ b/src/main/java/ladder/exception/ExceptionMessage.java @@ -0,0 +1,21 @@ +package ladder.exception; + +public enum ExceptionMessage { + + INVALID_LADDER_POSITION("유효하지 않은 위치입니다."), + INVALID_NUMBER_OF_PERSON("참여 인원은 2명 이상이어야 합니다."), + INVALID_ROW_POSITION("라인 생성이 불가능한 위치입니다."), + INVALID_NATURAL_NUMBER("1 이상의 정수여야 합니다."); + + //.. + + private final String message; + + ExceptionMessage(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } +} \ 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..1b59c87 --- /dev/null +++ b/src/test/java/ladder/LadderGameTest.java @@ -0,0 +1,81 @@ +package ladder; + +import ladder.application.creator.LadderCreator; +import ladder.application.LadderGame; +import ladder.domain.NaturalNumber; +import ladder.domain.Position; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class LadderGameTest { + +// @Test +// void 사다리_생성_확인() { +// //given +// NaturalNumber numberOfRow = NaturalNumber.of(3); +// NaturalNumber numberOfPerson = NaturalNumber.of(5); +// +// //when +// LadderCreator ladderCreator = new LadderCreator(numberOfRow, numberOfPerson); +// +// //then +// assertNotNull(ladderCreator); +// } + +// @Test +// void 사다리_시작위치_예외_처리() { +// //given +// NaturalNumber numberOfPerson = NaturalNumber.of(3); +// NaturalNumber numberOfRow = NaturalNumber.of(1); +// LadderCreator ladderCreator = new LadderCreator(numberOfRow, numberOfPerson); +// LadderGame ladderGame = new LadderGame(ladderCreator); +// +// //when +// int nthOfPerson = 3; +// Position position = Position.of(nthOfPerson); +// +// //then +// assertThrows(IllegalArgumentException.class, ()->ladderGame.run(position)); +// } + +// @Test +// void 사다리_결과_확인() { +// //given +// NaturalNumber numberOfPerson = NaturalNumber.of(4); +// NaturalNumber numberOfRow = NaturalNumber.of(4); +// +// LadderCreator ladderCreator = new LadderCreator(numberOfRow, numberOfPerson); +// LadderGame ladderGame = new LadderGame(ladderCreator); +// +// ladderCreator.drawLine(Position.of(1), Position.of(0)); +// ladderCreator.drawLine(Position.of(1), Position.of(2)); +// ladderCreator.drawLine(Position.of(2), Position.of(1)); +// +// +// //when +// int position = 0; +// int resultPosition = ladderGame.run(Position.of(position)); +// //then +// assertEquals(2, resultPosition); +// +// //when +// position = 1; +// resultPosition = ladderGame.run(Position.of(position)); +// //then +// assertEquals(0, resultPosition); +// +// //when +// position = 2; +// resultPosition = ladderGame.run(Position.of(position)); +// //then +// assertEquals(3, resultPosition); +// +// //when +// position = 3; +// resultPosition = ladderGame.run(Position.of(position)); +// //then +// assertEquals(1, resultPosition); +// +// } +} \ No newline at end of file diff --git a/src/test/java/ladder/LadderTest.java b/src/test/java/ladder/LadderTest.java deleted file mode 100644 index db63615..0000000 --- a/src/test/java/ladder/LadderTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package ladder; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -class LadderTest { - - @Test - void 사다리_생성_확인() { - //given - int numberOfRows = 3; - int numberOfPerson = 5; - - //when - Ladder ladder = new Ladder(numberOfRows, numberOfPerson); - - //then - assertNotNull(ladder); - } - - @Test - void 사다리_시작위치_예외_처리() { - //given - int numberOfPerson = 3; - int numberOfRows = 1; - Ladder ladder = new Ladder(numberOfRows, numberOfPerson); - - //when - int position = 3; - - //then - assertThrows(IllegalArgumentException.class, () -> ladder.run(3)); - } - - @Test - void 사다리_결과_확인() { - //given - int numberOfPerson = 4; - int numberOfRows = 4; - Ladder ladder = new Ladder(numberOfRows, numberOfPerson); - ladder.drawLine(1,0); - ladder.drawLine(1,2); - ladder.drawLine(2,1); - - - //when - int position = 0; - int resultPosition = ladder.run(position); - //then - assertEquals(2, resultPosition); - - //when - position = 1; - resultPosition = ladder.run(position); - //then - assertEquals(0, resultPosition); - - //when - position = 2; - resultPosition = ladder.run(position); - //then - assertEquals(3, resultPosition); - - //when - position = 3; - resultPosition = ladder.run(position); - //then - assertEquals(1, resultPosition); - - - - } -} \ No newline at end of file diff --git a/src/test/java/ladder/NodeTest.java b/src/test/java/ladder/NodeTest.java new file mode 100644 index 0000000..e19a916 --- /dev/null +++ b/src/test/java/ladder/NodeTest.java @@ -0,0 +1,73 @@ +package ladder; + +import ladder.domain.Direction; +import ladder.domain.Node; +import ladder.domain.Position; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class NodeTest { + + private Node leftNode; + private Node rightNode; + private Node noneNode; + + @BeforeEach + void setUp() { + leftNode = Node.of(Direction.LEFT); + rightNode = Node.of(Direction.RIGHT); + noneNode = Node.of(Direction.NONE); + } + + @Test + void 왼쪽_방향_위치_이동_확인() { + //given + Position currentPosition = Position.of(2); + + //when + Position nextPosition = leftNode.move(currentPosition); + + //then + assertEquals(1, nextPosition.getValue()); + } + + @Test + void 오른쪽_방향_위치_이동_확인() { + //given + Position currentPosition = Position.of(2); + + //when + Position nextPosition = rightNode.move(currentPosition); + + //then + assertEquals(3, nextPosition.getValue()); + } + + @Test + void 방향_없을_때_위치_이동_확인() { + //given + Position initialPosition = Position.of(2); + + //when + Position nextPosition = noneNode.move(initialPosition); + + //then + assertEquals(2, nextPosition.getValue()); + } + + @Test + void 오른쪽_방향_확인() { + assertTrue(rightNode.isRight()); + assertFalse(leftNode.isRight()); + assertFalse(noneNode.isRight()); + } + + @Test + void 왼쪽_방향_확인() { + assertTrue(leftNode.isLeft()); + assertFalse(rightNode.isLeft()); + assertFalse(noneNode.isLeft()); + } +} \ No newline at end of file diff --git a/src/test/java/ladder/RowTest.java b/src/test/java/ladder/RowTest.java index c5eeed9..fe3a9f3 100644 --- a/src/test/java/ladder/RowTest.java +++ b/src/test/java/ladder/RowTest.java @@ -1,7 +1,11 @@ package ladder; +import ladder.domain.NaturalNumber; +import ladder.domain.Position; +import ladder.domain.Row; import org.junit.jupiter.api.Test; + import static org.junit.jupiter.api.Assertions.*; class RowTest { @@ -9,77 +13,81 @@ class RowTest { @Test void 참여자_한_명_사다리_이동() { //given - int numberOfPerson = 1; + NaturalNumber numberOfPerson = NaturalNumber.of(1); Row row = new Row(numberOfPerson); //when - int position = 0; + int nthOfPerson = 0; + Position position = Position.of(nthOfPerson); //then - assertEquals(0,row.nextPosition(position)); + assertEquals(0, row.nextPosition(position).getValue()); } @Test void 참여자_두_명_사다리_열간_이동() { //given - int numberOfPerson = 2; + NaturalNumber numberOfPerson = NaturalNumber.of(2); Row row = new Row(numberOfPerson); - row.drawLine(0); + row.drawLine(Position.of(0)); + + //given + int nthOfPerson = 0; + Position position = Position.of(nthOfPerson); - //when - int position = 0; - int resultPosition = row.nextPosition(position); //then - assertEquals(1,resultPosition); + assertEquals(1, row.nextPosition(position).getValue()); + //given + nthOfPerson = 1; + position = Position.of(nthOfPerson); - //when - position = 1; - resultPosition = row.nextPosition(position); //then - assertEquals(0, resultPosition); + assertEquals(0, row.nextPosition(position).getValue()); } @Test void 참여자_세_명_사다리_열간_이동() { //given - int numberOfPerson = 3; + NaturalNumber numberOfPerson = NaturalNumber.of(3); Row row = new Row(numberOfPerson); - row.drawLine(0); + row.drawLine(Position.of(0)); //when - int position = 0; - int resultPosition = row.nextPosition(position); + int nthOfPerson = 0; + Position position = Position.of(nthOfPerson); //then - assertEquals(1,resultPosition); + assertEquals(1, row.nextPosition(position).getValue()); //when - position = 1; - resultPosition = row.nextPosition(position); + nthOfPerson = 1; + position = Position.of(nthOfPerson); //then - assertEquals(0, resultPosition); + assertEquals(0, row.nextPosition(position).getValue()); + //when - position = 2; - resultPosition = row.nextPosition(position); + nthOfPerson = 2; + position = Position.of(nthOfPerson); //then - assertEquals(2, resultPosition); + assertEquals(2, row.nextPosition(position).getValue()); } @Test void 사다리_사람수_예외_처리() { - assertThrows(IllegalArgumentException.class, () -> new Row(0)); + assertThrows(IllegalArgumentException.class, () -> new Row(NaturalNumber.of(0))); } @Test void 사다리_위치_최대값_초과_예외_처리() { //given - int numberOfPerson = 3; + NaturalNumber numberOfPerson = NaturalNumber.of(3); Row row = new Row(numberOfPerson); //when - int position = 3; + int nthOfPerson = 3; + Position position = Position.of(nthOfPerson); //then assertThrows(IllegalArgumentException.class, () -> row.nextPosition(position)); @@ -88,69 +96,69 @@ class RowTest { @Test void 사다리_위치_최소값_미만_예외_처리() { //given - int numberOfPerson = 3; + NaturalNumber numberOfPerson = NaturalNumber.of(3); Row row = new Row(numberOfPerson); //when int position = -1; //then - assertThrows(IllegalArgumentException.class, () -> row.nextPosition(position)); + assertThrows(IllegalArgumentException.class, () -> row.nextPosition(Position.of(position))); } @Test void 사다리_라인_그리기_위치_초과_예외() { //given - int numberOfPerson = 3; + NaturalNumber numberOfPerson = NaturalNumber.of(3); Row row = new Row(numberOfPerson); //when - int lineStartPosition = 2; + int position = 2; //then - assertThrows(IllegalArgumentException.class, () -> row.drawLine(lineStartPosition)); + assertThrows(IllegalArgumentException.class, () -> row.drawLine(Position.of(position))); } @Test void 사다리_라인_그리기_위치_미만_예외() { //given - int numberOfPerson = 3; + NaturalNumber numberOfPerson = NaturalNumber.of(3); Row row = new Row(numberOfPerson); //when - int lineStartPosition = -1; + int position = -1; //then - assertThrows(IllegalArgumentException.class, () -> row.drawLine(lineStartPosition)); + assertThrows(IllegalArgumentException.class, () -> row.drawLine(Position.of(position))); } @Test void 라인_그리기_좌측_라인_중복_예외() { //given - int numberOfPerson = 3; + NaturalNumber numberOfPerson = NaturalNumber.of(3); Row row = new Row(numberOfPerson); - row.drawLine(0); + row.drawLine(Position.of(0)); //when int lineStartPosition = 1; //then - assertThrows(IllegalArgumentException.class, () -> row.drawLine(lineStartPosition)); + assertThrows(IllegalArgumentException.class, () -> row.drawLine(Position.of(lineStartPosition))); } @Test void 라인_그리기_우측_라인_중복_예외() { //given - int numberOfPerson = 3; + NaturalNumber numberOfPerson = NaturalNumber.of(3); Row row = new Row(numberOfPerson); - row.drawLine(1); + row.drawLine(Position.of(1)); //when int lineStartPosition = 0; //then - assertThrows(IllegalArgumentException.class, () -> row.drawLine(lineStartPosition)); + assertThrows(IllegalArgumentException.class, () -> row.drawLine(Position.of(lineStartPosition))); }