Skip to content
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

[사다리 게임] 베디 미션 제출합니다 #25

Merged
merged 59 commits into from
May 20, 2019
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
2cc3e99
feat: README.md 문자열 덧셈 계산기 요구사항 및 기능 추가
starkim06 May 14, 2019
cb3b717
feat: StringSplitter.class 추가
starkim06 May 14, 2019
6df9cc2
feat: Positive.class, StringCalculator.class 추가
starkim06 May 14, 2019
01d5811
feat: StringSplitter 를 이용한 StringCalculator 테스트 추가
starkim06 May 14, 2019
6608d8d
feat: calculatorTodo.md 추가
starkim06 May 14, 2019
eb86751
refactor: Positive.class 인스턴스 변수 final 추가
starkim06 May 14, 2019
74363d7
refactor: StringSplitter.class 수정 (정규패턴 구분자로 인식)
starkim06 May 14, 2019
aadab6e
feat: README.md 사다리 게임 -1단계 요구사항 및 기능 추가
starkim06 May 14, 2019
3c0bd46
docs: ladderToDo.md, 사다리 게임 TDD를 위한 ToDo 작성
starkim06 May 15, 2019
55f30a5
feat: Player.class 생성
starkim06 May 15, 2019
649509b
refactor: Player.class name 에 공백처리 추가.
starkim06 May 15, 2019
c420611
feat: PlayGenerator.class 추가
starkim06 May 15, 2019
a0b95aa
refactor: Player.class 이름 유효성 검사 별도의 메소드로 추출
starkim06 May 15, 2019
e098dda
feat: GamePlayers.class 추가
starkim06 May 15, 2019
2f850a8
feat: Line.class 추가
starkim06 May 15, 2019
b827d25
refactor: Line.class equals 메소드 추가
starkim06 May 15, 2019
d662d9b
feat: SubLineGenerator 인터페이스, SubLineRandomGenerator.class 추가
starkim06 May 15, 2019
f4b91f0
feat: Ladder.class 추가
starkim06 May 15, 2019
3e2a108
fix: SubLineRandomGenerator 버그 해결
starkim06 May 15, 2019
3450cfb
feat: OutputConsoleView.class, LadderConsoleApp.class 추가
starkim06 May 15, 2019
cc4ffcc
refactor: OutputConsoleView.class 사다리 출력 변경
starkim06 May 16, 2019
d42089b
refactor: SubLineRandomGenerator.class Stack을 사용하여 subLine 생성 수정
starkim06 May 16, 2019
cd88537
refactor: Line 생성시 직접 generator를 받는 방식으로 수정
starkim06 May 16, 2019
8897d37
feat: LadderGame.class 추가
starkim06 May 16, 2019
f50eedd
feat: LadderGameController.class 추가
starkim06 May 16, 2019
b725d33
feat: GameResult.class, GameResultGenerator.class 추가
starkim06 May 16, 2019
dfcbd41
refactor: GameResults.class -> PlayRewards.class 로 이름 변경
starkim06 May 16, 2019
78801fa
refactor: LineGenerator.class 추가
starkim06 May 16, 2019
9f0c993
임시 push
starkim06 May 16, 2019
392cac3
refactor: generator 패키지 생성
starkim06 May 17, 2019
fb41b73
feat: LadderGame.class 에 findPlayerReward method 추가
starkim06 May 17, 2019
7e08808
feat: LadderGame.class 삭제, GameResult.class 추가
starkim06 May 17, 2019
f5dbd97
feat: LadderGameController.class 결과보기 기능 출력
starkim06 May 17, 2019
b18c3ba
feat: GamePlayers.class 이름 중복 체크 추가
starkim06 May 17, 2019
f15db16
feat: OutputConsoleView.printResult() 없는 사람일 경우 예외처리
starkim06 May 17, 2019
3aa21d4
feat: Player.name 예외처리 추가
starkim06 May 17, 2019
1554134
refactor: 상수 생성
starkim06 May 17, 2019
62b6493
refactor: Player.class
starkim06 May 17, 2019
50e91f9
Update README.md
dpudpu May 17, 2019
1b44dff
refactor: controller 삭제 후 main이 대신 기능하게 수행하게 수정
dpudpu May 18, 2019
02902e6
refactor: LadderConsoleApp 의미 없는 메소드 추출한 부분들 수정
dpudpu May 18, 2019
0f86542
fix: PlayerGeneartor 상수 접근제어자 때문에 테스트가 안되는 문제 해결
dpudpu May 18, 2019
7cb9333
feat: Direction.class 추가
dpudpu May 18, 2019
6162346
refactor: Direction.last() 수정
dpudpu May 19, 2019
df1b9d2
feat: DirectionGenerator.class 추가
dpudpu May 19, 2019
f36dd55
refactor: 원시값 boolean subLine을 Direction.class로 변경
dpudpu May 19, 2019
e733222
feat: DirectionsGenerator 팩토리 패턴 구현
dpudpu May 19, 2019
59c15ed
refactor: DirectionGenerator -> DirectionsGenerator 이름 변경
dpudpu May 19, 2019
a052ea2
refactor: Player.class postion:int 필드 추가
dpudpu May 19, 2019
7ed1cc9
refactor GamePlayers.class players 타입 set으로 변경
dpudpu May 19, 2019
80fbdc1
feat: Ladder.play(GamePlayer, PlayerRewards) 구현
dpudpu May 19, 2019
3357048
feat: Ladder.class 사람수와 결과 사이즈 같은지 검사 추가
dpudpu May 19, 2019
14b251f
refactor: GameResult는 값만 가지고 있는 vo 역할로 수정
dpudpu May 19, 2019
de74195
refactor: 기존 코드의 변경에 따른 OutputConsoleView 변경
dpudpu May 19, 2019
b2a38d0
refactor: PlayerRewards.class -> Rewards.class로 이름 변경
dpudpu May 19, 2019
d8498ed
refactor: GamePlayers.class -> Players.class 로 이름 변경
dpudpu May 19, 2019
73e243a
refactor: PlayersGenerator.generate() 에서 직접 Players 인스턴스를 반환하게 변경
dpudpu May 19, 2019
746e6d5
refactor: 일급컬렉션의 컬렉션 getter 할 때 새로 복사해서 return하게 변경
dpudpu May 19, 2019
f801ebc
style: 자동 포맷팅
dpudpu May 19, 2019
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
68 changes: 67 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,70 @@
사다리타기 미션 저장소

