Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file modified gradlew
100644 → 100755
Empty file.
17 changes: 17 additions & 0 deletions src/main/java/baseball/App.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package baseball;

import baseball.controller.GameController;
import baseball.game.Game;

import java.util.Scanner;

public class App {
public static void main(String[] args) {
Game game = new Game();
Scanner scanner = new Scanner(System.in);

GameController gameController = new GameController(game, scanner);

gameController.run();
}
}
32 changes: 32 additions & 0 deletions src/main/java/baseball/checker/BallChecker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package baseball.checker;

import baseball.matcher.NumberMatcher;
import baseball.matcher.PositionMatcher;
import baseball.config.Constants;
import java.util.List;

public class BallChecker {
private final NumberMatcher numberMatcher;
private final PositionMatcher positionMatcher;

public BallChecker() {
this.numberMatcher = new NumberMatcher();
this.positionMatcher = new PositionMatcher();
}

public int countBalls(List<Integer> guess, List<Integer> answer) {
int ballCount = Constants.ZERO;
for (int i = 0; i < Constants.NUMBER_COUNT; i++) {
if (isBall(guess.get(i), answer, i)) {
ballCount++;
}
}
return ballCount;
}

private boolean isBall(int guessedNumber, List<Integer> answer, int index) {
// 볼 조건: 위치가 맞지 않고 숫자가 정답에 포함된 경우
return !positionMatcher.isPositionMatching(answer, guessedNumber, index)
&& answer.contains(guessedNumber);
}
}
32 changes: 32 additions & 0 deletions src/main/java/baseball/checker/StrikeChecker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package baseball.checker;

import baseball.matcher.NumberMatcher;
import baseball.matcher.PositionMatcher;
import baseball.config.Constants;
import java.util.List;

// 스트라이크 개수 계산
public class StrikeChecker {
private final NumberMatcher numberMatcher;
private final PositionMatcher positionMatcher;

public StrikeChecker() {
this.numberMatcher = new NumberMatcher();
this.positionMatcher = new PositionMatcher();
}

public int countStrikes(List<Integer> guess, List<Integer> answer) {
int strikeCount = Constants.ZERO;
for (int i = 0; i < Constants.NUMBER_COUNT; i++) {
if (isStrike(guess.get(i), answer, i)) {
strikeCount++;
}
}
return strikeCount;
}

private boolean isStrike(int guessedNumber, List<Integer> answer, int index) {
return numberMatcher.isMatching(guessedNumber, answer.get(index))
&& positionMatcher.isPositionMatching(answer, guessedNumber, index);
}
}
9 changes: 9 additions & 0 deletions src/main/java/baseball/config/Constants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package baseball.config;

public class Constants {
public static final int NUMBER_COUNT = 3; // 숫자 개수
public static final int MIN_NUMBER = 1; // 최소 숫자
public static final int MAX_NUMBER = 9; // 최대 숫자
public static final int ZERO = 0;
public static final int WINNING_STRIKES = 3;
}
32 changes: 32 additions & 0 deletions src/main/java/baseball/controller/GameController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package baseball.controller;

import baseball.game.Game;
import baseball.io.Message;

import java.util.Scanner;

public class GameController {
private final Game game;
private final Scanner scanner;

// 의존성 주입: 외부에서 객체를 주입받도록 생성자 수정
public GameController(Game game, Scanner scanner) {
this.game = game;
this.scanner = scanner;
}

public void run() {
boolean isRunning = true;
while (isRunning) {
game.start();
isRunning = promptRestart();
}
Message.printMessage(Message.GAME_END);
}

private boolean promptRestart() {
Message.printMessage(Message.RESTART_PROMPT);
String choice = scanner.nextLine().trim();
return choice.equals("1");
}
}
60 changes: 60 additions & 0 deletions src/main/java/baseball/game/Game.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package baseball.game;

import baseball.validation.Validator;
import baseball.io.InputView;
import baseball.io.ResultView;
import baseball.model.Result;

import java.util.List;

public class Game {
private List<Integer> answer;
private Validator validator;
private RandomNumberGenerator randomNumberGenerator;
private GuessChecker guessChecker;

public Game() {
this.randomNumberGenerator = new RandomNumberGenerator();
this.answer = randomNumberGenerator.generate();
this.validator = new Validator();
this.guessChecker = new GuessChecker(answer);
}

public Game(List<Integer> answer) {
this.answer = answer;
this.validator = new Validator();
this.guessChecker = new GuessChecker(answer);
}

// 주석으로 바꾸면 RED
public List<Integer> getAnswer() {
return answer;
}
// 주석으로 바꾸면 RED
public Result checkGuess(List<Integer> guess) {
validator.validate(guess); // 유효성 검사
return guessChecker.check(guess); // 스트라이크와 볼 계산 후 Result 반환
}

public void start() {
boolean isCorrect = false;
while (!isCorrect) {
try {
List<Integer> guess = InputView.getUserInput();
validator.validate(guess);

// GuessChecker로부터 얻는 결과를 StrikeAndBall로 변경
Result strikeAndBall = guessChecker.check(guess);

// StrikeAndBall 객체를 ResultView로 전달
ResultView.printResult(strikeAndBall);

// 스트라이크가 3개일 때 isCorrect를 true로 설정
isCorrect = strikeAndBall.getStrike() == 3;
} catch (IllegalArgumentException e) {
System.out.println("입력 오류: " + e.getMessage());
}
}
System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료");
}
}
26 changes: 26 additions & 0 deletions src/main/java/baseball/game/GuessChecker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package baseball.game;

import baseball.checker.BallChecker;
import baseball.checker.StrikeChecker;
import baseball.model.Result;
import baseball.model.Result;

import java.util.List;

