Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 23 additions & 0 deletions src/main/java/BowlingGameConsoleApp.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import domain.frame.Frame;
import domain.frame.NormalFrame;
import view.InputView;
import view.OutputView;

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

public class BowlingGameConsoleApp {
public static void main(String[] args) {
String playerName = InputView.showGetPlayerNameView();
List<Frame> frames = new ArrayList<>();

do {
int pinCount = InputView.showGetPinCountView(frames);
Frame currentFrame = frames.isEmpty() ? new NormalFrame(pinCount) : frames.get(frames.size() - 1).bowl(pinCount);
if (!frames.contains(currentFrame)) {
frames.add(currentFrame);
}
OutputView.showStatusBoardView(playerName, frames);
} while(!frames.get(frames.size() - 1).isFinalFrame() || !frames.get(frames.size() - 1).isComplete());
}
}
52 changes: 52 additions & 0 deletions src/main/java/domain/Pitch.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package domain;

import domain.frame.Frame;

public class Pitch {
private int pinCount;
private int startPinCount;

public Pitch(int startPinCount, int pinCount) {
if (startPinCount < pinCount) {
throw new IllegalArgumentException("쓰러뜨린 핀수는 투구 시작 전 남아있는 핀수보다 작거나 같아야 한다.");
}
this.startPinCount = startPinCount;
this.pinCount = pinCount;
}

public int getRemainPinCount() {
return startPinCount - pinCount;
}

public boolean isClear() {
return startPinCount - pinCount == 0;
}

public PlayStatus getStatus() {
if(startPinCount == Frame.DEFAULT_START_PIN_COUNT) {
if(pinCount == 0) {
return PlayStatus.GUTTER;
}

if(isClear()) {
return PlayStatus.STRIKE;
}

return PlayStatus.NONE;
}

if(pinCount == 0) {
return PlayStatus.MISS;
}

if(isClear()) {
return PlayStatus.SPARE;
}

return PlayStatus.OPEN;
}

public String getDisplayValue() {
return String.format(getStatus().getDisplayFormat(), pinCount);
}
}
20 changes: 20 additions & 0 deletions src/main/java/domain/PlayStatus.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package domain;

public enum PlayStatus {
STRIKE("X"),
SPARE("/"),
MISS("-"),
GUTTER("-"),
OPEN("%d"),
NONE("%d");

private String displayFormat;

PlayStatus(String displayFormat) {
this.displayFormat = displayFormat;
}

public String getDisplayFormat() {
return displayFormat;
}
}
59 changes: 59 additions & 0 deletions src/main/java/domain/frame/FinalFrame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package domain.frame;

import domain.PlayStatus;
import domain.Pitch;

import java.util.List;

public class FinalFrame extends Frame {
private Pitch thirdPitch;

public FinalFrame(int firstPitch) {
super(Frame.MAX_FRAME_NUMBER, firstPitch);
}

@Override
public List<Pitch> getPitches() {
List<Pitch> pitches = super.getPitches();
if(hasThirdPitch()) {
pitches.add(thirdPitch);
}
return pitches;
}

public boolean hasThirdPitch() {
return thirdPitch != null;
}

@Override
public boolean isComplete() {
if(hasThirdPitch()) {
return true;
}

if(hasSecondPitch()) {
PlayStatus secondPitchStatus = getSecondPitch().getStatus();
return secondPitchStatus == PlayStatus.OPEN
|| secondPitchStatus == PlayStatus.STRIKE;
}

return false;
}

@Override
public Frame bowl(int pinCount) {
if(isComplete()) {
return this;
}

if(!hasSecondPitch()) {
return getLastPitch().isClear() ? super.resetAndBowl(pinCount) : super.bowl(pinCount);
}

if(!hasThirdPitch()) {
thirdPitch = new Pitch(getLastPitch().isClear() ? DEFAULT_START_PIN_COUNT : getLastPitch().getRemainPinCount(), pinCount);
}

return this;
}
}
89 changes: 89 additions & 0 deletions src/main/java/domain/frame/Frame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package domain.frame;

import domain.Pitch;
import domain.PlayStatus;

import java.util.*;


