Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
25 changes: 25 additions & 0 deletions src/main/java/BowlingMain.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import domain.Player;
import view.InputView;
import view.OutputView;

import static view.InputView.getScore;

public class BowlingMain {

public static void main(String[] args) {
Player player = InputView.getPlayer();
while (!player.isFinish()) {
doGame(player);
}
}

private static void doGame(Player player) {
try {
player.recordScore(getScore(player.getCurrentFrameNum()));
OutputView.printResult(player);
} catch (IllegalArgumentException e) {
InputView.printMessage(e.getMessage());
doGame(player);
}
}
}
37 changes: 37 additions & 0 deletions src/main/java/domain/Player.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package domain;

import domain.frame.Frames;
import domain.frame.result.FrameResults;

public class Player {
private PlayerName name;
private Frames frames;
private FrameResults results;

public Player(String name) throws IllegalArgumentException {
this.name = new PlayerName(name);
frames = new Frames();
results = new FrameResults();
}

public String getName() {
return name.getName();
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Player와 Frames간의 객체 관계는 어떻게 될까?
현재와 같이 분리해서 구현하는 경우와 Player가 Frames와 의존 관계를 가지도록 구현하는 경우 중 어느 것이 더 나은 설계일까?


public boolean isFinish() {
return frames.isFinish();
}

public FrameResults recordScore(int score) {
results.addResult(frames.getCurrentFrameIdx(), frames.recordScore(score));
return results;
}

public int getCurrentFrameNum() {
return frames.getCurrentFrameNum();
}

public FrameResults getResults() {
return results;
}
}
35 changes: 35 additions & 0 deletions src/main/java/domain/PlayerName.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package domain;

public class PlayerName {
public static final int LENGTH = 3;
private String name;

public PlayerName(String name) {
if (!isValidNameLength(name)) {
throw new IllegalArgumentException("이름은 " + LENGTH + "자로 해야함");
}

if (!isValidEnglishName(name)) {
throw new IllegalArgumentException("영어만 입력 해야함");
}
this.name = name;
}

public static boolean isValidNameLength(String name) {
return name.length() == LENGTH;
}

public static boolean isValidEnglishName(String name) {
char[] convertName = name.toCharArray();
for (char ch : convertName) {
if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

확실하지는 않은데 String에 이를 위해 제공해 주는 메소드가 있지 않나?
나도 확실치가 않네. 찾아보니 Character에 있는 것 같네.

return false;
}
}
return true;
}

public String getName() {
return name;
}
}
29 changes: 29 additions & 0 deletions src/main/java/domain/Score.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package domain;

import java.util.List;

public class Score {
public static final int MIN = 0;
public static final int MAX = 10;
private int score;

public Score(int score) {
if (!isValidRange(score)) {
throw new IllegalArgumentException("유효하지않은 범위의 점수입니다");
}
this.score = score;
}

public static boolean isValidRange(int score) {
return score >= MIN && score <= MAX;
}

public static boolean isScoreLimit(List<Score> scores) {
return scores.stream().mapToInt(scoreInstance -> scoreInstance.score).sum() == MAX;
}

public boolean isOverRecord(List<Score> scores) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

isScoreLimit(), isOverRecord() 메소드를 분리한 이유는?
둘 다 필요한가?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

isOverRecord는 Scores에 총 2번 기록이 되는데 이전에 저장되어있는 Score에 지금 몇점의 점수를 추가하려고 하는데 최대 10점(정규 투구)을 넘었을 경우 입력 예외처리를 하기위해서 만들어진 것입니다. 메소드를 사용할 때 이전에 저장되어있다는 조건을 달아주지않아서 의도가 명확하지않았던 것 같습니다.

isScoreLimit은 프레임의 상태를 설정하기 전에 Scores에 점수가 10점인지 아닌지를 물어볼 때 사용하려고 구현했습니다.

두 메소드의 차이는 10점이냐 10점을 넘어가냐의 의미적인 차이와 평가를 할 때 주어지는 조건값이 달라 각각 만들어놓았습니다.

int existingSum = scores.stream().mapToInt(scoreInstance -> scoreInstance.score).sum();
return existingSum + this.score > MAX;
}
}
30 changes: 30 additions & 0 deletions src/main/java/domain/Scores.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package domain;

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

public class Scores {
private static final int LIMIT_NUM = 2;
private List<Score> scores = new ArrayList<>();

public Score addScore(int number) throws IllegalArgumentException {
Score newScore = new Score(number);
if (scores.size() != 0 && newScore.isOverRecord(scores)) {
throw new IllegalArgumentException("합산 : " + Score.MAX + "점을 넘을 수 없습니다");
}
scores.add(newScore);
return newScore;
}

public boolean isFinish() {
return isLimitSize() || isScoreLimit();
}

public boolean isScoreLimit() {
return Score.isScoreLimit(scores);
}

public boolean isLimitSize() {
return scores.size() == LIMIT_NUM;
}
}
10 changes: 10 additions & 0 deletions src/main/java/domain/frame/Frame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package domain.frame;

