-
Notifications
You must be signed in to change notification settings - Fork 748
사다리타기: 2단계 - 사다리(생성) #2357
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: hongyeseul
Are you sure you want to change the base?
사다리타기: 2단계 - 사다리(생성) #2357
Changes from all commits
5cb3abe
35f1390
b5cd01e
16c1bec
b552839
973d990
36e38b6
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,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); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
## 2단계 - 사다리(생성) | ||
|
||
### 기능 요구사항 | ||
- 사다리 게임에 참여하는 사람에 이름을 최대5글자까지 부여할 수 있다. 사다리를 출력할 때 사람 이름도 같이 출력한다. | ||
- 사람 이름은 쉼표(,)를 기준으로 구분한다. | ||
- 사람 이름을 5자 기준으로 출력하기 때문에 사다리 폭도 넓어져야 한다. | ||
- 사다리 타기가 정상적으로 동작하려면 라인이 겹치지 않도록 해야 한다. | ||
- `|-----|-----|` 모양과 같이 가로 라인이 겹치는 경우 어느 방향으로 이동할지 결정할 수 없다. | ||
|
||
|
||
### 프로그래밍 요구사항 | ||
|
||
- 자바 8의 스트림과 람다를 적용해 프로그래밍한다. | ||
- 규칙 6: 모든 엔티티를 작게 유지한다. | ||
|
||
### 실행 결과 | ||
위 요구사항에 따라 4명의 사람을 위한 5개 높이 사다리를 만들 경우, 프로그램을 실행한 결과는 다음과 같다. | ||
|
||
``` | ||
참여할 사람 이름을 입력하세요. (이름은 쉼표(,)로 구분하세요) | ||
pobi,honux,crong,jk | ||
|
||
최대 사다리 높이는 몇 개인가요? | ||
5 | ||
|
||
실행결과 | ||
|
||
pobi honux crong jk | ||
|-----| |-----| | ||
| |-----| | | ||
|-----| | | | ||
| |-----| | | ||
|-----| |-----| | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<Line> lines; | ||
|
||
public Ladder(int height, int countOfPlayers) { | ||
lines = new ArrayList<>(); | ||
IntStream.range(0, height) | ||
.forEach(i -> lines.add(new Line(countOfPlayers))); | ||
} | ||
|
||
public List<Line> getLines() { | ||
return lines; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<Point> points; | ||
|
||
public Line(int countOfPlayers) { | ||
int numberOfPoints = countOfPlayers - 1; | ||
this.points = initializePoints(numberOfPoints); | ||
} | ||
|
||
private List<Point> initializePoints(int numberOfPoints) { | ||
boolean previousHasLine = false; | ||
List<Point> 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<Point> getPoints() { | ||
return points; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
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.
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package ladder.domain.player; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
public class Players { | ||
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 static final String DELIMITER_COMMA = ","; | ||
|
||
private final List<Player> 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<Player> getPlayers() { | ||
return players; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package ladder.view.input; | ||
|
||
public abstract class BaseInputView implements InputView { | ||
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. 후에 리팩토링을 위해 만들어 둔 것입니다. |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package ladder.view.input; | ||
|
||
public interface InputView { | ||
String read(); | ||
String inputPlayerNames(); | ||
int inputLadderHeight(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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("참여자의 이름은 쉼표가 아닌 다른 구분자가 사용되면 예외가 발생한다.") | ||
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.
|
||
void getSplitter() { | ||
FakeInputView inputView = new FakeInputView("yeseul,pobi|crong"); | ||
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.
|
||
assertThatThrownBy(() -> new Players(inputView.inputPlayerNames())) | ||
.isInstanceOf(IllegalArgumentException.class); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
} |
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.
stream의 종단 연산은 안티패턴입니다 😄
lines = new ArrayList<>()
로 별도 선언하고 추가하기보다는map
으로 바로 만들어 할당해볼 수 있을 것 같아요 :)