public abstract class Frame {
public static final int DEFAULT_START_PIN_COUNT = 10;
public static final int MIN_FRAME_NUMBER = 1;
public static final int MAX_FRAME_NUMBER = 10;

private Pitch firstPitch;
private Pitch secondPitch;
private Frame nextFrame;
private int frameNumber;


public Frame(int frameNumber, int firstPitch) {
this.frameNumber = frameNumber;
if(firstPitch > DEFAULT_START_PIN_COUNT) {
throw new IllegalArgumentException("10개 이상의 pinCount는 집계할 수 없습니다.");
}
this.firstPitch = new Pitch(DEFAULT_START_PIN_COUNT, firstPitch);
}

public int getFrameNumber() {
return frameNumber;
}

protected Pitch getFirstPitch() {
return firstPitch;
}

protected Pitch getSecondPitch() {
return secondPitch;
}

public List<Pitch> getPitches() {
List<Pitch> pitches = new ArrayList<>();
pitches.add(firstPitch);

if(hasSecondPitch()) {
pitches.add(secondPitch);
}
return pitches;
}

public boolean hasSecondPitch() {
return secondPitch != null;
}

public boolean isFinalFrame() {
return frameNumber == MAX_FRAME_NUMBER;
}

public Frame bowl(int pinCount) {
secondPitch = new Pitch(firstPitch.getRemainPinCount(), pinCount);
return this;
}

public Frame resetAndBowl(int pinCount) {
secondPitch = new Pitch(DEFAULT_START_PIN_COUNT, pinCount);
return this;
}

protected Frame createNextFrame(int firstPitch) {
if(frameNumber == MAX_FRAME_NUMBER) {
throw new IllegalArgumentException("마지막 프레임 이후에는 프레임을 생성할 수 없습니다.");
}

if(frameNumber < MAX_FRAME_NUMBER - 1) {
return nextFrame = new NormalFrame(frameNumber + 1, firstPitch);
}
return nextFrame = new FinalFrame(firstPitch);
}

public PlayStatus getStatus() {
return getLastPitch().getStatus();
}

public Pitch getLastPitch() {
List<Pitch> pitches = getPitches();
return pitches.get(pitches.size() - 1);
}

public abstract boolean isComplete();
}
25 changes: 25 additions & 0 deletions src/main/java/domain/frame/NormalFrame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package domain.frame;

public class NormalFrame extends Frame {
public NormalFrame(int frameNumber, int firstPitch) {
super(frameNumber, firstPitch);
}

public NormalFrame(int firstPitch) {
super(MIN_FRAME_NUMBER, firstPitch);
}

@Override
public boolean isComplete() {
return getFirstPitch().isClear() || getSecondPitch() != null;
}

@Override
public Frame bowl(int pinCount) {
if(isComplete()) {
return createNextFrame(pinCount);
}

return super.bowl(pinCount);
}
}
Empty file removed src/main/java/empty.txt
Empty file.
33 changes: 33 additions & 0 deletions src/main/java/view/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package view;

import domain.frame.Frame;

import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

public class InputView {
private static Scanner scanner = new Scanner(System.in);

public static String showGetPlayerNameView() {
System.out.print("플레이어 이름은(3 english letters)?: ");
return scanner.nextLine();
}

public static int showGetPinCountView(List<Frame> frames) {
System.out.print(getNextFrameNumber(frames) + "프레임 투구 : ");
return Integer.parseInt(scanner.nextLine());
}

private static int getNextFrameNumber(List<Frame> frames) {
if(frames.isEmpty()) {
return Frame.MIN_FRAME_NUMBER;
}

if(frames.get(frames.size() - 1).isComplete()) {
return frames.size() + 1;
}

return frames.size();
}
}
39 changes: 39 additions & 0 deletions src/main/java/view/OutputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package view;

import domain.Pitch;
import domain.PlayStatus;
import domain.frame.FinalFrame;
import domain.frame.Frame;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class OutputView {
public static void showStatusBoardView(String playerName, List<Frame> playedFrames) {
StringBuilder headerBuilder = new StringBuilder("| NAME |");
StringBuilder statusBuilder = new StringBuilder(String.format("| %4s |", playerName));

playedFrames.stream()
.forEach(frame -> {
headerBuilder.append(String.format(" %02d |", frame.getFrameNumber()));
statusBuilder.append(String.format(" %-4s |", getFrameStatus(frame)));
});

IntStream.range(playedFrames.size(), Frame.MAX_FRAME_NUMBER)
.forEach(frameNumber -> {
headerBuilder.append(String.format(" %02d |", frameNumber + 1));
statusBuilder.append(String.format(" %4s |", ""));
});
System.out.println(headerBuilder);
System.out.println(statusBuilder);
}

private static String getFrameStatus(Frame frame) {
List<Pitch> pitches = frame.getPitches();
String displayValue = pitches.stream()
.map(Pitch::getDisplayValue)
.collect(Collectors.joining("|"));
return displayValue;
}
}
9 changes: 9 additions & 0 deletions src/test/java/domain/FrameStatusTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package domain;

import domain.frame.NormalFrame;
import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class FrameStatusTest {
}
23 changes: 23 additions & 0 deletions src/test/java/domain/PitchTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package domain;

import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class PitchTest {
@Test(expected = IllegalArgumentException.class)
public void 생성테스트() {
new Pitch(5, 6);
}

@Test
public void getRemainPinCount테스트() {
assertThat(new Pitch(10, 7).getRemainPinCount()).isEqualTo(3);
}

@Test
public void isClear테스트() {
assertThat(new Pitch(10, 10).isClear()).isEqualTo(true);
assertThat(new Pitch(10, 9).isClear()).isEqualTo(false);
}
}
Loading