public interface Frame {

String addScore(int score) throws IllegalArgumentException;

boolean isFinish();

String convertScore(int score);
}
52 changes: 52 additions & 0 deletions src/main/java/domain/frame/Frames.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package domain.frame;

import utils.FrameFactory;

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

public class Frames {
public static final int LIMIT_NUM = 10;
private List<Frame> frames;
private int nextFrameIdx;

public Frames() {
frames = new ArrayList<>();
nextFrameIdx = 0;
}

public String recordScore(int score) {
Frame currentFrame = getCurrentFrame();
String convertedScore = currentFrame.addScore(score);
if (currentFrame.isFinish()) {
nextFrameIdx++;
}
return convertedScore;
}

public Frame getCurrentFrame() {
try {
return frames.get(nextFrameIdx);
} catch (IndexOutOfBoundsException e) {
int frameNum = nextFrameIdx + 1;
frames.add(FrameFactory.of(frameNum));
return frames.get(nextFrameIdx);
}
}

public int getCurrentFrameIdx() {
return nextFrameIdx;
}

public int getCurrentFrameNum() {
return nextFrameIdx + 1;
}

public boolean isFinish() {
return frames.size() == LIMIT_NUM && frames.stream().allMatch(Frame::isFinish);
}

public static boolean isLast(int frameNum) {
return frameNum == LIMIT_NUM;
}
}
48 changes: 48 additions & 0 deletions src/main/java/domain/frame/LastFrame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package domain.frame;

import domain.Score;
import domain.Scores;
import domain.frame.result.ScoreMessage;
import domain.frame.status.FrameStatus;

public class LastFrame implements Frame {
private FrameStatus status;
private Scores scores;
private Score bonusScore;

public LastFrame() {
scores = new Scores();
status = FrameStatus.getInitStatus();
}

@Override
public String addScore(int score) throws IllegalArgumentException {
if (status.isBonus()) {
bonusScore = new Score(score);
return convertScore(score);
}
scores.addScore(score);
status = status.changeStatus(scores);
return convertScore(score);
}

@Override
public String convertScore(int score) {
if (scores.isFinish()) {
return ScoreMessage.convertMessage(score);
}
return status.convertScore(score);
}

@Override
public boolean isFinish() {
if (!status.isFinish()) {
return false;
}

if (!status.isBonus()) {
return true;
}
return bonusScore != null;
}
}
31 changes: 31 additions & 0 deletions src/main/java/domain/frame/NormalFrame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package domain.frame;

import domain.Scores;
import domain.frame.status.FrameStatus;

public class NormalFrame implements Frame {
private FrameStatus status;
private Scores scores;

public NormalFrame() {
scores = new Scores();
status = FrameStatus.getInitStatus();
}

@Override
public String addScore(int score) throws IllegalArgumentException {
scores.addScore(score);
status = status.changeStatus(scores);
return convertScore(score);
}

@Override
public String convertScore(int score) {
return status.convertScore(score);
}

@Override
public boolean isFinish() {
return status.isFinish();
}
}
19 changes: 19 additions & 0 deletions src/main/java/domain/frame/result/FrameResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package domain.frame.result;

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

import static java.util.stream.Collectors.joining;

public class FrameResult {
private List<String> results = new ArrayList<>();

public void add(String resultMessage) {
results.add(resultMessage);
}

@Override
public String toString() {
return results.stream().collect(joining("|"));
}
}
44 changes: 44 additions & 0 deletions src/main/java/domain/frame/result/FrameResults.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package domain.frame.result;

import domain.frame.Frames;

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

public class FrameResults {
private List<FrameResult> results = new ArrayList<>();

public void addResult(int frameIdx, String convertedScore) {
if (!isExistFrameResult(frameIdx)) {
results.add(new FrameResult());
}
FrameResult result = results.get(frameIdx);
result.add(convertedScore);
}

public boolean isExistFrameResult(int frameIdx) {
try {
results.get(frameIdx);
return true;
} catch (IndexOutOfBoundsException e) {
return false;
}
}

public int getSavedSize() {
return results.size();
}

public int getMaxSaveSize() {
return Frames.LIMIT_NUM;
}

public String getFrameResultMessage(int frameIdx) {
try {
FrameResult frameResult = results.get(frameIdx);
return frameResult.toString();
} catch (IndexOutOfBoundsException e) {
return null;
}
}
}
Loading