-
Notifications
You must be signed in to change notification settings - Fork 60
[그리디] 김지우 사다리 미션 제출합니다. #50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: ji-woo-kim
Are you sure you want to change the base?
Changes from 10 commits
5ff0798
6aa9170
d330a53
5b2aea1
b074532
b44fff5
e159f80
130ed3c
6e94082
b295f2a
e708075
37f13b4
8c728c7
8f398df
72751c3
495dccc
b1c8c29
4c28612
fe5128b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| # 🪜 사다리 타기 게임 | ||
| 참가자의 이름과 원하는 결과를 입력하면 랜덤한 사다리를 생성하고, | ||
| 각 사람이 어떤 결과에 도착하는지 확인할 수 있는 **사다리 게임**입니다. | ||
|
|
||
| --- | ||
|
|
||
| ## 🕹️ 사용 방법 | ||
|
|
||
| ### 1. 참여자 이름 입력 | ||
| - 최대 5글자까지 입력 가능합니다. | ||
| - 이름은 쉼표 `,`로 구분해서 입력해야 합니다. | ||
| - 입력한 순서대로 사다리 시작 위치가 지정됩니다. | ||
|
|
||
| ### 2. 실행 결과 입력 | ||
| - 참여자 수와 같은 개수의 결과 입력해주세요. | ||
| - 순서는 이름과 일치해야 합니다. | ||
| - 입력한 순서대로 실행 결과 위치가 지정됩니다. | ||
|
|
||
| ### 3. 사다리 높이 입력 | ||
| - 사다리의 세로 줄 수를 숫자로 입력해주세요. | ||
|
|
||
| ### 4. 생성된 사다리 확인 | ||
| - 각 참여자의 시작 지점, 실행 결과 위치가 출력됩니다. | ||
|
|
||
| ### 5. 결과 확인 | ||
|
|
||
| - 특정 이름을 입력하면 해당 사람의 결과가 출력됩니다. | ||
| - `"all"`을 입력하면 전체 결과를 한 번에 확인할 수 있습니다. | ||
| - `"all"`을 입력하면 모든 참여자의 최종 결과를 출력하고 프로그램이 종료됩니다. | ||
|
|
||
| --- | ||
| ## 🖥️ 실행 예시 | ||
| ``` | ||
| 참여할 사람 이름을 입력하세요. (이름은 쉼표(,)로 구분하세요) | ||
| neo,brown,brie,tommy | ||
|
|
||
| 실행 결과를 입력하세요. (결과는 쉼표(,)로 구분하세요) | ||
| 꽝,5000,꽝,3000 | ||
|
|
||
| 최대 사다리 높이는 몇 개인가요? | ||
| 5 | ||
|
|
||
| 사다리 결과 | ||
|
|
||
| neo brown brie tommy | ||
| |-----| |-----| | ||
| | |-----| | | ||
| |-----| | | | ||
| | |-----| | | ||
| |-----| |-----| | ||
| 꽝 5000 꽝 3000 | ||
|
|
||
| 결과를 보고 싶은 사람은? | ||
| neo | ||
|
|
||
| 실행 결과 | ||
| 꽝 | ||
|
|
||
| 결과를 보고 싶은 사람은? | ||
| all | ||
|
|
||
| 실행 결과 | ||
| neo : 꽝 | ||
| brown : 3000 | ||
| brie : 꽝 | ||
| tommy : 5000 | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| import controller.LadderController; | ||
| import view.InputView; | ||
| import view.OutputView; | ||
|
|
||
| public class LadderApplication { | ||
|
|
||
| public static void main(String[] args) { | ||
| InputView inputview = new InputView(); | ||
| OutputView outputview = new OutputView(); | ||
|
|
||
| LadderController ladderController = new LadderController(inputview, outputview); | ||
| ladderController.run(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| package controller; | ||
|
|
||
| import domain.Height; | ||
| import domain.Ladder; | ||
| import domain.Width; | ||
| import view.InputView; | ||
| import view.OutputView; | ||
|
|
||
| import java.util.List; | ||
| import java.util.Random; | ||
|
|
||
| public class LadderController { | ||
|
|
||
| private final InputView inputView; | ||
| private final OutputView outputView; | ||
|
|
||
| public LadderController(InputView inputView, OutputView outputView) { | ||
| this.inputView = inputView; | ||
| this.outputView = outputView; | ||
| } | ||
|
Comment on lines
+13
to
+19
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. View를 생성자 매개변수로 받아 의존성을 확실하게 표현해주고 있는 점이 좋은 것 같아요 |
||
|
|
||
| public void run() { | ||
| List<String> playerNames = readValidatedPlayerNames(); | ||
| List<String> gameResults = readValidatedGameResults(playerNames.size()); | ||
|
|
||
| Width width = new Width(playerNames.size()); | ||
| Height height = inputView.readHeight(); | ||
| Ladder ladder = Ladder.generate(width, height, new Random()); | ||
| outputView.printLadder(playerNames, ladder, gameResults); | ||
|
|
||
| String request = inputView.readResultRequest(); | ||
| handleResultRequest(request, playerNames, ladder, gameResults); | ||
| } | ||
|
|
||
| private List<String> readValidatedPlayerNames() { | ||
| List<String> names = inputView.readPlayerNames(); | ||
| for (String name : names) { | ||
| if (name.isEmpty() || name.length() > 5) { | ||
| throw new IllegalArgumentException("참여자 이름은 1자 이상 5자 이하여야 합니다: " + name); | ||
| } | ||
| } | ||
| return names; | ||
| } | ||
|
|
||
| private List<String> readValidatedGameResults(int expectedSize) { | ||
| List<String> results = inputView.readGameResults(); | ||
| if (results.size() != expectedSize) { | ||
| throw new IllegalArgumentException("이름과 결과의 개수가 일치하지 않습니다."); | ||
| } | ||
| return results; | ||
| } | ||
|
||
|
|
||
| private void handleResultRequest(String request, List<String> names, Ladder ladder, List<String> results) { | ||
| while (!request.equals("all")) {// 입력이 'all'이 아닐 때 | ||
| try { | ||
| int playerIndex = getValidPlayerIndex(request, names); | ||
| outputView.printSingleResult( | ||
| names.get(playerIndex), | ||
| results.get(ladder.getFinalPosition(playerIndex)) | ||
| ); | ||
| } catch (IllegalArgumentException e) { | ||
| System.out.println("잘못된 이름입니다. 다시 입력해주세요."); | ||
| } | ||
| request = inputView.readResultRequest(); | ||
| } | ||
| // 'all' 입력될 때 | ||
| outputView.printAllResults(names, results, ladder); | ||
| } | ||
|
||
|
|
||
| private int getValidPlayerIndex(String name, List<String> names) { | ||
| int index = names.indexOf(name); | ||
| if (index == -1) { | ||
| throw new IllegalArgumentException("잘못된 이름입니다: " + name); | ||
| } | ||
| return index; | ||
| } | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Height, Width가 잘 포장되어있네요! 👍 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package domain; | ||
|
|
||
| public record Height(int value) { | ||
|
|
||
| private static final int MIN_HEIGHT_VALUE = 1; | ||
|
|
||
| public Height { | ||
| if (value < MIN_HEIGHT_VALUE) { | ||
| throw new IllegalArgumentException("사다리의 높이는 1 이상이어야 합니다."); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| package domain; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import java.util.Random; | ||
|
|
||
| public class Ladder { | ||
|
|
||
| private final List<Line> lines; | ||
| private final Width width; | ||
|
|
||
| public Ladder(List<Line> lines, Width width) { | ||
| this.lines = lines; | ||
| this.width = width; | ||
| } | ||
|
|
||
| public static Ladder generate(Width width, Height height, Random random) { | ||
| List<Line> lines = new ArrayList<>(); | ||
| for (int i = 0; i < height.value(); i++) { | ||
| Line line = new Line(width); | ||
| line.connect(random); | ||
| lines.add(line); | ||
| } | ||
| return new Ladder(lines, width); | ||
| } | ||
|
||
|
|
||
| public int getFinalPosition(int startPosition) { | ||
| int currentPosition = startPosition; | ||
| for (Line line : lines) { | ||
| currentPosition = moveToNextPosition(currentPosition, line); | ||
| } | ||
| return currentPosition; | ||
| } | ||
|
|
||
| private int moveToNextPosition(int currentPosition, Line line) { | ||
| List<Point> points = line.getPoints(); | ||
|
|
||
| if (canMoveLeft(currentPosition, points)) { | ||
| return currentPosition - 1; | ||
| } | ||
| if (canMoveRight(currentPosition, points)) { | ||
| return currentPosition + 1; | ||
| } | ||
| return currentPosition; | ||
| } | ||
|
|
||
| private boolean canMoveLeft(int currentPosition, List<Point> points) { | ||
| return currentPosition > 0 && points.get(currentPosition - 1).isConnectedToRight(); | ||
| } | ||
|
|
||
| private boolean canMoveRight(int currentPosition, List<Point> points) { | ||
| return currentPosition < points.size() - 1 && points.get(currentPosition).isConnectedToRight(); | ||
| } | ||
|
||
|
|
||
| public List<Line> getLines() { | ||
| return lines; | ||
| } | ||
|
|
||
| public Width getWidth() { | ||
| return width; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| package domain; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import java.util.Random; | ||
|
|
||
| public class Line { | ||
|
|
||
| private final List<Point> points; | ||
|
|
||
| public Line(Width width) { | ||
| points = new ArrayList<>(); | ||
| for (int i = 0; i < width.value(); i++) { | ||
| points.add(new Point()); | ||
| } | ||
| } | ||
|
|
||
| public void connect(Random random) { | ||
| for (int i = 0; i < points.size() - 1; i++) { // 가로줄 겹침 방지 | ||
| if (i > 0 && points.get(i - 1).isConnectedToRight()) { | ||
| continue; | ||
| } | ||
| if (random.nextBoolean()) { | ||
| points.get(i).connectToRight(); | ||
| points.get(i + 1).connectToLeft(); | ||
| } | ||
| } | ||
| } | ||
|
||
|
|
||
| public List<Point> getPoints() { | ||
| return points; | ||
| } | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Point 클래스는 사다리 클래스를 만들기 위해 아마 가장 깔끔한 구성인 것 같아요! 다른 리뷰에서 언급드렸듯이 enum을 적용하면 미션 요구사항도 맞추고 조금 더 직관적인 코드를 만들 수 있을 것 같습니다! |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package domain; | ||
|
|
||
| public class Point { | ||
|
|
||
| private boolean connectedToRight; | ||
| private boolean connectedToLeft; | ||
|
|
||
| public Point() { | ||
| this.connectedToRight = false; | ||
| this.connectedToLeft = false; | ||
| } | ||
|
|
||
| public boolean isConnectedToRight() { | ||
| return connectedToRight; | ||
| } | ||
|
|
||
| public void connectToRight() { | ||
| this.connectedToRight = true; | ||
| } | ||
|
|
||
| public void connectToLeft() { | ||
| this.connectedToLeft = true; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package domain; | ||
|
|
||
| public record Width(int value) { | ||
|
|
||
| private static final int MIN_WIDTH_VALUE = 1; | ||
|
|
||
| public Width { | ||
| if (value < MIN_WIDTH_VALUE) { | ||
| throw new IllegalArgumentException("사다리의 넓이는 1 이상이어야 합니다."); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| package view; | ||
|
|
||
| import domain.Height; | ||
| import domain.Width; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Arrays; | ||
| import java.util.List; | ||
| import java.util.Scanner; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| public class InputView { | ||
|
|
||
| private static final Scanner scanner = new Scanner(System.in); | ||
|
|
||
| public List<String> readPlayerNames() { | ||
| System.out.println("참여할 사람 이름을 입력하세요. (이름은 쉼표(,)로 구분하세요): "); | ||
|
|
||
| String userInput = scanner.nextLine(); | ||
| return Arrays.stream(userInput.split(",")) | ||
| .map(String::trim) | ||
| .filter(name -> !name.isEmpty()) | ||
| .collect(Collectors.toList()); | ||
|
Comment on lines
+18
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 콤마 사이에 빈 값이 있을 경우 아예 입력에서 없애도록 하셨네요! 프로그램이 멈춰버리는 상황을 피하기 위한 좋은 방법인 것 같아요. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 부분이 예외로 처리할지 시스템 자동적으로 처리할지에 대한 고민의 결과로 나온 것이 아니라 제가 코드 하나하나에 생각보다 많은 판단을 하지 않고 넘어가는 것 같아 반성하게 되네요 ㅜㅜ
이 질문에 대해 고민해 본 결과 다음과 같은 생각을 하게 됐습니다: 지환님의 의견도 궁금해지는 부분이네요..! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 네 저도 공백정도는 처리하고 넘어가는 것이 좋다고 생각해요! 하지만 특정 상황에 있어서는 사용자의 인지 없이 입력값을 변경하는 것이 위험을 초래할 수 있다고는 생각하는 편이었어요! 사실 그냥 없애도 되고... 가장 좋은 방법은 없애고 난 뒤 사용자에게 따로 고지하는 방법도 좋다고 생각해요 여러가지 의견이 나와서 좋네요! |
||
| } | ||
|
|
||
| public List<String> readGameResults() { | ||
| System.out.println(); | ||
| System.out.println("실행 결과를 입력하세요. (결과는 쉼표(,)로 구분하세요): "); | ||
|
|
||
| String userInput = scanner.nextLine(); | ||
| return new ArrayList<>(Arrays.asList(userInput.split(","))); | ||
| } | ||
|
|
||
| public Height readHeight() { | ||
| System.out.println(); | ||
| System.out.println("최대 사다리 높이는 몇 개인가요?"); | ||
| int height = scanner.nextInt(); | ||
| scanner.nextLine(); | ||
| return new Height(height); | ||
| } | ||
|
|
||
| public String readResultRequest() { | ||
| System.out.println(); | ||
| System.out.println("결과를 보고 싶은 사람은?"); | ||
| return scanner.nextLine().trim(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| package view; | ||
|
|
||
| import domain.Ladder; | ||
| import domain.Line; | ||
| import domain.Point; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public class LadderPrinter { | ||
|
|
||
| private static final int CONNECTION_WIDTH = 5; | ||
|
|
||
| public void printLadder(Ladder ladder) { | ||
| int width = ladder.getWidth().value(); | ||
| for (Line line : ladder.getLines()) { | ||
| printLine(line, width); | ||
| } | ||
| } | ||
|
|
||
| private void printLine(Line line, int width) { | ||
| StringBuilder lineBuilder = new StringBuilder(); | ||
| List<Point> points = line.getPoints(); | ||
|
|
||
| for (int i = 0; i < width; i++) { | ||
| lineBuilder.append("|"); | ||
| lineBuilder.append(printConnection(points, i)); | ||
| } | ||
|
|
||
| System.out.println(lineBuilder); | ||
| } | ||
|
|
||
| private String printConnection(List<Point> points, int i) { | ||
| if (i < points.size() && points.get(i).isConnectedToRight()) { | ||
| return "-".repeat(CONNECTION_WIDTH); | ||
| } | ||
| return " ".repeat(CONNECTION_WIDTH); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
README를 잘 작성해 주셨군요! 사용자가 보고 이해하기 쉬운 좋은 README라고 생각 합니다! 그리고 프로젝트 구조가 변경되어도 크게 고칠 부분이 없다는 점도 좋아요! 👍