-
Notifications
You must be signed in to change notification settings - Fork 708
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
Step2 (사다리 생성) : 리뷰 요청드립니다. #413
Changes from 25 commits
d39d67a
220357c
8ae279b
0958512
f37fb00
b8d4a3a
5045f38
2079132
827837b
789f432
da348aa
0d359af
e943628
c278208
2adc6fd
10caac7
802a180
3d4b138
7687130
d588560
91756bf
8657821
ac862a4
abd6382
4de92a9
2f232ec
df6f938
cc1bfa7
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,19 @@ | ||
package ladder; | ||
|
||
import ladder.domain.Ladder; | ||
import ladder.domain.LadderFactory; | ||
import ladder.domain.PlayersGroup; | ||
import ladder.view.InputView; | ||
import ladder.view.OutputView; | ||
|
||
public class Application { | ||
|
||
public static void main(String[] args) { | ||
PlayersGroup playersGroup = PlayersGroup.of(InputView.inputPlayerNames()); | ||
LadderFactory ladderFactory = new LadderFactory(InputView.inputLadderHeight()); | ||
Ladder ladder = ladderFactory.buildLadder(playersGroup); | ||
|
||
OutputView.printPlayerNames(playersGroup); | ||
OutputView.printLadder(ladder); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
## 사다리 게임 구현 기능 목록 | ||
|
||
### Domain | ||
|
||
* Player | ||
* 게임 참가자 객체 | ||
* 이름에 대한 예외 처리 | ||
* 이름이 NULL이거나 빈 문자열이거나 5자를 넘는 경우 예외 발생 | ||
|
||
* PlayersGroup | ||
* 게임 참가지 객체의 리스트(List<Player>) 일급 컬렉션 | ||
* 참가자 객체의 이름 목록을 파라미터로 받아 객체 생성 | ||
* Player들의 이름 명단(List<String>) 반환 | ||
* Player들 수를 반환 | ||
|
||
* Point | ||
* 사다리 한 수평 라인의 한 점을 구성하는 객체 | ||
* 해당 부분에 값이 존재하는지 아닌지(boolean)를 결정함. | ||
* 난수를 받아 객체 생성 시, 해당 부분에 값이 존재하는지 아닌지를 결정함. | ||
|
||
* Line | ||
* 사다리의 수평 라인 한 줄을 의미하는 객체 | ||
* 수평 라인이 존재하는 부분과 아닌 부분을 List<Point>으로 가짐 | ||
* 생성된 Line을 구성하는 각 Point들의 정보를 담은 List<Boolean> 반환 | ||
|
||
* DrawingLineStrategy | ||
* 선을 그리는 전략 인터페이스 | ||
* RandomDrawingLineStrategy는 인자로 참가자의 수(사다리의 너비)를 받음. | ||
|
||
* LadderFactory | ||
* 게임 참가자 수와 Ladder 높이를 파라미터로 받아 적합한 크기의 Ladder 생성 | ||
* 높이가 1보다 작을 경우 예외 발생 | ||
|
||
* Ladder | ||
* 사다리 2차원 배열의 정보를 List<Line>으로 가지고 있는 일급 컬렉션. | ||
* 플레이어 명단과 사다리 높이를 바탕으로 사다리를 생성함. | ||
* 사다리의 설계도면을 List<List<Boolean>>으로 반환함 | ||
|
||
### View | ||
|
||
* InputView | ||
* 쉼표로 구분되는 게임 참가자(Player) 명단을 입력 받음. | ||
* 사다리 높이를 입력 받음. | ||
|
||
* OutputView | ||
* Ladder 객체를 바탕으로 사다리의 모습을 그림 | ||
|
||
### Application |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package ladder.domain; | ||
|
||
import java.util.List; | ||
|
||
public interface DrawingLineStrategy { | ||
|
||
public List<Point> drawLine(int playerCounts); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package ladder.domain; | ||
|
||
public class ErrorMessages { | ||
|
||
public static final String INVALID_PLAYER_NAME = "게임 참가자의 이름은 빈 문자열이 아닌 1 ~ 5자리의 문자만 가능합니다."; | ||
public static final String INVALID_PLAYER_COUNTS = "게임 참가자는 1명 이상이어야 합니다."; | ||
public static final String INVALID_LADDER_HEIGHT = "사다리 높이는 1 이상이어야 합니다."; | ||
|
||
private ErrorMessages() { | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package ladder.domain; | ||
|
||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
|
||
public class Ladder { | ||
|
||
private final List<Line> lines; | ||
|
||
private Ladder(List<Line> lines) { | ||
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. 생성자에서 DrawingLineStrategy를 받도록 처리해 주세요. 이렇게 처리해야 확장성이 높아집니다. |
||
this.lines = lines; | ||
} | ||
|
||
public static Ladder buildLadder(PlayersGroup playersGroup, int ladderHeight) { | ||
int playerCounts = playersGroup.getPlayerCounts(); | ||
List<Line> ladder = Stream.generate(() -> Line.drawLine(playerCounts)) | ||
.limit(ladderHeight) | ||
.collect(Collectors.toList()); | ||
return new Ladder(ladder); | ||
} | ||
|
||
public List<List<Boolean>> getLadderBluePrint() { | ||
return lines.stream() | ||
.map(Line::getPointPositions) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
public int getLadderHeight() { | ||
return lines.size(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package ladder.domain; | ||
|
||
public class LadderFactory { | ||
|
||
private static final int MINIMUM_LADDER_HEIGHT = 1; | ||
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 final int ladderHeight; | ||
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 LadderFactory(int ladderHeight) { | ||
validateLadderHeight(ladderHeight); | ||
this.ladderHeight = ladderHeight; | ||
} | ||
|
||
private void validateLadderHeight(int ladderHeight) { | ||
if (ladderHeight < MINIMUM_LADDER_HEIGHT) { | ||
throw new IllegalArgumentException(ErrorMessages.INVALID_LADDER_HEIGHT); | ||
} | ||
} | ||
|
||
public Ladder buildLadder(PlayersGroup playersGroup) { | ||
return Ladder.buildLadder(playersGroup, ladderHeight); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package ladder.domain; | ||
|
||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
public class Line { | ||
|
||
private static final int MINIMUM_PLAYER_COUNTS = 1; | ||
private final List<Point> 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. 위의 코멘트와 동일한 컨벤션으로 변경시켜 주세요. 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 Line(List<Point> points) { | ||
this.points = points; | ||
} | ||
|
||
public static Line drawLine(int playerCounts) { | ||
validatePlayerCounts(playerCounts); | ||
List<Point> points = drawLineWithStrategy(playerCounts, new RandomDrawingLineStrategy()); | ||
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. 인터페이스를 활용해 주셨는데 인터페이스의 확장성은 열려있지 않습니다. 외부에서 어떠한 인터페이스를 사용할지 결정시켜 주어야 하는데 파라미터 혹은 생성자 파라미터로 의존성을 열어 주세요. |
||
return new Line(points); | ||
} | ||
|
||
private static void validatePlayerCounts(int playerCounts) { | ||
if (playerCounts < MINIMUM_PLAYER_COUNTS) { | ||
throw new IllegalArgumentException(ErrorMessages.INVALID_PLAYER_COUNTS); | ||
} | ||
} | ||
|
||
private static List<Point> drawLineWithStrategy(int playerCounts, | ||
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. 불필요한 메서드로 보입니다. 이미 클래스로 충분히 설명되는것 같아요. |
||
DrawingLineStrategy drawingLineStrategy) { | ||
return drawingLineStrategy.drawLine(playerCounts); | ||
} | ||
|
||
public List<Boolean> getPointPositions() { | ||
return points.stream() | ||
.map(Point::getIsExisting) | ||
.collect(Collectors.toList()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package ladder.domain; | ||
|
||
public class Player { | ||
|
||
private static final int MAXIMUM_NAME_LENGTH = 5; | ||
private final String name; | ||
|
||
public Player(String name) { | ||
validateName(name); | ||
this.name = name; | ||
} | ||
|
||
private void validateName(String name) { | ||
if (isNullOrEmpty(name) || isInvalidLength(name)) { | ||
throw new IllegalArgumentException(ErrorMessages.INVALID_PLAYER_NAME); | ||
} | ||
} | ||
|
||
private boolean isNullOrEmpty(String name) { | ||
return name == null || name.isEmpty(); | ||
} | ||
|
||
private boolean isInvalidLength(String name) { | ||
return name.length() > MAXIMUM_NAME_LENGTH; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package ladder.domain; | ||
|
||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
public class PlayersGroup { | ||
|
||
private final List<Player> players; | ||
|
||
private PlayersGroup(List<Player> players) { | ||
this.players = players; | ||
} | ||
|
||
public static PlayersGroup of(List<String> playerNames) { | ||
List<Player> players = playerNames.stream() | ||
.map(Player::new) | ||
.collect(Collectors.toList()); | ||
return new PlayersGroup(players); | ||
} | ||
|
||
public List<String> getPlayerNames() { | ||
return players.stream() | ||
.map(Player::getName) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
public int getPlayerCounts() { | ||
return players.size(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package ladder.domain; | ||
|
||
public class Point { | ||
|
||
private static final int RANDOM_NUMBER_BOUNDARY = 5; | ||
private final boolean isExisting; | ||
|
||
public Point(boolean isExisting) { | ||
this.isExisting = isExisting; | ||
} | ||
|
||
public static Point drawPoint(int randomNumber) { | ||
if (randomNumber < RANDOM_NUMBER_BOUNDARY) { | ||
return new Point(false); | ||
} | ||
return new Point(true); | ||
} | ||
|
||
public boolean getIsExisting() { | ||
return isExisting; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package ladder.domain; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Random; | ||
|
||
public class RandomDrawingLineStrategy implements DrawingLineStrategy { | ||
|
||
private static final int LOOP_ZERO = 0; | ||
private static final int LINE_WIDTH_CONSTANT = 1; | ||
private static final int INDEX_CONSTANT = 1; | ||
private static final int RANDOM_NUMBER_RANGE = 10; | ||
private static final Random random = new Random(); | ||
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. 상수라면 변수명이 대문자여야 합니다. |
||
|
||
@Override | ||
public List<Point> drawLine(int playerCounts) { | ||
List<Point> points = new ArrayList<>(); | ||
int lineWidth = playerCounts - LINE_WIDTH_CONSTANT; | ||
for (int i = LOOP_ZERO; i < lineWidth; i++) { | ||
Point point = drawPoint(points); | ||
points.add(point); | ||
} | ||
return points; | ||
} | ||
|
||
private Point drawPoint(List<Point> points) { | ||
int randomNumber = generateRandomNumber(); | ||
if (points.isEmpty()) { | ||
return Point.drawPoint(randomNumber); | ||
} | ||
if (isLastPointExisting(points)) { | ||
return new Point(false); | ||
} | ||
return Point.drawPoint(randomNumber); | ||
} | ||
|
||
private boolean isLastPointExisting(List<Point> points) { | ||
int lastPointIndex = points.size() - INDEX_CONSTANT; | ||
Point lastPoint = points.get(lastPointIndex); | ||
return lastPoint.getIsExisting(); | ||
} | ||
|
||
private int generateRandomNumber() { | ||
return random.nextInt(RANDOM_NUMBER_RANGE); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package ladder.view; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.Scanner; | ||
|
||
public class InputView { | ||
|
||
private static Scanner scanner = new Scanner(System.in); | ||
|
||
private InputView() { | ||
} | ||
|
||
public static List<String> inputPlayerNames() { | ||
System.out.println(ViewMessages.INSTRUCTION_PLAYER_NAMES); | ||
String[] inputPlayerNames = scanner.nextLine().split(ViewMessages.COMMA); | ||
return Arrays.asList(inputPlayerNames); | ||
} | ||
|
||
public static int inputLadderHeight() { | ||
System.out.println(ViewMessages.INSTRUCTION_LADDER_HEIGHT); | ||
return Integer.parseInt(scanner.nextLine()); | ||
} | ||
} |
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.
이보다는 RuntimeException을 상속하여 에러를 정의한 클래스를 만들어서 사용해 보면 어떨까요?