## 우아한테크코스 코드리뷰
* [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md)
* [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md)

# 문자열 덧셈 계산기

## 요구사항

- 쉼표(,) 또는 콜론(:)을 구분자로 가지는 문자열을 전달하는 경우 구분자를 기준으로 분리한 각 숫자의 합을 반환 (예: “” => 0, "1,2" => 3, "1,2,3" => 6, “1,2:3” => 6)
- 앞의 기본 구분자(쉼표, 콜론)외에 커스텀 구분자를 지정할 수 있다. 커스텀 구분자는 문자열 앞부분의 “//”와 “\n” 사이에 위치하는 문자를 커스텀 구분자로 사용한다. 예를 들어 “//;\n1;2;3”과 같이 값을 입력할 경우 커스텀 구분자는 세미콜론(;)이며, 결과 값은 6이 반환되어야 한다.
- 문자열 계산기에 숫자 이외의 값 또는 음수를 전달하는 경우 RuntimeException 예외를 throw한다.

## 기능

- 구분자를 기준으로 숫자를 분리한다.
- 커스텀 구분자를 기준으로 숫자를 분리한다.
- 분리된 숫자들을 더해준다.
- 숫자 이외의 값 또는 음수가 있을 경우 RuntimeException을 throw한다.

# 사다리 게임 - 1단계

## 요구사항

- 사다리 게임에 참여하는 사람에 이름을 최대5글자까지 부여할 수 있다. 사다리를 출력할 때 사람 이름도 같이 출력한다.
- 사람 이름은 쉼표(,)를 기준으로 구분한다.
- 사람 이름을 5자 기준으로 출력하기 때문에 사다리 폭도 넓어져야 한다.
- 사다리 타기가 정상적으로 동작하려면 라인이 겹치지 않도록 해야 한다.
- `|-----|-----|` 모양과 같이 가로 라인이 겹치는 경우 어느 방향으로 이동할지 결정할 수 없다

## 필요한 기능

- 문자열을 입력받아 객체를 생성
- 문자열을 입력받는다.
- 입력받은 문자열을 쉼표(',')를 기준으로 구분한다.
- 객체를 생성한다.
- 일급 컬렉션에 담아준다.
- 사다리 높이를 입력받아 사다리를 만든다.
- 사다리 높이를 입력받는다.
- 사다리 높이 만큼 세로 라인 길이를 설정한다.
- 사람의 수 만큼 가로 라인을 설정한다.
- 겹치지 않게 가로 라인을 만든다.
- 사다리를 출력해준다.

## 가능한 예외

문자열을 입력받아 객체를 생성

- 문자열을 입력받아 객체를 생성
- 쉼표로 구분하지 않는 경우
- 구분된 문자열의 길이가 5를 초과하는 경우
- 문자열이 공백인 경우
- 문자열이 NULL인 경우
- 사다리 높이를 입력받아 사다리를 만든다.
- 높이가 음수인 경우
- 가로라인이 연속되는 경우


