diff --git a/README.md b/README.md index 8d7e8aee..91767400 100644 --- a/README.md +++ b/README.md @@ -1 +1,24 @@ -# java-baseball-precourse \ No newline at end of file +# java-baseball-precourse + + + +## <구현기능> + +1. 컴퓨터가 무작위로 숫자 생성하는 기능 +- generateComputerNumbers() 메서드는 주어진 DIGIT_COUNT에 따라 랜덤한 숫자 배열을 생성. +- Random 클래스를 사용해 MIN_NUMBER와 MAX_NUMBER 사이의 랜덤한 숫자를 생성. +- 중복된 숫자가 생성되지 않도록 중복 체크 + +2. 사용자로부터 숫자를 입력받고 유효성을 검사하는 기능 +- getUserNumbers(Scanner scanner) +- 입력된 숫자의 길이가 DIGIT_COUNT와 일치하는지 확인하고 숫자가 아닌 문자가 입력되었는지 검사 +- 입력된 숫자가 MIN_NUMBER와 MAX_NUMBER 사이의 범위 내에 있는지 확인 + +3. 입력된 숫자와 컴퓨터가 생성한 숫자를 비교해 결과를 출력하는 기능 +- checkMatch(int[] computerNumbers, int[] userNumbers) +- 스트라이크와 볼을 계산하여 결과를 출력 +- 모든 숫자가 일치시 게임을 종료 + +4. 게임 재시작 또는 종료하는 기능 +- 게임을 종료할지 재시작할지 사용자로부터 입력 받기 +- 사용자가 1을 입력하면 게임을 재시작하고, 2 입력시 종료 diff --git a/src/main/java/Main.java b/src/main/java/Main.java new file mode 100644 index 00000000..35d24e7e --- /dev/null +++ b/src/main/java/Main.java @@ -0,0 +1,118 @@ + + +import java.util.Random; +import java.util.Scanner; + +public class Main { + public static final int DIGIT_COUNT = 3; + public static final int MIN_NUMBER = 1; + public static final int MAX_NUMBER = 9; + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + + while (true) { + int[] computerNumbers = generateComputerNumbers(); + + int[] userNumbers; + try { + userNumbers = getUserNumbers(scanner); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + System.out.println("게임을 종료합니다."); + scanner.close(); + return; + } + + while (!checkMatch(computerNumbers, userNumbers)) { + try { + userNumbers = getUserNumbers(scanner); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + System.out.println("게임을 종료합니다."); + scanner.close(); + return; + } + } + + System.out.println("게임을 다시 시작하려면 1, 종료하려면 2를 입력하세요."); + int choice = scanner.nextInt(); + if (choice != 1) { + break; + } + } + + System.out.println("게임을 종료합니다."); + scanner.close(); + } + + public static int[] getUserNumbers(Scanner scanner) { + int[] numbers = new int[DIGIT_COUNT]; + System.out.print("숫자를 입력해 주세요: "); + String input = scanner.next(); + if (input.length() != DIGIT_COUNT) { + throw new IllegalArgumentException("숫자의 길이가 올바르지 않습니다."); + } + for (int i = 0; i < DIGIT_COUNT; i++) { + char ch = input.charAt(i); + if (!Character.isDigit(ch)) { + throw new IllegalArgumentException("숫자가 아닙니다."); + } + numbers[i] = Character.getNumericValue(ch); + if (numbers[i] < MIN_NUMBER || numbers[i] > MAX_NUMBER) { + throw new IllegalArgumentException("숫자가 범위를 벗어납니다."); + } + } + return numbers; + } + + public static int[] generateComputerNumbers() { + int[] numbers = new int[DIGIT_COUNT]; + Random random = new Random(); + for (int i = 0; i < DIGIT_COUNT; i++) { + numbers[i] = random.nextInt(MAX_NUMBER - MIN_NUMBER + 1) + MIN_NUMBER; + for (int j = 0; j < i; j++) { + if (numbers[i] == numbers[j]) { + i--; + break; + } + } + } + return numbers; + } + + public static boolean checkMatch(int[] computerNumbers, int[] userNumbers) { + int strike = 0; + int ball = 0; + boolean match = false; + + for (int i = 0; i < DIGIT_COUNT; i++) { + for (int j = 0; j < DIGIT_COUNT; j++) { + if (userNumbers[i] == computerNumbers[j]) { + match = true; + if (i == j) { + strike++; + } else { + ball++; + } + } + } + } + + if (!match) { + System.out.println("낫싱"); + } else if (strike == DIGIT_COUNT) { + System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료"); + return true; + } else { + System.out.printf("%d볼 %d스트라이크\n", ball, strike); + } + return false; + } + + public static boolean gameRestartChoice(Scanner scanner) { + System.out.println("게임을 다시 시작하려면 1, 종료하려면 2를 입력하세요."); + int choice = scanner.nextInt(); + return choice == 1; + } +} \ No newline at end of file diff --git a/src/test/java/baseTest.java b/src/test/java/baseTest.java new file mode 100644 index 00000000..d75a1f15 --- /dev/null +++ b/src/test/java/baseTest.java @@ -0,0 +1,80 @@ + +import org.junit.jupiter.api.*; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.Scanner; + +import static org.junit.jupiter.api.Assertions.*; + +public class baseTest { + private static final String LINE_SEPARATOR = System.getProperty("line.separator"); + private static final String VALID_INPUT = "123" + LINE_SEPARATOR; + private static final String INVALID_LENGTH_INPUT = "12" + LINE_SEPARATOR; + private static final String INVALID_RANGE_INPUT = "102" + LINE_SEPARATOR; + + private static final int[] COMPUTER_NUMBERS = {1, 2, 3}; + private static final int[] USER_NUMBERS_ALL_MATCH = {1, 2, 3}; + private static final int[] USER_NUMBERS_PARTIAL_MATCH = {1, 4, 2}; + private static final int[] USER_NUMBERS_NO_MATCH = {4, 5, 6}; + + private static ByteArrayInputStream validInputStream; + private static ByteArrayInputStream invalidLengthInputStream; + private static ByteArrayInputStream invalidRangeInputStream; + + @BeforeAll + static void setUpStreams() { + validInputStream = new ByteArrayInputStream(VALID_INPUT.getBytes()); + invalidLengthInputStream = new ByteArrayInputStream(INVALID_LENGTH_INPUT.getBytes()); + invalidRangeInputStream = new ByteArrayInputStream(INVALID_RANGE_INPUT.getBytes()); + } + + @AfterAll + static void closeStreams() { + validInputStream = null; + invalidLengthInputStream = null; + invalidRangeInputStream = null; + } + + @Test + void testGenerateComputerNumbers() { + int[] numbers = Main.generateComputerNumbers(); + assertEquals(3, numbers.length, "생성된 숫자 배열의 길이가 3이어야 합니다."); + for (int number : numbers) { + assertTrue(number >= Main.MIN_NUMBER && number <= Main.MAX_NUMBER, "숫자 범위 확인"); + } + } + + @Test + void testGetUserNumbers() { + System.setIn(validInputStream); + int[] userNumbers = Main.getUserNumbers(new Scanner(System.in)); + assertNotNull(userNumbers, "유효한 입력이 제대로 처리되어야 합니다."); + + System.setIn(invalidLengthInputStream); + assertThrows(IllegalArgumentException.class, () -> Main.getUserNumbers(new Scanner(System.in)), + "올바르지 않은 길이의 입력이 예외를 발생시켜야 합니다."); + + System.setIn(invalidRangeInputStream); + assertThrows(IllegalArgumentException.class, () -> Main.getUserNumbers(new Scanner(System.in)), + "올바르지 않은 범위의 입력이 예외를 발생시켜야 합니다."); + } + + @Test + void testCheckMatch() { + assertFalse(Main.checkMatch(COMPUTER_NUMBERS, USER_NUMBERS_NO_MATCH), "일치하는 숫자가 없으면 false를 반환해야 합니다."); + assertTrue(Main.checkMatch(COMPUTER_NUMBERS, USER_NUMBERS_ALL_MATCH), "모든 숫자가 일치하면 true를 반환해야 합니다."); + assertFalse(Main.checkMatch(COMPUTER_NUMBERS, USER_NUMBERS_PARTIAL_MATCH), "부분적으로 일치하면 false를 반환해야 합니다."); + } + + @Test + void testGameRestartChoice() { + // 다시 시작 선택 + System.setIn(new ByteArrayInputStream("1\n".getBytes())); + assertTrue(Main.gameRestartChoice(new Scanner(System.in)), "1을 입력하면 true를 반환해야 합니다."); + + // 종료 선택 + System.setIn(new ByteArrayInputStream("2\n".getBytes())); + assertFalse(Main.gameRestartChoice(new Scanner(System.in)), "2를 입력하면 false를 반환해야 합니다."); + } +} \ No newline at end of file