diff --git a/.gitignore b/.gitignore
index b63da455..9b3878c4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,8 @@ build/
!**/src/test/**/build/
### IntelliJ IDEA ###
+.idea
+.idea/workspace.xml
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
diff --git a/.idea/.name b/.idea/.name
deleted file mode 100644
index e67596c4..00000000
--- a/.idea/.name
+++ /dev/null
@@ -1 +0,0 @@
-java-lotto
\ No newline at end of file
diff --git a/.idea/aws.xml b/.idea/aws.xml
deleted file mode 100644
index 99de319b..00000000
--- a/.idea/aws.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
deleted file mode 100644
index 611e7c8a..00000000
--- a/.idea/gradle.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index b9d0bedb..00000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 94a25f7f..00000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
deleted file mode 100644
index cc0a8fd0..00000000
--- a/.idea/workspace.xml
+++ /dev/null
@@ -1,83 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 1672210428730
-
-
- 1672210428730
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/README.md b/README.md
index ad6e6861..8004bec1 100644
--- a/README.md
+++ b/README.md
@@ -7,3 +7,52 @@
* [텍스트와 이미지로 살펴보는 코드스쿼드의 온라인 코드 리뷰 과정](https://github.com/code-squad/codesquad-docs/blob/master/codereview/README.md)
* [동영상으로 살펴보는 코드스쿼드의 온라인 코드 리뷰 과정](https://youtube.com/watch?v=lFinZfu3QO0&si=EnSIkaIECMiOmarE)
+
+## 요구사항 분석
+
+- 사람과 사다리의 높이를 입력한다
+ - 사람 `n`명과 사다리 높이 `m`을 입력한다
+ - 입력값이 정수인지 검증한다
+ - (추가) 사람의 이름을 입력한다
+ - 사람의 이름이 5글자 이하인지 검증한다
+ - 사람의 이름은 "`,`" 기준으로 구분한다
+
+- 사다리의 라인을 랜덤하게 만든다
+ - 라인은 랜덤값에 따라 있거나 없다
+ - 라인이 존재한다면 "`-`"를 없으면 "` `"(공백문자)를 표시한다
+ - 라인의 양 옆에는 "`|`"로 세로를 표시한다
+ - (추가) 같은 높이에 라인이 겹치지 않아야 한다
+- 사다리 상태를 화면에 출력한다
+ - (추가) 사람의 이름을 출력한다
+ - 사람의 이름을 최대 5자로 정하므로 이에 따라 사다리의 폭도 넓게 출력한다
+
+## 구현 계획 및 학습 계획
+### 3.7 화 오전
+-[x] 사다리를 나타낼 배열을 먼저 구현한다
+-[x] 사다리의 라인을 랜덤하게 구현한다
+### 3.7 화 오후
+-[x] 사다리의 모습을 출력한다 (3.7 화 오후까지)
+-[x] 사람의 이름으로 사다리 배열을 구현한다
+### ~~3.8 수~~ 3.13 월
+-[ ] 같은 높이에서 라인이 겹치지 않으면서 랜덤하게 나타나도록 구현한다
+-[ ] 사람의 이름과 사다리를 출력한다
+-[ ] 로직을 구현하는 단위테스트를 추가한다
+### ~~3.8 목~~ 3.14 화
+-[ ] 한 라인의 좌표 값을 가지는 객체를 추가해 구현한다
+-[ ] 클래스들을 역할에 맞게 패키지 분리한다
+-[ ] 실행 결과 입력기능을 구현한다
+### ~~3.9 금~~ 3.15 수
+-[ ] 개인별 결과를 출력한다
+-[ ] 전체 참여자의 결과를 출력한다
+-[ ] 춘식이 입력시 프로그램을 종료하는 기능을 구현한다.
+### 3.16 목
+-[ ] 자바 클린 코딩 기초
+-[ ] 자바 문자열
+-[ ] 리스트와 제네릭
+-[ ] Java Collection Framework
+-[ ] TDD Basic
+### 3.17 금
+-[ ] Java Exception
+-[ ] Java Enum
+-[ ] SparkJava
+-[ ] JVM
\ No newline at end of file
diff --git a/src/main/java/kr/codesquad/Main.java b/src/main/java/kr/codesquad/Main.java
index b5ec785b..1d627f89 100644
--- a/src/main/java/kr/codesquad/Main.java
+++ b/src/main/java/kr/codesquad/Main.java
@@ -1,7 +1,13 @@
package kr.codesquad;
+import kr.codesquad.domain.LadderGame;
+import kr.codesquad.domain.RandomLadderGenerator;
+import kr.codesquad.view.Console;
+
public class Main {
public static void main(String[] args) {
- System.out.println("Hello world!");
+ Console console = new Console();
+ RandomLadderGenerator generator = new RandomLadderGenerator();
+ new LadderGame(console, generator).run();
}
}
\ No newline at end of file
diff --git a/src/main/java/kr/codesquad/domain/Ladder.java b/src/main/java/kr/codesquad/domain/Ladder.java
new file mode 100644
index 00000000..3f831034
--- /dev/null
+++ b/src/main/java/kr/codesquad/domain/Ladder.java
@@ -0,0 +1,29 @@
+package kr.codesquad.domain;
+
+import java.util.ArrayList;
+
+public class Ladder {
+ private ArrayList ladder;
+
+ public Ladder(ArrayList ladder) {
+ this.ladder = ladder;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ for (var line : ladder) {
+ sb.append(" "); // 사람 이름 5글자가 기준이므로 사다리 앞에 2칸의 간격 추가
+ for (int i = 0; i < line.size(); i++) {
+ sb.append(line.hasBridge(i) ? "|-----" : "| ");
+ }
+ sb.append("\n");
+ }
+
+ return String.valueOf(sb);
+ }
+
+ public ArrayList getLadder() {
+ return ladder;
+ }
+}
diff --git a/src/main/java/kr/codesquad/domain/LadderGame.java b/src/main/java/kr/codesquad/domain/LadderGame.java
new file mode 100644
index 00000000..2526123e
--- /dev/null
+++ b/src/main/java/kr/codesquad/domain/LadderGame.java
@@ -0,0 +1,87 @@
+package kr.codesquad.domain;
+
+import kr.codesquad.view.Console;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Optional;
+
+public class LadderGame implements Runnable {
+ private final int MIN_SIZE_OF_PEOPLE = 2;
+ private final int MIN_SIZE_OF_LADDER = 1;
+ private final int MAX_NAME_SIZE = 5;
+ private final Console console;
+ private final RandomLadderGenerator generator;
+
+ public LadderGame(Console console, RandomLadderGenerator generator) {
+ this.console = console;
+ this.generator = generator;
+ }
+
+ @Override
+ public void run() {
+ ArrayList players = inputNamesToPlayers();
+ int ladderSize = inputNumberToLadderSize();
+
+ Ladder ladder = generator.generate(players.size(), ladderSize);
+ printPlayerList(players); // 사람 이름 출력
+ System.out.println(ladder); // 사다리 출력
+ }
+
+ private void printPlayerList(ArrayList playerArrayList) {
+ StringBuilder sb = new StringBuilder();
+ for (var player : playerArrayList) {
+ sb.append(alignCenter(player.getName())).append(" ");
+ }
+ System.out.println(sb);
+ }
+
+ // 5글자를 기준으로 이름을 가운데로 정렬하는 메소드
+ private String alignCenter(String name) {
+ StringBuilder sb = new StringBuilder();
+ while (sb.length() < (MAX_NAME_SIZE - name.length()) / 2) sb.append(" ");
+ sb.append(name);
+ while (sb.length() < MAX_NAME_SIZE) sb.append(" ");
+ return sb.toString();
+ }
+
+ private ArrayList inputNamesToPlayers() {
+ var input = console.input("참여할 사람 이름을 입력하세요. (이름은 쉼표(,)로 구분하세요)");
+ if (input.isEmpty()) return inputNamesToPlayers();
+ var parsedValue = parsePlayerList(input.get());
+ return parsedValue.orElseGet(this::inputNamesToPlayers);
+ }
+
+ private Optional> parsePlayerList(String inputString) {
+ String[] playerNames = inputString.split(",");
+ if (!isValidPlayer(playerNames)) return Optional.empty();
+
+ ArrayList result = new ArrayList<>();
+ for (int i = 0; i < playerNames.length; i++) {
+ result.add(new Player(playerNames[i], i));
+ }
+ return Optional.of(result);
+ }
+
+ private boolean isValidPlayer(String[] playerNames) {
+ if (playerNames.length < MIN_SIZE_OF_PEOPLE) return false; // 최소 플레이어수 확인
+ return Arrays.stream(playerNames).allMatch(name -> name.length() < MAX_NAME_SIZE);
+ }
+
+ private Optional parseLadderSize(String inputString) {
+ try {
+ int result = Integer.parseInt(inputString);
+ if (result < MIN_SIZE_OF_LADDER) return Optional.empty();
+ return Optional.of(result);
+ } catch (NumberFormatException e) {
+ return Optional.empty();
+ }
+ }
+
+ private int inputNumberToLadderSize() {
+ var input = console.input("최대 사다리 높이는 몇 개인가요?");
+ if (input.isEmpty()) return inputNumberToLadderSize();
+ var parsedValue = parseLadderSize(input.get());
+ return parsedValue.orElseGet(this::inputNumberToLadderSize);
+ }
+}
diff --git a/src/main/java/kr/codesquad/domain/Line.java b/src/main/java/kr/codesquad/domain/Line.java
new file mode 100644
index 00000000..3f225e1c
--- /dev/null
+++ b/src/main/java/kr/codesquad/domain/Line.java
@@ -0,0 +1,19 @@
+package kr.codesquad.domain;
+
+import java.util.ArrayList;
+
+public class Line {
+ private ArrayList points = new ArrayList<>();
+
+ public boolean hasBridge(int i) {
+ return points.get(i);
+ }
+
+ public int size() {
+ return points.size();
+ }
+
+ public void add(boolean point) {
+ points.add(point);
+ }
+}
diff --git a/src/main/java/kr/codesquad/domain/Player.java b/src/main/java/kr/codesquad/domain/Player.java
new file mode 100644
index 00000000..d5b114a3
--- /dev/null
+++ b/src/main/java/kr/codesquad/domain/Player.java
@@ -0,0 +1,33 @@
+package kr.codesquad.domain;
+
+public class Player {
+ private final String name;
+ private int col;
+ private int row;
+
+ public Player(String name, int col) {
+ this.name = name;
+ this.col = col;
+ this.row = 0;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getCol() {
+ return col;
+ }
+
+ public int getRow() {
+ return row;
+ }
+
+ public void setCol(int col) {
+ this.col = col;
+ }
+
+ public void setRow(int row) {
+ this.row = row;
+ }
+}
diff --git a/src/main/java/kr/codesquad/domain/RandomLadderGenerator.java b/src/main/java/kr/codesquad/domain/RandomLadderGenerator.java
new file mode 100644
index 00000000..ec187754
--- /dev/null
+++ b/src/main/java/kr/codesquad/domain/RandomLadderGenerator.java
@@ -0,0 +1,23 @@
+package kr.codesquad.domain;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+public class RandomLadderGenerator {
+ private final Random random = new Random();
+
+ public Ladder generate(int sizeOfPeople, int sizeOfLadder) {
+ ArrayList ladder = new ArrayList<>();
+ while (sizeOfLadder-- > 0) {
+ Line line = new Line();
+ line.add(random.nextBoolean());
+ for (int col = 1; col < sizeOfPeople - 1; col++) {
+ // 이전 열의 라인 유무확인
+ line.add(line.hasBridge(col - 1) ? false : random.nextBoolean());
+ }
+ line.add(false); // 마지막 열은 라인이 없으므로 false를 저장한다.
+ ladder.add(line);
+ }
+ return new Ladder(ladder);
+ }
+}
diff --git a/src/main/java/kr/codesquad/view/Console.java b/src/main/java/kr/codesquad/view/Console.java
new file mode 100644
index 00000000..9afee241
--- /dev/null
+++ b/src/main/java/kr/codesquad/view/Console.java
@@ -0,0 +1,23 @@
+package kr.codesquad.view;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.Optional;
+
+public class Console {
+ private final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
+
+ public Optional input(String prompt) {
+ System.out.println(prompt);
+ try {
+ return Optional.of(br.readLine());
+ } catch (IOException e) {
+ return Optional.empty();
+ }
+ }
+
+ public void inputError() {
+ System.out.println("입력이 잘못되었습니다.");
+ }
+}
diff --git a/src/test/java/kr/codesquad/RandomLadderGeneratorTest.java b/src/test/java/kr/codesquad/RandomLadderGeneratorTest.java
new file mode 100644
index 00000000..e8e86838
--- /dev/null
+++ b/src/test/java/kr/codesquad/RandomLadderGeneratorTest.java
@@ -0,0 +1,38 @@
+package kr.codesquad;
+
+import kr.codesquad.domain.Line;
+import kr.codesquad.domain.RandomLadderGenerator;
+import org.assertj.core.api.SoftAssertions;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+class RandomLadderGeneratorTest {
+ @Test
+ @DisplayName("랜덤하게 생성시 사다리의 라인은 겹치지 않습니다.")
+ public void testRandomGenerate() {
+ RandomLadderGenerator generator = new RandomLadderGenerator();
+ var ladder = generator.generate(5, 5);
+
+ SoftAssertions softAssertions = new SoftAssertions();
+ for (Line line : ladder.getLadder()) {
+ for (int i = 1; i < line.size() - 1; i++) {
+ // 현재위치와 앞 또는 뒤 위치에 라인이 모두 있는 경우는 없습니다.
+ softAssertions.assertThat(line.hasBridge(i)).isTrue()
+ .isNotEqualTo(line.hasBridge(i - 1))
+ .isNotEqualTo(line.hasBridge(i + 1));
+ }
+ }
+ }
+
+ @Test
+ @DisplayName("사다리의 마지막 열은 라인이 없습니다.")
+ public void testLastRow() {
+ RandomLadderGenerator generator = new RandomLadderGenerator();
+ var ladder = generator.generate(5, 5);
+ for (Line line : ladder.getLadder()) {
+ assertFalse(line.hasBridge(4));
+ }
+ }
+}
\ No newline at end of file