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

Step3 볼링점수판 #992

Open
wants to merge 41 commits into
base: parkyunhwan
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
c12bbc0
docs : 도메인 규칙 정리
Parkyunhwan Nov 9, 2022
5adeec4
feat : BowlingPin과 단위테스트 추가
Parkyunhwan Nov 9, 2022
2a9955d
feat : 한라운드의 Pin상태를 관리하고 기록하는 Frame 추가
Parkyunhwan Nov 9, 2022
891c0f9
feat : 볼링점수판 관리 객체 추가
Parkyunhwan Nov 9, 2022
d2f3a0a
feat : 볼링점수판 출력을 위한 추가
Parkyunhwan Nov 10, 2022
e881841
Merge branch 'parkyunhwan' into step2
Parkyunhwan Nov 10, 2022
89511f0
refactor : FrameNumber를 추가하여 프레임진행상태관리
Parkyunhwan Nov 12, 2022
233f0ff
refactor : 마지막 보너스 프레임 로직 frame으로 이동
Parkyunhwan Nov 12, 2022
aa12420
refactor : plus -> next 메서드 명 변경
Parkyunhwan Nov 12, 2022
2c386db
feat : frames 테스트 추가
Parkyunhwan Nov 12, 2022
682acf0
refactor : 프레임 파라미터에서 삭제
Parkyunhwan Nov 12, 2022
c2958f9
refactor : OutputView 출력 로직 개선
Parkyunhwan Nov 12, 2022
0e4cf29
refactor : 사용하지 않는 Scanner 삭제
Parkyunhwan Nov 12, 2022
c8b36eb
refactor : 출력로직 중복 출력되는 문제 수정
Parkyunhwan Nov 12, 2022
8f3d3be
refactor : FinalFrame이 Frame을 상속받아 상이한 조건 부분을 오버라이딩 처리
Parkyunhwan Nov 15, 2022
fb52c6a
refactor : 다형성을 이용해 Frame객체만으로 일반프레임과 마지막프레임 수행할 수 있도록 수정
Parkyunhwan Nov 15, 2022
be3e100
refactor : 컬렉션 필드값에 final 추가
Parkyunhwan Nov 15, 2022
0370f04
refactor : 마지막프레임의 로직인 pitchingLast삭제
Parkyunhwan Nov 15, 2022
7c0be80
refactor : score 추가
Parkyunhwan Nov 16, 2022
4cffcd9
refactor : score를 저장하고 miss가 났을 때 점수를 계산하도록 추가
Parkyunhwan Nov 16, 2022
1aa45f6
feat : 점수출력 추가
Parkyunhwan Nov 16, 2022
3149326
feat : BowlingPin과 단위테스트 추가
Parkyunhwan Nov 9, 2022
5cf08a5
feat : 한라운드의 Pin상태를 관리하고 기록하는 Frame 추가
Parkyunhwan Nov 9, 2022
aee060a
feat : 볼링점수판 관리 객체 추가
Parkyunhwan Nov 9, 2022
02b2620
feat : 볼링점수판 출력을 위한 추가
Parkyunhwan Nov 10, 2022
6240488
refactor : FrameNumber를 추가하여 프레임진행상태관리
Parkyunhwan Nov 12, 2022
0fa9b91
refactor : 마지막 보너스 프레임 로직 frame으로 이동
Parkyunhwan Nov 12, 2022
1b7adc3
refactor : plus -> next 메서드 명 변경
Parkyunhwan Nov 12, 2022
93a9a5d
feat : frames 테스트 추가
Parkyunhwan Nov 12, 2022
2ef1e8f
refactor : 프레임 파라미터에서 삭제
Parkyunhwan Nov 12, 2022
793292b
refactor : OutputView 출력 로직 개선
Parkyunhwan Nov 12, 2022
94be0c5
refactor : 사용하지 않는 Scanner 삭제
Parkyunhwan Nov 12, 2022
5e8d2e3
refactor : 출력로직 중복 출력되는 문제 수정
Parkyunhwan Nov 12, 2022
6812ccb
refactor : FinalFrame이 Frame을 상속받아 상이한 조건 부분을 오버라이딩 처리
Parkyunhwan Nov 15, 2022
1e39ba1
refactor : 다형성을 이용해 Frame객체만으로 일반프레임과 마지막프레임 수행할 수 있도록 수정
Parkyunhwan Nov 15, 2022
6f4a592
refactor : 컬렉션 필드값에 final 추가
Parkyunhwan Nov 15, 2022
011e1a0
refactor : 마지막프레임의 로직인 pitchingLast삭제
Parkyunhwan Nov 15, 2022
0f996a8
refactor : score 추가
Parkyunhwan Nov 16, 2022
7ef92d9
refactor : score를 저장하고 miss가 났을 때 점수를 계산하도록 추가
Parkyunhwan Nov 16, 2022
443d2f3
feat : 점수출력 추가
Parkyunhwan Nov 16, 2022
832c52f
Merge remote-tracking branch 'origin/step2' into step2
Parkyunhwan Nov 16, 2022
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
2 changes: 1 addition & 1 deletion src/main/java/bowling/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static void main(String[] args) {
frameNumber = bowlingGame.pitchingBall(count);

Frames frames = bowlingGame.getFrames();
OutputView.printScoreScreen(username, frames);
OutputView.printScoreScreen(username, frames, bowlingGame);
}
}
}
7 changes: 4 additions & 3 deletions src/main/java/bowling/BowlingGame.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ public BowlingGame() {
}