-----------------------------------------------

1. 사람의 이름을 입력받는다.
2. 입력 받은 이름을 컴마(,) 기준으로 나눠준다.
3. 사람 객체를 생성한다.
4. 사람 컨테이너 객체를 만든다.
5. 사다리의 높이를 입력 받는다.
6. 사다리 객체를 사람수와 사다리 높이를 인자로 받아서 생성하다.
7. 사다리 높이만큼 Line 클래스 리스트를 만들어준다.
1. Line은 가로라인을 boolean List로 가지고 있는다 (사람 수 - 1)
2. 가로 라인을 그어준다. 이 때 연속되면 안된다
8. 사다리를 출력해준다.
20 changes: 20 additions & 0 deletions src/main/java/calculator/Positive.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package calculator;

public class Positive {
Copy link
Contributor

Choose a reason for hiding this comment

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

오호. 이 연습도 했군요. 👍

Copy link
Author

Choose a reason for hiding this comment

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

의식적인 연습으로 TDD 영상 잘 봤습니다 👍

private final int number;

public Positive(final String number) {
this(Integer.parseInt(number));
}

public Positive(final int number) {
if (number < 0) {
throw new RuntimeException();
}
this.number = number;
}

int getNumber() {
return number;
}
}
26 changes: 26 additions & 0 deletions src/main/java/calculator/StringCalculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package calculator;

public class StringCalculator {
static int calculate(String[] numbers) {
if (isValidSize(numbers)) {
return 0;
}
return plus(numbers);
}

private static boolean isValidSize(String[] numbers) {
return numbers == null || numbers.length == 0;
}

private static int plus(String[] numbers) {
int sum = 0;
for (String number : numbers) {
sum += toPositive(number).getNumber();
}
return sum;
}

private static Positive toPositive(String number) {
return new Positive(number);
}
}
24 changes: 24 additions & 0 deletions src/main/java/calculator/StringSplitter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package calculator;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class StringSplitter {
private static final String CUSTOM_DELIMITER_REGEX = "//(.)\n(.*)";
private static final String DEFAULT_DELIMITER = ",|;";

static String[] split(String numbers) {
Matcher m = Pattern.compile(CUSTOM_DELIMITER_REGEX).matcher(numbers);

return m.find() ? splitCustom(m) : splitDefault(numbers);
}

private static String[] splitDefault(String numbers) {
return numbers.split(DEFAULT_DELIMITER);
}

private static String[] splitCustom(Matcher m) {
String customDelimiter = m.group(1);
return m.group(2).split(Pattern.quote(customDelimiter));
}
}
Empty file removed src/main/java/empty.txt
Empty file.
10 changes: 10 additions & 0 deletions src/main/java/ladder/LadderConsoleApp.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package ladder;

import ladder.controller.LadderGameController;

public class LadderConsoleApp {
public static void main(String[] args) {
LadderGameController ladderGameController = new LadderGameController();
ladderGameController.run();
Copy link
Contributor

Choose a reason for hiding this comment

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

굳이 Controller를 별도로 추가하지 않고 main() 메소드를 controller처럼 사용해도 되지 않을까?

Copy link
Author

Choose a reason for hiding this comment

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

네 반영했습니다.

}
}
45 changes: 45 additions & 0 deletions src/main/java/ladder/controller/LadderGameController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package ladder.controller;

import ladder.domain.*;
import ladder.domain.generator.PlayerGenerator;
import ladder.domain.generator.PlayerRewardsGenerator;
import ladder.view.InputConsoleView;
import ladder.view.OutputConsoleView;

import java.util.List;

