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
20 changes: 20 additions & 0 deletions src/main/java/baseball/App.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package baseball;

import java.util.Scanner;

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

while (true) {
game.start();
System.out.println("게임을 새로 시작은 1, 종료 2를 입력하세요.");
String choice = scanner.nextLine().trim();
if (!choice.equals("1")) {
System.out.println("게임 종료");
break;
}
}
}
}
76 changes: 76 additions & 0 deletions src/main/java/baseball/Game.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package baseball;

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

public class Game {
private List<Integer> answer;

public Game() {
this.answer = generateRandomNumbers();
}

public Game(List<Integer> answer) {
this.answer = answer;
}

public void start() {
boolean isCorrect = false;
while (!isCorrect) {
try {
List<Integer> guess = InputView.getUserInput();
Result result = checkGuess(guess);
ResultView.printResult(result);
isCorrect = result.isCorrect();
} catch (IllegalArgumentException e) {
System.out.println("입력 오류: " + e.getMessage());
}
}
System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료");
}

private List<Integer> generateRandomNumbers() {
List<Integer> numbers = new ArrayList<>();
Random random = new Random();
while (numbers.size() < 3) {
int num = random.nextInt(9) + 1;
if (!numbers.contains(num)) {
numbers.add(num);
}
}
return numbers;
}

public Result checkGuess(List<Integer> guess) {
validateInput(guess);

int strike = 0;
int ball = 0;
for (int i = 0; i < 3; i++) {
if (guess.get(i).equals(answer.get(i))) {
strike++;
}
if (!guess.get(i).equals(answer.get(i)) && answer.contains(guess.get(i))) {
ball++;
}
}
return new Result(strike, ball);
}

private void validateInput(List<Integer> guess) {
if (guess.size() != 3) {
throw new IllegalArgumentException("숫자 3개를 정확히 입력해야 합니다.");
}
if (guess.stream().distinct().count() != 3) {
throw new IllegalArgumentException("각 숫자는 중복되지 않아야 합니다.");
}
if (!guess.stream().allMatch(n -> n >= 1 && n <= 9)) {
throw new IllegalArgumentException("모든 숫자는 1에서 9 사이여야 합니다.");
}
}

public List<Integer> getAnswer() {
return new ArrayList<>(answer);
}
}
67 changes: 67 additions & 0 deletions src/main/java/baseball/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package baseball;

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 사이여야 합니다.");
}
}
}
23 changes: 23 additions & 0 deletions src/main/java/baseball/Result.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package baseball;

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

public Result(int strike, int ball) {
this.strike = strike;
this.ball = ball;
}

public int getStrike() {
return strike;
}

public int getBall() {
return ball;
}

public boolean isCorrect() {
return strike == 3;
}
}
11 changes: 11 additions & 0 deletions src/main/java/baseball/ResultView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package baseball;

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

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;

import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

public class GameTest {

@Test
@DisplayName("정상적인 랜덤 숫자 생성 테스트")
public void testGenerateRandomNumbers() {
Game game = new Game();
List<Integer> numbers = game.getAnswer();

assertEquals(3, numbers.size(), "숫자 개수가 3개여야 됩니다.");
assertTrue(numbers.stream().allMatch(n -> n >= 1 && n <= 9),
"모든 숫자는 1에서 9 사이");
assertEquals(3, numbers.stream().distinct().count(),
"숫자는 중복되지 않됨.");
}

@Test
@DisplayName("정답을 맞췄을 때 3 스트라이크 확인")
public void testCheckGuessCorrect() {
Game game = new Game(List.of(4, 2, 5));
Result result = game.checkGuess(List.of(4, 2, 5));

assertEquals(3, result.getStrike(), "3 스트라이크임.");
assertEquals(0, result.getBall(), "볼이 없음.");
assertTrue(result.isCorrect(), "정답을 맞췄으므로 게임이 종료.");
}


}
89 changes: 89 additions & 0 deletions src/test/java/baseball/InputViewTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package baseball;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

public class InputViewTest {

@Test
@DisplayName("정상적인 입력 테스트")
public void testValidInput() {
// 사용자 입력을 시뮬레이션 (Scanner 대신 직접 입력 전달)
String input = "123";
List<Integer> numbers = InputView.extractNumbers(input);

assertEquals(3, numbers.size(), "숫자 개수가 3개여야 합니다.");
assertTrue(numbers.containsAll(List.of(1, 2, 3)), "입력된 숫자는 1, 2, 3이어야 합니다.");
}

@Test
@DisplayName("빈 입력값 테스트")
public void testEmptyInputThrowsException() {
IllegalArgumentException exception = assertThrows(
IllegalArgumentException.class,
() -> InputView.validateRawInput("")
);
assertEquals("입력값이 비어있습니다. 숫자 3개를 입력하세요.", exception.getMessage());
}

@ParameterizedTest
@ValueSource(strings = {"12", "1234", "12a", "1,2,3", "1 2 3"})
@DisplayName("잘못된 입력값에 대한 테스트")
public void testInvalidInputThrowsException(String input) {
IllegalArgumentException exception = assertThrows(
IllegalArgumentException.class,
() -> InputView.validateRawInput(input)
);
assertTrue(exception.getMessage().startsWith("입력값은 정확히") ||
exception.getMessage().startsWith("입력값에는"),
"예외 메시지가 정확히");
}

@Test
@DisplayName("중복된 숫자 입력 테스트")
public void testDuplicateNumbersThrowsException() {
List<Integer> numbers = List.of(1, 1, 2);
IllegalArgumentException exception = assertThrows(
IllegalArgumentException.class,
() -> InputView.validateNumbers(numbers)
);
assertEquals("각 숫자는 중복되지 않아야 합니다.", exception.getMessage());
}

@Test
@DisplayName("범위 밖의 숫자 입력 테스트")
public void testOutOfRangeNumbersThrowsException() {
List<Integer> numbers = List.of(1, 10, 2);
IllegalArgumentException exception = assertThrows(
IllegalArgumentException.class,
() -> InputView.validateNumbers(numbers)
);
assertEquals("엥간하면 0이하 10 이상은 하지 말자", exception.getMessage());
}

@Test
@DisplayName("공백이 포함된 입력 처리 테스트")
public void testInputWithSpaces() {
String input = " 1 2 3 ";
List<Integer> numbers = InputView.extractNumbers(input);

assertEquals(3, numbers.size(), "숫자 개수가 3개여야 합니다.");
assertTrue(numbers.containsAll(List.of(1, 2, 3)), "공백 처리 쏘 괜츈");
}

@Test
@DisplayName("특수문자 포함된 입력 처리 테스트")
public void testInputWithSpecialCharacters() {
String input = "1,2,3";
List<Integer> numbers = InputView.extractNumbers(input);

assertEquals(3, numbers.size(), "숫자 개수가 3개여야 합니다.");
assertTrue(numbers.containsAll(List.of(1, 2, 3)), "특수 문자 X , 숫자만 가능 합니다.");
}
}
13 changes: 0 additions & 13 deletions src/test/java/study/StringTest.java

This file was deleted.