public FrameNumber pitchingBall(int hitCount) {

Choose a reason for hiding this comment

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

pitchingBall메서드에서 반환값이 필요할까요? 🤔

if (frameNumber.isSameNumber(FRAME_SIZE)) {
return frames.pitchingLast(frameNumber, hitCount);
}
this.frameNumber = frames.pitching(frameNumber, hitCount);
return this.frameNumber;
}

public Frames getFrames() {
return frames;
}

public FrameNumber getFrameNumber() {
return frameNumber;
}
}
22 changes: 22 additions & 0 deletions src/main/java/bowling/FinalFrame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package bowling;

public class FinalFrame extends Frame {

Choose a reason for hiding this comment

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

Frame을 상속하는 FinalFrame을 만들어주셨네요!
다만 일반 Frame은 Frame객체를 만들어서 사용중인데요, FinalFrame과 공통된 기능은 묶고 서로 다르게 동작해야하는 것들은 추상메서드로 만들어보면 어떨까요?


@Override
public boolean strikeCondition() {
return (!hitRecords.hitTimes(HIT_TWICE) || hitRecords.isRecordAllStrike()) && bowlingPin.isZero();
}

@Override
public boolean finishFrame() {
boolean result = hitRecords.hitTimes(HIT_TRIPLE) || failedBounsFrame();
if (clearAllFrame()) {
chargeBowlingPin();
}
return result;
}

private boolean failedBounsFrame() {
return hitRecords.hitTimes(HIT_TWICE) && !clearAllFrame();
}
}
77 changes: 26 additions & 51 deletions src/main/java/bowling/Frame.java
Original file line number Diff line number Diff line change
@@ -1,89 +1,64 @@
package bowling;

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