class GuessChecker {
private List<Integer> answer;
private StrikeChecker strikeChecker;
private BallChecker ballChecker;

public GuessChecker(List<Integer> answer) {
this.answer = answer;
this.strikeChecker = new StrikeChecker();
this.ballChecker = new BallChecker();
}

public Result check(List<Integer> guess) {
int strike = strikeChecker.countStrikes(guess, answer);
int ball = ballChecker.countBalls(guess, answer);
return new Result(strike, ball);
}
}
22 changes: 22 additions & 0 deletions src/main/java/baseball/game/RandomNumberGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package baseball.game;

import baseball.config.Constants;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class RandomNumberGenerator {

public List<Integer> generate() {
List<Integer> numbers = new ArrayList<>();
Random random = new Random();
while (numbers.size() < Constants.NUMBER_COUNT) {
int num = random.nextInt(Constants.MAX_NUMBER) + Constants.MIN_NUMBER;
if (!numbers.contains(num)) {
numbers.add(num);
}
}
return numbers;
}
}
67 changes: 67 additions & 0 deletions src/main/java/baseball/io/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package baseball.io;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class InputView {

private static final Scanner scanner = new Scanner(System.in);

public static List<Integer> getUserInput() {
while (true) {
try {
String input = getInputFromUser();
validateRawInput(input);
List<Integer> numbers = extractNumbers(input);
validateNumbers(numbers);
return numbers;
} catch (IllegalArgumentException e) {
System.out.println("ERROR : " + e.getMessage());
}
}
}

private static String getInputFromUser() {
System.out.print("숫자를 입력해 주세요(1에서 9 사이의 숫자 3개): ");
return scanner.nextLine().trim();
}

static void validateRawInput(String input) {
if (input.isEmpty()) {
throw new IllegalArgumentException("입력값이 비어있습니다. 숫자 3개를 입력하세요.");
}
if (input.length() != 3) {
throw new IllegalArgumentException("입력값은 정확히 3자리여야 합니다.");
}
if (!input.matches("[1-9]+")) { // 숫자가 아닌 문자나 특수기호를 처리
throw new IllegalArgumentException("입력값에는 1에서 9 사이의 숫자만 포함되어야 합니다.");
}
}

static List<Integer> extractNumbers(String input) {
List<Integer> numbers = new ArrayList<>();

// 입력에서 숫자만 추출하고 공백은 무시
for (char c : input.toCharArray()) {
if (Character.isDigit(c)) {
int num = Character.getNumericValue(c);
numbers.add(num);
}
}

return numbers;
}

static void validateNumbers(List<Integer> numbers) {
if (numbers.size() != 3) {
throw new IllegalArgumentException("숫자 3개를 정확히 입력해야 합니다.");
}
if (numbers.stream().distinct().count() != 3) {
throw new IllegalArgumentException("각 숫자는 중복되지 않아야 합니다.");
}
if (!numbers.stream().allMatch(n -> n >= 1 && n <= 9)) {
throw new IllegalArgumentException("모든 숫자는 1에서 9 사이여야 합니다.");
}
}
}
12 changes: 12 additions & 0 deletions src/main/java/baseball/io/Message.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package baseball.io;

public class Message {

public static final String RESTART_PROMPT = "게임을 새로 시작은 1, 종료 2를 입력하세요.";
public static final String GAME_END = "게임 종료";
public static final String GAME_COMPLETE = "3개의 숫자를 모두 맞히셨습니다! 게임 종료한다요~~~~~~~~~";

public static void printMessage(String message) {
System.out.println(message);
}
}
13 changes: 13 additions & 0 deletions src/main/java/baseball/io/ResultView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package baseball.io;

import baseball.model.Result;

public class ResultView {
public static void printResult(Result strikeAndBall) {
if (strikeAndBall.getStrike() == 0 && strikeAndBall.getBall() == 0) {
System.out.println("낫싱");
} else {
System.out.println(strikeAndBall.getBall() + "볼 " + strikeAndBall.getStrike() + "스트라이크");
}
}
}
15 changes: 15 additions & 0 deletions src/main/java/baseball/matcher/NumberMatcher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package baseball.matcher;

import java.util.List;

// 숫자가 일치 하는지 비교 하고 싶은데....
public class NumberMatcher {

public boolean isMatching(int guessedNumber, int answerNumber) {
return guessedNumber == answerNumber;
}
// 숫자가 정답 리스트에 포함되어 있는지 확인하는 메서드
public boolean isNumberMatching(List<Integer> answer, int guessedNumber) {
return answer.contains(guessedNumber);
}
}
11 changes: 11 additions & 0 deletions src/main/java/baseball/matcher/PositionMatcher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package baseball.matcher;

import java.util.List;

//숫자가 위치가 일치 하는지 비교
public class PositionMatcher {

public boolean isPositionMatching(List<Integer> answer, int guessedNumber, int index) {
return answer.get(index) == guessedNumber;
}
}
36 changes: 36 additions & 0 deletions src/main/java/baseball/model/Result.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package baseball.model;

import baseball.config.Constants;
import baseball.validation.Validator;

public class Result {
private final int strike;
private final int ball;

// 생성자
public Result(int strike, int ball) {
Validator.validateStrikeAndBall(strike, ball); // 유효성 검증
this.strike = strike;
this.ball = ball;
}

// 스트라이크 개수 반환
public int getStrike() {
return strike;
}

// 볼 개수 반환
public int getBall() {
return ball;
}

// 정답 여부 확인
public boolean isCorrect() {
return strike == Constants.WINNING_STRIKES; // 상수로 대체
}

@Override
public String toString() {
return String.format("결과: %d 스트라이크, %d 볼!", strike, ball);
}
}
Loading