diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..51f9fd7 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +kuit-ladder \ No newline at end of file diff --git a/.idea/dbnavigator.xml b/.idea/dbnavigator.xml new file mode 100644 index 0000000..6dafaf6 --- /dev/null +++ b/.idea/dbnavigator.xml @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 8f86b33..690f4c6 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/ExceptionMessage.java b/src/main/java/ExceptionMessage.java new file mode 100644 index 0000000..c237610 --- /dev/null +++ b/src/main/java/ExceptionMessage.java @@ -0,0 +1,16 @@ +public enum ExceptionMessage { + + INVALID_LADDER_SIZE("사다리의 열과 행은 2이상의 자연수입니다."), + INVALID_LINE_POSITION("선의 위치가 사다리를 벗어납니다."), + INVALID_START_POSITION("출발 위치는 1이상의 자연수입니다."); + + private final String message; + + ExceptionMessage(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } +} diff --git a/src/main/java/Ladder.java b/src/main/java/Ladder.java index 0d2b070..a90c0ea 100644 --- a/src/main/java/Ladder.java +++ b/src/main/java/Ladder.java @@ -1,8 +1,56 @@ -public class Ladder { +import java.util.ArrayList; +import java.util.List; - private final int[][] rows; +class Ladder { +private final int[][] rows; +private final List lines; - public Ladder(int row, int numberOfPerson) { - rows = new int[row][numberOfPerson]; +public Ladder(int row, int column) { + validateLadderDimensions(row, column); + this.rows = new int[row][column]; + lines = new ArrayList<>(); +} + +private void validateLadderDimensions(int row, int column) { + if(row < 2 || column < 2) { + throw new IllegalArgumentException(ExceptionMessage.INVALID_LADDER_SIZE.getMessage()); + } +} + +public void addLine(int fromLine, int toLine, int currentRow) { + Line line = new Line(fromLine, toLine, currentRow, this.rows); + lines.add(line); +} + +public boolean isLine(int row, int col) { + return rows[row][col] == 1 || rows[row][col] == -1; +} + +public boolean isLineAtLeft(int row, int col) { + return col > 0 && rows[row][col - 1] == - 1; +} + +public boolean isLineAtRight(int row, int col) { + return col + 1 < rows[row].length && rows[row][col + 1] == 1; +} + +public int getHeight() { + return rows.length; +} + +public int getWidth() { + return rows[0].length; +} + +public int getRows(int row, int col) { + return rows[row][col]; +} + + public boolean isLeftLine(int currentRow, int currentCol) { + return rows[currentRow][currentCol] == 1; + } + + public boolean isRightLine(int currentRow, int currentCol) { + return rows[currentRow][currentCol] == - 1; } } diff --git a/src/main/java/LadderCreator.java b/src/main/java/LadderCreator.java new file mode 100644 index 0000000..ca0d035 --- /dev/null +++ b/src/main/java/LadderCreator.java @@ -0,0 +1,3 @@ +public interface LadderCreator { + Ladder createLine(int rows, int columns); +} diff --git a/src/main/java/LadderGame.java b/src/main/java/LadderGame.java new file mode 100644 index 0000000..eafd256 --- /dev/null +++ b/src/main/java/LadderGame.java @@ -0,0 +1,28 @@ +import java.util.Scanner; + +public class LadderGame { + private Ladder ladder; + private static Scanner scanner; + private int startPosition; + private LadderRunner ladderRunner; + + public LadderGame(Ladder ladder) { + this.ladder = ladder; + } + + public void play() { + System.out.print("Enter the start position: "); + startPosition = scanner.nextInt(); + + ladderRunner = new LadderRunner(ladder, startPosition); + int result = ladderRunner.run()+1; + System.out.println("Final position: " + result); + } + + public static void main(String[] args) { + scanner = new Scanner(System.in); + LadderGame game = LadderGameFactory.createRandomLadderGame(5, 5); + game.play(); + scanner.close(); + } +} diff --git a/src/main/java/LadderGameFactory.java b/src/main/java/LadderGameFactory.java new file mode 100644 index 0000000..63f1268 --- /dev/null +++ b/src/main/java/LadderGameFactory.java @@ -0,0 +1,7 @@ +public class LadderGameFactory { + public static LadderGame createRandomLadderGame(int rows, int columns) { + LadderCreator creator = new RandomLadderCreator(); + Ladder ladder = creator.createLine(rows, columns); + return new LadderGame(ladder); + } +} diff --git a/src/main/java/LadderPrinter.java b/src/main/java/LadderPrinter.java new file mode 100644 index 0000000..63adb15 --- /dev/null +++ b/src/main/java/LadderPrinter.java @@ -0,0 +1,16 @@ +public class LadderPrinter { + + // 정적메소드 적용 + public static void print(Ladder ladder, Player player) { + for (int i = 0; i < ladder.getHeight(); i++) { + for (int j = 0; j < ladder.getWidth(); j++) { + System.out.print(ladder.getRows(i, j)); + if (player.getxPosition() == j && player.getyPosition() == i) { + System.out.print("*"); + } + System.out.print(" "); + } + System.out.println(); + } + } +} \ No newline at end of file diff --git a/src/main/java/LadderRunner.java b/src/main/java/LadderRunner.java new file mode 100644 index 0000000..b5e23df --- /dev/null +++ b/src/main/java/LadderRunner.java @@ -0,0 +1,54 @@ +public class LadderRunner { + + private final Ladder ladder; + private Player player; + + public LadderRunner(Ladder ladder, int startPosition) { + this.ladder = ladder; + this.player = new Player(startPosition); + } + + int run() { + while (true) { + printLadderState("Before"); + + // 오른쪽으로 가기 + if (ladder.isLeftLine(player.getyPosition(), player.getxPosition())) { + player.right(); + printLadderState("After"); + player.down(); + } + // 왼쪽으로 가기 + else if (ladder.isRightLine(player.getyPosition(), player.getxPosition())) { + player.left(); + printLadderState("After"); + player.down(); + } + // 그냥 아래로 가기 + else { + player.down(); + if (isGameOver()) { + printLadderState("Final"); + break; + } + printLadderState("After"); + } + + if (isGameOver()) { + printLadderState("Final"); + break; + } + } + return player.getxPosition(); + } + + private boolean isGameOver() { + return player.getyPosition() == ladder.getHeight() - 1; + } + + private void printLadderState(String state) { + System.out.println(state); + LadderPrinter.print(ladder, player); + } +} + diff --git a/src/main/java/Line.java b/src/main/java/Line.java new file mode 100644 index 0000000..588e942 --- /dev/null +++ b/src/main/java/Line.java @@ -0,0 +1,57 @@ +public class Line { + private int fromLine; + private int toLine; + private int t; + private int[][] rows; + + public Line(int fromLine, int toLine, int currentRow, int[][] rows) { + sort(fromLine, toLine); + this.rows = rows; + + if (validateFromLine(rows) && currentRow >= 0 && validateCurrentRow(currentRow, rows)) { + this.rows[currentRow][this.fromLine] = 1; + } + if (validateToLine(rows) && currentRow >= 0 && validateCurrentRow(currentRow, rows)) { + this.rows[currentRow][this.toLine] = - 1; + } + } + + private static boolean validateCurrentRow(int currentRow, int[][] rows) { + if(currentRow < rows.length){ + return true; + } + else{ + throw new IllegalArgumentException(ExceptionMessage.INVALID_LINE_POSITION.getMessage()); + } + } + + private boolean validateToLine(int[][] rows) { + if(this.toLine >= 0 && this.toLine <= rows[0].length){ + return true; + } + else{ + throw new IllegalArgumentException(ExceptionMessage.INVALID_LINE_POSITION.getMessage()); + } + } + + private boolean validateFromLine(int[][] rows) { + if(this.fromLine >= 0 && this.fromLine <= rows[0].length){ + return true; + } + else{ + throw new IllegalArgumentException(ExceptionMessage.INVALID_LINE_POSITION.getMessage()); + } + } + + public void sort(int x, int y) { + this.fromLine = x; + this.toLine = y; + + if (this.fromLine > this.toLine) { + this.t = y; + this.toLine = x; + this.fromLine = t; + } + } + +} \ No newline at end of file diff --git a/src/main/java/Player.java b/src/main/java/Player.java new file mode 100644 index 0000000..2880539 --- /dev/null +++ b/src/main/java/Player.java @@ -0,0 +1,41 @@ +public class Player { + private int xPosition; + private int yPosition; + + public Player(int startPosition) { + // 사다리는 0부터 시작하기 때문에 + this.xPosition = startPosition-1; + this.yPosition = 0; + validatePosition(); + } + + private void validatePosition(){ + if(this.xPosition<0){ + throw new IllegalArgumentException(ExceptionMessage.INVALID_START_POSITION.getMessage()); + } + } + + public void right(){ + this.xPosition += 1; + } + + public void left(){ + this.xPosition -= 1; + } + + public void down(){ + this.yPosition += 1; + } + + public int getStartPosition() { + return xPosition; + } + + public int getxPosition(){ + return xPosition; + } + + public int getyPosition(){ + return yPosition; + } +} diff --git a/src/main/java/RandomLadderCreator.java b/src/main/java/RandomLadderCreator.java new file mode 100644 index 0000000..0632982 --- /dev/null +++ b/src/main/java/RandomLadderCreator.java @@ -0,0 +1,46 @@ +import java.util.Random; + +public class RandomLadderCreator implements LadderCreator { + private Random random = new Random(); + + @Override + public Ladder createLine(int rows, int columns) { + Ladder ladder = new Ladder(rows, columns); + int totalLines = (int) (rows * (columns - 1) * 0.3); + int createdLines = 0; + + while (createdLines < totalLines) { + int row = random.nextInt(rows); + int col = random.nextInt(columns - 1); + + if (canAddLine(ladder, row, col)) { + ladder.addLine(col, col + 1, row); + createdLines++; + } + } + + return ladder; + } + + boolean canAddLine(Ladder ladder, int row, int col) { + // 현재 선택된 위치에 이미 가로선이 있는지 확인 + if (ladder.isLine(row, col)) { + return false; + } + // 현재 위치의 왼쪽에 가로선이 있는지를 확인 + if (col > 0 && ladder.isLineAtLeft(row, col)) { + return false; + } + // 현재 위치의 오른쪽에 가로선이 있는지를 확인 + if (col < ladder.getWidth() - 1 && ladder.isLineAtRight(row, col)) { + return false; + } + // 마지막 열에는 선이 생성되지 않습니다 + if (row >= ladder.getHeight() - 1){ + return false; + } + return true; + } + + +} \ No newline at end of file diff --git a/src/test/java/LadderRunnerTest.java b/src/test/java/LadderRunnerTest.java new file mode 100644 index 0000000..cefdb7e --- /dev/null +++ b/src/test/java/LadderRunnerTest.java @@ -0,0 +1,57 @@ +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class LadderRunnerTest { + + @Test + @DisplayName("오른쪽 이동") + void testMoveRight() { + + // Given + Ladder ladder = new Ladder(5, 3); + ladder.addLine(0, 1, 0); + ladder.addLine(1, 2, 1); + + // When + LadderRunner runner = new LadderRunner(ladder, 1); + int finalPosition = runner.run()+1; + + //Then + Assertions.assertEquals(3, finalPosition); + } + + @Test + @DisplayName("왼쪽 이동") + void testMoveLeft() { + // Given + Ladder ladder = new Ladder(5, 3); + ladder.addLine(1, 2, 0); + ladder.addLine(0, 1, 1); + LadderRunner runner = new LadderRunner(ladder, 3); + + // When + int finalPosition = runner.run()+1; + + // Then + Assertions.assertEquals(1, finalPosition); + } + + @Test + @DisplayName("사다리가 연달아 있는 경우") + void testMoveBetween() { + // Given + Ladder ladder = new Ladder(5, 4); + ladder.addLine(0, 1, 1); + ladder.addLine(2, 3, 1); + LadderRunner runner = new LadderRunner(ladder, 3); + + // When + int finalPosition = runner.run() + 1; + + // Then + Assertions.assertEquals(4, finalPosition); + } + + +} \ No newline at end of file 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/RandomLadderCreatorTest.java b/src/test/java/RandomLadderCreatorTest.java new file mode 100644 index 0000000..4fe3c2f --- /dev/null +++ b/src/test/java/RandomLadderCreatorTest.java @@ -0,0 +1,98 @@ +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class RandomLadderCreatorTest { + + @Test + @DisplayName("사다리의 크기가 올바르게 생성되는지 확인") + void testCreateLineWithCorrectSize() { + RandomLadderCreator creator = new RandomLadderCreator(); + Ladder ladder = creator.createLine(5, 3); + + Assertions.assertEquals(5, ladder.getHeight()); + Assertions.assertEquals(3, ladder.getWidth()); + } + + @Test + @DisplayName("라인이 위치에 추가되는지 확인") + void testCanAddLineAtValidPosition() { + + // Given + RandomLadderCreator creator = new RandomLadderCreator(); + Ladder ladder = new Ladder(5, 3); + + // When + boolean canAddLineAt00 = creator.canAddLine(ladder, 0, 0); + boolean canAddLineAt21 = creator.canAddLine(ladder, 2, 1); + + // Then + Assertions.assertTrue(canAddLineAt00); + Assertions.assertTrue(canAddLineAt21); + + } + + @Test + @DisplayName("이미 라인이 있는 위치에는 라인을 추가할 수 없는지 확인") + void testCannotAddLineAtOccupiedPosition() { + + // Given + RandomLadderCreator creator = new RandomLadderCreator(); + Ladder ladder = new Ladder(5, 3); + ladder.addLine(0, 1, 0); + + // When + boolean canAddLineAt00 = creator.canAddLine(ladder, 0, 0); + + // Then + Assertions.assertFalse(canAddLineAt00); + } + + @Test + @DisplayName("마지막 행에는 라인을 추가할 수 없는지 확인") + void testCannotAddLineAtLastRow() { + + // Given + RandomLadderCreator creator = new RandomLadderCreator(); + Ladder ladder = new Ladder(5, 3); + + // When + boolean canAddLineAt41 = creator.canAddLine(ladder, 4, 1); + + // Then + Assertions.assertFalse(canAddLineAt41); + } + + @Test + @DisplayName("이미 오른쪽에 라인이 있는 위치에는 라인을 추가할 수 없는지 확인") + void testCannotAddLineAtAlreadyRight() { + + //Given + RandomLadderCreator creator = new RandomLadderCreator(); + Ladder ladder = new Ladder(5, 3); + ladder.addLine(1, 2, 0); + + // When + boolean canAddLineAt00 = creator.canAddLine(ladder, 0, 0); + + // Then + Assertions.assertFalse(canAddLineAt00); + } + + @Test + @DisplayName("이미 왼쪽에 라인이 있는 위치에는 라인을 추가할 수 없는지 확인") + void testCannotAddLineAtAlreadyLeft() { + + //Given + RandomLadderCreator creator = new RandomLadderCreator(); + Ladder ladder = new Ladder(5, 3); + ladder.addLine(0, 1, 0); + + // When + boolean canAddLineAt00 = creator.canAddLine(ladder, 0, 1); + + // Then + Assertions.assertFalse(canAddLineAt00); + } + +} \ No newline at end of file