-
Notifications
You must be signed in to change notification settings - Fork 432
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 - 볼링 점수판(그리기) #993
base: mnyok
Are you sure you want to change the base?
Step2 - 볼링 점수판(그리기) #993
Changes from all commits
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,22 @@ | ||
package bowling; | ||
|
||
import bowling.domain.Hit; | ||
import bowling.domain.Name; | ||
import bowling.domain.Round; | ||
import bowling.view.InputView; | ||
import bowling.view.ResultView; | ||
|
||
public class App { | ||
|
||
public static void main(String[] args) { | ||
Name name = InputView.inputName(); | ||
|
||
Round round = new Round(); | ||
ResultView.printRound(name, round); | ||
while (!round.isEnd()) { | ||
Hit hit = InputView.inputPins(round.getCurrentFrameNumber()); | ||
round.hit(hit); | ||
ResultView.printRound(name, round); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package bowling.domain; | ||
|
||
public interface Frame { | ||
|
||
void play(Hit hit); | ||
|
||
FrameStatus getFirstStatus(); | ||
FrameStatus getSecondStatus(); | ||
FrameStatus getThirdStatus(); | ||
Comment on lines
+7
to
+9
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.
|
||
|
||
Hit getFirstHit(); | ||
Hit getSecondHit(); | ||
Hit getThirdHit(); | ||
|
||
boolean isEnd(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package bowling.domain; | ||
|
||
public enum FrameStatus { | ||
BEFORE, | ||
PLAYING, | ||
SKIP, | ||
STRIKE, | ||
SPARE, | ||
MISS, | ||
GUTTER; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package bowling.domain; | ||
|
||
public class Hit { | ||
public static final int MIN = 0; | ||
public static final int MAX = 10; | ||
private final int hit; | ||
|
||
|
||
public Hit(int hit) { | ||
Comment on lines
+7
to
+9
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. 👍 |
||
validate(hit); | ||
this.hit = hit; | ||
} | ||
|
||
private void validate(int hit) { | ||
if (hit < MIN || hit > MAX) { | ||
throw new IllegalArgumentException("범위를 벗어나는 점수가 입력되었습니다."); | ||
} | ||
} | ||
|
||
public Hit plus(Hit target) { | ||
return new Hit(hit + target.hit); | ||
} | ||
|
||
public boolean isMin() { | ||
return hit == MIN; | ||
} | ||
|
||
public boolean isMax() { | ||
return hit == MAX; | ||
} | ||
|
||
public int getScore() { | ||
return hit; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (!(obj instanceof Hit)) { | ||
return false; | ||
} | ||
return hit == ((Hit) obj).hit; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package bowling.domain; | ||
|
||
public class LastFrame implements Frame { | ||
private Hit first; | ||
private Hit second; | ||
private Hit third; | ||
|
||
@Override | ||
public void play(Hit hit) { | ||
if (getFirstStatus() == FrameStatus.BEFORE) { | ||
firstThrow(hit); | ||
return; | ||
} | ||
if (getSecondStatus() == FrameStatus.BEFORE) { | ||
secondThrow(hit); | ||
return; | ||
} | ||
thirdThrow(hit); | ||
} | ||
|
||
private void firstThrow(Hit hit) { | ||
this.first = hit; | ||
} | ||
|
||
private void secondThrow(Hit hit) { | ||
this.second = hit; | ||
} | ||
|
||
private void thirdThrow(Hit hit) { | ||
this.third = hit; | ||
} | ||
|
||
@Override | ||
public FrameStatus getFirstStatus() { | ||
return getNormalStatus(first); | ||
} | ||
|
||
@Override | ||
public FrameStatus getSecondStatus() { | ||
if (first == null || second == null) { | ||
return FrameStatus.BEFORE; | ||
} | ||
if (first.isMax()) { | ||
return getNormalStatus(second); | ||
} | ||
Hit sum = first.plus(second); | ||
if (sum.isMax()) { | ||
return FrameStatus.SPARE; | ||
} | ||
if (second.isMin()) { | ||
return FrameStatus.GUTTER; | ||
} | ||
return FrameStatus.MISS; | ||
} | ||
|
||
@Override | ||
public FrameStatus getThirdStatus() { | ||
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. 각 상태에 따른 if 문이 너무 많다. |
||
if (first == null || second == null || third == null) { | ||
return FrameStatus.BEFORE; | ||
} | ||
if (!canPlayThird()) { | ||
return FrameStatus.SKIP; | ||
} | ||
if (third.isMax()) { | ||
return FrameStatus.STRIKE; | ||
} | ||
if (third.isMin()) { | ||
return FrameStatus.GUTTER; | ||
} | ||
if (second.isMax()) { | ||
return FrameStatus.MISS; | ||
} | ||
Hit sum = second.plus(third); | ||
if (sum.isMax()) { | ||
return FrameStatus.SPARE; | ||
} | ||
return FrameStatus.MISS; | ||
} | ||
|
||
private FrameStatus getNormalStatus(Hit hit) { | ||
if (hit == null) { | ||
return FrameStatus.BEFORE; | ||
} | ||
if (hit.isMax()) { | ||
return FrameStatus.STRIKE; | ||
} | ||
if (hit.isMin()) { | ||
return FrameStatus.GUTTER; | ||
} | ||
return FrameStatus.MISS; | ||
} | ||
|
||
@Override | ||
public Hit getFirstHit() { | ||
return first; | ||
} | ||
|
||
@Override | ||
public Hit getSecondHit() { | ||
return second; | ||
} | ||
|
||
@Override | ||
public Hit getThirdHit() { | ||
return third; | ||
} | ||
|
||
@Override | ||
public boolean isEnd() { | ||
if (first == null || second == null) { | ||
return false; | ||
} | ||
if (third != null) { | ||
return true; | ||
} | ||
return !canPlayThird(); | ||
} | ||
|
||
private boolean canPlayThird() { | ||
return getFirstStatus() == FrameStatus.STRIKE || getSecondStatus() == FrameStatus.SPARE; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package bowling.domain; | ||
|
||
public class Name { | ||
private final String name; | ||
|
||
|
||
public Name(String name) { | ||
validate(name); | ||
this.name = name; | ||
} | ||
|
||
private void validate(String name) { | ||
if (name.length() != 3) { | ||
throw new IllegalArgumentException("이름은 3글자로 입력되어야 합니다"); | ||
} | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package bowling.domain; | ||
|
||
public class NormalFrame implements Frame { | ||
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. NormalFrame과 FinalFrame을 보면 중복 코드가 많다. |
||
private Hit first; | ||
private Hit second; | ||
|
||
@Override | ||
public void play(Hit hit) { | ||
if (getFirstStatus() == FrameStatus.BEFORE) { | ||
firstThrow(hit); | ||
return; | ||
} | ||
secondThrow(hit); | ||
} | ||
|
||
private void firstThrow(Hit hit) { | ||
this.first = hit; | ||
if (hit.isMax()) { | ||
second = new Hit(0); | ||
} | ||
} | ||
|
||
private void secondThrow(Hit hit) { | ||
this.second = hit; | ||
} | ||
|
||
@Override | ||
public FrameStatus getFirstStatus() { | ||
if (first == null) { | ||
return FrameStatus.BEFORE; | ||
} | ||
if (first.isMax()) { | ||
return FrameStatus.STRIKE; | ||
} | ||
if (first.isMin()) { | ||
return FrameStatus.GUTTER; | ||
} | ||
return FrameStatus.MISS; | ||
} | ||
|
||
@Override | ||
public FrameStatus getSecondStatus() { | ||
if (first == null || second == null) { | ||
return FrameStatus.BEFORE; | ||
} | ||
if (first.isMax()) { | ||
return FrameStatus.SKIP; | ||
} | ||
Hit sum = first.plus(second); | ||
if (sum.isMax()) { | ||
return FrameStatus.SPARE; | ||
} | ||
if (second.isMin()) { | ||
return FrameStatus.GUTTER; | ||
} | ||
return FrameStatus.MISS; | ||
} | ||
|
||
@Override | ||
public FrameStatus getThirdStatus() { | ||
return FrameStatus.SKIP; | ||
} | ||
|
||
@Override | ||
public Hit getFirstHit() { | ||
return first; | ||
} | ||
|
||
@Override | ||
public Hit getSecondHit() { | ||
return second; | ||
} | ||
|
||
@Override | ||
public Hit getThirdHit() { | ||
return new Hit(0); | ||
} | ||
|
||
@Override | ||
public boolean isEnd() { | ||
return first != null && second != null; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package bowling.domain; | ||
|
||
import java.util.List; | ||
import java.util.Optional; | ||
import java.util.function.Consumer; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.IntStream; | ||
|
||
public class Round { | ||
private static final int ROUND_COUNT = 10; | ||
private final List<Frame> frames; | ||
|
||
public Round() { | ||
frames = IntStream.range(0, ROUND_COUNT - 1) | ||
.mapToObj(i -> new NormalFrame()) | ||
.collect(Collectors.toList()); | ||
frames.add(new LastFrame()); | ||
} | ||
|
||
public void hit(Hit hit) { | ||
Frame last = getLastPlayingFrame() | ||
.orElseThrow(() -> new IllegalStateException("모든 프레임이 종료되었습니다.")); | ||
last.play(hit); | ||
} | ||
|
||
public boolean isEnd() { | ||
Optional<Frame> last = getLastPlayingFrame(); | ||
return last.isEmpty(); | ||
} | ||
|
||
public int getCurrentFrameNumber() { | ||
Optional<Frame> last = getLastPlayingFrame(); | ||
if (last.isEmpty()) { | ||
return ROUND_COUNT; | ||
} | ||
Frame currentFrame = last.get(); | ||
return frames.indexOf(currentFrame) + 1; | ||
|
||
} | ||
|
||
private Optional<Frame> getLastPlayingFrame() { | ||
return frames.stream() | ||
.filter(frame -> !frame.isEnd()) | ||
.findFirst(); | ||
} | ||
|
||
public void forEach(Consumer<Frame> consumer) { | ||
frames.forEach(consumer); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package bowling.view; | ||
|
||
import bowling.domain.Name; | ||
import bowling.domain.Hit; | ||
|
||
import java.util.Scanner; | ||
|
||
public class InputView { | ||
private static final Scanner scanner = new Scanner(System.in); | ||
|
||
public static Name inputName() { | ||
System.out.print("플레이어 이름은 (3 english letters)?: "); | ||
|
||
String name = scanner.nextLine(); | ||
return new Name(name); | ||
} | ||
|
||
public static Hit inputPins(int frame) { | ||
System.out.printf("%d프레임 투구: ", frame); | ||
|
||
return new Hit(scanner.nextInt()); | ||
} | ||
} |
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.
인터페이스에 메서드 수가 너무 많다.
메서드 수를 줄일 수 있는 방법을 찾아보면 어떨까?