diff --git a/src/main/java/ladder/LadderGameController.java b/src/main/java/ladder/LadderGameController.java new file mode 100644 index 0000000000..fbabbaf3f0 --- /dev/null +++ b/src/main/java/ladder/LadderGameController.java @@ -0,0 +1,33 @@ +package ladder; + +import ladder.domain.ladder.Ladder; +import ladder.domain.player.Players; +import ladder.view.input.ConsoleInputView; +import ladder.view.input.InputView; +import ladder.view.output.OutputView; + +public class LadderGameController { + + private final InputView inputView; + private final OutputView outputView; + + public LadderGameController(InputView inputView, OutputView outputView) { + this.inputView = inputView; + this.outputView = outputView; + } + + public static void main(String[] args) { + LadderGameController game = new LadderGameController(new ConsoleInputView(), new OutputView()); + game.run(); + } + + private void run() { + String inputNames = inputView.inputPlayerNames(); + Players players = new Players(inputNames); + + int height = inputView.inputLadderHeight(); + Ladder ladder = new Ladder(height, players.count()); + + outputView.printResult(players, ladder); + } +} diff --git a/src/main/java/ladder/README.md b/src/main/java/ladder/README.md new file mode 100644 index 0000000000..fcc32481a6 --- /dev/null +++ b/src/main/java/ladder/README.md @@ -0,0 +1,34 @@ +## 2단계 - 사다리(생성) + +### 기능 요구사항 +- 사다리 게임에 참여하는 사람에 이름을 최대5글자까지 부여할 수 있다. 사다리를 출력할 때 사람 이름도 같이 출력한다. +- 사람 이름은 쉼표(,)를 기준으로 구분한다. +- 사람 이름을 5자 기준으로 출력하기 때문에 사다리 폭도 넓어져야 한다. +- 사다리 타기가 정상적으로 동작하려면 라인이 겹치지 않도록 해야 한다. + - `|-----|-----|` 모양과 같이 가로 라인이 겹치는 경우 어느 방향으로 이동할지 결정할 수 없다. + + +### 프로그래밍 요구사항 + +- 자바 8의 스트림과 람다를 적용해 프로그래밍한다. +- 규칙 6: 모든 엔티티를 작게 유지한다. + +### 실행 결과 +위 요구사항에 따라 4명의 사람을 위한 5개 높이 사다리를 만들 경우, 프로그램을 실행한 결과는 다음과 같다. + +``` +참여할 사람 이름을 입력하세요. (이름은 쉼표(,)로 구분하세요) +pobi,honux,crong,jk + +최대 사다리 높이는 몇 개인가요? +5 + +실행결과 + +pobi honux crong jk + |-----| |-----| + | |-----| | + |-----| | | + | |-----| | + |-----| |-----| +``` diff --git a/src/main/java/ladder/domain/ladder/Ladder.java b/src/main/java/ladder/domain/ladder/Ladder.java new file mode 100644 index 0000000000..bfb56197cf --- /dev/null +++ b/src/main/java/ladder/domain/ladder/Ladder.java @@ -0,0 +1,19 @@ +package ladder.domain.ladder; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.IntStream; + +public class Ladder { + private final List lines; + + public Ladder(int height, int countOfPlayers) { + lines = new ArrayList<>(); + IntStream.range(0, height) + .forEach(i -> lines.add(new Line(countOfPlayers))); + } + + public List getLines() { + return lines; + } +} diff --git a/src/main/java/ladder/domain/ladder/Line.java b/src/main/java/ladder/domain/ladder/Line.java new file mode 100644 index 0000000000..b04ba750a1 --- /dev/null +++ b/src/main/java/ladder/domain/ladder/Line.java @@ -0,0 +1,29 @@ +package ladder.domain.ladder; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Line { + private final List points; + + public Line(int countOfPlayers) { + int numberOfPoints = countOfPlayers - 1; + this.points = initializePoints(numberOfPoints); + } + + private List initializePoints(int numberOfPoints) { + boolean previousHasLine = false; + List points = new ArrayList<>(); + for (int i = 0; i < numberOfPoints; i++) { + Point point = Point.create(previousHasLine); + points.add(point); + previousHasLine = point.hasLine(); + } + return Collections.unmodifiableList(points); + } + + public List getPoints() { + return points; + } +} diff --git a/src/main/java/ladder/domain/ladder/Point.java b/src/main/java/ladder/domain/ladder/Point.java new file mode 100644 index 0000000000..c32a541d3f --- /dev/null +++ b/src/main/java/ladder/domain/ladder/Point.java @@ -0,0 +1,18 @@ +package ladder.domain.ladder; + +public class Point { + private final boolean hasLine; + + public Point(boolean hasLine) { + this.hasLine = hasLine; + } + + public boolean hasLine() { + return hasLine; + } + + public static Point create(boolean previousHasLine) { + if (previousHasLine) return new Point(false); + return new Point(Math.random() > 0.5); + } +} diff --git a/src/main/java/ladder/domain/player/Player.java b/src/main/java/ladder/domain/player/Player.java new file mode 100644 index 0000000000..7a7d9a6a42 --- /dev/null +++ b/src/main/java/ladder/domain/player/Player.java @@ -0,0 +1,17 @@ +package ladder.domain.player; + +public class Player { + private static final int MAX_NAME_LENGTH = 5; + private final String name; + + public Player(String name) { + if (name.length() > MAX_NAME_LENGTH) { + throw new IllegalArgumentException("이름은 최대 5자까지 가능합니다."); + } + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/ladder/domain/player/Players.java b/src/main/java/ladder/domain/player/Players.java new file mode 100644 index 0000000000..797f37cc53 --- /dev/null +++ b/src/main/java/ladder/domain/player/Players.java @@ -0,0 +1,26 @@ +package ladder.domain.player; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class Players { + private static final String DELIMITER_COMMA = ","; + + private final List players; + + public Players(String input) { + this.players = Arrays.stream(input.split(DELIMITER_COMMA)) + .map(String::trim) + .map(Player::new) + .collect(Collectors.toList()); + } + + public int count() { + return players.size(); + } + + public List getPlayers() { + return players; + } +} diff --git a/src/main/java/ladder/view/input/BaseInputView.java b/src/main/java/ladder/view/input/BaseInputView.java new file mode 100644 index 0000000000..0f42246b76 --- /dev/null +++ b/src/main/java/ladder/view/input/BaseInputView.java @@ -0,0 +1,4 @@ +package ladder.view.input; + +public abstract class BaseInputView implements InputView { +} diff --git a/src/main/java/ladder/view/input/ConsoleInputView.java b/src/main/java/ladder/view/input/ConsoleInputView.java new file mode 100644 index 0000000000..6a3ee81a60 --- /dev/null +++ b/src/main/java/ladder/view/input/ConsoleInputView.java @@ -0,0 +1,24 @@ +package ladder.view.input; + +import java.util.Scanner; + +public class ConsoleInputView extends BaseInputView { + private static final Scanner scanner = new Scanner(System.in); + + @Override + public String read() { + return scanner.nextLine(); + } + + @Override + public String inputPlayerNames() { + System.out.println("참여할 사람 이름을 입력하세요. (이름은 쉼표(,)로 구분하세요)"); + return read(); + } + + @Override + public int inputLadderHeight() { + System.out.println("최대 사다리 높이는 몇 개인가요?"); + return Integer.parseInt(read()); + } +} diff --git a/src/main/java/ladder/view/input/InputView.java b/src/main/java/ladder/view/input/InputView.java new file mode 100644 index 0000000000..89003d96ef --- /dev/null +++ b/src/main/java/ladder/view/input/InputView.java @@ -0,0 +1,7 @@ +package ladder.view.input; + +public interface InputView { + String read(); + String inputPlayerNames(); + int inputLadderHeight(); +} diff --git a/src/main/java/ladder/view/output/OutputView.java b/src/main/java/ladder/view/output/OutputView.java new file mode 100644 index 0000000000..e93f5c27f2 --- /dev/null +++ b/src/main/java/ladder/view/output/OutputView.java @@ -0,0 +1,36 @@ +package ladder.view.output; + +import ladder.domain.ladder.Ladder; +import ladder.domain.ladder.Line; +import ladder.domain.ladder.Point; +import ladder.domain.player.Players; + +public class OutputView { + + public static void printResult(Players players, Ladder ladder) { + System.out.println("\n실행결과\n"); + + printPlayerNames(players); + printLadder(ladder); + } + + private static void printPlayerNames(Players players) { + players.getPlayers() + .forEach(p -> System.out.printf("%-6s", p.getName())); + System.out.println(); + } + + private static void printLadder(Ladder ladder) { + ladder.getLines().forEach(OutputView::printLine); + } + + private static void printLine(Line line) { + StringBuilder sb = new StringBuilder(); + for (Point point : line.getPoints()) { + sb.append("|").append(point.hasLine() ? "-----" : " "); + } + sb.append("|"); + System.out.println(sb); + } + +} diff --git a/src/test/java/ladder/domain/player/PlayerTest.java b/src/test/java/ladder/domain/player/PlayerTest.java new file mode 100644 index 0000000000..d601abfa94 --- /dev/null +++ b/src/test/java/ladder/domain/player/PlayerTest.java @@ -0,0 +1,26 @@ +package ladder.domain.player; + +import ladder.view.fake.FakeInputView; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + +class PlayerTest { + + @Test + @DisplayName("참여자의 이름이 5글자가 넘으면 예외가 발생한다.") + void getPlayerName() { + FakeInputView inputView = new FakeInputView("yeseul"); + assertThatThrownBy(() -> new Player(inputView.inputPlayerNames())) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("참여자의 이름은 쉼표가 아닌 다른 구분자가 사용되면 예외가 발생한다.") + void getSplitter() { + FakeInputView inputView = new FakeInputView("yeseul,pobi|crong"); + assertThatThrownBy(() -> new Players(inputView.inputPlayerNames())) + .isInstanceOf(IllegalArgumentException.class); + } +} diff --git a/src/test/java/ladder/view/fake/FakeInputView.java b/src/test/java/ladder/view/fake/FakeInputView.java new file mode 100644 index 0000000000..b77941de12 --- /dev/null +++ b/src/test/java/ladder/view/fake/FakeInputView.java @@ -0,0 +1,27 @@ +package ladder.view.fake; + +import ladder.view.input.BaseInputView; + +public class FakeInputView extends BaseInputView { + + private final String input; + + public FakeInputView(String input) { + this.input = input; + } + + @Override + public String read() { + return input.trim(); + } + + @Override + public String inputPlayerNames() { + return this.input; + } + + @Override + public int inputLadderHeight() { + return Integer.parseInt(this.input); + } +}