From 7686f8cfd2713f05bbc5ef2490c5b7610cdc5424 Mon Sep 17 00:00:00 2001 From: yaevrai Date: Fri, 6 Jun 2025 19:58:42 +0900 Subject: [PATCH 1/6] =?UTF-8?q?docs:=20=EC=9A=94=EA=B5=AC=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EB=AC=B8=EC=84=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..6dc28cec --- /dev/null +++ b/README.md @@ -0,0 +1,56 @@ +# java-ladder : 사다리 - 함수형 프로그래밍 + +## Level1. 사다리 출력 + +### - 요구사항 + +- [] 네이버 사다리 게임을 참고하여 도메인을 분석하여 구현한다. +- [] 사다리는 4x4 크기로 고정되고, 연결 여부는 랜덤으로 결정한다. +- [] 사다리 타기가 정상적으로 동작하려면 라인이 겹치지 않도록 해야 한다. +- [] 모든 엔티티를 작게 유지한다. +- [] 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다. + +## Level2. 사다리 생성 + +### - 요구사항 + +- [] 사다리는 크기를 입력 받아 생성할 수 있다. (넓이 & 높이) + +## Level3. 사다리 타기 + +### - 요구사항 + +- [] 사다리의 시작 지점과 도착 지점을 출력한다. + +## Level4. 게임 실행 + +### - 요구사항 + +- [] 사다리 게임에 참여하는 사람에 이름을 최대 5글자까지 부여할 수 있다. 사다리를 출력할 때 사람 이름도 같이 출력한다. +- [] 사람 이름은 쉼표(,)를 기준으로 구분한다. +- [] 개인별 이름을 입력하면 개인별 결과를 출력하고, "all"을 입력하면 전체 참여자의 실행 결과를 출력한다. + +## Level5. 리팩토링 + +### - 요구사항 + +- [] 학습 테스트를 통해 학습한 내용을 반영한다. 자바에서 제공하는 함수형 문법을 적용해보고, 어떠한 차이가 있는지 경험한다. + +### - 기존 프로그래밍 요구사항 + +- [] 자바 코드 컨벤션을 지키면서 프로그래밍한다. +- [] 기본적으로 Java Style Guide을 원칙으로 한다. +- [] indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다. 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다. 힌트: + indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메서드)를 분리하면 + 된다. +- [] 3항 연산자를 쓰지 않는다. +- [] else 예약어를 쓰지 않는다. +- [] else 예약어를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다. 힌트: if문에서 값을 반환하는 방식으로 + 구현하면 else 예약어를 사용하지 않아도 된다. +- [] 배열 대신 컬렉션을 사용한다. +- [] 줄여 쓰지 않는다(축약 금지). +- [] 함수(또는 메서드)의 길이가 10라인을 넘어가지 않도록 구현한다. +- [] 함수(또는 메서드)가 한 가지 일만 하도록 최대한 작게 만들어라. +- [] 모든 원시 값과 문자열을 포장한다. +- [] 일급 컬렉션을 쓴다. +- [] Java Enum을 적용한다. From 88dea608e226748010aa22519508fecb9a78b550 Mon Sep 17 00:00:00 2001 From: yaevrai Date: Fri, 6 Jun 2025 20:55:39 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat(level1):=20=EC=82=AC=EB=8B=A4=EB=A6=AC?= =?UTF-8?q?=20=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 10 ++-- .../java/ladder/controller/Application.java | 13 +++++ .../java/ladder/controller/LadderGame.java | 21 ++++++++ src/main/java/ladder/model/Ladder.java | 29 ++++++++++ src/main/java/ladder/model/Line.java | 53 +++++++++++++++++++ src/main/java/ladder/view/InputView.java | 18 +++++++ src/main/java/ladder/view/OutputView.java | 10 ++++ 7 files changed, 149 insertions(+), 5 deletions(-) create mode 100644 src/main/java/ladder/controller/Application.java create mode 100644 src/main/java/ladder/controller/LadderGame.java create mode 100644 src/main/java/ladder/model/Ladder.java create mode 100644 src/main/java/ladder/model/Line.java create mode 100644 src/main/java/ladder/view/InputView.java create mode 100644 src/main/java/ladder/view/OutputView.java diff --git a/README.md b/README.md index 6dc28cec..e9699335 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,11 @@ ### - 요구사항 -- [] 네이버 사다리 게임을 참고하여 도메인을 분석하여 구현한다. -- [] 사다리는 4x4 크기로 고정되고, 연결 여부는 랜덤으로 결정한다. -- [] 사다리 타기가 정상적으로 동작하려면 라인이 겹치지 않도록 해야 한다. -- [] 모든 엔티티를 작게 유지한다. -- [] 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다. +- [x] 네이버 사다리 게임을 참고하여 도메인을 분석하여 구현한다. +- [x] 사다리는 4x4 크기로 고정되고, 연결 여부는 랜덤으로 결정한다. +- [x] 사다리 타기가 정상적으로 동작하려면 라인이 겹치지 않도록 해야 한다. +- [x] 모든 엔티티를 작게 유지한다. +- [x] 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다. ## Level2. 사다리 생성 diff --git a/src/main/java/ladder/controller/Application.java b/src/main/java/ladder/controller/Application.java new file mode 100644 index 00000000..4c8a16e4 --- /dev/null +++ b/src/main/java/ladder/controller/Application.java @@ -0,0 +1,13 @@ +package ladder.controller; + +import ladder.view.InputView; +import ladder.view.OutputView; + +public class Application { + public static void main(String[] args) { + InputView inputView = new InputView(); + OutputView outputView = new OutputView(); + LadderGame game = new LadderGame(inputView, outputView); + game.play(); + } +} diff --git a/src/main/java/ladder/controller/LadderGame.java b/src/main/java/ladder/controller/LadderGame.java new file mode 100644 index 00000000..bdccc58f --- /dev/null +++ b/src/main/java/ladder/controller/LadderGame.java @@ -0,0 +1,21 @@ +package ladder.controller; + +import ladder.model.Ladder; +import ladder.view.InputView; +import ladder.view.OutputView; + +public class LadderGame { + + private final InputView inputView; + private final OutputView outputView; + + public LadderGame(InputView inputView, OutputView outputView) { + this.inputView = inputView; + this.outputView = outputView; + } + + public void play() { + Ladder ladder = Ladder.create(); + outputView.printLadder(ladder); + } +} diff --git a/src/main/java/ladder/model/Ladder.java b/src/main/java/ladder/model/Ladder.java new file mode 100644 index 00000000..d22f756d --- /dev/null +++ b/src/main/java/ladder/model/Ladder.java @@ -0,0 +1,29 @@ +package ladder.model; + +import java.util.ArrayList; +import java.util.List; + +public class Ladder { + private static final int HEIGHT = 4; + private static final int WIDTH = 4; + + private final List lines; + + private Ladder(List lines) { + this.lines = lines; + } + + public static Ladder create() { + List lines = new ArrayList<>(); + for (int i = 0; i < HEIGHT; i++) { + lines.add(Line.create(WIDTH)); + } + return new Ladder(lines); + } + + public void draw() { + for (Line line : lines) { + line.draw(); + } + } +} diff --git a/src/main/java/ladder/model/Line.java b/src/main/java/ladder/model/Line.java new file mode 100644 index 00000000..3aec1fc8 --- /dev/null +++ b/src/main/java/ladder/model/Line.java @@ -0,0 +1,53 @@ +package ladder.model; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +public class Line { + + private final List points; + + private Line(List points) { + this.points = points; + } + + public static Line create(int width) { + List points = new ArrayList<>(); + Random random = new Random(); + + for (int i = 0; i < width - 1; i++) { + addConnection(points, i, random); + } + + return new Line(points); + } + + private static void addConnection(List points, int index, Random random) { + if (isConnectedToPrevious(index, points)) { + points.add(false); + return; + } + + points.add(random.nextBoolean()); + } + + private static boolean isConnectedToPrevious(int index, List points) { + return index > 0 && points.get(index - 1); + } + + public void draw() { + for (Boolean point : points) { + System.out.print("|"); + printLine(point); + } + System.out.println("|"); + } + + private void printLine(Boolean connected) { + if (connected) { + System.out.print("-----"); + return; + } + System.out.print(" "); + } +} diff --git a/src/main/java/ladder/view/InputView.java b/src/main/java/ladder/view/InputView.java new file mode 100644 index 00000000..a02a6504 --- /dev/null +++ b/src/main/java/ladder/view/InputView.java @@ -0,0 +1,18 @@ +package ladder.view; + +import java.util.Scanner; + +public class InputView { + + public int inputWidth() { + Scanner scanner = new Scanner(System.in); + System.out.print("사다리의 넓이는 몇 개인가요?\n: "); + return Integer.parseInt(scanner.nextLine()); + } + + public int inputHeight() { + Scanner scanner = new Scanner(System.in); + System.out.print("사다리의 높이는 몇 개인가요?\n: "); + return Integer.parseInt(scanner.nextLine()); + } +} diff --git a/src/main/java/ladder/view/OutputView.java b/src/main/java/ladder/view/OutputView.java new file mode 100644 index 00000000..3a941f30 --- /dev/null +++ b/src/main/java/ladder/view/OutputView.java @@ -0,0 +1,10 @@ +package ladder.view; + +import ladder.model.Ladder; + +public class OutputView { + + public void printLadder(Ladder ladder) { + ladder.draw(); + } +} From 7196c8e0040ac597dc590c07f8dc6a19d22f5df6 Mon Sep 17 00:00:00 2001 From: yaevrai Date: Fri, 6 Jun 2025 20:59:09 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat(level2):=20=EC=82=AC=EB=8B=A4=EB=A6=AC?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../java/ladder/controller/LadderGame.java | 5 +++- src/main/java/ladder/model/Ladder.java | 30 +++++++++---------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index e9699335..7bd8cb3e 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ ### - 요구사항 -- [] 사다리는 크기를 입력 받아 생성할 수 있다. (넓이 & 높이) +- [x] 사다리는 크기를 입력 받아 생성할 수 있다. (넓이 & 높이) ## Level3. 사다리 타기 diff --git a/src/main/java/ladder/controller/LadderGame.java b/src/main/java/ladder/controller/LadderGame.java index bdccc58f..465f6a5c 100644 --- a/src/main/java/ladder/controller/LadderGame.java +++ b/src/main/java/ladder/controller/LadderGame.java @@ -15,7 +15,10 @@ public LadderGame(InputView inputView, OutputView outputView) { } public void play() { - Ladder ladder = Ladder.create(); + int width = inputView.inputWidth(); + int height = inputView.inputHeight(); + + Ladder ladder = Ladder.create(width, height); outputView.printLadder(ladder); } } diff --git a/src/main/java/ladder/model/Ladder.java b/src/main/java/ladder/model/Ladder.java index d22f756d..f69ea21c 100644 --- a/src/main/java/ladder/model/Ladder.java +++ b/src/main/java/ladder/model/Ladder.java @@ -4,26 +4,24 @@ import java.util.List; public class Ladder { - private static final int HEIGHT = 4; - private static final int WIDTH = 4; - private final List lines; + private final List lines; - private Ladder(List lines) { - this.lines = lines; - } + private Ladder(List lines) { + this.lines = lines; + } - public static Ladder create() { - List lines = new ArrayList<>(); - for (int i = 0; i < HEIGHT; i++) { - lines.add(Line.create(WIDTH)); + public static Ladder create(int width, int height) { + List lines = new ArrayList<>(); + for (int i = 0; i < height; i++) { + lines.add(Line.create(width)); + } + return new Ladder(lines); } - return new Ladder(lines); - } - public void draw() { - for (Line line : lines) { - line.draw(); + public void draw() { + for (Line line : lines) { + line.draw(); + } } - } } From 15d8a2eeaa1a65a042b37a6650f649f33a792532 Mon Sep 17 00:00:00 2001 From: yaevrai Date: Fri, 6 Jun 2025 21:43:42 +0900 Subject: [PATCH 4/6] =?UTF-8?q?feat(level3):=20=EC=82=AC=EB=8B=A4=EB=A6=AC?= =?UTF-8?q?=20=ED=83=80=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../java/ladder/controller/LadderGame.java | 1 + src/main/java/ladder/model/Ladder.java | 41 +++++++++++ src/main/java/ladder/model/Line.java | 71 ++++++++++--------- src/main/java/ladder/view/OutputView.java | 7 ++ 5 files changed, 88 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 7bd8cb3e..7338646f 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ ### - 요구사항 -- [] 사다리의 시작 지점과 도착 지점을 출력한다. +- [x] 사다리의 시작 지점과 도착 지점을 출력한다. ## Level4. 게임 실행 diff --git a/src/main/java/ladder/controller/LadderGame.java b/src/main/java/ladder/controller/LadderGame.java index 465f6a5c..a94f1089 100644 --- a/src/main/java/ladder/controller/LadderGame.java +++ b/src/main/java/ladder/controller/LadderGame.java @@ -20,5 +20,6 @@ public void play() { Ladder ladder = Ladder.create(width, height); outputView.printLadder(ladder); + outputView.printResults(ladder.result()); } } diff --git a/src/main/java/ladder/model/Ladder.java b/src/main/java/ladder/model/Ladder.java index f69ea21c..d2ca7429 100644 --- a/src/main/java/ladder/model/Ladder.java +++ b/src/main/java/ladder/model/Ladder.java @@ -24,4 +24,45 @@ public void draw() { line.draw(); } } + + public List result() { + int width = lines.get(0).getPoints().size() + 1; + List results = new ArrayList<>(); + + for (int start = 0; start < width; start++) { + results.add(getEndPoint(start)); + } + + return results; + } + + private int getEndPoint(int start) { + int position = start; + + for (Line line : lines) { + position = move(position, line.getPoints()); + } + + return position; + } + + private int move(int position, List points) { + if (canMoveLeft(position, points)) { + return position - 1; + } + + if (canMoveRight(position, points)) { + return position + 1; + } + + return position; + } + + private boolean canMoveLeft(int position, List points) { + return position > 0 && points.get(position - 1); + } + + private boolean canMoveRight(int position, List points) { + return position < points.size() && points.get(position); + } } diff --git a/src/main/java/ladder/model/Line.java b/src/main/java/ladder/model/Line.java index 3aec1fc8..40179a23 100644 --- a/src/main/java/ladder/model/Line.java +++ b/src/main/java/ladder/model/Line.java @@ -3,51 +3,56 @@ import java.util.ArrayList; import java.util.List; import java.util.Random; -public class Line { - private final List points; +public class Line { - private Line(List points) { - this.points = points; - } + private final List points; - public static Line create(int width) { - List points = new ArrayList<>(); - Random random = new Random(); + private Line(List points) { + this.points = points; + } - for (int i = 0; i < width - 1; i++) { - addConnection(points, i, random); + public List getPoints() { + return points; } - return new Line(points); - } + public static Line create(int width) { + List points = new ArrayList<>(); + Random random = new Random(); + + for (int i = 0; i < width - 1; i++) { + addConnection(points, i, random); + } - private static void addConnection(List points, int index, Random random) { - if (isConnectedToPrevious(index, points)) { - points.add(false); - return; + return new Line(points); } - points.add(random.nextBoolean()); - } + private static void addConnection(List points, int index, Random random) { + if (isConnectedToPrevious(index, points)) { + points.add(false); + return; + } - private static boolean isConnectedToPrevious(int index, List points) { - return index > 0 && points.get(index - 1); - } + points.add(random.nextBoolean()); + } + + private static boolean isConnectedToPrevious(int index, List points) { + return index > 0 && points.get(index - 1); + } - public void draw() { - for (Boolean point : points) { - System.out.print("|"); - printLine(point); + public void draw() { + for (Boolean point : points) { + System.out.print("|"); + printLine(point); + } + System.out.println("|"); } - System.out.println("|"); - } - private void printLine(Boolean connected) { - if (connected) { - System.out.print("-----"); - return; + private void printLine(Boolean connected) { + if (connected) { + System.out.print("-----"); + return; + } + System.out.print(" "); } - System.out.print(" "); - } } diff --git a/src/main/java/ladder/view/OutputView.java b/src/main/java/ladder/view/OutputView.java index 3a941f30..bf59a5d0 100644 --- a/src/main/java/ladder/view/OutputView.java +++ b/src/main/java/ladder/view/OutputView.java @@ -1,5 +1,6 @@ package ladder.view; +import java.util.List; import ladder.model.Ladder; public class OutputView { @@ -7,4 +8,10 @@ public class OutputView { public void printLadder(Ladder ladder) { ladder.draw(); } + + public void printResults(List results) { + for (int i = 0; i < results.size(); i++) { + System.out.println(i + " -> " + results.get(i)); + } + } } From 4a6b1c7c2687a20f9351bf827477e4fbed441117 Mon Sep 17 00:00:00 2001 From: yaevrai Date: Sat, 7 Jun 2025 00:38:26 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat(level4,5):=20=EA=B2=8C=EC=9E=84=20?= =?UTF-8?q?=EC=8B=A4=ED=96=89=20+=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 27 ++-------- .../java/ladder/controller/LadderGame.java | 50 +++++++++++++++++-- src/main/java/ladder/model/GameSetup.java | 29 +++++++++++ src/main/java/ladder/model/Ladder.java | 24 ++++----- src/main/java/ladder/model/Line.java | 30 ++++------- src/main/java/ladder/model/Name.java | 18 +++++++ src/main/java/ladder/model/Participants.java | 32 ++++++++++++ src/main/java/ladder/model/ResultType.java | 16 ++++++ src/main/java/ladder/model/Results.java | 31 ++++++++++++ src/main/java/ladder/view/InputView.java | 27 +++++++--- src/main/java/ladder/view/OutputView.java | 38 ++++++++++++-- src/test/java/ladder/LadderTest.java | 22 ++++++++ src/test/java/ladder/LineTest.java | 22 ++++++++ src/test/java/ladder/NameTest.java | 25 ++++++++++ src/test/java/ladder/ParticipantsTest.java | 24 +++++++++ 15 files changed, 346 insertions(+), 69 deletions(-) create mode 100644 src/main/java/ladder/model/GameSetup.java create mode 100644 src/main/java/ladder/model/Name.java create mode 100644 src/main/java/ladder/model/Participants.java create mode 100644 src/main/java/ladder/model/ResultType.java create mode 100644 src/main/java/ladder/model/Results.java create mode 100644 src/test/java/ladder/LadderTest.java create mode 100644 src/test/java/ladder/LineTest.java create mode 100644 src/test/java/ladder/NameTest.java create mode 100644 src/test/java/ladder/ParticipantsTest.java diff --git a/README.md b/README.md index 7338646f..2e8305bc 100644 --- a/README.md +++ b/README.md @@ -26,31 +26,12 @@ ### - 요구사항 -- [] 사다리 게임에 참여하는 사람에 이름을 최대 5글자까지 부여할 수 있다. 사다리를 출력할 때 사람 이름도 같이 출력한다. -- [] 사람 이름은 쉼표(,)를 기준으로 구분한다. -- [] 개인별 이름을 입력하면 개인별 결과를 출력하고, "all"을 입력하면 전체 참여자의 실행 결과를 출력한다. +- [x] 사다리 게임에 참여하는 사람에 이름을 최대 5글자까지 부여할 수 있다. 사다리를 출력할 때 사람 이름도 같이 출력한다. +- [x] 사람 이름은 쉼표(,)를 기준으로 구분한다. +- [x] 개인별 이름을 입력하면 개인별 결과를 출력하고, "all"을 입력하면 전체 참여자의 실행 결과를 출력한다. ## Level5. 리팩토링 ### - 요구사항 -- [] 학습 테스트를 통해 학습한 내용을 반영한다. 자바에서 제공하는 함수형 문법을 적용해보고, 어떠한 차이가 있는지 경험한다. - -### - 기존 프로그래밍 요구사항 - -- [] 자바 코드 컨벤션을 지키면서 프로그래밍한다. -- [] 기본적으로 Java Style Guide을 원칙으로 한다. -- [] indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다. 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다. 힌트: - indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메서드)를 분리하면 - 된다. -- [] 3항 연산자를 쓰지 않는다. -- [] else 예약어를 쓰지 않는다. -- [] else 예약어를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다. 힌트: if문에서 값을 반환하는 방식으로 - 구현하면 else 예약어를 사용하지 않아도 된다. -- [] 배열 대신 컬렉션을 사용한다. -- [] 줄여 쓰지 않는다(축약 금지). -- [] 함수(또는 메서드)의 길이가 10라인을 넘어가지 않도록 구현한다. -- [] 함수(또는 메서드)가 한 가지 일만 하도록 최대한 작게 만들어라. -- [] 모든 원시 값과 문자열을 포장한다. -- [] 일급 컬렉션을 쓴다. -- [] Java Enum을 적용한다. +- [x] 학습 테스트를 통해 학습한 내용을 반영한다. 자바에서 제공하는 함수형 문법을 적용해보고, 어떠한 차이가 있는지 경험한다. diff --git a/src/main/java/ladder/controller/LadderGame.java b/src/main/java/ladder/controller/LadderGame.java index a94f1089..9f45d89a 100644 --- a/src/main/java/ladder/controller/LadderGame.java +++ b/src/main/java/ladder/controller/LadderGame.java @@ -1,6 +1,13 @@ package ladder.controller; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import ladder.model.GameSetup; import ladder.model.Ladder; +import ladder.model.Participants; +import ladder.model.ResultType; +import ladder.model.Results; import ladder.view.InputView; import ladder.view.OutputView; @@ -15,11 +22,46 @@ public LadderGame(InputView inputView, OutputView outputView) { } public void play() { - int width = inputView.inputWidth(); + GameSetup setup = createGameSetup(); + displayLadder(setup); + processResult(setup); + } + + private GameSetup createGameSetup() { + Participants participants = inputView.inputParticipants(); + List results = inputView.inputResults(); int height = inputView.inputHeight(); + Ladder ladder = Ladder.create(participants.size(), height); + return new GameSetup(participants, results, ladder); + } + + private void displayLadder(GameSetup setup) { + outputView.printLadder(setup.getLadder(), setup.getParticipants(), setup.getResults()); + } + + private void processResult(GameSetup setup) { + String result = inputView.inputGameResult(); + Results gameResults = createGameResults(setup); + printGameResults(result, gameResults); + } + + private Results createGameResults(GameSetup setup) { + List ladderResults = setup.getLadder().result(); + return new Results(setup.getParticipants(), + mapResults(setup.getResults(), ladderResults)); + } + + private void printGameResults(String result, Results gameResults) { + if (ResultType.ALL.equals(ResultType.from(result))) { + outputView.printAllResults(gameResults); + return; + } + outputView.printSingleResult(gameResults.getResult(result)); + } - Ladder ladder = Ladder.create(width, height); - outputView.printLadder(ladder); - outputView.printResults(ladder.result()); + private List mapResults(List inputResults, List ladderResults) { + return IntStream.range(0, inputResults.size()) + .mapToObj(i -> inputResults.get(ladderResults.get(i))) + .collect(Collectors.toList()); } } diff --git a/src/main/java/ladder/model/GameSetup.java b/src/main/java/ladder/model/GameSetup.java new file mode 100644 index 00000000..ee3d1904 --- /dev/null +++ b/src/main/java/ladder/model/GameSetup.java @@ -0,0 +1,29 @@ +package ladder.model; + +import java.util.ArrayList; +import java.util.List; + +public class GameSetup { + + private final Participants participants; + private final List results; + private final Ladder ladder; + + public GameSetup(Participants participants, List results, Ladder ladder) { + this.participants = participants; + this.results = new ArrayList<>(results); + this.ladder = ladder; + } + + public Participants getParticipants() { + return participants; + } + + public List getResults() { + return new ArrayList<>(results); + } + + public Ladder getLadder() { + return ladder; + } +} diff --git a/src/main/java/ladder/model/Ladder.java b/src/main/java/ladder/model/Ladder.java index d2ca7429..f6ea79a1 100644 --- a/src/main/java/ladder/model/Ladder.java +++ b/src/main/java/ladder/model/Ladder.java @@ -1,7 +1,8 @@ package ladder.model; -import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; public class Ladder { @@ -12,11 +13,11 @@ private Ladder(List lines) { } public static Ladder create(int width, int height) { - List lines = new ArrayList<>(); - for (int i = 0; i < height; i++) { - lines.add(Line.create(width)); - } - return new Ladder(lines); + return new Ladder( + IntStream.range(0, height) + .mapToObj(i -> Line.create(width)) + .collect(Collectors.toList()) + ); } public void draw() { @@ -27,13 +28,10 @@ public void draw() { public List result() { int width = lines.get(0).getPoints().size() + 1; - List results = new ArrayList<>(); - - for (int start = 0; start < width; start++) { - results.add(getEndPoint(start)); - } - - return results; + return IntStream.range(0, width) + .map(this::getEndPoint) + .boxed() + .collect(Collectors.toList()); } private int getEndPoint(int start) { diff --git a/src/main/java/ladder/model/Line.java b/src/main/java/ladder/model/Line.java index 40179a23..74076efd 100644 --- a/src/main/java/ladder/model/Line.java +++ b/src/main/java/ladder/model/Line.java @@ -3,6 +3,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Random; +import java.util.stream.Collectors; +import java.util.stream.IntStream; public class Line { @@ -13,31 +15,21 @@ private Line(List points) { } public List getPoints() { - return points; + return new ArrayList<>(points); } public static Line create(int width) { - List points = new ArrayList<>(); Random random = new Random(); - - for (int i = 0; i < width - 1; i++) { - addConnection(points, i, random); - } - - return new Line(points); - } - - private static void addConnection(List points, int index, Random random) { - if (isConnectedToPrevious(index, points)) { - points.add(false); - return; - } - - points.add(random.nextBoolean()); + List points = new ArrayList<>(); + return new Line(IntStream.range(0, width - 1) + .mapToObj(i -> shouldConnect(points, i, random)) + .collect(Collectors.toList())); } - private static boolean isConnectedToPrevious(int index, List points) { - return index > 0 && points.get(index - 1); + private static boolean shouldConnect(List points, int index, Random random) { + boolean connection = (index <= 0 || !points.get(index - 1)) && random.nextBoolean(); + points.add(connection); + return connection; } public void draw() { diff --git a/src/main/java/ladder/model/Name.java b/src/main/java/ladder/model/Name.java new file mode 100644 index 00000000..d2846c18 --- /dev/null +++ b/src/main/java/ladder/model/Name.java @@ -0,0 +1,18 @@ +package ladder.model; + +public class Name { + + private static final int MAX_LENGTH = 5; + private final String name; + + public Name(String name) { + if (name.length() > MAX_LENGTH) { + throw new IllegalArgumentException("이름은 최대 5글자까지 가능합니다."); + } + this.name = name; + } + + public boolean matches(String other) { + return name.equals(other); + } +} diff --git a/src/main/java/ladder/model/Participants.java b/src/main/java/ladder/model/Participants.java new file mode 100644 index 00000000..00f230c0 --- /dev/null +++ b/src/main/java/ladder/model/Participants.java @@ -0,0 +1,32 @@ +package ladder.model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class Participants { + + private final List names; + + private Participants(List names) { + this.names = names; + } + + public static Participants from(String input) { + return new Participants( + Arrays.stream(input.split(",")) + .map(String::trim) + .map(Name::new) + .collect(Collectors.toList()) + ); + } + + public int size() { + return names.size(); + } + + public List values() { + return new ArrayList<>(names); + } +} diff --git a/src/main/java/ladder/model/ResultType.java b/src/main/java/ladder/model/ResultType.java new file mode 100644 index 00000000..f08e03b6 --- /dev/null +++ b/src/main/java/ladder/model/ResultType.java @@ -0,0 +1,16 @@ +package ladder.model; + +public enum ResultType { + ALL("all"), + SINGLE(""); + + private final String value; + + ResultType(String value) { + this.value = value; + } + + public static ResultType from(String input) { + return "all".equals(input) ? ALL : SINGLE; + } +} diff --git a/src/main/java/ladder/model/Results.java b/src/main/java/ladder/model/Results.java new file mode 100644 index 00000000..14ca31c3 --- /dev/null +++ b/src/main/java/ladder/model/Results.java @@ -0,0 +1,31 @@ +package ladder.model; + +import java.util.ArrayList; +import java.util.List; + +public class Results { + + private final Participants participants; + private final List results; + + public Results(Participants participants, List results) { + this.participants = participants; + this.results = results; + } + + public List getAll() { + return new ArrayList<>(results); + } + + public List getParticipants() { + return participants.values(); + } + + public String getResult(String participant) { + return participants.values().stream() + .filter(name -> name.matches(participant)) + .findFirst() + .map(name -> results.get(participants.values().indexOf(name))) + .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 참가자입니다.")); + } +} diff --git a/src/main/java/ladder/view/InputView.java b/src/main/java/ladder/view/InputView.java index a02a6504..50454e97 100644 --- a/src/main/java/ladder/view/InputView.java +++ b/src/main/java/ladder/view/InputView.java @@ -1,18 +1,33 @@ package ladder.view; +import java.util.Arrays; +import java.util.List; import java.util.Scanner; +import ladder.model.Participants; public class InputView { - public int inputWidth() { - Scanner scanner = new Scanner(System.in); - System.out.print("사다리의 넓이는 몇 개인가요?\n: "); - return Integer.parseInt(scanner.nextLine()); + private static final Scanner scanner = new Scanner(System.in); + + public Participants inputParticipants() { + System.out.println("참여할 사람 이름을 입력하세요. (이름은 쉼표(,)로 구분하세요)"); + String input = scanner.nextLine(); + return Participants.from(input); + } + + public List inputResults() { + System.out.println("\n실행 결과를 입력하세요. (결과는 쉼표(,)로 구분하세요)"); + String input = scanner.nextLine(); + return Arrays.asList(input.split(",")); } public int inputHeight() { - Scanner scanner = new Scanner(System.in); - System.out.print("사다리의 높이는 몇 개인가요?\n: "); + System.out.println("\n최대 사다리 높이는 몇 개인가요?"); return Integer.parseInt(scanner.nextLine()); } + + public String inputGameResult() { + System.out.println("\n결과를 보고 싶은 사람은?"); + return scanner.nextLine(); + } } diff --git a/src/main/java/ladder/view/OutputView.java b/src/main/java/ladder/view/OutputView.java index bf59a5d0..f9ac9319 100644 --- a/src/main/java/ladder/view/OutputView.java +++ b/src/main/java/ladder/view/OutputView.java @@ -1,17 +1,47 @@ package ladder.view; import java.util.List; +import java.util.stream.IntStream; import ladder.model.Ladder; +import ladder.model.Name; +import ladder.model.Participants; +import ladder.model.Results; public class OutputView { - public void printLadder(Ladder ladder) { + public void printLadder(Ladder ladder, Participants participants, List results) { + System.out.println("\n사다리 결과\n"); + printParticipants(participants); ladder.draw(); + printResults(results); } - public void printResults(List results) { - for (int i = 0; i < results.size(); i++) { - System.out.println(i + " -> " + results.get(i)); + private void printParticipants(Participants participants) { + System.out.print(" "); + for (Name name : participants.values()) { + System.out.printf("%-6s", name); } + System.out.println(); + } + + public void printResults(List results) { + System.out.print(" "); + for (String result : results) { + System.out.printf("%-6s", result); + } + System.out.println("\n"); + } + + public void printSingleResult(String result) { + System.out.println("\n실행 결과"); + System.out.println(result); + } + + public void printAllResults(Results results) { + System.out.println("\n실행 결과"); + IntStream.range(0, results.getParticipants().size()) + .forEach(i -> System.out.printf("%s : %s%n", + results.getParticipants().get(i), + results.getAll().get(i))); } } diff --git a/src/test/java/ladder/LadderTest.java b/src/test/java/ladder/LadderTest.java new file mode 100644 index 00000000..a5e23020 --- /dev/null +++ b/src/test/java/ladder/LadderTest.java @@ -0,0 +1,22 @@ +package ladder; + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; + +import java.util.List; +import ladder.model.Ladder; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class LadderTest { + + @Test + @DisplayName("사다리 생성") + void generateLadder() { + Ladder ladder = Ladder.create(4, 5); + List results = ladder.result(); + + assertThat(results).hasSize(4); + assertThat(results) + .allMatch(position -> position >= 0 && position < 4); + } +} diff --git a/src/test/java/ladder/LineTest.java b/src/test/java/ladder/LineTest.java new file mode 100644 index 00000000..486018cc --- /dev/null +++ b/src/test/java/ladder/LineTest.java @@ -0,0 +1,22 @@ +package ladder; + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; + +import java.util.List; +import ladder.model.Line; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class LineTest { + + @Test + @DisplayName("라인 생성") + void generateLine() { + Line line = Line.create(4); + List points = line.getPoints(); + + assertThat(points).hasSize(3); // width-1 개 포인트 + assertThat(points) + .doesNotContainSequence(true, true); // 연속된 true가 XXX + } +} diff --git a/src/test/java/ladder/NameTest.java b/src/test/java/ladder/NameTest.java new file mode 100644 index 00000000..50dd27cd --- /dev/null +++ b/src/test/java/ladder/NameTest.java @@ -0,0 +1,25 @@ +package ladder; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThatNoException; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + +import ladder.model.Name; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class NameTest { + + @Test + @DisplayName("이름 정상 입력") + void generateName() { + assertThatNoException().isThrownBy(() -> new Name("pobi")); + } + + @Test + @DisplayName("이름 5글자 초과시 예외발생") + void overLengthName() { + assertThatThrownBy(() -> new Name("pobiii")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("이름은 최대 5글자까지 가능합니다."); + } +} diff --git a/src/test/java/ladder/ParticipantsTest.java b/src/test/java/ladder/ParticipantsTest.java new file mode 100644 index 00000000..862353dc --- /dev/null +++ b/src/test/java/ladder/ParticipantsTest.java @@ -0,0 +1,24 @@ +package ladder; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import java.util.List; +import ladder.model.Name; +import ladder.model.Participants; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class ParticipantsTest { + + @Test + @DisplayName("참가자 생성") + void generateParticipants() { + Participants participants = Participants.from("pobi,jason,brown"); + List names = participants.values(); + + assertThat(participants.size()).isEqualTo(3); + assertThat(names.get(0).matches("pobi")).isTrue(); + assertThat(names.get(1).matches("jason")).isTrue(); + assertThat(names.get(2).matches("brown")).isTrue(); + } +} From 40e6aba6a61ce0872f6b6be5e4b19dbbf65d104d Mon Sep 17 00:00:00 2001 From: yaevrai Date: Fri, 13 Jun 2025 01:49:41 +0900 Subject: [PATCH 6/6] =?UTF-8?q?feat(level5):=20PR=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/ladder/controller/LadderGame.java | 53 ++++++++----------- src/main/java/ladder/model/GameSetup.java | 29 ---------- src/main/java/ladder/model/Ladder.java | 11 ++-- .../model/{Results.java => LadderResult.java} | 16 +++--- src/main/java/ladder/model/Line.java | 40 ++++++-------- src/main/java/ladder/model/Name.java | 34 ++++++++++-- src/main/java/ladder/model/Participants.java | 13 ++--- src/main/java/ladder/model/Point.java | 44 +++++++++++++++ src/main/java/ladder/model/Result.java | 31 +++++++++++ src/main/java/ladder/model/ResultType.java | 16 ------ src/main/java/ladder/view/InputView.java | 18 +++++-- src/main/java/ladder/view/OutputView.java | 42 +++++++++++---- src/test/java/ladder/LadderTest.java | 39 ++++++++++++-- src/test/java/ladder/LineTest.java | 31 ++++++++--- src/test/java/ladder/ParticipantsTest.java | 18 ++++--- 15 files changed, 272 insertions(+), 163 deletions(-) delete mode 100644 src/main/java/ladder/model/GameSetup.java rename src/main/java/ladder/model/{Results.java => LadderResult.java} (52%) create mode 100644 src/main/java/ladder/model/Point.java create mode 100644 src/main/java/ladder/model/Result.java delete mode 100644 src/main/java/ladder/model/ResultType.java diff --git a/src/main/java/ladder/controller/LadderGame.java b/src/main/java/ladder/controller/LadderGame.java index 9f45d89a..fdcbdcfc 100644 --- a/src/main/java/ladder/controller/LadderGame.java +++ b/src/main/java/ladder/controller/LadderGame.java @@ -2,12 +2,11 @@ import java.util.List; import java.util.stream.Collectors; -import java.util.stream.IntStream; -import ladder.model.GameSetup; import ladder.model.Ladder; +import ladder.model.LadderResult; import ladder.model.Participants; -import ladder.model.ResultType; -import ladder.model.Results; +import ladder.model.Point; +import ladder.model.Result; import ladder.view.InputView; import ladder.view.OutputView; @@ -22,46 +21,36 @@ public LadderGame(InputView inputView, OutputView outputView) { } public void play() { - GameSetup setup = createGameSetup(); - displayLadder(setup); - processResult(setup); - } - - private GameSetup createGameSetup() { Participants participants = inputView.inputParticipants(); - List results = inputView.inputResults(); + List results = inputView.inputResults(); int height = inputView.inputHeight(); - Ladder ladder = Ladder.create(participants.size(), height); - return new GameSetup(participants, results, ladder); - } - private void displayLadder(GameSetup setup) { - outputView.printLadder(setup.getLadder(), setup.getParticipants(), setup.getResults()); - } + Ladder ladder = Ladder.create(participants.size(), height); + outputView.printLadder(ladder, participants, results); - private void processResult(GameSetup setup) { - String result = inputView.inputGameResult(); - Results gameResults = createGameResults(setup); - printGameResults(result, gameResults); + String resultRequest = inputView.inputGameResult(); + processResult(ladder, participants, results, resultRequest); } - private Results createGameResults(GameSetup setup) { - List ladderResults = setup.getLadder().result(); - return new Results(setup.getParticipants(), - mapResults(setup.getResults(), ladderResults)); + private void processResult(Ladder ladder, Participants participants, List results, + String resultRequest) { + List ladderResults = ladder.result(); + List mappedResults = mapResults(results, ladderResults); + LadderResult ladderResult = new LadderResult(participants, mappedResults); + printGameResults(resultRequest, ladderResult); } - private void printGameResults(String result, Results gameResults) { - if (ResultType.ALL.equals(ResultType.from(result))) { - outputView.printAllResults(gameResults); + private void printGameResults(String result, LadderResult gameLadderResult) { + if ("all".equals(result)) { + outputView.printAllResults(gameLadderResult); return; } - outputView.printSingleResult(gameResults.getResult(result)); + outputView.printSingleResult(gameLadderResult.getResult(result)); } - private List mapResults(List inputResults, List ladderResults) { - return IntStream.range(0, inputResults.size()) - .mapToObj(i -> inputResults.get(ladderResults.get(i))) + private List mapResults(List inputResults, List ladderResults) { + return ladderResults.stream() + .map(point -> inputResults.get(point.getEnd())) .collect(Collectors.toList()); } } diff --git a/src/main/java/ladder/model/GameSetup.java b/src/main/java/ladder/model/GameSetup.java deleted file mode 100644 index ee3d1904..00000000 --- a/src/main/java/ladder/model/GameSetup.java +++ /dev/null @@ -1,29 +0,0 @@ -package ladder.model; - -import java.util.ArrayList; -import java.util.List; - -public class GameSetup { - - private final Participants participants; - private final List results; - private final Ladder ladder; - - public GameSetup(Participants participants, List results, Ladder ladder) { - this.participants = participants; - this.results = new ArrayList<>(results); - this.ladder = ladder; - } - - public Participants getParticipants() { - return participants; - } - - public List getResults() { - return new ArrayList<>(results); - } - - public Ladder getLadder() { - return ladder; - } -} diff --git a/src/main/java/ladder/model/Ladder.java b/src/main/java/ladder/model/Ladder.java index f6ea79a1..c37b698b 100644 --- a/src/main/java/ladder/model/Ladder.java +++ b/src/main/java/ladder/model/Ladder.java @@ -20,17 +20,14 @@ public static Ladder create(int width, int height) { ); } - public void draw() { - for (Line line : lines) { - line.draw(); - } + public List getLines() { + return lines; } - public List result() { + public List result() { int width = lines.get(0).getPoints().size() + 1; return IntStream.range(0, width) - .map(this::getEndPoint) - .boxed() + .mapToObj(start -> new Point(start, getEndPoint(start))) // 출발점과 도착점을 Point로 묶음 .collect(Collectors.toList()); } diff --git a/src/main/java/ladder/model/Results.java b/src/main/java/ladder/model/LadderResult.java similarity index 52% rename from src/main/java/ladder/model/Results.java rename to src/main/java/ladder/model/LadderResult.java index 14ca31c3..b0d41b59 100644 --- a/src/main/java/ladder/model/Results.java +++ b/src/main/java/ladder/model/LadderResult.java @@ -3,29 +3,29 @@ import java.util.ArrayList; import java.util.List; -public class Results { +public class LadderResult { private final Participants participants; - private final List results; + private final List results; - public Results(Participants participants, List results) { + public LadderResult(Participants participants, List results) { this.participants = participants; this.results = results; } - public List getAll() { + public List getAll() { return new ArrayList<>(results); } public List getParticipants() { - return participants.values(); + return participants.getParticipantsNameList(); } - public String getResult(String participant) { - return participants.values().stream() + public Result getResult(String participant) { + return participants.getParticipantsNameList().stream() .filter(name -> name.matches(participant)) .findFirst() - .map(name -> results.get(participants.values().indexOf(name))) + .map(name -> results.get(participants.getParticipantsNameList().indexOf(name))) .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 참가자입니다.")); } } diff --git a/src/main/java/ladder/model/Line.java b/src/main/java/ladder/model/Line.java index 74076efd..a29039e6 100644 --- a/src/main/java/ladder/model/Line.java +++ b/src/main/java/ladder/model/Line.java @@ -3,11 +3,10 @@ import java.util.ArrayList; import java.util.List; import java.util.Random; -import java.util.stream.Collectors; -import java.util.stream.IntStream; public class Line { + private static final Random random = new Random(); private final List points; private Line(List points) { @@ -19,32 +18,23 @@ public List getPoints() { } public static Line create(int width) { - Random random = new Random(); - List points = new ArrayList<>(); - return new Line(IntStream.range(0, width - 1) - .mapToObj(i -> shouldConnect(points, i, random)) - .collect(Collectors.toList())); - } - - private static boolean shouldConnect(List points, int index, Random random) { - boolean connection = (index <= 0 || !points.get(index - 1)) && random.nextBoolean(); - points.add(connection); - return connection; - } - - public void draw() { - for (Boolean point : points) { - System.out.print("|"); - printLine(point); + List connections = new ArrayList<>(); + for (int i = 0; i < width - 1; i++) { + // 새로운 라인 연결 여부 + boolean shouldConnect = isConnectable(i, connections); + connections.add(shouldConnect); } - System.out.println("|"); + return new Line(connections); } - private void printLine(Boolean connected) { - if (connected) { - System.out.print("-----"); - return; + private static boolean isConnectable(int currentIndex, List connections) { + // 첫 번째 위치라면? 바로 Random 값 설정 + if (currentIndex == 0) { + return random.nextBoolean(); } - System.out.print(" "); + + // 바로 이전 연결 여부를 확인 -> 연속된 라인(true) 방지 + boolean previousConnected = connections.get(currentIndex - 1); + return !previousConnected && new Random().nextBoolean(); } } diff --git a/src/main/java/ladder/model/Name.java b/src/main/java/ladder/model/Name.java index d2846c18..6268998a 100644 --- a/src/main/java/ladder/model/Name.java +++ b/src/main/java/ladder/model/Name.java @@ -1,18 +1,42 @@ package ladder.model; +import java.util.Objects; + public class Name { private static final int MAX_LENGTH = 5; - private final String name; + private final String value; - public Name(String name) { - if (name.length() > MAX_LENGTH) { + public Name(String value) { + if (value.length() > MAX_LENGTH) { throw new IllegalArgumentException("이름은 최대 5글자까지 가능합니다."); } - this.name = name; + this.value = value; } public boolean matches(String other) { - return name.equals(other); + return value.equals(other); + } + + @Override + public String toString() { + return value; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Name name = (Name) o; + return Objects.equals(value, name.value); + } + + @Override + public int hashCode() { + return Objects.hash(value); } } diff --git a/src/main/java/ladder/model/Participants.java b/src/main/java/ladder/model/Participants.java index 00f230c0..5e3f694b 100644 --- a/src/main/java/ladder/model/Participants.java +++ b/src/main/java/ladder/model/Participants.java @@ -1,9 +1,7 @@ package ladder.model; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; -import java.util.stream.Collectors; public class Participants { @@ -13,20 +11,15 @@ private Participants(List names) { this.names = names; } - public static Participants from(String input) { - return new Participants( - Arrays.stream(input.split(",")) - .map(String::trim) - .map(Name::new) - .collect(Collectors.toList()) - ); + public static Participants of(List names) { + return new Participants(new ArrayList<>(names)); } public int size() { return names.size(); } - public List values() { + public List getParticipantsNameList() { return new ArrayList<>(names); } } diff --git a/src/main/java/ladder/model/Point.java b/src/main/java/ladder/model/Point.java new file mode 100644 index 00000000..51c3d3c7 --- /dev/null +++ b/src/main/java/ladder/model/Point.java @@ -0,0 +1,44 @@ +package ladder.model; + +import java.util.Objects; + +public class Point { + + private final int start; + private final int end; + + public Point(int start, int end) { + this.start = start; + this.end = end; + } + + public int getStart() { + return start; + } + + public int getEnd() { + return end; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Point point = (Point) o; + return start == point.start && end == point.end; + } + + @Override + public int hashCode() { + return Objects.hash(start, end); + } + + @Override + public String toString() { + return "Point{" + "start=" + start + ", end=" + end + '}'; + } +} diff --git a/src/main/java/ladder/model/Result.java b/src/main/java/ladder/model/Result.java new file mode 100644 index 00000000..d30fdff1 --- /dev/null +++ b/src/main/java/ladder/model/Result.java @@ -0,0 +1,31 @@ +package ladder.model; + +public class Result { + + private final String value; + + public Result(String value) { + if (value == null || value.isBlank()) { + throw new IllegalArgumentException("결과 값은 비어있을 수 없습니다."); + } + this.value = value; + } + + @Override + public String toString() { + return value; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Result result = (Result) o; + return value.equals(result.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } +} diff --git a/src/main/java/ladder/model/ResultType.java b/src/main/java/ladder/model/ResultType.java deleted file mode 100644 index f08e03b6..00000000 --- a/src/main/java/ladder/model/ResultType.java +++ /dev/null @@ -1,16 +0,0 @@ -package ladder.model; - -public enum ResultType { - ALL("all"), - SINGLE(""); - - private final String value; - - ResultType(String value) { - this.value = value; - } - - public static ResultType from(String input) { - return "all".equals(input) ? ALL : SINGLE; - } -} diff --git a/src/main/java/ladder/view/InputView.java b/src/main/java/ladder/view/InputView.java index 50454e97..00dc549f 100644 --- a/src/main/java/ladder/view/InputView.java +++ b/src/main/java/ladder/view/InputView.java @@ -3,22 +3,32 @@ import java.util.Arrays; import java.util.List; import java.util.Scanner; +import java.util.stream.Collectors; +import ladder.model.Name; import ladder.model.Participants; +import ladder.model.Result; public class InputView { - private static final Scanner scanner = new Scanner(System.in); + private final Scanner scanner = new Scanner(System.in); public Participants inputParticipants() { System.out.println("참여할 사람 이름을 입력하세요. (이름은 쉼표(,)로 구분하세요)"); String input = scanner.nextLine(); - return Participants.from(input); + List names = Arrays.stream(input.split(",")) + .map(String::trim) + .map(Name::new) + .collect(Collectors.toList()); + return Participants.of(names); } - public List inputResults() { + public List inputResults() { System.out.println("\n실행 결과를 입력하세요. (결과는 쉼표(,)로 구분하세요)"); String input = scanner.nextLine(); - return Arrays.asList(input.split(",")); + return Arrays.stream(input.split(",")) + .map(String::trim) + .map(Result::new) + .collect(Collectors.toList()); } public int inputHeight() { diff --git a/src/main/java/ladder/view/OutputView.java b/src/main/java/ladder/view/OutputView.java index f9ac9319..98f2af03 100644 --- a/src/main/java/ladder/view/OutputView.java +++ b/src/main/java/ladder/view/OutputView.java @@ -2,42 +2,64 @@ import java.util.List; import java.util.stream.IntStream; +import ladder.model.LadderResult; import ladder.model.Ladder; +import ladder.model.Line; import ladder.model.Name; import ladder.model.Participants; -import ladder.model.Results; +import ladder.model.Result; public class OutputView { - public void printLadder(Ladder ladder, Participants participants, List results) { + public void printLadder(Ladder ladder, Participants participants, List results) { System.out.println("\n사다리 결과\n"); printParticipants(participants); - ladder.draw(); + printLadderLines(ladder); printResults(results); } private void printParticipants(Participants participants) { - System.out.print(" "); - for (Name name : participants.values()) { + for (Name name : participants.getParticipantsNameList()) { System.out.printf("%-6s", name); } System.out.println(); } - public void printResults(List results) { - System.out.print(" "); - for (String result : results) { + private void printLadderLines(Ladder ladder) { + for (Line line : ladder.getLines()) { + printLine(line); + } + } + + private void printLine(Line line) { + for (Boolean point : line.getPoints()) { + System.out.print("|"); + printLineSegment(point); + } + System.out.println("|"); + } + + private void printLineSegment(Boolean connected) { + if (connected) { + System.out.print("-----"); + return; + } + System.out.print(" "); + } + + public void printResults(List results) { + for (Result result : results) { System.out.printf("%-6s", result); } System.out.println("\n"); } - public void printSingleResult(String result) { + public void printSingleResult(Result result) { System.out.println("\n실행 결과"); System.out.println(result); } - public void printAllResults(Results results) { + public void printAllResults(LadderResult results) { System.out.println("\n실행 결과"); IntStream.range(0, results.getParticipants().size()) .forEach(i -> System.out.printf("%s : %s%n", diff --git a/src/test/java/ladder/LadderTest.java b/src/test/java/ladder/LadderTest.java index a5e23020..fe58bc91 100644 --- a/src/test/java/ladder/LadderTest.java +++ b/src/test/java/ladder/LadderTest.java @@ -4,19 +4,48 @@ import java.util.List; import ladder.model.Ladder; +import ladder.model.Point; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; public class LadderTest { @Test - @DisplayName("사다리 생성") + @DisplayName("입력받은 넓이와 높이대로 사다리가 생성되어야한다.") void generateLadder() { + // given + int width = 4; // 넓이 + int height = 5; // 높이 + + // when + Ladder ladder = Ladder.create(width, height); + + // then + assertThat(ladder.getLines()).hasSize(height); // 높이에 맞게 생성되었는지 확인 + + // 각 Line의 너비 확인 (width - 1개의 Boolean 리스트여야 함) + ladder.getLines().forEach(line -> + assertThat(line.getPoints()).hasSize(width - 1) + ); + + } + + @Test + @DisplayName("사다리 게임의 결과를 확인한다.") + void getLadderResult() { + // given Ladder ladder = Ladder.create(4, 5); - List results = ladder.result(); - assertThat(results).hasSize(4); - assertThat(results) - .allMatch(position -> position >= 0 && position < 4); + // when + List results = ladder.result(); + + // then + assertThat(results).hasSize(4); // 참가자 수 = 결과가 나와야 한다. + + // 각 결과의 출발점과 도착점 검사 + for (int i = 0; i < results.size(); i++) { + assertThat(results.get(i).getStart()).isEqualTo(i); // 출발점이 i와 같음 + assertThat(results.get(i).getEnd()).isBetween(0, 3); // 도착점은 [0, 3](넓이 값) 사이 + } } } diff --git a/src/test/java/ladder/LineTest.java b/src/test/java/ladder/LineTest.java index 486018cc..2dad6ead 100644 --- a/src/test/java/ladder/LineTest.java +++ b/src/test/java/ladder/LineTest.java @@ -10,13 +10,32 @@ public class LineTest { @Test - @DisplayName("라인 생성") - void generateLine() { - Line line = Line.create(4); + @DisplayName("라인이 넓이에 따라 정확히 생성돼야한다") + void generateLineWithWidth() { + int width = 5; + Line line = Line.create(width); + List points = line.getPoints(); + assertThat(points).hasSize(width - 1); // 연결 여부는 width-1 사이즈여야 함 + } + + @Test + @DisplayName("라인을 연결할 때 연속된 true가 나오지 않는다") + void validateNoConsecutiveTrueConnections() { - assertThat(points).hasSize(3); // width-1 개 포인트 - assertThat(points) - .doesNotContainSequence(true, true); // 연속된 true가 XXX + /* + * 사다리 타기가 정상적으로 동작하려면 라인이 겹치지 않도록 해야 한다. + * |-----|-----| 모양과 같이 가로 라인이 겹치는 경우 + * 어느 방향으로 이동할지 결정할 수 없다. + * */ + + int width = 5; + Line line = Line.create(width); + + List points = line.getPoints(); + for (int i = 0; i < points.size() - 1; i++) { + assertThat(points.get(i) && points.get(i + 1)) + .isFalse(); + } } } diff --git a/src/test/java/ladder/ParticipantsTest.java b/src/test/java/ladder/ParticipantsTest.java index 862353dc..4258af11 100644 --- a/src/test/java/ladder/ParticipantsTest.java +++ b/src/test/java/ladder/ParticipantsTest.java @@ -2,6 +2,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import java.util.Arrays; import java.util.List; import ladder.model.Name; import ladder.model.Participants; @@ -11,14 +12,19 @@ public class ParticipantsTest { @Test - @DisplayName("참가자 생성") + @DisplayName("참가자 List을 통해서 Participants를 생성해야한다.") void generateParticipants() { - Participants participants = Participants.from("pobi,jason,brown"); - List names = participants.values(); + List names = Arrays.asList( + new Name("pobi"), + new Name("jason"), + new Name("brown") + ); + Participants participants = Participants.of(names); assertThat(participants.size()).isEqualTo(3); - assertThat(names.get(0).matches("pobi")).isTrue(); - assertThat(names.get(1).matches("jason")).isTrue(); - assertThat(names.get(2).matches("brown")).isTrue(); + assertThat(participants.getParticipantsNameList().get(0).matches("pobi")).isTrue(); + assertThat(participants.getParticipantsNameList().get(1).matches("jason")).isTrue(); + assertThat(participants.getParticipantsNameList().get(2).matches("brown")).isTrue(); + } }