-
Notifications
You must be signed in to change notification settings - Fork 60
[그리디] 서현진 사다리 미션 제출합니다. #81
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
Changes from 15 commits
2c7ac0b
601989e
45188f7
6bc5102
25114d9
2d98c95
4ae4ed7
e2f073b
e46be8a
c29c860
5aeab91
d6ac423
c90102f
53b8d01
00f8644
35bc4d1
9eff889
4b32197
1007500
e6710c5
af2e6a8
7ed8f0a
04b80c8
4db07ab
4fe7fca
cf2700c
82afadc
88d3fc3
86db6b1
c60e922
cee5e54
3c3f2e2
12dcf0d
3dac03c
7b421a9
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,29 @@ | ||
| # 자바 사다리 게임 | ||
|
|
||
| ## 주요 기능 | ||
|
|
||
| * 쉼표로 구분하여 여러 플레이어 이름 입력 | ||
| * 사다리 끝에 위치할 보상 입력 | ||
| * 사다리 높이 설정 | ||
| * 가로 라인이 무작위로 생성되는 사다리 | ||
| * 최종 생성된 사다리 모양 출력 | ||
| * 각 플레이어의 최종 결과(보상) 표시 | ||
| * 전체 플레이어 또는 특정 플레이어의 결과 조회 기능 | ||
|
|
||
| ## 코드 설명 | ||
| * **`Application.java`**: 프로그램의 시작점입니다. 전체 게임의 흐름을 제어합니다. | ||
|
|
||
| * **`controller` 패키지**: | ||
| * `Controller.java`: 사용자의 입력을 받아 Model을 업데이트하고, 결과를 View에 전달하는 등 게임의 핵심 로직을 관리합니다. | ||
|
|
||
| * **`model` 패키지**: 게임의 데이터와 비즈니스 로직을 담당합니다. | ||
| * `Player.java`: 게임에 참여하는 플레이어들의 정보를 관리합니다. | ||
| * `Rewards.java`: 사다리 게임의 결과로 주어지는 보상 정보를 관리합니다. | ||
| * `Bridge.java`: 전체 사다리의 구조를 나타냅니다. 가로 줄(`BridgeStep`)들의 리스트로 구성됩니다. | ||
| * `BridgeStep.java`: 사다리의 한 칸이 가로 줄을 가지고 있는지 여부(`EXIST` 또는 `EMPTY`)를 나타내는 Enum입니다. | ||
| * `LadderDescentService.java`: 플레이어가 사다리를 내려가는 과정을 처리하는 서비스 클래스입니다. | ||
| * `SplitMethod.java`: 사용자 입력을 쉼표 기준으로 분리하는 유틸리티 클래스입니다. | ||
|
|
||
| * **`view` 패키지**: 사용자 인터페이스(입력/출력)를 담당합니다. | ||
| * `InputView.java`: 사용자로부터 플레이어 이름, 보상, 사다리 높이 등의 입력을 받습니다. | ||
| * `OutputView.java`: 게임 진행 상황, 사다리 모양, 최종 결과 등을 콘솔에 출력합니다. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| import Controller.Controller; | ||
|
|
||
| public class Application { | ||
| public static void main(String[] args) { | ||
| Controller controller = new Controller(); | ||
| controller.startLadder(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,43 @@ | ||||||
| package Controller; | ||||||
|
|
||||||
| import Model.Bridge; | ||||||
| import Model.Player; | ||||||
| import Model.Rewards; | ||||||
| import view.InputView; | ||||||
| import view.OutputView; | ||||||
|
|
||||||
| public class Controller { | ||||||
| InputView inputView = new InputView(); | ||||||
| OutputView outputView = new OutputView(); | ||||||
|
|
||||||
| public void startLadder() { | ||||||
| int height; | ||||||
| boolean isAll = false; | ||||||
| outputView.askPlayers(); | ||||||
| String inputs = inputView.getScanner().nextLine(); | ||||||
| Player players = new Player(inputs); | ||||||
|
||||||
|
|
||||||
| outputView.askRewards(); | ||||||
| inputs = inputView.getScanner().nextLine(); | ||||||
|
||||||
| Rewards rewards = new Rewards(inputs); | ||||||
|
|
||||||
| outputView.askLadderHeight(); | ||||||
| height = inputView.getWidthAndHeight(); | ||||||
|
||||||
| height = inputView.getWidthAndHeight(); | |
| int height = inputView.getWidthAndHeight(); |
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.
수정하겠습니다!
Outdated
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.
isAll을 계속 가지고 있는 상태로 while문을 돌리는 대신, 차라리 무한루프문을 만들어서 all을 입력할 때 break문으로 탈출하는건 어떨까요??
아래에 적어둔 OutputView 코멘트도 그렇고, 위에 isAll 선언도 그렇고 isAll이 범인이네요 ㅋㅋ
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.
저 혹시 무한루프와 isAll을 가지고 있는 while문에 어떤 차이가 존재하는지 궁금합니다.
printRewards가 all이라면 true를 리턴하는 메소드여서 while문의 조건으로 구조했었는데 저는 무한루프와 큰차이를 모르겠어서 질문드립니다!!
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.
코드를 읽을 때 변수를 하나 더 기억하고, 관련 메서드를 확인해야하는지의 유무라고 생각하시면 됩니다
앞으로 개발하면서 우리는 새로 작성하는 코드보다 같은 코드를 반복해서 읽는 시간이 많다는 점을 알고 있어야 하는데요
(읽어보면 좋은 글)
이런 맥락으로 생각하면 코드 자체는 isAll이든 무한루프문이든 큰 차이는 없지만, 무한루프문이 코드 읽고 수정하는 입장에서는 하나의 메서드만 봐도 되니 좀 더 관리하기 편한 코드라고 생각하시면 편해요
- isAll을 가지고 있는 while문: isAll을 결정하는
outputView.printRewards(...)내부 코드까지 확인해야함 - 무한루프문:
string == "all"을 통해 break문을 사용하면outputView.printRewards(...)를 선택적으로 볼 수 있는 기회가 주어짐
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.
아아 넵 감사합니다!! 메소드를 실행하기 전에 if문으로 메소드의 실행여부를 한번 확인하는 로직이 관리하기 편한 코드가 된다는 걸 이해했습니다!
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| package Model; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import java.util.Random; | ||
| import java.util.Collections; | ||
|
|
||
| public class Bridge { | ||
|
|
||
| private final List<List<BridgeStep>> rows; | ||
|
||
| private final Random random = new Random(); | ||
|
|
||
| public Bridge(int height, int width) { | ||
| this.rows = new ArrayList<>(); | ||
| initializeBridgeRows(height, width); | ||
| } | ||
|
||
|
|
||
| private void initializeBridgeRows(int height, int width) { | ||
| for (int i = 0; i < height; i++) { | ||
| this.rows.add(createOneRow(width)); | ||
| } | ||
| } | ||
|
|
||
| private List<BridgeStep> createOneRow(int width) { | ||
| List<BridgeStep> row = generateRandomRow(width); | ||
| ensureNoSideBySideSteps(row); | ||
| return row; | ||
| } | ||
|
|
||
| private List<BridgeStep> generateRandomRow(int width) { | ||
| List<BridgeStep> row = new ArrayList<>(); | ||
| for (int i = 0; i < width; i++) { | ||
| row.add(BridgeStep.createRandomStep(this.random)); | ||
| } | ||
| return row; | ||
| } | ||
|
|
||
| private void ensureNoSideBySideSteps(List<BridgeStep> row) { | ||
| for (int i = 0; i < row.size() - 1; i++) { | ||
| fixSideBySideStepIfNeeded(row, i); | ||
| } | ||
| } | ||
|
|
||
| private void fixSideBySideStepIfNeeded(List<BridgeStep> row, int index) { | ||
| if (areBothStepsExisting(row, index)) { | ||
| setOneToNoneRandomly(row, index); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| private boolean areBothStepsExisting(List<BridgeStep> row, int index) { | ||
| return row.get(index).isExist() && row.get(index + 1).isExist(); | ||
| } | ||
|
|
||
| private void setOneToNoneRandomly(List<BridgeStep> row, int index) { | ||
| if (this.random.nextBoolean()) { | ||
| row.set(index, BridgeStep.NONE); | ||
| return; | ||
| } | ||
| row.set(index + 1, BridgeStep.NONE); | ||
| } | ||
|
|
||
| public List<List<BridgeStep>> getRows() { | ||
| return Collections.unmodifiableList(this.rows); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| // BridgeStep.java | ||
| package Model; | ||
|
|
||
| import java.util.Random; | ||
|
|
||
| public enum BridgeStep { | ||
| NONE(0), // 다리 없음 | ||
| EXIST(1); // 다리 있음 | ||
|
|
||
| private final int value; | ||
|
|
||
| BridgeStep(int value) { | ||
| this.value = value; | ||
| } | ||
|
|
||
| public static BridgeStep createRandomStep(Random random) { | ||
| if (random.nextBoolean()) { | ||
| return EXIST; | ||
| } | ||
| return NONE; | ||
| } | ||
|
|
||
| public boolean isExist() { | ||
| return this == EXIST; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| package Model; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public class LadderDescentService { | ||
|
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. 로직 깔끔해서 좋네요 👍👍 |
||
| private Bridge bridge; | ||
|
|
||
| public LadderDescentService(Bridge bridge) { | ||
| this.bridge = bridge; | ||
| } | ||
|
|
||
| public int descent(int curPos){ | ||
| int pos = curPos; | ||
| for (List<BridgeStep> row : bridge.getRows()) { | ||
| pos += checkRightBridge(row,pos) + checkLeftBridge(row,pos); | ||
| } | ||
| return pos; | ||
| } | ||
|
|
||
|
|
||
| private int checkRightBridge(List<BridgeStep> row, int pos) { | ||
| if (pos >= row.size()) { | ||
| return 0; | ||
| } | ||
| if (row.get(pos) == BridgeStep.EXIST) { | ||
| return 1; | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| private int checkLeftBridge(List<BridgeStep> row, int pos) { | ||
| if (pos == 0) { | ||
| return 0; | ||
| } | ||
| if (row.get(pos - 1) == BridgeStep.EXIST) { | ||
| return -1; | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| package Model; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Collections; | ||
| import java.util.List; | ||
|
|
||
| public class Player extends SplitMethod { | ||
| List<String> players; | ||
| List<Integer> destinatioinPos = new ArrayList<>(); | ||
|
|
||
| public Player(String players) { | ||
| this.players = split(players); | ||
| } | ||
|
|
||
| public List<String> getPlayers() { | ||
| return Collections.unmodifiableList(players); | ||
| } | ||
|
|
||
| public int getDestinatioinPos(String string) { | ||
| return destinatioinPos.get(players.indexOf(string)); | ||
| } | ||
|
|
||
| public int getPlayersNumber() { | ||
| return players.size(); | ||
| } | ||
|
|
||
| public void playerOnDestination(Bridge bridge) { | ||
| LadderDescentService descentService = new LadderDescentService(bridge); | ||
|
|
||
| for (String player : players) { | ||
| destinatioinPos.add(descentService.descent(players.indexOf(player))); | ||
| } | ||
| } | ||
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| package Model; | ||
|
|
||
| import java.util.Collections; | ||
| import java.util.List; | ||
|
|
||
| public class Rewards extends SplitMethod { | ||
| List<String> rewards; | ||
|
|
||
| public Rewards(String rewards) { | ||
| this.rewards = split(rewards); | ||
| } | ||
|
|
||
| public String getRewardskey(int index) { | ||
| return rewards.get(index); | ||
| } | ||
|
||
|
|
||
| public List<String> getRewards() { | ||
| return Collections.unmodifiableList(rewards); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| package Model; | ||
|
|
||
| import java.util.Collections; | ||
| import java.util.List; | ||
| import java.util.regex.Pattern; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| public class SplitMethod { | ||
|
||
| protected static List<String> split(String input) { | ||
|
|
||
| final Pattern DELIMITER = Pattern.compile(","); | ||
|
|
||
| if (input == null || input.isEmpty()) { | ||
| return Collections.emptyList(); | ||
| } | ||
|
|
||
| return DELIMITER.splitAsStream(input) | ||
| .map(String::trim) // 양쪽 공백 제거 | ||
| .filter(name -> !name.isEmpty()) // 빈 값 제거 (예: "neo,,brie") | ||
| .collect(Collectors.toList()); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package view; | ||
|
|
||
| import java.util.Scanner; | ||
|
|
||
| public class InputView { | ||
| Scanner scanner = new Scanner(System.in); | ||
|
|
||
| public int getWidthAndHeight() { | ||
| return scanner.nextInt(); | ||
| } | ||
|
|
||
| public Scanner getScanner() { | ||
| return scanner; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| package view; | ||
|
|
||
|
|
||
| import Model.Bridge; | ||
| import Model.BridgeStep; | ||
| import Model.Player; | ||
| import Model.Rewards; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.List; | ||
|
|
||
| public class OutputView { | ||
| public void print(Bridge bridge) { | ||
| for (List<BridgeStep> row : bridge.getRows()) { | ||
| printRow(row); | ||
| System.out.print("|"); | ||
| System.out.println(); | ||
| } | ||
|
|
||
| } | ||
|
|
||
| private void printRow(List<BridgeStep> row) { | ||
| row.forEach(bridgeStep -> { | ||
| System.out.print("|"); | ||
| printBridgeStep(bridgeStep); | ||
| }); | ||
| } | ||
|
||
|
|
||
| public void printPlayersAndRewards(List<String> strings) { | ||
| strings.forEach(string -> System.out.printf("%-6s", string)); | ||
| System.out.println(); | ||
| } | ||
|
|
||
| private void printBridgeStep(BridgeStep bridgeStep) { | ||
| if (bridgeStep == BridgeStep.EXIST) { | ||
| System.out.print("-----"); | ||
| } else { | ||
| System.out.print(" "); | ||
| } | ||
| } | ||
|
|
||
| public void askResults() { | ||
| System.out.println("결과를 보고 싶은 사람은?"); | ||
| } | ||
|
|
||
| public boolean printRewards(Rewards rewards, Player players, String inputNames) { | ||
|
||
| System.out.println("실행 결과"); | ||
| String trimmedInput = inputNames.trim(); | ||
| if (trimmedInput.equals("all")) { | ||
| players.getPlayers().stream() | ||
| .forEach(player -> System.out.println(player + " : " + rewards.getRewardskey(players.getDestinatioinPos(player)))); | ||
| return true; | ||
| } | ||
|
|
||
| Arrays.stream(trimmedInput.split(",")) | ||
| .map(String::trim) | ||
| .forEach(trimmedName -> { | ||
| try { | ||
| System.out.println(trimmedName + " : " + rewards.getRewardskey(players.getDestinatioinPos(trimmedName))); | ||
| } catch (Exception e) { | ||
| throw new IllegalArgumentException("[ERROR] 존재하지 않는 플레이어 이름입니다: " + trimmedName); | ||
| } | ||
| }); | ||
| return false; | ||
| } | ||
|
|
||
| public void askPlayers() { | ||
| System.out.println("참여할 사람 이름을 입력하세요. (이름은 쉼표(,)로 구분하세요)"); | ||
| } | ||
|
|
||
| public void askRewards() { | ||
| System.out.println("실행 결과를 입력하세요. (결과는 쉼표(,)로 구분하세요)"); | ||
| } | ||
|
|
||
| public void askLadderHeight() { | ||
| System.out.println("사다리의 높이는 몇 개인가요?"); | ||
| } | ||
| } | ||

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.
height와 isAll이 가장 위에 있는데 먼저 선언한 이유가 있나요??
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.
따로 의미를 두고 필드를 위에 선언 한 이유는 없습니다!
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.
아하 보통 변수는 선언과 동시에 초기화하는게 좋아요