Skip to content
Open
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
16 changes: 16 additions & 0 deletions src/main/java/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import game.BaseballGame;
import number_generator.NumberGenerator;
import view.InputView;
import view.OutputView;

import java.io.IOException;

public class Main {
public static void main(String[] args) throws IOException {
InputView inputView = new InputView();
OutputView outputView = new OutputView();
NumberGenerator numberGenerator = new NumberGenerator();
BaseballGame baseballGame = new BaseballGame(inputView, outputView, numberGenerator);
baseballGame.game();
}
}
41 changes: 41 additions & 0 deletions src/main/java/checker/BaseballChecker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package checker;

public class BaseballChecker {
private static final int NUMBER_LENGTH = 3;
private CountVO countVO;
private final String targetNumber;

public BaseballChecker(String targetNumber) {
this.targetNumber = targetNumber;
}

public CheckEnum checkGuess(String slicedGenerated, String given) {
if (slicedGenerated.equals(given)) return CheckEnum.STRIKE;
if (this.targetNumber.contains(given)) return CheckEnum.BALL;
return CheckEnum.NOTHING;
}

public void evaluateGuess(String guess) {
countVO = new CountVO();
for (int i = 1; i <= NUMBER_LENGTH; i++) {
String generatedDigit = targetNumber.substring(i - 1, i);
String guessedDigit = guess.substring(i - 1, i);
CheckEnum checkEnum = this.checkGuess(generatedDigit, guessedDigit);
updateCount(checkEnum);
}
}

private void updateCount(CheckEnum checkEnum) {
if (checkEnum == CheckEnum.STRIKE) {
countVO.increaseStrikeCount();
return;
}
if (checkEnum == CheckEnum.BALL) {
countVO.increaseBallCount();
}
}

public CountVO getResult() {
return this.countVO;
}
}
9 changes: 9 additions & 0 deletions src/main/java/checker/CheckEnum.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package checker;

public enum CheckEnum {
STRIKE,
BALL,
NOTHING


}
60 changes: 60 additions & 0 deletions src/main/java/checker/CountVO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package checker;

import java.util.Objects;

public class CountVO {
private int strikeCount = 0;
private int ballCount = 0;
public int getStrikeCount() {
return strikeCount;
}

public int getBallCount() {
return ballCount;
}

public CountVO() {
}

public CountVO(int strikeCount, int ballCount) {
this.strikeCount = strikeCount;
this.ballCount = ballCount;
}

public void increaseStrikeCount(){
this.strikeCount++;
}

public void increaseBallCount(){
this.ballCount++;
}

public boolean isCorrect(){
return this.strikeCount == 3;
}

public boolean isNothing(){
return this.strikeCount == 0 && this.ballCount == 0;
}

public boolean isNoStrike(){
return this.strikeCount == 0;
}

public boolean isNoBall(){
return this.ballCount == 0;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CountVO countVO = (CountVO) o;
return strikeCount == countVO.strikeCount && ballCount == countVO.ballCount;
}

@Override
public int hashCode() {
return Objects.hash(strikeCount, ballCount);
}
}
46 changes: 46 additions & 0 deletions src/main/java/game/BaseballGame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package game;

import checker.BaseballChecker;
import checker.CountVO;
import number_generator.NumberGenerator;
import view.InputView;
import view.OutputView;

import java.io.IOException;

public class BaseballGame {
private final InputView inputView;
private final OutputView outputView;
private final NumberGenerator numberGenerator;

public BaseballGame(InputView inputView, OutputView outputView, NumberGenerator numberGenerator) {
this.inputView = inputView;
this.outputView = outputView;
this.numberGenerator = numberGenerator;
}

public void game() throws IOException {
outputView.printGetInputNumbers();
guessUntilCorrect();
outputView.moreGame();
if (inputView.getInput()) game();
}

private void guessUntilCorrect() throws IOException {
String targetNumber = numberGenerator.generateNumber();
BaseballChecker checker = new BaseballChecker(targetNumber);
guess(checker);
}

private void guess(BaseballChecker checker) throws IOException {
CountVO countVO = new CountVO();
while (!countVO.isCorrect()){
String input = inputView.getNumericInput();
if (!outputView.validCheck(input)) continue;
// 여기서 인덴트가 2가 되는데, VO가 상태를 추가로 가지게 되는 것보다는 위와 같은 형식이 더 자연스럽다고 판단함
checker.evaluateGuess(input);
countVO = checker.getResult();
outputView.printResult(countVO);
}
}
}
21 changes: 21 additions & 0 deletions src/main/java/number_generator/NumberGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package number_generator;

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

public class NumberGenerator {
public String generateNumber() {
List<Integer> integers = IntStream.range(1, 10)
.boxed()
.collect(Collectors.toList());

Collections.shuffle(integers);

return integers.stream()
.limit(3)
.map(String::valueOf)
.collect(Collectors.joining());
}
}
42 changes: 42 additions & 0 deletions src/main/java/view/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package view;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.Set;

