diff --git a/docs/README.md b/docs/README.md index e69de29bb2..fa06da19b0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,8 @@ +# 기능 목록 + +- [x] 게임 관리 - GameManager class + - [x] 게임 시작 - start() +- [x] 숫자 야구 구현 - BaseballGame class + - [x] 세 자리수 랜덤 숫자 생성 - generateAnswer() + - [x] 사용자 입력 받기 - receiveUserInput() + - [x] 사용자 숫자를 받아 채점 및 정답 여부 반환 - score() \ No newline at end of file diff --git a/src/main/java/baseball/Application.java b/src/main/java/baseball/Application.java index dd95a34214..3c0aad9897 100644 --- a/src/main/java/baseball/Application.java +++ b/src/main/java/baseball/Application.java @@ -2,6 +2,7 @@ public class Application { public static void main(String[] args) { - // TODO: 프로그램 구현 + GameManager gameManager = new GameManager(); + gameManager.start(); } } diff --git a/src/main/java/baseball/BaseballGame.java b/src/main/java/baseball/BaseballGame.java new file mode 100644 index 0000000000..0b7b1f293f --- /dev/null +++ b/src/main/java/baseball/BaseballGame.java @@ -0,0 +1,109 @@ +package baseball; + +import camp.nextstep.edu.missionutils.Console; +import camp.nextstep.edu.missionutils.Randoms; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class BaseballGame { + + private Integer answer; + + public BaseballGame() { + this.answer = 0; + } + + public Integer getAnswer() { + return answer; + } + + public int generateAnswer() { + + AtomicInteger index = new AtomicInteger(); + + LinkedHashSet numbers = new LinkedHashSet<>(); + while (numbers.size() < 3) { + numbers.add(Randoms.pickNumberInRange(1, 9)); + } + + answer = numbers.stream().reduce(0, (x, y) -> { + int result = (int) (x + y * Math.pow(10, 2 - index.doubleValue())); + index.getAndIncrement(); + return result; + }); + return answer; + } + + public int receiveUserInput() { + System.out.print("숫자를 입력해주세요 : "); + + String input = Console.readLine(); + validateInput(input); + + try { + return Integer.parseInt(input); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("잘못된 입력 형식입니다."); + } + } + + private void validateInput(String input) { + if (input.length() != 3) { + throw new IllegalArgumentException("잘못된 입력 형식입니다."); + } + } + + public boolean score(int answer, int userAnswer) { + + List answerDigits = getDigits(answer); + List userAnswerDigits = getDigits(userAnswer); + + int strike = 0; + int ball = 0; + for (int index = 0; index < 3; index++) { + int num = userAnswerDigits.get(index); + + if (num == answerDigits.get(index)) { + strike++; + continue; + } + + if (answerDigits.contains(num)) { + ball++; + } + } + + StringBuilder sb = new StringBuilder(); + if (strike == 0 && ball == 0) { + sb.append("낫싱"); + } + + if (ball > 0) { + sb.append(ball).append("볼 "); + } + if (strike > 0) { + sb.append(strike).append("스트라이크 "); + } + System.out.println(sb); + + if (strike == 3) { + System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료"); + return true; + } + return false; + } + + private static List getDigits(int num) { + List answerNums = new ArrayList<>(); + int current = num; + for (int i = 0; i < 3; i++) { + answerNums.add(0, current % 10); + current /= 10; + } + return answerNums; + } +} diff --git a/src/main/java/baseball/GameManager.java b/src/main/java/baseball/GameManager.java new file mode 100644 index 0000000000..5619fc1daf --- /dev/null +++ b/src/main/java/baseball/GameManager.java @@ -0,0 +1,37 @@ +package baseball; + +import camp.nextstep.edu.missionutils.Console; + +public class GameManager { + + private BaseballGame game; + + public GameManager() { + this.game = new BaseballGame(); + } + + public void start() { + + System.out.println("숫자 야구 게임을 시작합니다."); + game.generateAnswer(); + + boolean result = false; + while (!result) { + int userInput = game.receiveUserInput(); + result = game.score(game.getAnswer(), userInput); + } + + String endInput = askRestart(); + if (endInput.equals("1")) { + start(); + } + if (endInput.equals("2")) { + return; + } + } + + private String askRestart() { + System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."); + return Console.readLine(); + } +} diff --git a/src/test/java/baseball/BaseballGameTest.java b/src/test/java/baseball/BaseballGameTest.java new file mode 100644 index 0000000000..05ac4184a0 --- /dev/null +++ b/src/test/java/baseball/BaseballGameTest.java @@ -0,0 +1,95 @@ +package baseball; + +import camp.nextstep.edu.missionutils.Console; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.PrintStream; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; + +class BaseballGameTest { + + private BaseballGame baseballGame; + + private final InputStream originalIn = System.in; + private final PrintStream originalOut = System.out; + private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + + @BeforeEach + void setUp() { + baseballGame = new BaseballGame(); + System.setOut(new PrintStream(outputStream)); + } + + @AfterEach + void tearDown() { + System.setOut(originalOut); + System.setIn(originalIn); + } + + @Test + void generateAnswer_정답을_answer에_채워넣는다() { + baseballGame.generateAnswer(); + + assertThat(baseballGame.getAnswer()).isNotEqualTo(0); + } + + @Test + void generateAnswer_정답은_세자리수_이다() { + baseballGame.generateAnswer(); + + int length = baseballGame.getAnswer().toString().length(); + assertThat(length).isEqualTo(3); + } + + @Test + void receiveUserInput_유저의_입력을_반환한다() { + String input = "123"; + ByteArrayInputStream inputStream = new ByteArrayInputStream(input.getBytes()); + System.setIn(inputStream); + + int result = baseballGame.receiveUserInput(); + + assertThat(result).isEqualTo(Integer.parseInt(input)); + } + + @Test + void score_한개만_맞으면_1스트라이크를_출력한다() { + boolean result = baseballGame.score(123, 145); + + String output = outputStream.toString().trim(); + + assertThat(result).isFalse(); + assertThat(output).isEqualTo("1스트라이크"); + } + + @Test + void score_다른_자리에_같은_숫자가_있으면_1볼을_출력한다() { + boolean result = baseballGame.score(123, 245); + + String output = outputStream.toString().trim(); + + assertThat(result).isFalse(); + assertThat(output).isEqualTo("1볼"); + } + + @Test + void score_3숫자_모두_맞추면_정답메세지를_출력하고_true를_반환한다() { + boolean result = baseballGame.score(123, 123); + + String output = outputStream.toString().trim(); + + assertThat(result).isTrue(); + assertThat(output).isEqualTo("3스트라이크 \n" + + "3개의 숫자를 모두 맞히셨습니다! 게임 종료"); + } +} \ No newline at end of file diff --git a/src/test/java/baseball/GameManagerTest.java b/src/test/java/baseball/GameManagerTest.java new file mode 100644 index 0000000000..4124bee819 --- /dev/null +++ b/src/test/java/baseball/GameManagerTest.java @@ -0,0 +1,12 @@ +package baseball; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class GameManagerTest { + + @Test + void start() { + } +} \ No newline at end of file