Skip to content

[그리디] 김지우 사다리 미션 제출합니다. #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

Open
wants to merge 18 commits into
base: ji-woo-kim
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions README.md
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
```
14 changes: 14 additions & 0 deletions src/main/java/LadderApplication.java
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();
}
}
74 changes: 74 additions & 0 deletions src/main/java/controller/LadderController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package controller;

import domain.*;
import view.InputView;
import view.OutputView;

import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;

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 +14 to +20

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

View를 생성자 매개변수로 받아 의존성을 확실하게 표현해주고 있는 점이 좋은 것 같아요
저는 view의 모든 메서드를 static으로 만들어 사용하는데 매개변수로 받는 점이 Controller만 View에 의존할 수 있다는 규칙을 잘 나타내는 것 같습니다.


public void run() {
Players players = readPlayers();
ResultItems resultItems = readResultItems(players.count());

LadderHeight height = inputView.readHeight();
LadderGame ladderGame = LadderGame.start(players.count(), height, new Random());

List<String> playerNames = players.extractNames();
List<String> resultItemNames = resultItems.extractNames();
outputView.printLadder(playerNames, ladderGame, resultItemNames);

String requestName = inputView.readResultRequest();
handleResultRequest(requestName, players, ladderGame, resultItems);
}

private Players readPlayers() {
List<String> names = inputView.readPlayerNames();
List<Player> players = names.stream()
.map(Player::new)
.toList();
return new Players(players);
}

private ResultItems readResultItems(int expectedSize) {
List<String> results = inputView.readResultItems();
List<ResultItem> resultItems = results.stream()
.map(ResultItem::new)
.toList();
return new ResultItems(resultItems, expectedSize);
}

private void handleResultRequest(String request, Players players, LadderGame ladder, ResultItems resultItems) {
LadderGameResult gameResult = new LadderGameResult(players, resultItems, ladder);

while (!request.equals("all")) {
try {
Player player = new Player(request);
outputView.printSingleResult(player.getName(), gameResult.getSingleResultFor(player).getItem());
} catch (IllegalArgumentException e) {
System.out.println("잘못된 이름입니다. 다시 입력해주세요.");
}
request = inputView.readResultRequest();
}

Map<String, String> resultMap = gameResult.getAllResults().entrySet().stream()
.collect(Collectors.toMap(
entry -> entry.getKey().getName(),
entry -> entry.getValue().getItem()
));

outputView.printAllResults(resultMap);
}
}
25 changes: 25 additions & 0 deletions src/main/java/domain/LadderGame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package domain;

import java.util.List;
import java.util.Random;

public class LadderGame {

private final LadderLines ladderLines;

public LadderGame(LadderLines ladderLines) {
this.ladderLines = ladderLines;
}

public static LadderGame start(int width, LadderHeight height, Random random) {
return new LadderGame(LadderLines.generate(width, height, random));
}

public int getFinalPosition(int startPosition) {
return ladderLines.getFinalPosition(startPosition);
}

public List<LadderLine> getLadderStructure() {
return ladderLines.getLines();
}
}
44 changes: 44 additions & 0 deletions src/main/java/domain/LadderGameResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package domain;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class LadderGameResult {

private final Map<Player, ResultItem> results = new LinkedHashMap<>();

public LadderGameResult(Players players, ResultItems resultItems, LadderGame ladder) {
List<Player> playerList = players.extractPlayers();
List<ResultItem> resultList = resultItems.extractItems();

for (int i = 0; i < playerList.size(); i++) {
int finalPosition = ladder.getFinalPosition(i);

if (finalPosition >= resultItems.count()) {
throw new IllegalArgumentException("최종 위치가 결과의 범위를 벗어났습니다.");
}

results.put(playerList.get(i), resultList.get(finalPosition));
}
}

public ResultItem getSingleResultFor(Player player) {
if (!results.containsKey(player)) {
throw new IllegalArgumentException("존재하지 않는 플레이어입니다: " + player.getName());
}
return results.get(player);
}

public Map<Player, ResultItem> getAllResults() {
return results.entrySet()
.stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(e1, e2) -> e1,
LinkedHashMap::new
));
}
}
12 changes: 12 additions & 0 deletions src/main/java/domain/LadderHeight.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package domain;

public record LadderHeight(int value) {

private static final int MIN_HEIGHT_VALUE = 1;

public LadderHeight {
if (value < MIN_HEIGHT_VALUE) {
throw new IllegalArgumentException("사다리의 높이는 1 이상이어야 합니다.");
}
}
}
63 changes: 63 additions & 0 deletions src/main/java/domain/LadderLine.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package domain;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class LadderLine {

private final List<Point> points;

public LadderLine(int width, Random random) {
points = new ArrayList<>();
Point previous = Point.NOT_CONNECTED;

for (int i = 0; i < width; i++) {
Point nextPoint = createNextPoint(previous, random);

// 마지막 포인트 연결 방지
if (i == width - 1) {
nextPoint = Point.NOT_CONNECTED;
}

points.add(nextPoint);
previous = nextPoint;
}
}

public LadderLine(List<Point> points) {
this.points = List.copyOf(points);
}

public List<Point> getPoints() {
return List.copyOf(points);
}

private Point createNextPoint(Point previous, Random random) {
// 이전 포인트가 오른쪽으로 연결되어 있으면, 현재 포인트는 왼쪽과 연결되어 있다는 것과 같음
if (previous.isConnectedRight()) {
return Point.CONNECTED_LEFT;
}
// 랜덤하게 오른쪽 연결 여부 결정
if (random.nextBoolean()) {
return Point.CONNECTED_RIGHT;
}
return Point.NOT_CONNECTED;
}

public int move(int currentPosition) {
// 오른쪽으로 가려할 때, 맨 끝부분에서는 더 이동하지 않도록
if (currentPosition < 0 || currentPosition >= points.size()) {
return currentPosition;
}

Point currentPoint = points.get(currentPosition);
int nextPosition = currentPoint.moveFrom(currentPosition);
// 다음 위치가 범위를 넘어서면 현재 위치 유지
if (nextPosition >= 0 && nextPosition < points.size()) {
return nextPosition;
}

return nextPosition;
}
}
40 changes: 40 additions & 0 deletions src/main/java/domain/LadderLines.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package domain;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class LadderLines {

private final List<LadderLine> lines;

public LadderLines(List<LadderLine> lines) {
this.lines = List.copyOf(lines);
}

public static LadderLines generate(int width, LadderHeight height, Random random) {
List<LadderLine> lines = new ArrayList<>();
for (int i = 0; i < height.value(); i++) {
lines.add(new LadderLine(width, random));
}

return new LadderLines(lines);
}

public int getFinalPosition(int startPosition) {
int currentPosition = startPosition;

for (LadderLine line : lines) {
int nextPosition = line.move(currentPosition);
if (nextPosition != currentPosition) {
currentPosition = nextPosition;
}
}

return currentPosition;
}

public List<LadderLine> getLines() {
return List.copyOf(lines);
}
}
38 changes: 38 additions & 0 deletions src/main/java/domain/Player.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package domain;

import java.util.Objects;

public class Player {

private static final int MAX_NAME_LENGTH = 5;

private final String name;

public Player(String name) {
validateInput(name);
this.name = name;
}

private void validateInput(String name) {
if (name.isEmpty() || name.length() > MAX_NAME_LENGTH) {
throw new IllegalArgumentException("참여할 사람의 이름은 1자 이상 " + MAX_NAME_LENGTH + "자 이하여야 합니다.");
}
}

public String getName() {
return name;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Player player = (Player) o;
return Objects.equals(name, player.name);
}

@Override
public int hashCode() {
return Objects.hash(name);
}
}
Loading