diff --git a/build.gradle b/build.gradle index 8172fb73f..bd111ae07 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,6 @@ dependencies { testImplementation "org.junit.jupiter:junit-jupiter:5.7.2" testImplementation "org.assertj:assertj-core:3.19.0" } - test { useJUnitPlatform() } diff --git a/src/main/java/Application.java b/src/main/java/Application.java new file mode 100644 index 000000000..875c3f01f --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,8 @@ +import gameController.GameController; + +public class Application { + public static void main(String[] args) { + GameController gameController = new GameController(); + gameController.start(); + } +} diff --git a/src/main/java/domain/generator/BaseBallNumbersGenerator.java b/src/main/java/domain/generator/BaseBallNumbersGenerator.java new file mode 100644 index 000000000..745dbaa1c --- /dev/null +++ b/src/main/java/domain/generator/BaseBallNumbersGenerator.java @@ -0,0 +1,25 @@ +package domain.generator; + +import domain.model.BaseBallNumbers; + +import java.util.ArrayList; +import java.util.List; + +public class BaseBallNumbersGenerator { + private final NumberGenerator numberGenerator; + + public BaseBallNumbersGenerator(NumberGenerator numberGenerator) { + this.numberGenerator = numberGenerator; + } + + public List generate() { + List numbers = new ArrayList<>(); + while (numbers.size() < BaseBallNumbers.NumberSize) { + int num = numberGenerator.generate(); + if (!numbers.contains(num)) { + numbers.add(num); + } + } + return numbers; + } +} diff --git a/src/main/java/domain/generator/NumberGenerator.java b/src/main/java/domain/generator/NumberGenerator.java new file mode 100644 index 000000000..c9af3a2db --- /dev/null +++ b/src/main/java/domain/generator/NumberGenerator.java @@ -0,0 +1,5 @@ +package domain.generator; + +public interface NumberGenerator { + int generate(); +} \ No newline at end of file diff --git a/src/main/java/domain/generator/RandomNumbersGenerator.java b/src/main/java/domain/generator/RandomNumbersGenerator.java new file mode 100644 index 000000000..a913b22cf --- /dev/null +++ b/src/main/java/domain/generator/RandomNumbersGenerator.java @@ -0,0 +1,12 @@ +package domain.generator; + +import java.util.Random; + +public class RandomNumbersGenerator implements NumberGenerator { + private final Random random = new Random(); + + @Override + public int generate() { + return random.nextInt(9) + 1; + } +} diff --git a/src/main/java/domain/model/BaseBallNumbers.java b/src/main/java/domain/model/BaseBallNumbers.java new file mode 100644 index 000000000..fa2218e38 --- /dev/null +++ b/src/main/java/domain/model/BaseBallNumbers.java @@ -0,0 +1,55 @@ +package domain.model; + +import java.util.ArrayList; +import java.util.List; + +public class BaseBallNumbers { + public static final int NumberSize = 3; + private final List numbers; + public static BaseBallNumbers from(List numbers) { + return new BaseBallNumbers(numbers); + } + public static BaseBallNumbers parse(String input) { + List numbers = new ArrayList<>(); + for (char c : input.toCharArray()) { + numbers.add(Character.getNumericValue(c)); + } + return new BaseBallNumbers(numbers); + } + + private BaseBallNumbers(List numbers) { + validate(numbers); + this.numbers = numbers; + } + + private void validate(List numbers) { + if (numbers.size() != NumberSize) { + throw new IllegalArgumentException("숫자는 " + NumberSize + "개여야 합니다."); + } + if (numbers.stream().distinct().count() != NumberSize) { + throw new IllegalArgumentException("중복된 숫자가 있습니다."); + } + for (int num : numbers) { + if (num < 1 || num > 9) { + throw new IllegalArgumentException("숫자는 1-9 사이여야 합니다."); + } + } + } + + public int get(int index) { + return numbers.get(index); + } + + public boolean contains(int num) { + return numbers.contains(num); + } + + public int size() { + return numbers.size(); + } + // 값 확인용 + @Override + public String toString() { + return numbers.toString(); + } +} diff --git a/src/main/java/domain/model/GameResult.java b/src/main/java/domain/model/GameResult.java new file mode 100644 index 000000000..75270158e --- /dev/null +++ b/src/main/java/domain/model/GameResult.java @@ -0,0 +1,27 @@ +package domain.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 isWin() { + return strike == BaseBallNumbers.NumberSize; + } + + public boolean isNothing() { + return strike == 0 && ball == 0; + } + + public int getStrike() { + return strike; + } + + public int getBall() { + return ball; + } +} \ No newline at end of file diff --git a/src/main/java/domain/service/Referee.java b/src/main/java/domain/service/Referee.java new file mode 100644 index 000000000..19d20f4ef --- /dev/null +++ b/src/main/java/domain/service/Referee.java @@ -0,0 +1,22 @@ +package domain.service; + +import domain.model.BaseBallNumbers; +import domain.model.GameResult; + +public class Referee { + + public GameResult decides(BaseBallNumbers problemNumbers, BaseBallNumbers inputNumber) { + int strike = 0; + int ball = 0; + + for (int i = 0; i < problemNumbers.size(); i++) { + int guessNum = inputNumber.get(i); + if (guessNum == problemNumbers.get(i)) { + strike++; + } else if (problemNumbers.contains(guessNum)) { + ball++; + } + } + return new GameResult(strike, ball); + } +} diff --git a/src/main/java/gameController/GameController.java b/src/main/java/gameController/GameController.java new file mode 100644 index 000000000..21cd8ea63 --- /dev/null +++ b/src/main/java/gameController/GameController.java @@ -0,0 +1,46 @@ +package gameController; + +import domain.model.BaseBallNumbers; +import domain.model.GameResult; +import domain.service.Referee; +import domain.generator.BaseBallNumbersGenerator; +import domain.generator.RandomNumbersGenerator; +import handler.InputHandler; +import view.OutputView; + + +public class GameController { + private final InputHandler inputHandler; + private final OutputView outputView; + private final Referee referee; + private int failCount; + + public GameController() { + this.inputHandler = new InputHandler(); + this.outputView = new OutputView(); + this.referee = new Referee(); + this.failCount = 0; + } + + public void start() { + BaseBallNumbersGenerator numberGenerator = new BaseBallNumbersGenerator(new RandomNumbersGenerator()); + BaseBallNumbers problemNumbers = BaseBallNumbers.from(numberGenerator.generate()); + outputView.printGameStart(); + try { + while (true) { + String userInput = inputHandler.getUserInput(); + BaseBallNumbers userNumbers = BaseBallNumbers.parse(userInput); + GameResult gameResult = referee.decides(problemNumbers, userNumbers); + if (gameResult.isWin()) { + outputView.printWin(); + break; + } + failCount++; + outputView.printResult(gameResult.getStrike(), gameResult.getBall(), failCount); + } + inputHandler.close(); + } catch (IllegalArgumentException error) { + System.out.println(error.getMessage()); + } + } +} diff --git a/src/main/java/handler/InputHandler.java b/src/main/java/handler/InputHandler.java new file mode 100644 index 000000000..6465720f5 --- /dev/null +++ b/src/main/java/handler/InputHandler.java @@ -0,0 +1,43 @@ +package handler; + +import domain.model.BaseBallNumbers; + +import java.util.Scanner; + +public class InputHandler { + private final Scanner scanner; + public InputHandler() { + this.scanner = new Scanner(System.in); + } + + public String getUserInput() { + System.out.print("숫자를 입력하세요: "); + String input = scanner.nextLine(); + validate(input); + return input; + } + + private void validate(String input) { + // 자릿수 체크 + if (input.length() != BaseBallNumbers.NumberSize) { + throw new IllegalArgumentException("3자리 숫자를 입력하세요."); + } + // 1-9 숫자 확인 + for (int i = 0; i < BaseBallNumbers.NumberSize; i++) { + char c = input.charAt(i); + if (c < '1' || c > '9') { + throw new IllegalArgumentException("1-9 사이 숫자만 입력하세요."); + } + } + // 중복 체크 + if (input.chars().distinct().count() != BaseBallNumbers.NumberSize) { + throw new IllegalArgumentException("중복된 숫자는 입력할 수 없습니다."); + } + + } + + // 재시작 로직이 + public void close() { + scanner.close(); + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 000000000..fc733b19a --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,28 @@ +package view; + +public class OutputView { + + public void printGameStart() { + System.out.println("숫자 야구 게임 시작"); + } + + public void printResult(int strike, int ball, int failCount) { + StringBuilder text = new StringBuilder(); + if (strike > 0) { + text.append(strike).append("스트라이크 "); + } + if (ball > 0) { + text.append(ball).append("볼 "); + } + if (strike == 0 && ball == 0) { + text.append("일치값 없음 "); + } + + text.append("(").append(failCount).append("번 실패)"); + System.out.println(text.toString()); + } + + public void printWin() { + System.out.println("정답!"); + } +} diff --git a/src/test/java/domain/generator/BaseBallNumbersGeneratorTest.java b/src/test/java/domain/generator/BaseBallNumbersGeneratorTest.java new file mode 100644 index 000000000..bcd308ae5 --- /dev/null +++ b/src/test/java/domain/generator/BaseBallNumbersGeneratorTest.java @@ -0,0 +1,39 @@ +package domain.generator; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class BaseBallNumbersGeneratorTest { + + @Test + void Numbers123Test() { + NumberGenerator fixedGenerator = new TestNumberGenerator(1, 2, 3); + BaseBallNumbersGenerator generator = new BaseBallNumbersGenerator(fixedGenerator); + List result = generator.generate(); + assertThat(result).containsExactly(1, 2, 3); + // assertThat(result) => 검사할 값 + // containsExactly > 배열이 일치하는지 확인(가변 배열을 인자로 받음) + System.out.println("Number123Test Check Complete"); + } + + @Test + void Numbers459() { + NumberGenerator fixedGenerator = new TestNumberGenerator(4, 5, 9); + BaseBallNumbersGenerator generator = new BaseBallNumbersGenerator(fixedGenerator); + List result = generator.generate(); + assertThat(result).containsExactly(4, 5, 9); + System.out.println("Numbers459 Check Complete"); + } + + @Test + void duplicateNumbersCheck() { + NumberGenerator fixedGenerator = new TestNumberGenerator(1, 1, 2, 3); + BaseBallNumbersGenerator generator = new BaseBallNumbersGenerator(fixedGenerator); + List result = generator.generate(); + assertThat(result).containsExactly(1, 2, 3); + assertThat(result).hasSize(3); + } +} diff --git a/src/test/java/domain/generator/TestNumberGenerator.java b/src/test/java/domain/generator/TestNumberGenerator.java new file mode 100644 index 000000000..f87e52056 --- /dev/null +++ b/src/test/java/domain/generator/TestNumberGenerator.java @@ -0,0 +1,15 @@ +package domain.generator; + +public class TestNumberGenerator implements NumberGenerator { + private final int[] numbers; + private int index = 0; + + public TestNumberGenerator(int... numbers) { + this.numbers = numbers; + } + + @Override + public int generate() { + return numbers[index++]; + } +}