diff --git a/src/main/java/BowlingMain.java b/src/main/java/BowlingMain.java new file mode 100644 index 00000000..6df7935c --- /dev/null +++ b/src/main/java/BowlingMain.java @@ -0,0 +1,28 @@ +import domain.BowlingGame; +import domain.Player; +import view.InputView; +import view.ResultView; + +import java.util.List; +import java.util.Scanner; + +public class BowlingMain { + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + BowlingGame bowlingGame = new BowlingGame(); + List players = bowlingGame.createPlayer(InputView.getUserName(scanner, InputView.getUserCount(scanner))); + + ResultView.printScoreBoard(players); + for (int index = 1; index < 11; index++) { + for (Player player : players) { + while (!bowlingGame.isEndFrame(player)) { + bowlingGame.bowl(player, InputView.getThrowing(scanner, player.getName())); + ResultView.printScoreBoard(players); + } + if (index < 10) { + bowlingGame.nextFrame(player); + } + } + } + } +} diff --git a/src/main/java/domain/BowlingGame.java b/src/main/java/domain/BowlingGame.java new file mode 100644 index 00000000..0ba5a2ac --- /dev/null +++ b/src/main/java/domain/BowlingGame.java @@ -0,0 +1,35 @@ +package domain; + +import state.State; + +import java.util.ArrayList; +import java.util.List; + +public class BowlingGame { + private static final int FIRST = 1; + private List players; + + public List createPlayer(List names) { + players = new ArrayList<>(); + for (String name : names) { + players.add(new Player(name)); + } + return players; + } + + public Pins createPins(int falledPins) { + return new Pins(falledPins); + } + + public State bowl(Player player, int falledPins) { + return player.bowl(createPins(falledPins)); + } + + public boolean isEndFrame(Player player) { + return player.isEnd(); + } + + public Frame nextFrame(Player player) { + return player.nextFrame(); + } +} diff --git a/src/main/java/domain/Frame.java b/src/main/java/domain/Frame.java new file mode 100644 index 00000000..e360c72d --- /dev/null +++ b/src/main/java/domain/Frame.java @@ -0,0 +1,27 @@ +package domain; + +import state.State; + +abstract public class Frame { + private static final int MAX_FRAME_NO = 10; + + public Frame(int no) { + isValidNo(no); + } + + abstract public State bowl(Pins falledPins); + abstract public boolean isEnd(); + abstract public String printState(); + abstract public Score createScore(int beforeScore); + abstract public int getScore(int beforeScore); + abstract public Frame next(); + abstract public boolean isLastFrame(); + abstract public int calculateAdditionalScore(Score beforeScore); + + public boolean isValidNo(int no) { + if ( no < 0 || no > 10 ) { + throw new RuntimeException("프레임의 번호는 0부터 10사이 입니다. 생성 시도한 프레임 번호는 " + no); + } + return true; + } +} diff --git a/src/main/java/domain/Frames.java b/src/main/java/domain/Frames.java new file mode 100644 index 00000000..6e3e6104 --- /dev/null +++ b/src/main/java/domain/Frames.java @@ -0,0 +1,42 @@ +package domain; + +import java.util.ArrayList; +import java.util.List; + +public class Frames { + private static final int FIRST = 1; + private static final int MAX_FRAME = 10; + + private List frames = new ArrayList<>(); + + public Frame createFirstFrame() { + return new NormalFrame(FIRST); + } + + public boolean isEmpty() { + return frames.isEmpty(); + } + + public int getFinishedFrame() { + return frames.size(); + } + + public void add(Frame frame) { + if (frames.size() > MAX_FRAME) { + throw new RuntimeException("1경기당 최대 10프레임입니다."); + } + frames.add(frame); + } + + public boolean equalsFrameCount(int frameCount) { + return frames.size() == frameCount; + } + + public String printFramesState(int index) { + return frames.get(index).printState(); + } + + public int printFramesScore(int index, int beforeScore) { + return frames.get(index).getScore(beforeScore); + } +} \ No newline at end of file diff --git a/src/main/java/domain/LastFrame.java b/src/main/java/domain/LastFrame.java new file mode 100644 index 00000000..0562c203 --- /dev/null +++ b/src/main/java/domain/LastFrame.java @@ -0,0 +1,97 @@ +package domain; + +import state.*; + +import java.util.ArrayList; +import java.util.List; + +public class LastFrame extends Frame { + private static final int FIRST_STATE = 0; + private static final int MAX = 3; + + private List states = new ArrayList<>(); + private State state = new Ready(); + private int index; + + public LastFrame(int no) { + super(no); + } + + @Override + public State bowl(Pins falledPins) { + state = state.bowl(falledPins); + if (FirstBowl.isFirstBowl(state) || Strike.isStrike(state)) { + states.add(state); + return state; + } + try { + states.set(index, state.clone()); + index++; + if (!Open.isOpen(state)) { + state = new Ready(); + } + } catch (CloneNotSupportedException e) { + e.getMessage(); + } + return state; + } + + @Override + public boolean isEnd() { + if (Open.isOpen(state) || states.size() == MAX) { + return true; + } + if (states.size() == 2 && Spare.isSpare(states.get(FIRST_STATE))) { + return true; + } + return false; + } + + @Override + public String printState() { + StringBuilder sb = new StringBuilder(); + for (State state : states) { + sb.append(state.printState()); + } + return sb.toString(); + } + + @Override + public Score createScore(int beforeScore) { + return states.get(0).getScore().calculateScore(beforeScore); + } + + @Override + public int getScore(int beforeScore) { + Score score = createScore(beforeScore); + if (score.canCalculateScore()) { + return score.getScore(); + } + return calculateAdditionalScore(score, 1); + } + + public int calculateAdditionalScore(Score beforeScore) { + return calculateAdditionalScore(beforeScore, 0); + } + + public int calculateAdditionalScore(Score beforeScore, int index) { + for (int i = index; i < states.size(); i++) { + state = states.get(index); + beforeScore = state.updateScore(beforeScore); + if (beforeScore.canCalculateScore()) { + return beforeScore.getScore(); + } + } + return 0; + } + + @Override + public Frame next() { + throw new RuntimeException("마지막 프레임에서는 다음 프레임을 생성할 수 없습니다."); + } + + @Override + public boolean isLastFrame() { + return true; + } +} diff --git a/src/main/java/domain/NormalFrame.java b/src/main/java/domain/NormalFrame.java new file mode 100644 index 00000000..d0515498 --- /dev/null +++ b/src/main/java/domain/NormalFrame.java @@ -0,0 +1,80 @@ +package domain; + +import state.Ready; +import state.State; + +public class NormalFrame extends Frame { + private static final int MAX_FRAME_NO = 10; + + private final int no; + private Frame next; + private State state = new Ready(); // strike; + + public NormalFrame(int no) { + super(no); + this.no = no; + } + + @Override + public State bowl(Pins falledPins) { + return state = state.bowl(falledPins); + } + + @Override + public Frame next() { + if (no == MAX_FRAME_NO - 1) { + return next = new LastFrame(no + 1); + } + return next = new NormalFrame(no + 1); + } + + @Override + public boolean isLastFrame() { + return false; + } + + @Override + public boolean isEnd() { + return state.isEnd(); + } + + @Override + public String printState() { + return state.printState(); + } + + @Override + public Score createScore(int beforeScore) { + return state.getScore().calculateScore(beforeScore); + } + + @Override + public int getScore(int beforeScore) { + Score score = createScore(beforeScore); + if (score.canCalculateScore()) { + return score.getScore(); + } + if (next != null) { + return next.calculateAdditionalScore(score); + } + return 0; + } + + public int calculateAdditionalScore(Score beforeScore) { + if (!Ready.isReady(state)) { + beforeScore = state.updateScore(beforeScore); + } + if (beforeScore.canCalculateScore()) { + return beforeScore.getScore(); + } + if (next != null) { + return next.calculateAdditionalScore(beforeScore); + } + return 0; + } + + @Override + public String toString() { + return "no : " + no + ", next : " + next.toString() + ", state : " + state.printState(); + } +} \ No newline at end of file diff --git a/src/main/java/domain/Pins.java b/src/main/java/domain/Pins.java new file mode 100644 index 00000000..bd0e85ce --- /dev/null +++ b/src/main/java/domain/Pins.java @@ -0,0 +1,62 @@ +package domain; + +public class Pins { + private static final int MAX_PINS = 10; + private static final int MIN_PINS = 0; + + private final int falledPins; + + public Pins(int falledPins) { + isValid(falledPins); + this.falledPins = falledPins; + } + + public boolean isValid(int falledPins) { + if (falledPins > MAX_PINS) { + throw new IllegalArgumentException( + String.format("볼링 핀은 최대 10을 넘을 수 없습니다. 현재 쓰러진 핀 수는 %d", falledPins)); + } + + if (falledPins < MIN_PINS) { + throw new IllegalArgumentException( + String.format("볼링 핀은 최초 0 미만이 될 수 없습니다. 현재 쓰러진 핀 수는 %d", falledPins)); + } + return true; + } + + public boolean isStrike() { + return this.falledPins == MAX_PINS; + } + + public boolean isSpare(Pins secondPins) { + return this.falledPins + secondPins.falledPins == MAX_PINS; + } + + public boolean isOpen(Pins secondPins) { + return this.falledPins + secondPins.falledPins < MAX_PINS; + } + + public boolean isGutter() { + return falledPins == MIN_PINS; + } + + @Override + public String toString() { + return String.valueOf(falledPins); + } + + public static int sumPins(Pins first, Pins second) { + if (first.falledPins + second.falledPins > 10 && first.falledPins + second.falledPins < 0) { + throw new RuntimeException("Pins.java : 쓰러진 핀의 합계는 0~10까지 입니다."); + } + return first.falledPins + second.falledPins; + } + + public int sumScore(int score) { + return this.falledPins + score; + } + + public Score createFirstBowlScore(int left) { + return new Score(falledPins, left); + } +} diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java new file mode 100644 index 00000000..d5288f7c --- /dev/null +++ b/src/main/java/domain/Player.java @@ -0,0 +1,67 @@ +package domain; + +import state.State; + +public class Player { + private final String name; + private Frames frames; + private Frame frame; + + public Player(String name) { + this.name = name; + frames = new Frames(); + frame = frames.createFirstFrame(); + } + + public String getName() { + return name; + } + + public String printPlayingFrameState() { + return frame.printState(); + } + + public State bowl(Pins falledPins) { + State state = frame.bowl(falledPins); + if (frame.isEnd()) { + saveFrameData(); + return state; + } + return state; + } + + public boolean isEnd() { + return frame.isEnd(); + } + + public int getFinishedFrame() { + return frames.getFinishedFrame(); + } + + public void saveFrameData() { + frames.add(frame); + } + + public String printFramesState(int index) { + return frames.printFramesState(index); + } + + public int printFramesScore(int index, int beforeScore) { + return frames.printFramesScore(index, beforeScore); + } + + public Frame nextFrame() { + return frame = frame.next(); + } + + public boolean isLastFrame() { + return frame.isLastFrame(); + } + + public String printLastFrameState() { + if (frame.isLastFrame()) { + return frame.printState(); + } + throw new RuntimeException("마지막 프레임이 아닙니다."); + } +} diff --git a/src/main/java/domain/Score.java b/src/main/java/domain/Score.java new file mode 100644 index 00000000..0e1e3499 --- /dev/null +++ b/src/main/java/domain/Score.java @@ -0,0 +1,51 @@ +package domain; + +public class Score { + private static final int NO_LEFT = 0; + private static final int MAX_PINS = 10; + + private int score; + private int left; + + public Score(int score, int left) { + this.score = score; + this.left = left; + } + + public static Score ofOpen(Pins first, Pins second) { + return new Score(Pins.sumPins(first, second), 0); + } + + public static Score ofSpare() { + return new Score(MAX_PINS, 1); + } + + public static Score ofStrike() { + return new Score(MAX_PINS, 2); + } + + public Score bowl(Pins falledPins) { + return new Score(score = falledPins.sumScore(score), left -= 1); + } + + public int getScore() { + return this.score; + } + + public int getLeft() { + return this.left; + } + + public boolean canCalculateScore() { + return left == NO_LEFT; + } + + public Score calculateScore(int score) { + return new Score(this.score + score, left); + } + + @Override + public String toString() { + return "score : " + score + " left : " + left; + } +} diff --git a/src/main/java/empty.txt b/src/main/java/empty.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/src/main/java/state/FirstBowl.java b/src/main/java/state/FirstBowl.java new file mode 100644 index 00000000..353011d2 --- /dev/null +++ b/src/main/java/state/FirstBowl.java @@ -0,0 +1,47 @@ +package state; + +import domain.Pins; +import domain.Score; + +public class FirstBowl extends State { + private static final String GUTTER = "-"; + private static final int NO_LEFT = 0; + + private Pins falledPins; + + public FirstBowl(Pins falledPins) { + super(false); + this.falledPins = falledPins; + } + + @Override + public State bowl(Pins falledPins) { + if (this.falledPins.isSpare(falledPins)) { + return new Spare(this.falledPins, falledPins); + } + return new Open(this.falledPins, falledPins); + } + + @Override + public Score updateScore(Score beforeScore) { + return beforeScore.bowl(falledPins); + } + + @Override + public String printState() { + String falledPins = String.valueOf(this.falledPins); + if (this.falledPins.isGutter()) { + falledPins = GUTTER; + } + return falledPins; + } + + @Override + public Score getScore() { + return falledPins.createFirstBowlScore(NO_LEFT); + } + + public static boolean isFirstBowl(State state) { + return state instanceof FirstBowl; + } +} diff --git a/src/main/java/state/Open.java b/src/main/java/state/Open.java new file mode 100644 index 00000000..6237d1f0 --- /dev/null +++ b/src/main/java/state/Open.java @@ -0,0 +1,60 @@ +package state; + +import domain.Pins; +import domain.Score; + +public class Open extends State implements Cloneable { + private static final int MIN_PINS = 0; + private static final String GUTTER = "-"; + private static final String PIPE = "|"; + + private final Pins first; + private final Pins second; + + public Open(Pins first, Pins second) { + super(true); + this.first = first; + this.second = second; + } + + @Override + public String printState() { + String first = this.first.toString(); + String second = this.second.toString(); + if (this.first.isGutter()) { + first = GUTTER; + } + if (this.second.isGutter()) { + second = GUTTER; + } + return first + PIPE + second; + } + + public static boolean isOpen(State state) { + return state instanceof Open; + } + + @Override + public Score getScore() { + return Score.ofOpen(first, second); + } + + @Override + public State bowl(Pins falledPins) { + throw new RuntimeException("Open 프레임에서는 더이상 투구할 수 없습니다."); + } + + @Override + public State clone() throws CloneNotSupportedException { + return super.clone(); + } + + @Override + public Score updateScore(Score beforeScore) { + beforeScore.bowl(first); + if (beforeScore.canCalculateScore()) { // left == 0 + return beforeScore; + } + return beforeScore.bowl(second); + } +} diff --git a/src/main/java/state/Ready.java b/src/main/java/state/Ready.java new file mode 100644 index 00000000..70c012a7 --- /dev/null +++ b/src/main/java/state/Ready.java @@ -0,0 +1,39 @@ +package state; + +import domain.Pins; +import domain.Score; + +public class Ready extends State { + private static final String EMPTY = ""; + + public Ready() { + super(false); + } + + @Override + public State bowl(Pins falledPins) { + if (falledPins.isStrike()) { + return new Strike(); + } + return new FirstBowl(falledPins); + } + + @Override + public Score updateScore(Score beforeScore) { + throw new RuntimeException("Ready : 계산할 수 없는 상태입니다."); + } + + @Override + public String printState() { + return EMPTY; + } + + @Override + public Score getScore() { + throw new RuntimeException("Ready : 현재 상태에서는 점수를 구할 수 없습니다."); + } + + public static boolean isReady(State state) { + return state instanceof Ready; + } +} diff --git a/src/main/java/state/Spare.java b/src/main/java/state/Spare.java new file mode 100644 index 00000000..dd040c99 --- /dev/null +++ b/src/main/java/state/Spare.java @@ -0,0 +1,57 @@ +package state; + +import domain.Pins; +import domain.Score; + +public class Spare extends State { + private static final String PIPE = "|"; + private static final String SPARE = "/"; + private static final String GUTTER = "-"; + + private final Pins first; + private final Pins second; + + public Spare(Pins first, Pins second) { + super(true); + this.first = first; + this.second = second; + } + + @Override + public String printState() { + String first = this.first.toString(); + if (this.first.isGutter()) { + first = GUTTER; + } + return first + PIPE + SPARE; + } + + public static boolean isSpare(State state) { + return state instanceof Spare; + } + + @Override + public State bowl(Pins falledPins) { + throw new RuntimeException("Spare.java : 해당 상태에서는 투구할 수 없습니다."); + } + + @Override + public Score getScore() { + return Score.ofSpare(); + } + + + @Override + public State clone() throws CloneNotSupportedException { + return super.clone(); + } + + @Override + public Score updateScore(Score beforeScore) { + beforeScore.bowl(first); + if (!beforeScore.canCalculateScore()) { + return beforeScore.bowl(second); + } + return beforeScore; + } +} diff --git a/src/main/java/state/Statable.java b/src/main/java/state/Statable.java new file mode 100644 index 00000000..b61f0fee --- /dev/null +++ b/src/main/java/state/Statable.java @@ -0,0 +1,8 @@ +package state; + +import domain.Score; + +public interface Statable { + String printState(); + Score getScore(); +} diff --git a/src/main/java/state/State.java b/src/main/java/state/State.java new file mode 100644 index 00000000..1be273c2 --- /dev/null +++ b/src/main/java/state/State.java @@ -0,0 +1,40 @@ +package state; + +import domain.Pins; +import domain.Score; + +import java.util.Objects; + +abstract public class State implements Statable, Cloneable { + private final boolean state; + + public State(boolean state) { + this.state = state; + } + + public boolean isEnd() { + return state; + } + + abstract public State bowl(Pins falledPins); + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + State state1 = (State) o; + return this.getClass().equals(state1.getClass()); + } + + @Override + public int hashCode() { + return Objects.hash(this); + } + + @Override + public State clone() throws CloneNotSupportedException { + return (State) super.clone(); + } + + abstract public Score updateScore(Score beforeScore); +} diff --git a/src/main/java/state/Strike.java b/src/main/java/state/Strike.java new file mode 100644 index 00000000..6c8968b0 --- /dev/null +++ b/src/main/java/state/Strike.java @@ -0,0 +1,45 @@ +package state; + +import domain.Pins; +import domain.Score; + +public class Strike extends State implements Cloneable { + private static final String STRIKE = "X"; + private static final int MAX_PINS = 10; + + public Strike() { + super(true); + } + + @Override + public String printState() { + return STRIKE; + } + + @Override + public State bowl(Pins falledPins) { + if (falledPins.isStrike()) { + return new Strike(); + } + return new FirstBowl(falledPins); + } + + public static boolean isStrike(State state) { + return state instanceof Strike; + } + + @Override + public Score getScore() { + return Score.ofStrike(); + } + + @Override + public State clone() throws CloneNotSupportedException { + return super.clone(); + } + + @Override + public Score updateScore(Score beforeScore) { + return beforeScore.bowl(new Pins(MAX_PINS)); + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 00000000..1508fa8a --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,33 @@ +package view; + +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +public class InputView { + public static List getUserName(Scanner scanner, int count) { + scanner.reset(); + List users = new ArrayList<>(); + for (int index = 0; index < count; index++) { + System.out.print("플레이어 " + (index + 1) + "의 이름은(3 english letters)?: "); + String name = scanner.nextLine(); + users.add(name); + } + return users; + } + + public static int getThrowing(Scanner scanner, String name) { + System.out.print("\n" + name + "'s trun : "); + return scanner.nextInt(); + } + + public static int getUserCount(Scanner scanner) { + System.out.print("How many people? "); + try { + return Integer.parseInt(scanner.nextLine()); + } catch (NumberFormatException e) { + System.out.println("숫자만 입력해주세요."); + return getUserCount(scanner); + } + } +} diff --git a/src/main/java/view/ResultView.java b/src/main/java/view/ResultView.java new file mode 100644 index 00000000..a5576126 --- /dev/null +++ b/src/main/java/view/ResultView.java @@ -0,0 +1,74 @@ +package view; + +import domain.Player; + +import java.util.List; + +public class ResultView { + static final private String NAME_TITLE = "| NAME |"; + static final private String EMPTY_SCORE = " |"; + static final private int MAX_FRAME = 10; + + private static void printHeader() { + StringBuilder sb = new StringBuilder(); + sb.append(NAME_TITLE); + for (int index = 0; index < 10; index++) { + sb.append(String.format(" %02d |", index + 1)); + } + System.out.println(sb.toString()); + } + + private static void printSymbol(Player player) { + StringBuilder sb = new StringBuilder(); + int offset = 0; // 현재 상태 출력시 공백 조절 + sb.append(String.format("| %3s |", player.getName())); + for (int index = 0; index < player.getFinishedFrame(); index++) { + sb.append(String.format(" %4s |", player.printFramesState(index))); + } + if (!player.isLastFrame() && !player.isEnd()) { + sb.append(String.format(" %4s |", player.printPlayingFrameState())); + offset = -1; + } + if (player.isLastFrame() && !player.isEnd()) { + sb.append(String.format(" %4s |", player.printLastFrameState())); + offset = -1; + } + for (int index = 0; index < MAX_FRAME - player.getFinishedFrame() + offset; index++) { + sb.append(EMPTY_SCORE); + } + offset = 0; + System.out.println(sb.toString()); + } + + public static void printScore(Player player) { + int beforeScore = 0; + StringBuilder sb = new StringBuilder(); + + sb.append("|" + EMPTY_SCORE); + for (int index = 0; index < player.getFinishedFrame(); index++) { + beforeScore = player.printFramesScore(index, beforeScore); + sb.append(String.format(" %-3s |", beforeScore)); + } + for (int index = 0; index < MAX_FRAME - player.getFinishedFrame(); index++) { + sb.append(EMPTY_SCORE); + } + System.out.println(sb.toString()); + } + + public static void printEmptyScore() { + printHeader(); + StringBuilder sb = new StringBuilder(); + for (int index = 0; index < 10; index++) { + sb.append(EMPTY_SCORE); + } + System.out.println(sb.toString()); + } + + public static void printScoreBoard(List players) { + printHeader(); + for (Player player : players) { + printSymbol(player); + printScore(player); + } + } +} \ No newline at end of file diff --git a/src/test/java/domain/BowlingGameTest.java b/src/test/java/domain/BowlingGameTest.java new file mode 100644 index 00000000..6b3e167c --- /dev/null +++ b/src/test/java/domain/BowlingGameTest.java @@ -0,0 +1,49 @@ +package domain; + +import org.junit.Before; +import org.junit.Test; +import view.InputView; + +import java.util.Arrays; +import java.util.List; +import java.util.Scanner; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class BowlingGameTest { + private List names; + private BowlingGame bowlingGame; + + @Before + public void setUp() { + names = Arrays.asList("htw"); + bowlingGame = new BowlingGame(); + } + + @Test + public void generateGame() { + bowlingGame = new BowlingGame(); + } + + @Test + public void createPlayer() { + List players = bowlingGame.createPlayer(names); + assertEquals(1, players.size()); + } + + @Test + public void bowl() { + Scanner scanner = new Scanner("10"); + List players = bowlingGame.createPlayer(Arrays.asList("htw", "pjs")); + bowlingGame.bowl(players.get(0), InputView.getThrowing(scanner, players.get(0).getName())); + } + + @Test + public void isEndFrame() { + List players = bowlingGame.createPlayer(Arrays.asList("htw", "pjs")); + bowlingGame.bowl(players.get(0), 4); + bowlingGame.bowl(players.get(0), 6); + assertTrue(bowlingGame.isEndFrame(players.get(0))); + } +} diff --git a/src/test/java/domain/FrameTest.java b/src/test/java/domain/FrameTest.java new file mode 100644 index 00000000..29935b96 --- /dev/null +++ b/src/test/java/domain/FrameTest.java @@ -0,0 +1,36 @@ +package domain; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class FrameTest { + private Frame frame; + + @Test + public void frameNoValidationPass() { + frame = new NormalFrame(1); + assertTrue(frame.isValidNo(1)); + } + + @Test(expected = RuntimeException.class) + public void frameNoValidationFail1() { + frame = new NormalFrame(1); + frame.isValidNo(11); + } + + @Test(expected = RuntimeException.class) + public void frameNoValidationFail2() { + frame = new NormalFrame(1); + frame.isValidNo(-1); + } + + @Test + public void generateLastFrame() { + Frame normalFrame = new NormalFrame(9); + Frame lastFrame = normalFrame.next(); + assertTrue(lastFrame instanceof LastFrame); + } +} diff --git a/src/test/java/domain/FramesTest.java b/src/test/java/domain/FramesTest.java new file mode 100644 index 00000000..86a9625f --- /dev/null +++ b/src/test/java/domain/FramesTest.java @@ -0,0 +1,63 @@ +package domain; + +import org.junit.Before; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +public class FramesTest { + private Frames frames; + + @Before + public void setUp() { + frames = new Frames(); + } + + @Test + public void createFirstFrame() { + Frame frame = frames.createFirstFrame(); + } + + @Test + public void isEmpty() { + frames.isEmpty(); + } + + @Test + public void add() { + Frame frame = frames.createFirstFrame(); + frames.add(frame); + } + + @Test + public void equalsFrameCount() { + Frame frame = frames.createFirstFrame(); + frames.add(frame); + assertEquals(true, frames.equalsFrameCount(1)); + } + + @Test + public void printFramesState() { + Frame frame = new NormalFrame(1); + frame.bowl(new Pins(3)); + frame.bowl(new Pins(7)); + frames.add(frame); + assertThat(frames.printFramesState(0), is("3|/")); + } + + @Test + public void printFramesScore() { + Frame frame1 = new NormalFrame(1); + frame1.bowl(new Pins(3)); + frame1.bowl(new Pins(7)); + frames.add(frame1); + + Frame frame2 = frame1.next(); + frame2.bowl(new Pins(10)); + frames.add(frame2); + + assertThat(frames.printFramesScore(0, 0), is(20)); + } +} diff --git a/src/test/java/domain/LastFrameTest.java b/src/test/java/domain/LastFrameTest.java new file mode 100644 index 00000000..d36c19e7 --- /dev/null +++ b/src/test/java/domain/LastFrameTest.java @@ -0,0 +1,149 @@ +package domain; + +import org.junit.Before; +import org.junit.Test; +import state.Open; +import state.Ready; +import state.State; +import state.Strike; + +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertTrue; + +public class LastFrameTest { + private List frames; + private Frame lastFrame; + + @Before + public void setup() { + frames = new ArrayList<>(); + for (int index = 0; index < 9; index++) { + Frame frame = new NormalFrame(index + 1); + frame.bowl(new Pins(1)); + frame.bowl(new Pins(9)); + frames.add(frame); + } + lastFrame = frames.get(8).next(); + } + + @Test + public void updateStateToStrike() { + State state = lastFrame.bowl(new Pins(10)); + assertTrue(Strike.isStrike(state)); + } + + @Test + public void updateStateToOpen() { + lastFrame.bowl(new Pins(1)); // 초구 + State state = lastFrame.bowl(new Pins(8)); + assertTrue(Open.isOpen(state)); + } + + @Test + public void updateState() { + // 내부적으로 다음 상태를 위해 Open을 제외한 나머지의 경우 Ready로 초기화 + State state = lastFrame.bowl(new Pins(1)); + state = lastFrame.bowl(new Pins(9)); + assertTrue(Ready.isReady(state)); + } + + @Test + public void isEnd_open일때() { + lastFrame.bowl(new Pins(1)); + lastFrame.bowl(new Pins(8)); + assertTrue(lastFrame.isEnd()); + } + + @Test + public void isEnd_spare후_보너스투구() { + lastFrame.bowl(new Pins(1)); + lastFrame.bowl(new Pins(9)); + lastFrame.bowl(new Pins(10)); + assertTrue(lastFrame.isEnd()); + } + + @Test + public void isEnd_초구스트라이크후_spare() { + lastFrame.bowl(new Pins(10)); + lastFrame.bowl(new Pins(1)); + lastFrame.bowl(new Pins(9)); + assertTrue(lastFrame.isEnd()); + } + + @Test + public void isEnd_초구스트라이크후_open() { + lastFrame.bowl(new Pins(10)); + lastFrame.bowl(new Pins(1)); + lastFrame.bowl(new Pins(8)); + assertTrue(lastFrame.isEnd()); + } + + @Test + public void isEnd_초구_2구_스트라이크후_마지막투구() { + lastFrame.bowl(new Pins(10)); + lastFrame.bowl(new Pins(10)); + lastFrame.bowl(new Pins(1)); + assertTrue(lastFrame.isEnd()); + } + + @Test + public void isEnd_세번모두스트라이크() { + lastFrame.bowl(new Pins(10)); + lastFrame.bowl(new Pins(10)); + lastFrame.bowl(new Pins(10)); + assertTrue(lastFrame.isEnd()); + } + + @Test + public void printState_모두스트라이크() { + lastFrame.bowl(new Pins(10)); + lastFrame.bowl(new Pins(10)); + lastFrame.bowl(new Pins(10)); + assertThat(lastFrame.printState(), is("XXX")); + } + + @Test + public void printState_spare후_스트라이크() { + lastFrame.bowl(new Pins(1)); + lastFrame.bowl(new Pins(9)); + lastFrame.bowl(new Pins(10)); + assertThat(lastFrame.printState(), is("1|/X")); + } + + @Test + public void printState_open() { + lastFrame.bowl(new Pins(1)); + lastFrame.bowl(new Pins(8)); + assertThat(lastFrame.printState(), is("1|8")); + } + + @Test + public void createScore() { + lastFrame.bowl(new Pins(1)); + lastFrame.bowl(new Pins(8)); + Score score = lastFrame.createScore(10); + assertThat(score.getScore(), is(19)); + } + + @Test + public void getScore() { + lastFrame.bowl(new Pins(1)); + lastFrame.bowl(new Pins(9)); + lastFrame.bowl(new Pins(10)); + assertThat(lastFrame.getScore(10), is(30)); + } + + @Test(expected = RuntimeException.class) + public void cannotGenerateNextFrame() { + lastFrame.next(); + } + + @Test + public void isLastFrame() { + assertThat(lastFrame.isLastFrame(), is(true)); + } +} diff --git a/src/test/java/domain/NormalFrameTest.java b/src/test/java/domain/NormalFrameTest.java new file mode 100644 index 00000000..4b972652 --- /dev/null +++ b/src/test/java/domain/NormalFrameTest.java @@ -0,0 +1,33 @@ +package domain; + +import org.junit.Before; +import org.junit.Test; +import state.Strike; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class NormalFrameTest { + private Frame frame; + + @Before + public void setUp() { + frame = new NormalFrame(1); + } + + @Test + public void bowl() { + assertTrue(Strike.isStrike(frame.bowl(new Pins(10)))); + } + + @Test + public void isLastFrame() { + assertFalse(frame.isLastFrame()); + } + + @Test + public void isEnd() { + frame.bowl(new Pins(10)); + assertTrue(frame.isEnd()); + } +} \ No newline at end of file diff --git a/src/test/java/domain/PinsTest.java b/src/test/java/domain/PinsTest.java new file mode 100644 index 00000000..c87a7eec --- /dev/null +++ b/src/test/java/domain/PinsTest.java @@ -0,0 +1,38 @@ +package domain; + +import org.junit.Before; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +public class PinsTest { + private Pins pins; + + @Before + public void setUp() { + pins = new Pins(1); + } + + @Test + public void generate() { + pins = new Pins(1); + } + + @Test + public void isValid() { + assertTrue(pins.isValid(1)); + } + @Test + public void sumPins() { + assertThat(Pins.sumPins(new Pins(4), new Pins(5)),is(9)); + } + + @Test + public void createFirstBowlScore() { + Pins pins = new Pins(5); + Score score = pins.createFirstBowlScore(0); + assertThat(score.toString(),is("score : 5 left : 0")); + } +} diff --git a/src/test/java/domain/PlayerTest.java b/src/test/java/domain/PlayerTest.java new file mode 100644 index 00000000..004af1e7 --- /dev/null +++ b/src/test/java/domain/PlayerTest.java @@ -0,0 +1,54 @@ +package domain; + +import org.junit.Before; +import org.junit.Test; +import state.Strike; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class PlayerTest { + private Player player; + private Frames frames; + + @Before + public void setUp() { + player = new Player("htw"); + } + + @Test + public void name() { + assertEquals("htw", player.getName()); + } + + @Test + public void bowl() { + assertTrue(Strike.isStrike(player.bowl(new Pins(10)))); + } + + @Test + public void isEnd() { + player.bowl(new Pins(10)); + assertTrue(player.isEnd()); + } + + @Test + public void getFinishedFrame() { + player.bowl(new Pins(10)); + assertEquals(1, player.getFinishedFrame()); + } + + @Test + public void saveFrameData() { + while (!player.isEnd()) { + player.bowl(new Pins(10)); + } + player.saveFrameData(); + } + + @Test + public void printPlayingFrameState() { + player.bowl(new Pins(8)); + assertEquals("8", player.printPlayingFrameState()); + } +} diff --git a/src/test/java/domain/ScoreTest.java b/src/test/java/domain/ScoreTest.java new file mode 100644 index 00000000..35e652df --- /dev/null +++ b/src/test/java/domain/ScoreTest.java @@ -0,0 +1,27 @@ +package domain; + +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +public class ScoreTest { + @Test + public void generate() { + Score myScore = new Score(10, 2); + } + + @Test + public void throwing() { + Score myScore = new Score(10, 2); + Score renewScore = myScore.bowl(new Pins(10)); + assertThat(1, is(renewScore.getLeft())); + } + + @Test + public void generateSpareScore() { + Score spare = Score.ofSpare(); + assertThat(10, is(spare.getScore())); + assertThat(1, is(spare.getLeft())); + } +} diff --git a/src/test/java/empty.txt b/src/test/java/empty.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/src/test/java/state/OpenTest.java b/src/test/java/state/OpenTest.java new file mode 100644 index 00000000..a34668ec --- /dev/null +++ b/src/test/java/state/OpenTest.java @@ -0,0 +1,29 @@ +package state; + +import domain.Pins; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class OpenTest { + private State state; + + @Test + public void equals() { + state = new Open(new Pins(1), new Pins(5)); + assertTrue(Open.isOpen(state)); + } + + @Test + public void print() { + state = new Open(new Pins(1), new Pins(5)); + assertEquals("1|5",state.printState()); + } + + @Test + public void printWithGutter() { + state = new Open(new Pins(0), new Pins(5)); + assertEquals("-|5",state.printState()); + } +} diff --git a/src/test/java/state/ReadyTest.java b/src/test/java/state/ReadyTest.java new file mode 100644 index 00000000..0aed266f --- /dev/null +++ b/src/test/java/state/ReadyTest.java @@ -0,0 +1,27 @@ +package state; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class ReadyTest { + private State state; + + @Test + public void generate() { + state = new Ready(); + } + + @Test + public void equals() { + state = new Ready(); + assertTrue(Ready.isReady(state)); + } + + @Test + public void print() { + state = new Ready(); + assertEquals("", state.printState()); + } +} diff --git a/src/test/java/state/SpareTest.java b/src/test/java/state/SpareTest.java new file mode 100644 index 00000000..8c59fade --- /dev/null +++ b/src/test/java/state/SpareTest.java @@ -0,0 +1,23 @@ +package state; + +import domain.Pins; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class SpareTest { + private State state; + + @Test + public void generate() { + state = new Spare(new Pins(1), new Pins(9)); + assertTrue(Spare.isSpare(state)); + } + + @Test + public void print() { + state = new Spare(new Pins(2), new Pins(8)); + assertEquals("2|/", state.printState()); + } +} diff --git a/src/test/java/state/StateTest.java b/src/test/java/state/StateTest.java new file mode 100644 index 00000000..f09f51b2 --- /dev/null +++ b/src/test/java/state/StateTest.java @@ -0,0 +1,23 @@ +package state; + +import domain.Pins; +import org.junit.Test; + +import static junit.framework.TestCase.assertTrue; + +public class StateTest { + @Test + public void equals() { + State state1 = new Ready(); + State state2 = new Ready(); + assertTrue(state1.equals(state2)); + } + + @Test + public void isEndAllState() { + State open = new Open(new Pins(1), new Pins(2)); + State spare = new Spare(new Pins(1), new Pins(9)); + State strike = new Strike(); + assertTrue(open.isEnd() && spare.isEnd() && strike.isEnd()); + } +} diff --git a/src/test/java/state/StrikeTest.java b/src/test/java/state/StrikeTest.java new file mode 100644 index 00000000..0b026d45 --- /dev/null +++ b/src/test/java/state/StrikeTest.java @@ -0,0 +1,27 @@ +package state; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class StrikeTest { + private State state; + + @Test + public void generate() { + state = new Strike(); + } + + @Test + public void equals() { + state = new Strike(); + assertTrue(Strike.isStrike(state)); + } + + @Test + public void print() { + state = new Strike(); + assertEquals("X", state.printState()); + } +} diff --git a/src/test/java/view/InputViewTest.java b/src/test/java/view/InputViewTest.java new file mode 100644 index 00000000..a795744f --- /dev/null +++ b/src/test/java/view/InputViewTest.java @@ -0,0 +1,16 @@ +package view; + +import domain.Player; +import org.junit.Test; + +import java.util.Scanner; + +import static org.junit.Assert.assertEquals; + +public class InputViewTest { + @Test + public void userCount() { + Scanner scanner = new Scanner("2"); + assertEquals(2, InputView.getUserCount(scanner)); + } +}