diff --git a/README.md b/README.md index 8d7e8aee..4c3efd6c 100644 --- a/README.md +++ b/README.md @@ -1 +1,17 @@ -# java-baseball-precourse \ No newline at end of file +# java-baseball-precourse + +## 1. View +1. 정답 추측: "숫자를 입력해주세요" 문구 출력 후 사용자 입력 받는 기능 +2. 힌트: 입력받은 결과를 처리하여 힌트를 출력하는 기능 +3. 게임 클리어: 클리어 문구 출력 후 다시하기 여부를 입력받는 기능 + +## 2. Validator +1. 추측 검증: 추측 정보를 검증하는 기능 +2. 다시하기 검증: 다시 시작 정보를 검증하는 기능 + +## 3. GameService +1. 무작위 정답 숫자를 생성하는 새 게임 기능 +2. 입력과 정답을 비교하여 결과를 반환하는 기능 + +## 4. Game +1. 실행: 위 기능들을 사용하여 게임의 전체적인 흐름을 관리하고 게임을 진행하는 기능 \ No newline at end of file diff --git a/src/main/java/Application.java b/src/main/java/Application.java new file mode 100644 index 00000000..bc9cae67 --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,6 @@ +public class Application { + + public static void main(String[] args) { + Game.start(); + } +} diff --git a/src/main/java/Game.java b/src/main/java/Game.java new file mode 100644 index 00000000..bf74c05f --- /dev/null +++ b/src/main/java/Game.java @@ -0,0 +1,49 @@ +import java.util.InputMismatchException; + +public class Game { + + public static void start() { + Game game = new Game(); + boolean flag = true; + + while (flag) { + flag = game.play(); + } + + } + + int answer; + + public boolean play() { + answer = GameService.getNewAnswer(); + int guess = 0; + + while (answer != guess) { + try { + guess = View.guessView(); + } catch (InputMismatchException e) { + throw new IllegalArgumentException("숫자를 입력해야합니다."); + } catch (Exception e) { + throw new IllegalArgumentException(); + } + + Validator.validateGuess(guess); + ResultDto resultDto = GameService.getResult(answer, guess); + + View.hintView(resultDto); + } + + int input; + try { + input = View.successView(); + } catch (InputMismatchException e) { + throw new IllegalArgumentException("숫자를 입력해야 합니다."); + } catch (Exception e) { + throw new IllegalArgumentException(); + } + Validator.validateReGame(input); + + return input == 1; + } + +} diff --git a/src/main/java/GameService.java b/src/main/java/GameService.java new file mode 100644 index 00000000..5a422b62 --- /dev/null +++ b/src/main/java/GameService.java @@ -0,0 +1,40 @@ +import java.util.Random; + +public class GameService { + + private GameService() { + } + + public static int getNewAnswer() { + Random rand = new Random(); + int num1 = rand.nextInt(9) + 1; + int num2 = rand.nextInt(9) + 1; + while (num1 == num2) { + num2 = rand.nextInt(9) + 1; + } + int num3 = rand.nextInt(9) + 1; + while (num3 == num1 || num3 == num2) { + num3 = rand.nextInt(9) + 1; + } + + return num1 * 100 + num2 * 10 + num3; + } + + public static ResultDto getResult(int answer, int guess) { + int strike = 0; + int ball = 0; + int[] answerArr = {answer / 100, (answer % 100) / 10, answer % 10}; + int[] guessArr = {guess / 100, (guess % 100) / 10, guess % 10}; + + for (int i = 0; i < 3; i++) { + if (answerArr[i] == guessArr[i]) { + strike++; + } else if (guessArr[i] == answerArr[(i + 1) % 3] || guessArr[i] == answerArr[(i + 2) + % 3]) { + ball++; + } + } + + return new ResultDto(strike, ball); + } +} diff --git a/src/main/java/ResultDto.java b/src/main/java/ResultDto.java new file mode 100644 index 00000000..058de924 --- /dev/null +++ b/src/main/java/ResultDto.java @@ -0,0 +1,19 @@ +public class ResultDto { + + private final int strike; + private final int ball; + + public ResultDto(int strike, int ball) { + this.strike = strike; + this.ball = ball; + } + + + public int getStrike() { + return strike; + } + + public int getBall() { + return ball; + } +} diff --git a/src/main/java/Validator.java b/src/main/java/Validator.java new file mode 100644 index 00000000..0f9eefc5 --- /dev/null +++ b/src/main/java/Validator.java @@ -0,0 +1,20 @@ +public class Validator { + + private Validator() {} + + public static void validateGuess(int num) { + if (num <= 100 || num >= 1000) { + throw new IllegalArgumentException("3자리 숫자를 입력해야 합니다."); + } else if (num/100 == (num%100)/10 || num/100 == num%10 || (num%100)/10 == num%10) { + throw new IllegalArgumentException("서로 다른 세 숫자를 입력해야 합니다."); + } else if ((num%100)/10 == 0 || num%10 == 0) { + throw new IllegalArgumentException("1부터 9까지의 숫자만 입력해야 합니다."); + } + } + + public static void validateReGame(int num) { + if (num != 1 && num != 2) { + throw new IllegalArgumentException("1 또는 2를 입력해야 합니다."); + } + } +} diff --git a/src/main/java/View.java b/src/main/java/View.java new file mode 100644 index 00000000..a9aed36b --- /dev/null +++ b/src/main/java/View.java @@ -0,0 +1,43 @@ +import java.io.InputStream; +import java.util.Scanner; + +public class View { + + private static Scanner sc = new Scanner(System.in); + + private View() {} + + public static int guessView() { + System.out.print("숫자를 입력해 주세요 : "); + int num = Integer.parseInt(sc.nextLine()); + return num; + } + + public static void hintView(ResultDto resultDto) { + int strike = resultDto.getStrike(); + int ball = resultDto.getBall(); + + if (strike == 0 && ball == 0) { + System.out.println("낫싱"); + } else if (strike == 0) { + System.out.println(ball + "볼"); + } else if (ball == 0) { + System.out.println(strike + "스트라이크"); + } else { + System.out.println(ball + "볼 " + strike + "스트라이크"); + } + } + + public static int successView() { + System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료"); + System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."); + int num = Integer.parseInt(sc.nextLine()); + return num; + } + + public static void resetScanner(InputStream inputStream) { + sc.close(); + sc = new Scanner(inputStream); + } + +} diff --git a/src/test/java/GameServiceTest.java b/src/test/java/GameServiceTest.java new file mode 100644 index 00000000..6bea4371 --- /dev/null +++ b/src/test/java/GameServiceTest.java @@ -0,0 +1,22 @@ +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +class GameServiceTest { + + @Test + void getNewAnswer() { + int answer = GameService.getNewAnswer(); + Assertions.assertThatCode(() -> Validator.validateGuess(answer)).doesNotThrowAnyException(); + } + + @Test + void getResult() { + int answer = 123; + int guess = 135; + + ResultDto resultDto = GameService.getResult(answer, guess); + + Assertions.assertThat(resultDto.getBall()).isEqualTo(1); + Assertions.assertThat(resultDto.getStrike()).isEqualTo(1); + } +} \ No newline at end of file diff --git a/src/test/java/ValidatorTest.java b/src/test/java/ValidatorTest.java new file mode 100644 index 00000000..5e951faf --- /dev/null +++ b/src/test/java/ValidatorTest.java @@ -0,0 +1,39 @@ +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +class ValidatorTest { + + @Test + void validateGuessSuccess() { + int guess = 123; + Assertions.assertThatCode(() -> Validator.validateGuess(guess)).doesNotThrowAnyException(); + } + + @Test + void validateGuessTwoDigit() { + int guess = 13; + Assertions.assertThatThrownBy(() -> Validator.validateGuess(guess)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void validateGuessSameDigit() { + int guess = 112; + Assertions.assertThatThrownBy(() -> Validator.validateGuess(guess)) + .isInstanceOf(IllegalArgumentException.class); + } + + + @Test + void validateReGameSucess() { + int num = 1; + Assertions.assertThatCode(() -> Validator.validateReGame(num)).doesNotThrowAnyException(); + } + + @Test + void validateReGameFail() { + int num = 3; + Assertions.assertThatThrownBy(() -> Validator.validateReGame(num)) + .isInstanceOf(IllegalArgumentException.class); + } +} \ No newline at end of file diff --git a/src/test/java/ViewTest.java b/src/test/java/ViewTest.java new file mode 100644 index 00000000..6cf3e0c3 --- /dev/null +++ b/src/test/java/ViewTest.java @@ -0,0 +1,76 @@ +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class ViewTest { + + OutputStream out; + + @BeforeEach + void beforeEach() { + out = new ByteArrayOutputStream(); + System.setOut(new PrintStream(out)); + } + + @Test + void guessView() { + InputStream in = new ByteArrayInputStream("123\n".getBytes()); + View.resetScanner(in); + + int num1 = View.guessView(); + + Assertions.assertThat(num1).isEqualTo(123); + } + + @Test + void hintViewNothing() { + ResultDto resultDto = new ResultDto(0, 0); + + View.hintView(resultDto); + + Assertions.assertThat(out.toString().trim()).isEqualTo("낫싱"); + } + + @Test + void hintViewStrike() { + ResultDto resultDto = new ResultDto(2, 0); + + View.hintView(resultDto); + + Assertions.assertThat(out.toString().trim()).isEqualTo("2스트라이크"); + } + + @Test + void hintViewBall() { + ResultDto resultDto = new ResultDto(0, 3); + + View.hintView(resultDto); + + Assertions.assertThat(out.toString().trim()).isEqualTo("3볼"); + } + + @Test + void hintViewBoth() { + ResultDto resultDto = new ResultDto(1, 1); + + View.hintView(resultDto); + + Assertions.assertThat(out.toString().trim()).isEqualTo("1볼 1스트라이크"); + } + + @Test + void successView() { + InputStream in = new ByteArrayInputStream("1\n".getBytes()); + View.resetScanner(in); + + int num1 = View.guessView(); + + Assertions.assertThat(num1).isEqualTo(1); + } +} \ No newline at end of file