public class Frame {
private static final int HIT_ONCE = 1;
private static final int HIT_TWICE = 2;
private static final int HIT_TRIPLE = 3;
protected static final int HIT_TWICE = 2;
protected static final int HIT_TRIPLE = 3;

private BowlingPin bowlingPin;
private final List<HitRecord> hitRecords;
protected BowlingPin bowlingPin;
protected final HitRecords hitRecords;

public Frame() {
this.bowlingPin = new BowlingPin(BowlingPin.MAX_PIN_NUMBER);
hitRecords = new ArrayList<>();
this.hitRecords = new HitRecords();
}

public boolean finishLastFrame() {
return hitThreeTimes() || hitDouble() || failedBounsFrame();
}

private boolean failedBounsFrame() {
return hitTwice() && !clearAllFrame();
}

public void hitBowlingPin(int count) {
public BowilingTerm hitBowlingPin(int count) {
bowlingPin = bowlingPin.hitPins(new BowlingPin(count));
BowilingTerm bowilingTerm = BowilingTerm.MISS;
if ((hitRecords.isEmpty() || hitRecords.size() == HIT_TRIPLE || hitStrike()) && bowlingPin.isZero()) {
bowilingTerm = BowilingTerm.STRIKE;
hitRecords.add(new HitRecord(count, bowilingTerm));
return ;
if (hitRecords.hitOnce() && bowlingPin.isZero()) {
hitRecords.addSpare();
return BowilingTerm.SPARE;
}

if (hitRecords.size() == HIT_ONCE && bowlingPin.isZero()) {
bowilingTerm = BowilingTerm.SPARE;
hitRecords.add(new HitRecord(count, bowilingTerm));
return ;
if (strikeCondition()) {
hitRecords.addStrike();
return BowilingTerm.STRIKE;
}

if (count == 0) {
bowilingTerm = BowilingTerm.GUTTER;
hitRecords.add(new HitRecord(count, bowilingTerm));
return ;
if (count == BowlingPin.ZERO) {
hitRecords.addGutter();
return BowilingTerm.GUTTER;
}
hitRecords.add(new HitRecord(count, bowilingTerm));
hitRecords.addMiss(count);
return BowilingTerm.MISS;
}

private boolean hitStrike() {
for (HitRecord hitRecord : hitRecords) {
if (!hitRecord.hitAll()) {
return false;
}
}
return true;
}

public boolean finishFrame() {
return clearAllFrame() || hitTwice();
protected boolean strikeCondition() {
return bowlingPin.isZero();
}

public boolean hitDouble() {
if (hitRecords.size() != HIT_TWICE) {
return false;
}
return hitStrike();
protected boolean finishFrame() {
return clearAllFrame() || hitRecords.hitTimes(HIT_TWICE);
Comment on lines +41 to +42

Choose a reason for hiding this comment

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

위와 같은 내용이지만 FinalFrame이 이 메서드를 override를 하는것보다 각기 구현하는게 구조가 더 나아보여요~

}

public void chargeBowlingPin() {
bowlingPin = new BowlingPin(BowlingPin.MAX_PIN_NUMBER);
}

public List<HitRecord> getHitRecords() {
return hitRecords;
return hitRecords.getHitRecords();
}

public boolean clearAllFrame() {
return bowlingPin.isZero();
}

public boolean hitThreeTimes() {
return hitRecords.size() == HIT_TRIPLE;
public void calculateBonus(int hitCount) {
hitRecords.calculateBonus(hitCount);
}

public boolean hitTwice() {
return hitRecords.size() == HIT_TWICE;
public HitRecords hitRecords() {
return hitRecords;
}
}
33 changes: 15 additions & 18 deletions src/main/java/bowling/Frames.java
Original file line number Diff line number Diff line change
@@ -1,39 +1,36 @@
package bowling;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

public class Frames {
private final List<Frame> frames;
private final LinkedList<Frame> frames;

public Frames(int size) {
this.frames = new ArrayList<>();
for (int i = 0; i < size; i++) {
this.frames = new LinkedList<>();
for (int i = 0; i < size - 1; i++) {
this.frames.add(new Frame());
}
this.frames.add(new FinalFrame());
}

public FrameNumber pitching(FrameNumber frameNumber, int hitCount) {
Frame frame = frames.get(frameNumber.retrieveIndexNumber());
frame.hitBowlingPin(hitCount);
if (frame.finishFrame()) {
return frameNumber.next();
BowilingTerm bowilingTerm = frame.hitBowlingPin(hitCount);

if (!bowilingTerm.equals(BowilingTerm.STRIKE)) {
ListIterator<Frame> frameListIterator = frames.listIterator(frameNumber.retrieveIndexNumber());
while (frameListIterator.hasPrevious()) {
Frame previous = frameListIterator.previous();
previous.calculateBonus(hitCount);
}
Comment on lines +23 to +28

Choose a reason for hiding this comment

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

depth를 줄이는 방향으로 고민해보면 어떨까요?

}
return frameNumber;
}


public FrameNumber pitchingLast(FrameNumber frameNumber, int hitCount) {
Frame frame = frames.get(frameNumber.retrieveIndexNumber());
frame.hitBowlingPin(hitCount);
if (frame.finishLastFrame()) {
if (frame.finishFrame()) {
return frameNumber.next();
}

if (frame.clearAllFrame()) {
frame.chargeBowlingPin();
return frameNumber;
}
return frameNumber;
}

Expand Down
4 changes: 4 additions & 0 deletions src/main/java/bowling/HitRecord.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ public class HitRecord {
private final int hitCount;
private final BowilingTerm bowilingTerm;

public static HitRecord of(int count, BowilingTerm bowilingTerm) {
return new HitRecord(count, bowilingTerm);
}

public HitRecord(int count, BowilingTerm bowilingTerm) {
this.hitCount = count;
this.bowilingTerm = bowilingTerm;
Expand Down
67 changes: 64 additions & 3 deletions src/main/java/bowling/HitRecords.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,72 @@
package bowling;

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

public class HitRecords {
private List<HitRecord> hitRecords;
private static final int HIT_ONCE = 1;

public HitRecords(List<HitRecord> hitRecords) {
this.hitRecords = hitRecords;
private final List<HitRecord> hitRecords;
private Score score;
Comment on lines +9 to +10

Choose a reason for hiding this comment

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

HitRecord안에 Score를 관리할 수 있는 구조로 개선해보면 어떨까요? 구조가 좀 많이 바뀔거같긴한데 한번 참고만 해보셔요!
추가적으로 도메인에 대한 테스트도 추가되면 더 좋을거같아요 :)


public HitRecords() {
this.hitRecords = new ArrayList<>();
this.score = Score.ofZero();
}

public boolean hitOnce() {
return hitRecords.size() == HIT_ONCE;
}


public void addRecord(HitRecord hitRecord) {
this.hitRecords.add(hitRecord);
}

public void addStrike() {
this.hitRecords.add(HitRecord.of(10, BowilingTerm.STRIKE));
score = Score.ofStrike();
}

public void addSpare() {
this.hitRecords.add(HitRecord.of(10, BowilingTerm.SPARE));
score = Score.ofSpare();
}

public void addGutter() {
this.hitRecords.add(HitRecord.of(0, BowilingTerm.GUTTER));
score = Score.ofMiss(hitSum());
}

public void addMiss(int count) {
this.hitRecords.add(HitRecord.of(count, BowilingTerm.MISS));
score = Score.ofMiss(hitSum());
}

public boolean isRecordAllStrike() {
return hitRecords.stream()
.allMatch(HitRecord::hitAll);
}

public boolean hitTimes(int hitTwice) {
return hitRecords.size() == hitTwice;
}

public List<HitRecord> getHitRecords() {
return hitRecords;
}

private int hitSum() {
return hitRecords.stream().mapToInt(HitRecord::getHitCount).sum();
}

public void calculateBonus(int hitCount) {
if (score.remainBonus()) {
score = score.addBonusScore(hitCount);
}
}

public Score getScore() {
return score;
}
}
47 changes: 47 additions & 0 deletions src/main/java/bowling/Score.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package bowling;

public class Score {
private final int hitCount;
private final int bonusCount;

public static Score ofZero() {
return new Score(0, -1);
}

public static Score ofStrike() {
return new Score(10, 2);
}

public static Score ofSpare() {
return new Score(10, 1);
}

public static Score ofMiss(int hitCount) {
return new Score(hitCount, 0);
}

private Score(int hitCount, int bonusCount) {
this.hitCount = hitCount;
this.bonusCount = bonusCount;
}

public boolean remainBonus() {
return bonusCount != 0;
}

public Score addBonusScore(int hitCount) {
return new Score(this.hitCount + hitCount, bonusCount - 1);
}

public int getHitCount() {
return hitCount;
}

public int getBonusCount() {
return bonusCount;
}

public boolean isMiss() {
return hitCount != 10;
}
}
12 changes: 12 additions & 0 deletions src/main/java/bowling/Scores.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package bowling;

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

public class Scores {

Choose a reason for hiding this comment

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

쓰이지 않는것 같네요 :)

private final List<Score> scores;

public Scores() {
this.scores = new ArrayList<>();
}
}
Loading