public class InputView {
private static final String RETRY_NUMBER = "1";
public static final String NOT_VALID = "NOT_VALID";
private final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public String getNumericInput() throws IOException {
String input = br.readLine();
if (!validateInput(input)) return NOT_VALID;
return input;
}

public boolean validateInput(String input){
if (input.length() != 3) return false;
try {
Integer.parseInt(input);
} catch (NumberFormatException e){
return false;
}
return isNotDuplicatedNumber(input);
}

private boolean isNotDuplicatedNumber(String input) {
Set<Character> charSet = new HashSet<>();
char[] charArray = input.toCharArray();
for (char c : charArray) {
charSet.add(c);
}
return charSet.size() == 3;
}

public boolean getInput() throws IOException {
String given = br.readLine();
return given.equals(RETRY_NUMBER);
}
}
74 changes: 74 additions & 0 deletions src/main/java/view/OutputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package view;

import checker.CountVO;

public class OutputView {
private static final String PROMPT_INPUT = "숫자를 입력해주세요";
private static final String PROMPT_VALID_INPUT = "세 개의 서로 다른 숫자를 입력하세요";
private static final String CORRECT_MESSAGE = "3개의 숫자를 모두 맞히셨습니다! 게임 종료";
private static final String NOTHING_MESSAGE = "낫싱";
private static final String STRIKE_MESSAGE = "%d스트라이크";
private static final String BALL_MESSAGE = "%d볼";
private static final String STRIKE_AND_BALL_MESSAGE = "%d스트라이크, %d볼";
private static final String MORE_GAME_PROMPT = "한번 더 하시려면 1, 종료하려면 2를 입력하세요";

public void printGetInputNumbers() {
System.out.println(PROMPT_INPUT);
}

public void printResult(CountVO countVO) {
if (isCorrect(countVO)) {
printCorrectMessage();
return;
}
if (countVO.isNothing()) {
printNothingMessage();
return;
}
if (countVO.isNoStrike()) {
printBallMessage(countVO.getBallCount());
return;
}
if (countVO.isNoBall()) {
printStrikeMessage(countVO.getStrikeCount());
return;
}
printStrikeAndBallMessage(countVO.getStrikeCount(), countVO.getBallCount());
}

public boolean validCheck(String input){
if (input.equals(InputView.NOT_VALID)){
System.out.println(PROMPT_VALID_INPUT);
return false;
}
return true;
}

private boolean isCorrect(CountVO countVO) {
return countVO.isCorrect();
}

private void printCorrectMessage() {
System.out.println(CORRECT_MESSAGE);
}

private void printNothingMessage() {
System.out.println(NOTHING_MESSAGE);
}

private void printStrikeMessage(int strikeCount) {
System.out.println(String.format(STRIKE_MESSAGE, strikeCount));
}

private void printBallMessage(int ballCount) {
System.out.println(String.format(BALL_MESSAGE, ballCount));
}

private void printStrikeAndBallMessage(int strikeCount, int ballCount) {
System.out.println(String.format(STRIKE_AND_BALL_MESSAGE, strikeCount, ballCount));
}

public void moreGame() {
System.out.println(MORE_GAME_PROMPT);
}
}
57 changes: 57 additions & 0 deletions src/test/java/CheckerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import checker.BaseballChecker;
import checker.CheckEnum;
import checker.CountVO;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

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

class CheckerTest {
BaseballChecker checker;
@BeforeEach
void init(){
checker = new BaseballChecker("321");
}
@Test
void strikeTest() {
CheckEnum checkEnum = checker.checkGuess("1", "1");
assertThat(checkEnum).isEqualTo(CheckEnum.STRIKE);
}

@Test
void nothingTest(){
CheckEnum checkEnum = checker.checkGuess("1", "8");
assertThat(checkEnum).isEqualTo(CheckEnum.NOTHING);
}

@Test
void ballTest(){
CheckEnum checkEnum = checker.checkGuess("321", "1");
assertThat(checkEnum).isEqualTo(CheckEnum.BALL);
}

@Test
void nothing_ofAll(){
checker.evaluateGuess( "789");
assertThat(checker.getResult()).isEqualTo(new CountVO(0, 0));

}

@Test
void one_ball_one_strike() {
checker.evaluateGuess( "316");
assertThat(checker.getResult()).isEqualTo(new CountVO(1, 1));
}

@Test
void three_strike(){
checker.evaluateGuess( "321");
assertThat(checker.getResult()).isEqualTo(new CountVO(3, 0));
}

@Test
void three_ball(){
checker.evaluateGuess("132");
assertThat(checker.getResult()).isEqualTo(new CountVO(0, 3));
}
}
Loading