From 9241cad2aba3631d5715532c12b4ac9299af7324 Mon Sep 17 00:00:00 2001 From: seonwoonam Date: Wed, 28 Jan 2026 18:34:43 +0900 Subject: [PATCH 01/16] =?UTF-8?q?docs=20:=20README=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8d7e8aee..ebbbcd56 100644 --- a/README.md +++ b/README.md @@ -1 +1,11 @@ -# java-baseball-precourse \ No newline at end of file +# java-baseball-precourse +## 기능 정리 +- 게임을 종료한 후 게임을 다시 시작하거나 완전히 종료 가능 +- 상대방의 역할을 컴퓨터가 진행. 컴퓨터는 서로 다른 임의의 수 3개 생성 +- 입력 및 출력 +- 컴퓨터의 수 맞추기 검증 + - 위 과정을 반복해 컴퓨터가 선택한 3개의 숫자를 모두 맞히면 게임 종료 +- 힌트 + - 같은 수가 같은 자리에 있으면 스트라이크, 다른 자리에 있으면 볼, 같은 수가 전혀 없으면 포볼 또는 낫싱이란 힌트 +- 에러처리 + - 사용자가 잘못된 값을 입력할 경우 [ERROR]로 시작하는 에러 메시지 출력하고 게임 계속 가능 \ No newline at end of file From 22833291ba6fd4087612cd09dc417355a362f2e6 Mon Sep 17 00:00:00 2001 From: seonwoonam Date: Sun, 1 Feb 2026 22:01:53 +0900 Subject: [PATCH 02/16] =?UTF-8?q?feat=20:=20=EC=9E=AC=EC=8B=9C=EB=8F=84=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Main.java | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/main/java/Main.java diff --git a/src/main/java/Main.java b/src/main/java/Main.java new file mode 100644 index 00000000..0502e919 --- /dev/null +++ b/src/main/java/Main.java @@ -0,0 +1,21 @@ +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.*; + +public class Main { + public static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + public static StringBuilder sb; + public static boolean checkRestart() throws IOException{ + System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."); + String str = br.readLine(); + if(str.equals("1")){ + return true; + } + if(str.equals("2")){ + return false; + } + return true; + } + } +} From 1c274759a034adb59ca571c37afc597067d5d526 Mon Sep 17 00:00:00 2001 From: seonwoonam Date: Sun, 1 Feb 2026 22:02:47 +0900 Subject: [PATCH 03/16] =?UTF-8?q?feat=20:=20=EC=BB=B4=ED=93=A8=ED=84=B0=20?= =?UTF-8?q?=EC=9E=84=EC=9D=98=EC=9D=98=20=EC=88=98=203=EA=B0=9C=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=ED=95=98=EB=8A=94=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Main.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 0502e919..909b10c8 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -17,5 +17,15 @@ public static boolean checkRestart() throws IOException{ } return true; } + public static List getRandomNumbers(){ + Random random = new Random(); + List computer = new ArrayList<>(); + while (computer.size() < 3) { + int randomNumber = random.nextInt(9) + 1; + if (!computer.contains(randomNumber)) { + computer.add(randomNumber); + } + } + return computer; } } From 3927b57c432ff683ca5b43abbb649b314c624706 Mon Sep 17 00:00:00 2001 From: seonwoonam Date: Sun, 1 Feb 2026 22:03:24 +0900 Subject: [PATCH 04/16] =?UTF-8?q?feat=20:=20=EC=A0=95=EB=8B=B5=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20=ED=95=A8=EC=88=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Main.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 909b10c8..52690152 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -17,6 +17,17 @@ public static boolean checkRestart() throws IOException{ } return true; } + + public static List inputNumber() throws IOException { + System.out.print("숫자를 입력해주세요 : "); + String str = br.readLine(); + List numbers = new ArrayList<>(); + for(char c : str.toCharArray()){ + numbers.add(c-'0'); + } + return numbers; + } + public static List getRandomNumbers(){ Random random = new Random(); List computer = new ArrayList<>(); From 4bd55aff0451933119e05e9787622f44f6fde966 Mon Sep 17 00:00:00 2001 From: seonwoonam Date: Sun, 1 Feb 2026 22:03:52 +0900 Subject: [PATCH 05/16] =?UTF-8?q?feat=20:=20=ED=9E=8C=ED=8A=B8=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=ED=95=A8=EC=88=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Main.java | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 52690152..79494601 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -6,6 +6,31 @@ public class Main { public static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); public static StringBuilder sb; + public static String getHint(List correctNumber, List userNumber){ + int strike = 0; + int ball = 0; + + for (int i = 0; i < 3; i++) { + if (correctNumber.get(i).equals(userNumber.get(i))) { + strike++; + continue; + } + if (correctNumber.contains(userNumber.get(i))) { + ball++; + } + } + + if (strike == 0 && ball == 0) { + return "낫싱"; + } + + String result = ""; + if (strike > 0) result += strike + "스트라이크 "; + if (ball > 0) result += ball + "볼"; + + return result.trim(); + } + public static boolean checkRestart() throws IOException{ System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."); String str = br.readLine(); From 99886c5dad01ba2cfab8bed52c437c7d4b372127 Mon Sep 17 00:00:00 2001 From: seonwoonam Date: Sun, 1 Feb 2026 22:04:31 +0900 Subject: [PATCH 06/16] =?UTF-8?q?feat=20:=20=EA=B2=8C=EC=9E=84=20=EC=8B=A4?= =?UTF-8?q?=ED=96=89=20=ED=95=A8=EC=88=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Main.java | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 79494601..4c8b9c06 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -6,6 +6,34 @@ public class Main { public static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); public static StringBuilder sb; + public static void main(String[] args) throws IOException { + boolean isRunning = true; + List computerList = getRandomNumbers(); + while (isRunning) { + boolean isCorrect = run(computerList); + if(isCorrect){ + System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 끝"); + isRunning = checkRestart(); + } + if(isCorrect && isRunning){ + computerList = getRandomNumbers(); + } + } + } + + public static boolean run(List correctNumber) throws IOException{ + List inputNumberList = inputNumber(); + int strike = 0; + for (int i = 0; i < 3; i++) { + if (correctNumber.get(i).equals(inputNumberList.get(i))) strike++; + } + System.out.println(getHint(correctNumber, inputNumberList)); + if(strike == 3){ + return true; + } + return false; + } + public static String getHint(List correctNumber, List userNumber){ int strike = 0; int ball = 0; From 16486a3de6ec1fbbc2364ff89adefe0e5aeea78b Mon Sep 17 00:00:00 2001 From: seonwoonam Date: Sun, 1 Feb 2026 22:05:34 +0900 Subject: [PATCH 07/16] =?UTF-8?q?feat=20:=20=EC=BB=B4=ED=93=A8=ED=84=B0=20?= =?UTF-8?q?=EB=9E=9C=EB=8D=A4=20=EC=83=9D=EC=84=B1=20=EC=88=98=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/MainTest.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/test/java/MainTest.java diff --git a/src/test/java/MainTest.java b/src/test/java/MainTest.java new file mode 100644 index 00000000..51697b72 --- /dev/null +++ b/src/test/java/MainTest.java @@ -0,0 +1,18 @@ +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class MainTest { + @Test + void 예외_테스트_길이오류(){ + List numbers = Main.getRandomNumbers(); + assertEquals(3, numbers.size(), "생성된 숫자 배열의 길이가 3이어야 합니다."); + for (int number : numbers) { + assertTrue(number >= 1 && number <= 9, "숫자 범위 확인"); + } + } +} From 36dd3ef9fa8d194a9714447137adfa14a993b412 Mon Sep 17 00:00:00 2001 From: seonwoonam Date: Sun, 8 Feb 2026 00:55:22 +0900 Subject: [PATCH 08/16] =?UTF-8?q?refactor=20:=20=EC=9E=85=EB=A0=A5=20?= =?UTF-8?q?=EB=B0=8F=20=EC=B6=9C=EB=A0=A5=20View=20=ED=98=95=ED=83=9C?= =?UTF-8?q?=EB=A1=9C=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/InputView.java | 31 ++++++++++++++++++++++++++++++ src/main/java/view/OutputView.java | 17 ++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 src/main/java/view/InputView.java create mode 100644 src/main/java/view/OutputView.java diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 00000000..c82bc29d --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,31 @@ +package view; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class InputView { + private final BufferedReader br; + + public InputView() { + this.br = new BufferedReader(new InputStreamReader(System.in)); + } + + public String inputNumber() { + System.out.print("숫자를 입력해주세요 : "); + try { + return br.readLine(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public String askRestart() { + System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."); + try { + return br.readLine(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 00000000..01a12f3c --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,17 @@ +package view; + +import model.GameResult; + +public class OutputView { + public void printResult(GameResult result) { + System.out.println(result.toString()); + } + + public void printGameEnd() { + System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 끝"); + } + + public void printError(String message) { + System.out.println(message); + } +} From 643b54963f9d9bd9f43d52f1fd993020cc5e29e3 Mon Sep 17 00:00:00 2001 From: seonwoonam Date: Sun, 8 Feb 2026 00:56:27 +0900 Subject: [PATCH 09/16] =?UTF-8?q?refactor=20:=20=EC=84=9C=EB=A1=9C=20?= =?UTF-8?q?=EB=8B=A4=EB=A5=B8=20=EC=9E=84=EC=9D=98=EC=9D=98=20=EC=88=98=20?= =?UTF-8?q?3=EA=B0=9C=20=EC=83=9D=EC=84=B1=ED=95=98=EB=8A=94=20=EC=BB=B4?= =?UTF-8?q?=ED=93=A8=ED=84=B0=20Model=20=ED=98=95=ED=83=9C=EB=A1=9C=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/model/Computer.java | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/main/java/model/Computer.java diff --git a/src/main/java/model/Computer.java b/src/main/java/model/Computer.java new file mode 100644 index 00000000..de4458ce --- /dev/null +++ b/src/main/java/model/Computer.java @@ -0,0 +1,23 @@ +package model; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class Computer { + private static final int NUMBER_SIZE = 3; + private static final int MIN_NUMBER = 1; + private static final int MAX_NUMBER = 9; + + public Numbers generate() { + Random random = new Random(); + List computer = new ArrayList<>(); + while (computer.size() < NUMBER_SIZE) { + int randomNumber = random.nextInt(MAX_NUMBER) + MIN_NUMBER; + if (!computer.contains(randomNumber)) { + computer.add(randomNumber); + } + } + return new Numbers(computer); + } +} From d645a7e8854254c47692127dd684bb07aef2c9c3 Mon Sep 17 00:00:00 2001 From: seonwoonam Date: Sun, 8 Feb 2026 00:57:40 +0900 Subject: [PATCH 10/16] =?UTF-8?q?refactor=20:=20=EA=B2=8C=EC=9E=84=20?= =?UTF-8?q?=EA=B2=B0=EA=B3=BC=20=ED=8C=90=EC=A0=95=20=EB=B0=8F=20=ED=9E=8C?= =?UTF-8?q?=ED=8A=B8=20=EA=B8=B0=EB=8A=A5=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/model/GameResult.java | 30 +++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/main/java/model/GameResult.java diff --git a/src/main/java/model/GameResult.java b/src/main/java/model/GameResult.java new file mode 100644 index 00000000..c1e590c0 --- /dev/null +++ b/src/main/java/model/GameResult.java @@ -0,0 +1,30 @@ +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 boolean isThreeStrike() { + return strike == 3; + } + + @Override + public String toString() { + if (strike == 0 && ball == 0) { + return "낫싱"; + } + String result = ""; + if (ball > 0) { + result += ball + "볼 "; + } + if (strike > 0) { + result += strike + "스트라이크"; + } + return result.trim(); + } +} From d8436404e3c250a0a329d7fd7b754bc471daa697 Mon Sep 17 00:00:00 2001 From: seonwoonam Date: Sun, 8 Feb 2026 01:04:26 +0900 Subject: [PATCH 11/16] =?UTF-8?q?refactor=20:=20=EC=9E=85=EB=A0=A5=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?Controller=20=ED=98=95=ED=83=9C=EB=A1=9C=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/BaseballGame.java | 65 ++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 src/main/java/controller/BaseballGame.java diff --git a/src/main/java/controller/BaseballGame.java b/src/main/java/controller/BaseballGame.java new file mode 100644 index 00000000..25cdb4bf --- /dev/null +++ b/src/main/java/controller/BaseballGame.java @@ -0,0 +1,65 @@ +package controller; + +import model.Computer; +import model.GameResult; +import model.Numbers; +import view.InputView; +import view.OutputView; + +import java.util.ArrayList; +import java.util.List; + +public class BaseballGame { + private final InputView inputView; + private final OutputView outputView; + private final Computer computer; + + public BaseballGame() { + this.inputView = new InputView(); + this.outputView = new OutputView(); + this.computer = new Computer(); + } + + private void playRound() { + Numbers target = computer.generate(); + boolean isCorrect = false; + while (!isCorrect) { + isCorrect = playTurn(target); + } + outputView.printGameEnd(); + } + + private boolean playTurn(Numbers target) { + try { + Numbers userNumbers = getUserInput(); + GameResult result = calculateResult(target, userNumbers); + outputView.printResult(result); + return result.isThreeStrike(); + } catch (IllegalArgumentException e) { + outputView.printError(e.getMessage()); + return false; + } + } + + private Numbers getUserInput() { + String input = inputView.inputNumber(); + return new Numbers(parse(input)); + } + + private List parse(String input) { + List numbers = new ArrayList<>(); + for (char c : input.toCharArray()) { + numbers.add(c - '0'); + } + return numbers; + } + + private GameResult calculateResult(Numbers target, Numbers user) { + int strike = target.countStrikes(user); + int ball = target.countBalls(user); + return new GameResult(strike, ball); + } + + } + } +} From d2e81b3421aea1694a89be1e1da18b45f6e81e93 Mon Sep 17 00:00:00 2001 From: seonwoonam Date: Sun, 8 Feb 2026 01:04:49 +0900 Subject: [PATCH 12/16] =?UTF-8?q?refactor=20:=20=EA=B2=8C=EC=9E=84?= =?UTF-8?q?=EC=9D=84=20=EC=A2=85=EB=A3=8C=ED=95=9C=20=ED=9B=84=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=EC=9D=84=20=EB=8B=A4=EC=8B=9C=20=EC=8B=9C=EC=9E=91?= =?UTF-8?q?=ED=95=98=EA=B1=B0=EB=82=98=20=EC=99=84=EC=A0=84=ED=9E=88=20?= =?UTF-8?q?=EC=A2=85=EB=A3=8C=20=EA=B8=B0=EB=8A=A5=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/BaseballGame.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/java/controller/BaseballGame.java b/src/main/java/controller/BaseballGame.java index 25cdb4bf..dfaea2fa 100644 --- a/src/main/java/controller/BaseballGame.java +++ b/src/main/java/controller/BaseballGame.java @@ -20,6 +20,14 @@ public BaseballGame() { this.computer = new Computer(); } + public void run() { + boolean isRunning = true; + while (isRunning) { + playRound(); + isRunning = checkRestart(); + } + } + private void playRound() { Numbers target = computer.generate(); boolean isCorrect = false; @@ -60,6 +68,16 @@ private GameResult calculateResult(Numbers target, Numbers user) { return new GameResult(strike, ball); } + private boolean checkRestart() { + while (true) { + String input = inputView.askRestart(); + if (input.equals("1")) { + return true; + } + if (input.equals("2")) { + return false; + } + outputView.printError("[ERROR] 1 또는 2만 입력 가능합니다."); } } } From 71bf60fa7233d6012b7435652a7d72e284fec911 Mon Sep 17 00:00:00 2001 From: seonwoonam Date: Sun, 8 Feb 2026 01:05:37 +0900 Subject: [PATCH 13/16] =?UTF-8?q?feat=20:=20=EC=9E=98=EB=AA=BB=EB=90=9C=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Main.java | 92 ++------------------------------ src/main/java/model/Numbers.java | 65 ++++++++++++++++++++++ 2 files changed, 68 insertions(+), 89 deletions(-) create mode 100644 src/main/java/model/Numbers.java diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 4c8b9c06..79ffed76 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,95 +1,9 @@ -import java.io.BufferedReader; +import controller.BaseballGame; import java.io.IOException; -import java.io.InputStreamReader; -import java.util.*; public class Main { - public static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - public static StringBuilder sb; public static void main(String[] args) throws IOException { - boolean isRunning = true; - List computerList = getRandomNumbers(); - while (isRunning) { - boolean isCorrect = run(computerList); - if(isCorrect){ - System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 끝"); - isRunning = checkRestart(); - } - if(isCorrect && isRunning){ - computerList = getRandomNumbers(); - } - } - } - - public static boolean run(List correctNumber) throws IOException{ - List inputNumberList = inputNumber(); - int strike = 0; - for (int i = 0; i < 3; i++) { - if (correctNumber.get(i).equals(inputNumberList.get(i))) strike++; - } - System.out.println(getHint(correctNumber, inputNumberList)); - if(strike == 3){ - return true; - } - return false; - } - - public static String getHint(List correctNumber, List userNumber){ - int strike = 0; - int ball = 0; - - for (int i = 0; i < 3; i++) { - if (correctNumber.get(i).equals(userNumber.get(i))) { - strike++; - continue; - } - if (correctNumber.contains(userNumber.get(i))) { - ball++; - } - } - - if (strike == 0 && ball == 0) { - return "낫싱"; - } - - String result = ""; - if (strike > 0) result += strike + "스트라이크 "; - if (ball > 0) result += ball + "볼"; - - return result.trim(); - } - - public static boolean checkRestart() throws IOException{ - System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."); - String str = br.readLine(); - if(str.equals("1")){ - return true; - } - if(str.equals("2")){ - return false; - } - return true; - } - - public static List inputNumber() throws IOException { - System.out.print("숫자를 입력해주세요 : "); - String str = br.readLine(); - List numbers = new ArrayList<>(); - for(char c : str.toCharArray()){ - numbers.add(c-'0'); - } - return numbers; - } - - public static List getRandomNumbers(){ - Random random = new Random(); - List computer = new ArrayList<>(); - while (computer.size() < 3) { - int randomNumber = random.nextInt(9) + 1; - if (!computer.contains(randomNumber)) { - computer.add(randomNumber); - } - } - return computer; + BaseballGame game = new BaseballGame(); + game.run(); } } diff --git a/src/main/java/model/Numbers.java b/src/main/java/model/Numbers.java new file mode 100644 index 00000000..9ca69667 --- /dev/null +++ b/src/main/java/model/Numbers.java @@ -0,0 +1,65 @@ +package model; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class Numbers { + private final List numbers; + + public Numbers(List numbers) { + validate(numbers); + this.numbers = numbers; + } + + private void validate(List numbers) { + if (numbers.size() != 3) { + throw new IllegalArgumentException("[ERROR] 3자리의 숫자를 입력해야 합니다."); + } + for (int number : numbers) { + validateRange(number); + } + validateUnique(numbers); + } + + private void validateRange(int number) { + if (number < 1 || number > 9) { + throw new IllegalArgumentException("[ERROR] 1~9 사이의 숫자만 입력 가능합니다."); + } + } + + private void validateUnique(List numbers) { + Set uniqueNumbers = new HashSet<>(numbers); + if (uniqueNumbers.size() != numbers.size()) { + throw new IllegalArgumentException("[ERROR] 중복된 숫자는 입력할 수 없습니다."); + } + } + + public int countStrikes(Numbers other) { + int count = 0; + for (int i = 0; i < numbers.size(); i++) { + if (numbers.get(i).equals(other.get(i))) { + count++; + } + } + return count; + } + + public int countBalls(Numbers other) { + int count = 0; + for (int i = 0; i < numbers.size(); i++) { + if (!numbers.get(i).equals(other.get(i)) && numbers.contains(other.get(i))) { + count++; + } + } + return count; + } + + public Integer get(int index) { + return numbers.get(index); + } + + public boolean contains(int number) { + return numbers.contains(number); + } +} From bcaac36b97df0a707d3858362cffc68728447d0a Mon Sep 17 00:00:00 2001 From: seonwoonam Date: Sun, 8 Feb 2026 01:18:54 +0900 Subject: [PATCH 14/16] =?UTF-8?q?test=20:=20=EA=B2=8C=EC=9E=84=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/model/GameResultTest.java | 23 +++++++++++++++++++++++ 1 file changed, 23 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..7c3be487 --- /dev/null +++ b/src/test/java/model/GameResultTest.java @@ -0,0 +1,23 @@ +package model; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class GameResultTest { + + @Test + void 결과_출력_형식_확인() { + GameResult result = new GameResult(1, 1); + assertEquals("1볼 1스트라이크", result.toString()); + + result = new GameResult(3, 0); + assertEquals("3스트라이크", result.toString()); + + result = new GameResult(0, 3); + assertEquals("3볼", result.toString()); + + result = new GameResult(0, 0); + assertEquals("낫싱", result.toString()); + } +} From c4f08345116cdc5f59183295484fa6fc64ec1129 Mon Sep 17 00:00:00 2001 From: seonwoonam Date: Sun, 8 Feb 2026 01:19:39 +0900 Subject: [PATCH 15/16] =?UTF-8?q?test=20:=20Numbers=20=EC=88=AB=EC=9E=90?= =?UTF-8?q?=20validation=20=EB=B0=8F=20=ED=8C=90=EC=A0=95=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/MainTest.java | 18 -------- src/test/java/model/NumbersTest.java | 64 ++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 18 deletions(-) delete mode 100644 src/test/java/MainTest.java create mode 100644 src/test/java/model/NumbersTest.java diff --git a/src/test/java/MainTest.java b/src/test/java/MainTest.java deleted file mode 100644 index 51697b72..00000000 --- a/src/test/java/MainTest.java +++ /dev/null @@ -1,18 +0,0 @@ -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class MainTest { - @Test - void 예외_테스트_길이오류(){ - List numbers = Main.getRandomNumbers(); - assertEquals(3, numbers.size(), "생성된 숫자 배열의 길이가 3이어야 합니다."); - for (int number : numbers) { - assertTrue(number >= 1 && number <= 9, "숫자 범위 확인"); - } - } -} diff --git a/src/test/java/model/NumbersTest.java b/src/test/java/model/NumbersTest.java new file mode 100644 index 00000000..54d25259 --- /dev/null +++ b/src/test/java/model/NumbersTest.java @@ -0,0 +1,64 @@ +package model; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class NumbersTest { + @Test + void 숫자_리스트_생성_정상() { + assertDoesNotThrow(() -> new Numbers(Arrays.asList(1, 2, 3))); + } + + @Test + void 예외_테스트_숫자_길이오류() { + assertThrows(IllegalArgumentException.class, () -> new Numbers(Arrays.asList(1, 2))); + assertThrows(IllegalArgumentException.class, () -> new Numbers(Arrays.asList(1, 2, 3, 4))); + } + + @Test + void 예외_테스트_숫자_범위오류() { + assertThrows(IllegalArgumentException.class, () -> new Numbers(Arrays.asList(1, 0, 3))); + } + + @Test + void 예외_테스트_숫자_중복오류() { + assertThrows(IllegalArgumentException.class, () -> new Numbers(Arrays.asList(1, 2, 1))); + } + + @Test + void 스트라이크_계산_3스트라이크() { + Numbers computer = new Numbers(Arrays.asList(1, 2, 3)); + Numbers user = new Numbers(Arrays.asList(1, 2, 3)); + assertEquals(3, computer.countStrikes(user)); + assertEquals(0, computer.countBalls(user)); + } + + @Test + void 볼_계산_3볼() { + Numbers computer = new Numbers(Arrays.asList(1, 2, 3)); + Numbers user = new Numbers(Arrays.asList(2, 3, 1)); + assertEquals(0, computer.countStrikes(user)); + assertEquals(3, computer.countBalls(user)); + } + + @Test + void 낫싱_계산() { + Numbers computer = new Numbers(Arrays.asList(1, 2, 3)); + Numbers user = new Numbers(Arrays.asList(4, 5, 6)); + assertEquals(0, computer.countStrikes(user)); + assertEquals(0, computer.countBalls(user)); + } + + @Test + void 스트라이크_1_볼_1_계산() { + Numbers computer = new Numbers(Arrays.asList(1, 2, 3)); + Numbers user = new Numbers(Arrays.asList(1, 3, 4)); + assertEquals(1, computer.countStrikes(user)); + assertEquals(1, computer.countBalls(user)); + } +} From edd5dcba1fb11d7995d0d16f8a68dc263daf5205 Mon Sep 17 00:00:00 2001 From: seonwoonam Date: Sun, 8 Feb 2026 01:26:49 +0900 Subject: [PATCH 16/16] =?UTF-8?q?docs=20:=20readme=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index ebbbcd56..0519cd89 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,29 @@ -# java-baseball-precourse -## 기능 정리 -- 게임을 종료한 후 게임을 다시 시작하거나 완전히 종료 가능 -- 상대방의 역할을 컴퓨터가 진행. 컴퓨터는 서로 다른 임의의 수 3개 생성 -- 입력 및 출력 -- 컴퓨터의 수 맞추기 검증 - - 위 과정을 반복해 컴퓨터가 선택한 3개의 숫자를 모두 맞히면 게임 종료 -- 힌트 - - 같은 수가 같은 자리에 있으면 스트라이크, 다른 자리에 있으면 볼, 같은 수가 전혀 없으면 포볼 또는 낫싱이란 힌트 -- 에러처리 - - 사용자가 잘못된 값을 입력할 경우 [ERROR]로 시작하는 에러 메시지 출력하고 게임 계속 가능 \ No newline at end of file +# 숫자 야구 게임 +1부터 9까지 서로 다른 수로 이루어진 3자리의 수를 맞추는 게임. + +## 기능 정리 + +### 게임 진행 +- 사용자는 3개의 숫자를 입력하여 컴퓨터의 수를 맞추기 +- 3개의 숫자를 모두 맞히면 게임이 종료 +- 게임 종료 후 재시작(1)하거나 완전히 종료(2) + +### 컴퓨터의 수 맞추기 검증 +- 위 과정을 반복해 컴퓨터가 선택한 3개의 숫자를 모두 맞히면 게임 종료 + +### 입력 및 출력 +- 게임 시작 문구, 결과, 오류 메시지 등을 출력 + +### 힌트 +- 같은 수가 같은 자리에 있으면 `스트라이크` +- 같은 수가 다른 자리에 있으면 `볼` +- 같은 수가 전혀 없으면 `낫싱` + +### 예외 처리 +- 사용자가 잘못된 값을 입력할 경우 에러 발생 + - `[ERROR]`로 시작하는 에러 메시지를 출력 + - 에러 발생 후에도 게임을 계속 진행할 수 있도록 구현 + - 3자리가 아닌 경우 + - 숫자가 아닌 문자가 포함된 경우 + - 중복된 숫자가 있는 경우 + - 1~9 범위를 벗어난 경우