From 32015c066501381d5371b42f6413379ecb2e4422 Mon Sep 17 00:00:00 2001 From: "justin.527" Date: Wed, 28 Jan 2026 17:23:25 +0900 Subject: [PATCH 01/14] feat: add README.md --- README.md | 54 +++++++++++++++++++++++- src/main/java/Main.java | 4 ++ src/main/java/controller/Controller.java | 4 ++ src/main/java/model/Game.java | 4 ++ src/main/java/model/Numbers.java | 4 ++ src/main/java/view/InputView.java | 4 ++ src/main/java/view/OutputView.java | 4 ++ 7 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 src/main/java/Main.java create mode 100644 src/main/java/controller/Controller.java create mode 100644 src/main/java/model/Game.java create mode 100644 src/main/java/model/Numbers.java create mode 100644 src/main/java/view/InputView.java create mode 100644 src/main/java/view/OutputView.java diff --git a/README.md b/README.md index 8d7e8aee..6e69824e 100644 --- a/README.md +++ b/README.md @@ -1 +1,53 @@ -# java-baseball-precourse \ No newline at end of file +# java-baseball-precourse + +--- + +## 프로그램 구현 기능 + +### 프로그램 시작 +- 숫자 야구 게임을 시작한다. +- 게임이 끝난다면 1 또는 2를 입력받아 새로 시작하거나 종료한다. + +### 숫자야구 게임 시작 +- 정답 숫자를 생성한다. +- 3자리 수 한 개를 입력받는다. +- 입력받은 수가 3 스트라이크 이면, 숫자 야구 게임을 종료한다. + +### 정답 숫자 생성 +- 1부터 9까지 서로 다른 수로 이루어진 랜덤한 3자리 수를 생성하여 정답으로 한다. + +### 숫자 입력 +- 3자리 수를 입력받는다. +- 서로 다른 수로 이루어진 3자리 수가 아니라면 [ERROR]처리한다. + +### 숫자 판단 +- 스트라이크, 볼, 낫싱을 판단한다. +- 3 스트라이크라면 숫자 야구 게임을 종료한다. + + +## 구조 + +### model +Game +- 정답 숫자와 유저 숫자를 비교하여 스트라이크, 볼, 낫싱 판정 +- 판정 결과 제공 + +Numbers +- 정답 숫자 생성 +- 유저 숫자 저장 + + +### view +InputView +- 유저 숫자 입력받기 +- 게임 재시작 및 종료 입력받기 + +OutputView +- 숫자 야구 결과 출력 +- 에러 메시지 출력 + +### controller +Controller +- 숫자 야구 실행 +- 숫자 판정 +- 결과 제공 \ No newline at end of file diff --git a/src/main/java/Main.java b/src/main/java/Main.java new file mode 100644 index 00000000..1e936b38 --- /dev/null +++ b/src/main/java/Main.java @@ -0,0 +1,4 @@ +package PACKAGE_NAME; + +public class Main { +} diff --git a/src/main/java/controller/Controller.java b/src/main/java/controller/Controller.java new file mode 100644 index 00000000..f406e60d --- /dev/null +++ b/src/main/java/controller/Controller.java @@ -0,0 +1,4 @@ +package controller; + +public class Controller { +} diff --git a/src/main/java/model/Game.java b/src/main/java/model/Game.java new file mode 100644 index 00000000..4fe5b9e8 --- /dev/null +++ b/src/main/java/model/Game.java @@ -0,0 +1,4 @@ +package model; + +public class Game { +} diff --git a/src/main/java/model/Numbers.java b/src/main/java/model/Numbers.java new file mode 100644 index 00000000..464e940f --- /dev/null +++ b/src/main/java/model/Numbers.java @@ -0,0 +1,4 @@ +package model; + +public class Numbers { +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 00000000..ae2791fb --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,4 @@ +package view; + +public class InputView { +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 00000000..d8f9743c --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,4 @@ +package view; + +public class OutputView { +} From 51770f478db4ca670487ec106f0aeb9f2930a6ea Mon Sep 17 00:00:00 2001 From: "justin.527" Date: Fri, 30 Jan 2026 07:14:53 +0900 Subject: [PATCH 02/14] =?UTF-8?q?feat:=20=EC=B4=88=EA=B8=B0=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/Main.java | 6 +++- src/main/java/controller/Controller.java | 36 ++++++++++++++++++++++ src/main/java/model/Game.java | 27 +++++++++++++++++ src/main/java/model/GameResult.java | 24 +++++++++++++++ src/main/java/model/Numbers.java | 38 ++++++++++++++++++++++++ src/main/java/view/InputView.java | 27 +++++++++++++++++ src/main/java/view/OutputView.java | 20 +++++++++++++ 8 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 src/main/java/model/GameResult.java diff --git a/README.md b/README.md index 6e69824e..11c9e28a 100644 --- a/README.md +++ b/README.md @@ -29,11 +29,11 @@ ### model Game +- 정답 숫자 생성 - 정답 숫자와 유저 숫자를 비교하여 스트라이크, 볼, 낫싱 판정 - 판정 결과 제공 Numbers -- 정답 숫자 생성 - 유저 숫자 저장 diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 1e936b38..fa9c8d4a 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,4 +1,8 @@ -package PACKAGE_NAME; +import controller.Controller; public class Main { + public static void main(String[] args) { + Controller controller = new Controller(); + controller.run(); + } } diff --git a/src/main/java/controller/Controller.java b/src/main/java/controller/Controller.java index f406e60d..149882b8 100644 --- a/src/main/java/controller/Controller.java +++ b/src/main/java/controller/Controller.java @@ -1,4 +1,40 @@ package controller; +import model.Game; +import model.GameResult; +import model.Numbers; +import view.InputView; +import view.OutputView; + +import java.util.List; + public class Controller { + private final InputView inputView = new InputView(); + private final OutputView outputView = new OutputView(); + + public void run() { + while (true) { + play(); + outputView.OutputCommand(); + + int inputCommand = inputView.InputCommand(); + if(inputCommand == 1) continue; + if(inputCommand == 2) break; + } + } + + private void play() { + Game game = new Game(); + while (true) { + outputView.OutputGameStart(); + + Numbers userNumbers = new Numbers(inputView.InputUserNumbers()); + + GameResult result = game.getResult(userNumbers); + outputView.OutputResult(result); + + if(result.isFinish()) break; + } + outputView.OutputWin(); + } } diff --git a/src/main/java/model/Game.java b/src/main/java/model/Game.java index 4fe5b9e8..1bf7d46f 100644 --- a/src/main/java/model/Game.java +++ b/src/main/java/model/Game.java @@ -1,4 +1,31 @@ package model; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + public class Game { + private final Numbers correctNumbers; + + public Game() { + this.correctNumbers = generateCorrectNumbers(); + } + + private Numbers generateCorrectNumbers() { + List tempNumbers = new ArrayList(); + + for (int i = 1; i <= 9; ++i) { + tempNumbers.add(i); + } + Collections.shuffle(tempNumbers); + + return new Numbers(tempNumbers.subList(0, 3)); + } + + public GameResult getResult(Numbers userNumbers) { + int strike = correctNumbers.countStrike(userNumbers); + int ball = correctNumbers.countBall(userNumbers); + + return new GameResult(strike, ball); + } } diff --git a/src/main/java/model/GameResult.java b/src/main/java/model/GameResult.java new file mode 100644 index 00000000..37210b63 --- /dev/null +++ b/src/main/java/model/GameResult.java @@ -0,0 +1,24 @@ +package model; + +public class GameResult { + private final int strike; + private final int ball; + + public GameResult(int strike, int ball) { + this.strike = strike; + this.ball = ball; + } + + public String getResultString() { + String ret = ""; + if(strike > 0) ret += strike + "스트라이크 "; + if(ball > 0) ret += ball + "볼 "; + if(strike == 0 && ball == 0) ret += "낫싱"; + return ret; + } + + public boolean isFinish() { + if (strike == 3) return true; + return false; + } +} diff --git a/src/main/java/model/Numbers.java b/src/main/java/model/Numbers.java index 464e940f..2882a14f 100644 --- a/src/main/java/model/Numbers.java +++ b/src/main/java/model/Numbers.java @@ -1,4 +1,42 @@ package model; +import java.util.ArrayList; +import java.util.List; + public class Numbers { + private final List numbers; + + public Numbers(List numbers) { + this.numbers = numbers; + } + + public boolean isValidateNumbers(List numbers) { + if (numbers.size() != 3) return false; + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + if (i == j) continue; + if (numbers.get(i).equals(numbers.get(j))) return false; + } + } + return true; + } + + public int countStrike(Numbers correctNumbers) { + int cnt = 0; + for (int i = 0; i < 3; ++i) { + if (this.numbers.get(i).equals(correctNumbers.numbers.get(i))) cnt += 1; + } + return cnt; + } + + public int countBall(Numbers correctNumbers) { + int cnt = 0; + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + if (i == j) continue; + if (this.numbers.get(i).equals(correctNumbers.numbers.get(j))) cnt += 1; + } + } + return cnt; + } } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index ae2791fb..638cf176 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,4 +1,31 @@ package view; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + public class InputView { + private final Scanner scanner = new Scanner(System.in); + + public List InputUserNumbers() { + String input = scanner.nextLine(); + + return numberToIntegerList(input); + } + + private List numberToIntegerList(String input) { + List ret = new ArrayList(); + for (int i = 0; i < 3; ++i) { + ret.add(input.charAt(i) - '0'); + } + return ret; + } + + public int InputCommand() { + String input = scanner.nextLine(); + + if (input.equals("1")) return 1; + if (input.equals("2")) return 2; + return 3; + } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index d8f9743c..e6493b7e 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,4 +1,24 @@ package view; +import model.Game; +import model.GameResult; +import model.Numbers; + public class OutputView { + public void OutputGameStart() { + System.out.print("숫자를 입력해주세요: "); + } + + public void OutputResult(GameResult result) { + System.out.println(result.getResultString()); + } + + public void OutputWin() { + System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 끝"); + } + + public void OutputCommand() { + System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."); + } } + From 5f518b6264ec2058b13e7c64d1dfa9a48d79920b Mon Sep 17 00:00:00 2001 From: afpine Date: Sun, 1 Feb 2026 17:37:05 +0900 Subject: [PATCH 03/14] refactor: OutputView methods identifier refactoring --- src/main/java/controller/Controller.java | 4 ++-- src/main/java/view/OutputView.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/controller/Controller.java b/src/main/java/controller/Controller.java index 149882b8..1af9ef8e 100644 --- a/src/main/java/controller/Controller.java +++ b/src/main/java/controller/Controller.java @@ -15,7 +15,7 @@ public class Controller { public void run() { while (true) { play(); - outputView.OutputCommand(); + outputView.OutputInputCommand(); int inputCommand = inputView.InputCommand(); if(inputCommand == 1) continue; @@ -26,7 +26,7 @@ public void run() { private void play() { Game game = new Game(); while (true) { - outputView.OutputGameStart(); + outputView.OutputInputNumber(); Numbers userNumbers = new Numbers(inputView.InputUserNumbers()); diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index e6493b7e..e82c0cb1 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -5,7 +5,7 @@ import model.Numbers; public class OutputView { - public void OutputGameStart() { + public void OutputInputNumber() { System.out.print("숫자를 입력해주세요: "); } @@ -17,7 +17,7 @@ public void OutputWin() { System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 끝"); } - public void OutputCommand() { + public void OutputInputCommand() { System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."); } } From 0982fcdeaa9d7c68f127ecc8c93e483a0832d5db Mon Sep 17 00:00:00 2001 From: afpine Date: Sun, 1 Feb 2026 17:37:38 +0900 Subject: [PATCH 04/14] refactor: minor change --- src/main/java/model/GameResult.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/model/GameResult.java b/src/main/java/model/GameResult.java index 37210b63..12789d04 100644 --- a/src/main/java/model/GameResult.java +++ b/src/main/java/model/GameResult.java @@ -11,14 +11,13 @@ public GameResult(int strike, int ball) { public String getResultString() { String ret = ""; - if(strike > 0) ret += strike + "스트라이크 "; - if(ball > 0) ret += ball + "볼 "; - if(strike == 0 && ball == 0) ret += "낫싱"; + if (strike > 0) ret += strike + "스트라이크 "; + if (ball > 0) ret += ball + "볼 "; + if (strike == 0 && ball == 0) ret += "낫싱"; return ret; } public boolean isFinish() { - if (strike == 3) return true; - return false; + return strike == 3; } } From 3e83b66674b0386e1ce89a2737cee713525b1e8c Mon Sep 17 00:00:00 2001 From: afpine Date: Sun, 1 Feb 2026 17:49:07 +0900 Subject: [PATCH 05/14] refactor: change parameter identifiers --- src/main/java/model/Numbers.java | 8 ++++---- src/main/java/view/InputView.java | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/model/Numbers.java b/src/main/java/model/Numbers.java index 2882a14f..836f4d77 100644 --- a/src/main/java/model/Numbers.java +++ b/src/main/java/model/Numbers.java @@ -21,20 +21,20 @@ public boolean isValidateNumbers(List numbers) { return true; } - public int countStrike(Numbers correctNumbers) { + public int countStrike(Numbers otherNumbers) { int cnt = 0; for (int i = 0; i < 3; ++i) { - if (this.numbers.get(i).equals(correctNumbers.numbers.get(i))) cnt += 1; + if (this.numbers.get(i).equals(otherNumbers.numbers.get(i))) cnt += 1; } return cnt; } - public int countBall(Numbers correctNumbers) { + public int countBall(Numbers otherNumbers) { int cnt = 0; for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { if (i == j) continue; - if (this.numbers.get(i).equals(correctNumbers.numbers.get(j))) cnt += 1; + if (this.numbers.get(i).equals(otherNumbers.numbers.get(j))) cnt += 1; } } return cnt; diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 638cf176..9789e802 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -9,7 +9,6 @@ public class InputView { public List InputUserNumbers() { String input = scanner.nextLine(); - return numberToIntegerList(input); } From b77ba7f865bbe775e182f781f7a117e27e572961 Mon Sep 17 00:00:00 2001 From: afpine Date: Sun, 1 Feb 2026 19:36:25 +0900 Subject: [PATCH 06/14] =?UTF-8?q?feat:=20=EC=9E=85=EB=A0=A5=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=EC=B2=98=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/Controller.java | 14 ++++--- src/main/java/model/Numbers.java | 48 +++++++++++++++++++++--- src/main/java/view/InputView.java | 13 +------ src/main/java/view/OutputView.java | 4 ++ 4 files changed, 57 insertions(+), 22 deletions(-) diff --git a/src/main/java/controller/Controller.java b/src/main/java/controller/Controller.java index 1af9ef8e..4a5d24da 100644 --- a/src/main/java/controller/Controller.java +++ b/src/main/java/controller/Controller.java @@ -26,14 +26,18 @@ public void run() { private void play() { Game game = new Game(); while (true) { - outputView.OutputInputNumber(); + try { + outputView.OutputInputNumber(); - Numbers userNumbers = new Numbers(inputView.InputUserNumbers()); + Numbers userNumbers = new Numbers(inputView.InputUserNumbers()); - GameResult result = game.getResult(userNumbers); - outputView.OutputResult(result); + GameResult result = game.getResult(userNumbers); + outputView.OutputResult(result); - if(result.isFinish()) break; + if(result.isFinish()) break; + } catch (IllegalArgumentException e) { + outputView.OutputError(e.getMessage()); + } } outputView.OutputWin(); } diff --git a/src/main/java/model/Numbers.java b/src/main/java/model/Numbers.java index 836f4d77..bf475eb5 100644 --- a/src/main/java/model/Numbers.java +++ b/src/main/java/model/Numbers.java @@ -6,21 +6,57 @@ public class Numbers { private final List numbers; + public Numbers(String inputNumbersString) { + this.numbers = validateAndParseInputString(inputNumbersString); + } + public Numbers(List numbers) { this.numbers = numbers; } - public boolean isValidateNumbers(List numbers) { - if (numbers.size() != 3) return false; + private List validateAndParseInputString(String inputNumbersString) { + if (!validateInputLength(inputNumbersString)) { + throw new IllegalArgumentException("3자리여야 합니다."); + } + if (!validateInputIsNumbers(inputNumbersString)) { + throw new IllegalArgumentException("숫자만 입력해야 합니다."); + } + if (!validateInputHasDistinctDigits(inputNumbersString)) { + throw new IllegalArgumentException("중복된 숫자를 다른 자릿수에 사용할 수 없습니다."); + } + return convertStringToIntegerList(inputNumbersString); + } + + private boolean validateInputLength(String inputNumbersString) { + return inputNumbersString.length() == 3; + } + + private boolean validateInputIsNumbers(String inputNumbersString) { for (int i = 0; i < 3; ++i) { - for (int j = 0; j < 3; ++j) { - if (i == j) continue; - if (numbers.get(i).equals(numbers.get(j))) return false; - } + if (inputNumbersString.charAt(i) < '0' || inputNumbersString.charAt(i) > '9') return false; + } + return true; + } + + private boolean validateInputHasDistinctDigits(String inputNumbersString) { + boolean[] digitsArray = new boolean[13]; + for (int i = 0; i < 3; ++i) { + int digit = inputNumbersString.charAt(i) - '0'; + if (digitsArray[digit]) return false; + digitsArray[digit] = true; } return true; } + private List convertStringToIntegerList(String inputNumbersString) { + List ret = new ArrayList(); + for (int i = 0; i < 3; ++i) { + ret.add(inputNumbersString.charAt(i) - '0'); + } + return ret; + } + + public int countStrike(Numbers otherNumbers) { int cnt = 0; for (int i = 0; i < 3; ++i) { diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 9789e802..ffe5bf94 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -7,17 +7,8 @@ public class InputView { private final Scanner scanner = new Scanner(System.in); - public List InputUserNumbers() { - String input = scanner.nextLine(); - return numberToIntegerList(input); - } - - private List numberToIntegerList(String input) { - List ret = new ArrayList(); - for (int i = 0; i < 3; ++i) { - ret.add(input.charAt(i) - '0'); - } - return ret; + public String InputUserNumbers() { + return scanner.nextLine(); } public int InputCommand() { diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index e82c0cb1..b3e062dc 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -20,5 +20,9 @@ public void OutputWin() { public void OutputInputCommand() { System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."); } + + public void OutputError(String errorMessage) { + System.out.println("[ERROR]: " + errorMessage); + } } From bae476ebe816ca297f1645585aa240a552e4cf51 Mon Sep 17 00:00:00 2001 From: afpine Date: Sun, 1 Feb 2026 19:44:29 +0900 Subject: [PATCH 07/14] =?UTF-8?q?refactor:=20countBall=20=EB=A9=94?= =?UTF-8?q?=EC=86=8C=EB=93=9C=EC=9D=98=20depth=20=EC=A4=84=EC=9D=B4?= =?UTF-8?q?=EB=8A=94=20refactoring?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/model/Numbers.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/model/Numbers.java b/src/main/java/model/Numbers.java index bf475eb5..731229c6 100644 --- a/src/main/java/model/Numbers.java +++ b/src/main/java/model/Numbers.java @@ -66,11 +66,15 @@ public int countStrike(Numbers otherNumbers) { } public int countBall(Numbers otherNumbers) { + boolean[] ballCountArray = new boolean[13]; int cnt = 0; + + for (int i = 0; i < 3; ++i) { + ballCountArray[this.numbers.get(i)] = true; + } for (int i = 0; i < 3; ++i) { - for (int j = 0; j < 3; ++j) { - if (i == j) continue; - if (this.numbers.get(i).equals(otherNumbers.numbers.get(j))) cnt += 1; + if (ballCountArray[otherNumbers.numbers.get(i)]) { + cnt += 1; } } return cnt; From f20ac5330a62f3eabcdc07c294eb722c1404f8af Mon Sep 17 00:00:00 2001 From: afpine Date: Sun, 1 Feb 2026 20:11:35 +0900 Subject: [PATCH 08/14] =?UTF-8?q?fix:=20=EB=B3=BC=20=EC=B9=B4=EC=9A=B4?= =?UTF-8?q?=ED=8C=85=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/model/Numbers.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/model/Numbers.java b/src/main/java/model/Numbers.java index 731229c6..f28a7909 100644 --- a/src/main/java/model/Numbers.java +++ b/src/main/java/model/Numbers.java @@ -67,13 +67,15 @@ public int countStrike(Numbers otherNumbers) { public int countBall(Numbers otherNumbers) { boolean[] ballCountArray = new boolean[13]; + int[] ballIndexArray = new int[13]; int cnt = 0; for (int i = 0; i < 3; ++i) { ballCountArray[this.numbers.get(i)] = true; + ballIndexArray[this.numbers.get(i)] = i; } for (int i = 0; i < 3; ++i) { - if (ballCountArray[otherNumbers.numbers.get(i)]) { + if (ballCountArray[otherNumbers.numbers.get(i)] && ballIndexArray[otherNumbers.numbers.get(i)] != i) { cnt += 1; } } From a42929c37bfc98c2930c28efda06ee44d8f22134 Mon Sep 17 00:00:00 2001 From: afpine Date: Sun, 1 Feb 2026 20:11:55 +0900 Subject: [PATCH 09/14] =?UTF-8?q?feat:=20=EA=B2=8C=EC=9E=84=20=EC=9E=AC?= =?UTF-8?q?=EC=8B=9C=EC=9E=91=20=EC=BB=A4=EB=A7=A8=EB=93=9C=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=EC=B2=98=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/Controller.java | 23 ++++++++++------ src/main/java/model/Game.java | 34 ++++++++++++++++++++++++ src/main/java/view/InputView.java | 8 ++---- 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/src/main/java/controller/Controller.java b/src/main/java/controller/Controller.java index 4a5d24da..90439579 100644 --- a/src/main/java/controller/Controller.java +++ b/src/main/java/controller/Controller.java @@ -14,16 +14,12 @@ public class Controller { public void run() { while (true) { - play(); - outputView.OutputInputCommand(); - - int inputCommand = inputView.InputCommand(); - if(inputCommand == 1) continue; - if(inputCommand == 2) break; + int result = play(); + if (result == 2) break; } } - private void play() { + private int play() { Game game = new Game(); while (true) { try { @@ -34,11 +30,22 @@ private void play() { GameResult result = game.getResult(userNumbers); outputView.OutputResult(result); - if(result.isFinish()) break; + if (result.isFinish()) { + break; + } } catch (IllegalArgumentException e) { outputView.OutputError(e.getMessage()); } } outputView.OutputWin(); + + while (true) { + try { + outputView.OutputInputCommand(); + return game.getCommand(inputView.InputCommand()); + } catch (IllegalArgumentException e) { + outputView.OutputError(e.getMessage()); + } + } } } diff --git a/src/main/java/model/Game.java b/src/main/java/model/Game.java index 1bf7d46f..2d908c96 100644 --- a/src/main/java/model/Game.java +++ b/src/main/java/model/Game.java @@ -28,4 +28,38 @@ public GameResult getResult(Numbers userNumbers) { return new GameResult(strike, ball); } + + public int getCommand(String commandString) { + return validateAndParseInputString(commandString); + } + + private int validateAndParseInputString(String commandString) { + if (!validateInputLength(commandString)) { + throw new IllegalArgumentException("1 또는 2만 입력해야 합니다."); + } + if (!validateInputIsNumber(commandString)) { + throw new IllegalArgumentException("1 또는 2만 입력해야 합니다."); + } + if (!validateInputIsOneOrTwo(commandString)) { + throw new IllegalArgumentException("1 또는 2만 입력해야 합니다."); + } + return convertStringToInteger(commandString); + } + + private boolean validateInputLength(String commandString) { + return commandString.length() == 1; + } + + private boolean validateInputIsNumber(String commandString) { + return commandString.charAt(0) >= '0' && commandString.charAt(0) <= '9'; + } + + private boolean validateInputIsOneOrTwo(String commandString) { + return commandString.charAt(0) == '1' || commandString.charAt(0) == '2'; + } + + private Integer convertStringToInteger(String commandString) { + return commandString.charAt(0) - '0'; + } + } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index ffe5bf94..09ae167e 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -11,11 +11,7 @@ public String InputUserNumbers() { return scanner.nextLine(); } - public int InputCommand() { - String input = scanner.nextLine(); - - if (input.equals("1")) return 1; - if (input.equals("2")) return 2; - return 3; + public String InputCommand() { + return scanner.nextLine(); } } From 69599dd5dd6cbdbc4cfd6d60a38b16eb1d116551 Mon Sep 17 00:00:00 2001 From: afpine Date: Tue, 3 Feb 2026 23:08:13 +0900 Subject: [PATCH 10/14] =?UTF-8?q?feat:=20NumbersTest=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/model/NumbersTest.java | 78 ++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/test/java/model/NumbersTest.java diff --git a/src/test/java/model/NumbersTest.java b/src/test/java/model/NumbersTest.java new file mode 100644 index 00000000..011a1a42 --- /dev/null +++ b/src/test/java/model/NumbersTest.java @@ -0,0 +1,78 @@ +package model; + +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class NumbersTest { + + @Test + @DisplayName("정상 입력이면 Numbers 생성 성공") + void create_success() { + Numbers stringNumbers = new Numbers("123"); + Numbers integerListNumbers = new Numbers(List.of(1, 2, 3)); + assertNotNull(stringNumbers); + assertNotNull(integerListNumbers); + } + + @Test + @DisplayName("길이가 3보다 짧으면 예외") + void create_fail_short_length() { + IllegalArgumentException e = + assertThrows(IllegalArgumentException.class, () -> new Numbers("12")); + assertEquals("3자리여야 합니다.", e.getMessage()); + } + + @Test + @DisplayName("길이가 3보다 길면 예외") + void create_fail_long_length() { + IllegalArgumentException e = + assertThrows(IllegalArgumentException.class, () -> new Numbers("1245")); + assertEquals("3자리여야 합니다.", e.getMessage()); + } + + @Test + @DisplayName("숫자가 아니면 예외") + void create_fail_notNumber() { + IllegalArgumentException e = + assertThrows(IllegalArgumentException.class, () -> new Numbers("1a3")); + assertEquals("숫자만 입력해야 합니다.", e.getMessage()); + } + + @Test + @DisplayName("중복된 자릿수가 있으면 예외") + void create_fail_duplicate() { + IllegalArgumentException e = + assertThrows(IllegalArgumentException.class, () -> new Numbers("112")); + assertEquals("중복된 숫자를 다른 자릿수에 사용할 수 없습니다.", e.getMessage()); + } + + @Test + @DisplayName("countStrike: 같은 위치 같은 숫자 개수") + void countStrike_success() { + Numbers a = new Numbers("123"); + Numbers b = new Numbers("103"); + assertEquals(2, a.countStrike(b)); + } + + @Test + @DisplayName("countBall: 숫자는 같지만 위치가 다른 개수") + void countBall_success() { + Numbers a = new Numbers("123"); + Numbers b = new Numbers("312"); + assertEquals(3, a.countBall(b)); + } + + @Test + @DisplayName("coundStrikeAndBall: 스트라이크와 볼의 개수") + void countStrikeAndBall_success() { + Numbers a = new Numbers("456"); + Numbers b = new Numbers("475"); + assertEquals(1, a.countStrike(b)); + assertEquals(1, a.countBall(b)); + } +} + From 9ae5c17e1ac03996ea09c4f8ec0cd7d607df7e5a Mon Sep 17 00:00:00 2001 From: afpine Date: Tue, 3 Feb 2026 23:27:17 +0900 Subject: [PATCH 11/14] =?UTF-8?q?feat:=20GameTest=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/model/GameTest.java | 53 +++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/test/java/model/GameTest.java diff --git a/src/test/java/model/GameTest.java b/src/test/java/model/GameTest.java new file mode 100644 index 00000000..82595e0a --- /dev/null +++ b/src/test/java/model/GameTest.java @@ -0,0 +1,53 @@ +package model; + +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class GameTest { + + @Test + @DisplayName("게임 재시작 커맨드 '1' 입력시 1 반환") + void getCommand_one_correct() { + Game game = new Game(); + assertEquals(1, game.getCommand("1")); + } + + @Test + @DisplayName("게임 재시작 커맨드 '2' 입력시 2 반환") + void getCommand_two_correct() { + Game game = new Game(); + assertEquals(2, game.getCommand("2")); + } + + @Test + @DisplayName("길이가 1이 아니면 예외") + void getCommand_fail_invalid_length() { + Game game = new Game(); + IllegalArgumentException e = + assertThrows(IllegalArgumentException.class, () -> game.getCommand("12")); + assertEquals("1 또는 2만 입력해야 합니다.", e.getMessage()); + } + + @Test + @DisplayName("숫자가 아니면 예외") + void create_fail_notNumber() { + Game game = new Game(); + IllegalArgumentException e = + assertThrows(IllegalArgumentException.class, () -> game.getCommand("a")); + assertEquals("1 또는 2만 입력해야 합니다.", e.getMessage()); + } + + @Test + @DisplayName("숫자가 아니면 예외") + void create_fail_notOneOrTwo() { + Game game = new Game(); + IllegalArgumentException e = + assertThrows(IllegalArgumentException.class, () -> game.getCommand("3")); + assertEquals("1 또는 2만 입력해야 합니다.", e.getMessage()); + } +} + From a2ffffc0683d3ed4af8dcc46a9df1c54f8f1c088 Mon Sep 17 00:00:00 2001 From: afpine Date: Tue, 3 Feb 2026 23:36:00 +0900 Subject: [PATCH 12/14] =?UTF-8?q?feat:=20GameResultTest=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/model/GameResultTest.java | 51 +++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/test/java/model/GameResultTest.java diff --git a/src/test/java/model/GameResultTest.java b/src/test/java/model/GameResultTest.java new file mode 100644 index 00000000..52d3bdec --- /dev/null +++ b/src/test/java/model/GameResultTest.java @@ -0,0 +1,51 @@ +package model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class GameResultTest { + + @Test + @DisplayName("게임 결과로 2스트라이크 출력") + void getResultString_correct_onlyStrike() { + GameResult result = new GameResult(2, 0); + assertEquals("2스트라이크 ", result.getResultString()); + } + + @Test + @DisplayName("게임 결과로 2스트라이크 출력") + void getResultString_correct_onlyBall() { + GameResult result = new GameResult(0, 1); + assertEquals("1볼 ", result.getResultString()); + } + + @Test + @DisplayName("게임 결과로 2스트라이크 출력") + void getResultString_correct_strikeAndBall() { + GameResult result = new GameResult(1, 2); + assertEquals("1스트라이크 2볼 ", result.getResultString()); + } + + @Test + @DisplayName("게임 결과로 2스트라이크 출력") + void getResultString_correct_nothing() { + GameResult result = new GameResult(0, 0); + assertEquals("낫싱", result.getResultString()); + } + + @Test + @DisplayName("3스트라이크 이면 게임 종료") + void isFinish_correct_finish() { + GameResult result = new GameResult(3, 0); + assertTrue(result.isFinish()); + } + + @Test + @DisplayName("3스트라이크가 아니면 게임 진행") + void isFinish_correct_notFinish() { + GameResult result = new GameResult(2, 1); + assertFalse(result.isFinish()); + } +} From bd4f95ce57d812a6d0fb062036573b519a7df4c0 Mon Sep 17 00:00:00 2001 From: afpine Date: Tue, 3 Feb 2026 23:36:20 +0900 Subject: [PATCH 13/14] =?UTF-8?q?minor:=20=ED=95=84=EC=9A=94=EC=97=86?= =?UTF-8?q?=EB=8A=94=20import=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/model/GameTest.java | 2 -- src/test/java/model/NumbersTest.java | 1 - 2 files changed, 3 deletions(-) diff --git a/src/test/java/model/GameTest.java b/src/test/java/model/GameTest.java index 82595e0a..9440e9c3 100644 --- a/src/test/java/model/GameTest.java +++ b/src/test/java/model/GameTest.java @@ -1,7 +1,5 @@ package model; -import java.util.ArrayList; -import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/model/NumbersTest.java b/src/test/java/model/NumbersTest.java index 011a1a42..88a4187c 100644 --- a/src/test/java/model/NumbersTest.java +++ b/src/test/java/model/NumbersTest.java @@ -1,6 +1,5 @@ package model; -import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; From 9a687e8c9b0b73daa0ed0781aee33713ed97be35 Mon Sep 17 00:00:00 2001 From: afpine Date: Fri, 6 Feb 2026 10:14:22 +0900 Subject: [PATCH 14/14] =?UTF-8?q?feat:=20README.md=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 11c9e28a..282c4d66 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,73 @@ # java-baseball-precourse ---- - ## 프로그램 구현 기능 ### 프로그램 시작 + - 숫자 야구 게임을 시작한다. - 게임이 끝난다면 1 또는 2를 입력받아 새로 시작하거나 종료한다. ### 숫자야구 게임 시작 + - 정답 숫자를 생성한다. - 3자리 수 한 개를 입력받는다. - 입력받은 수가 3 스트라이크 이면, 숫자 야구 게임을 종료한다. ### 정답 숫자 생성 + - 1부터 9까지 서로 다른 수로 이루어진 랜덤한 3자리 수를 생성하여 정답으로 한다. ### 숫자 입력 + - 3자리 수를 입력받는다. - 서로 다른 수로 이루어진 3자리 수가 아니라면 [ERROR]처리한다. ### 숫자 판단 + - 스트라이크, 볼, 낫싱을 판단한다. - 3 스트라이크라면 숫자 야구 게임을 종료한다. - ## 구조 ### model + +Numbers + +- 숫자 야구에 사용되는 3자리 수 model +- 숫자 입력 값 예외 처리 +- 스트라이크, 볼 계산 + Game + - 정답 숫자 생성 - 정답 숫자와 유저 숫자를 비교하여 스트라이크, 볼, 낫싱 판정 -- 판정 결과 제공 +- 게임 재시작 및 종료 값 예외 처리 -Numbers -- 유저 숫자 저장 +GameResult +- 숫자 야구 결과를 출력 + - 스트라이크, 볼, 낫싱 +- 게임 종료 조건(3스트라이크) 확인 ### view + InputView + - 유저 숫자 입력받기 - 게임 재시작 및 종료 입력받기 OutputView + +- 숫자 야구 시작 메시지 출력 - 숫자 야구 결과 출력 +- 게임 재시작 및 종료 메시지 출력 - 에러 메시지 출력 ### controller + Controller + - 숫자 야구 실행 - 숫자 판정 -- 결과 제공 \ No newline at end of file +- 결과 제공 +- 게임 재시작 및 종료 판단 \ No newline at end of file