public class LadderGameController {
public void run() {
GamePlayers gamePlayers = new GamePlayers(generatePlayers(inputNames()));
PlayerRewards playerRewards = generateRewards(inputRewards());
Ladder ladder = new Ladder(inputHeight(), gamePlayers.size());
GameResult gameResult = new GameResult(ladder, gamePlayers, playerRewards);

OutputConsoleView.printLadderGame(ladder, gamePlayers, playerRewards);
String name;
while (!(name = InputConsoleView.inputResultName()).equals("all")) {
OutputConsoleView.printResult(gameResult, name);
}
OutputConsoleView.printResult(gameResult);
}

private List<Player> generatePlayers(String names) {
return new PlayerGenerator(names).generate();
}

private String inputNames() {
return InputConsoleView.inputNames();
Copy link
Contributor

Choose a reason for hiding this comment

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

굳이 이런 부분까지 메소드로 분리할 필요가 있을까?

Copy link
Author

Choose a reason for hiding this comment

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

수정했습니다. 👍

}

private int inputHeight() {
return InputConsoleView.inputHeight();
}

private String inputRewards() {
return InputConsoleView.inputRewards();
}

private PlayerRewards generateRewards(String results) {
return new PlayerRewardsGenerator(results).generate();
}
}
45 changes: 45 additions & 0 deletions src/main/java/ladder/domain/GamePlayers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package ladder.domain;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public final class GamePlayers {
Copy link
Contributor

Choose a reason for hiding this comment

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

일급 콜렉션 적용 👍

private final List<Player> players;

public GamePlayers(final List<Player> players) {
validate(players);
this.players = new ArrayList<>(players);
}

private void validate(List<Player> players) {
validateSize(players);
validateDuplication(players);
}

private void validateSize(List<Player> players) {
if (players.isEmpty()) {
throw new IllegalArgumentException("두 명 이상 입력 해주세요.");
}
}

private void validateDuplication(List<Player> players) {
Set<Player> set = new HashSet<>(players);
Copy link
Contributor

Choose a reason for hiding this comment

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

중복 체크를 위해 Set을 사용한다면 인스턴스 변수를 'List players' 대신 'Set players`로 구현하는 것은 어떨까?

Copy link
Author

Choose a reason for hiding this comment

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

List를 한 이유가 Player는 필드로 이름만 가지고 있어서 List의 index로 position을 찾기 위해서 한거였는데요.
Player에 position 필드를 추가하고 Set으로 변경 했습니다.

if (set.size() != players.size()) {
throw new IllegalArgumentException("이름 중복은 안됩니다.");
}
}

String getPlayerName(int index) {
return players.get(index).getName();
}

public int size() {
return players.size();
}

public List<Player> getPlayers() {
return players;
}
}
35 changes: 35 additions & 0 deletions src/main/java/ladder/domain/GameResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package ladder.domain;

import java.util.HashMap;
import java.util.Map;

public class GameResult {
Copy link
Contributor

Choose a reason for hiding this comment

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

GameResult에 Ladder를 전달하기 보다 Map<Integer, Integer> result = ladder.play()와 같은 실행 결과만을 GameResult에 전달하는 것은 어떨까?

또는 GameResult result = ladder.play(gamePlayers, playerRewards)와 같이 구현하는 것은 어떨까?

Copy link
Author

Choose a reason for hiding this comment

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

네 다시 생각해보니 이렇게 하는게 좋을거 같아서 반영했습니다.

private final Map<String, String> results;

public GameResult(Ladder ladder, GamePlayers gamePlayers, PlayerRewards playerRewards) {
this.results = new HashMap<>();
init(ladder, gamePlayers, playerRewards);
}

private void init(Ladder ladder, GamePlayers gamePlayers, PlayerRewards playerRewards) {
validate(gamePlayers.size(), playerRewards.size());
for (int i = 0; i < gamePlayers.size(); i++) {
int result = ladder.moveLadder(i);
results.put(gamePlayers.getPlayerName(i), playerRewards.getReward(result));
}
}

private void validate(int countOfPlayers, int countOfRewards) {
if (countOfPlayers != countOfRewards) {
throw new IllegalArgumentException();
}
}

public String get(String playerName) {
return results.get(playerName);
}

public Map<String, String> getAll() {
return new HashMap<>(results);
}
}
50 changes: 50 additions & 0 deletions src/main/java/ladder/domain/Ladder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package ladder.domain;

import ladder.domain.generator.LineGenerator;
import ladder.domain.generator.LineRandomGenerator;

import java.util.List;

public final class Ladder {
private static final int MIN_HEIGHT = 1;
private static final int MIN_PLAYER_COUNT = 2;

private final List<Line> lines;

public Ladder(int height, int countOfPlayers) {
this(height, countOfPlayers, new LineRandomGenerator(countOfPlayers, height));
}

public Ladder(int height, int countOfPlayers, LineGenerator lineGenerator) {
validate(height, countOfPlayers);
this.lines = lineGenerator.generate();
}

private void validate(int height, int countOfPlayers) {
validateHeight(height);
validateCount(countOfPlayers);
}

private void validateHeight(int height) {
if (height < MIN_HEIGHT) {
throw new IllegalArgumentException("높이는 1이상 이어야 합니다.");
}
}

private void validateCount(int countOfPlayers) {
if (countOfPlayers < MIN_PLAYER_COUNT) {
throw new IllegalArgumentException("사람수는 2명 이상 이어야 합니다.");
}
}

public int moveLadder(int position) {
for (Line line : lines) {
position += line.move(position);
}
return position;
}

public List<Line> getLines() {
return lines;
}
}
Loading