diff --git a/docs/README.md b/docs/README.md index e69de29..7d035a2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,11 @@ +[ ] 경주할 자동차 이름 입력 받기 (쉼표로 구분, 5자 이하만 가능) + +[ ] 시도할 횟수 입력 받기 + +[ ] 입력값에 대한 예외 처리 (IllegalArgumentException 발생 후 종료) + +[ ] 각 차수별로 무작위 값(0~9)을 구해 4 이상일 경우 전진 + +[ ] 각 차수별 실행 결과 출력 + +[ ] 우승자 판별 및 출력 (중복 시 쉼표로 구분) \ No newline at end of file diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java index a17a52e..535d0ef 100644 --- a/src/main/java/racingcar/Application.java +++ b/src/main/java/racingcar/Application.java @@ -1,7 +1,138 @@ -package racingcar; +/*package racingcar; public class Application { public static void main(String[] args) { // TODO: 프로그램 구현 } +}*/ +package racingcar; + +import camp.nextstep.edu.missionutils.Console; +import camp.nextstep.edu.missionutils.Randoms; + +import java.util.ArrayList; +import java.util.List; + +public class Application { + public static void main(String[] args) { + // [변경 1] 예외 발생 시 애플리케이션 종료 요구 반영 + try { + runRacingGame(); + } catch (IllegalArgumentException e) { + throw e; // 잘못된 값 입력 시 예외 발생 후 종료 + } + } + + private static void runRacingGame() { + List cars = setupCars(); + int tryCount = readTryCount(); + + System.out.println("\n실행 결과"); + for (int i = 0; i < tryCount; i++) { + playOneRound(cars); + printRoundStatus(cars); + } + printWinner(cars); + } + + // [변경 2] 함수 분리를 통한 Indent(들여쓰기) depth 줄이기 + // while문이나 if문 중첩을 피하기 위해 로직을 잘게 쪼개어 depth 2를 유지함 + private static List setupCars() { + System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"); + String input = Console.readLine(); // Scanner 대신 전용 Console API 사용 + return createCarList(input); + } + + private static List createCarList(String input) { + List cars = new ArrayList<>(); + for (String name : input.split(",")) { // 쉼표(,) 기준 구분 요구사항 반영 + String trimmedName = name.trim(); + validateName(trimmedName); // 이름은 5자 이하만 가능하다는 규칙 검증 + cars.add(new Car(trimmedName)); + } + return cars; + } + + private static void validateName(String name) { + if (name.isEmpty() || name.length() > 5) { + throw new IllegalArgumentException("이름은 5자 이하만 가능합니다."); + } + } + + private static int readTryCount() { + System.out.println("시도할 회수는 몇회인가요?"); + String input = Console.readLine(); + return parseValidCount(input); + } + + private static int parseValidCount(String input) { + try { + int count = Integer.parseInt(input); + validatePositive(count); + return count; + } catch (NumberFormatException e) { + throw new IllegalArgumentException("숫자만 입력 가능합니다."); + } + } + + private static void validatePositive(int count) { + if (count < 0) { + throw new IllegalArgumentException("시도 횟수는 0 이상이어야 합니다."); + } + } + + private static void playOneRound(List cars) { + for (Car car : cars) { + moveIfLucky(car); + } + } + + private static void moveIfLucky(Car car) { + // [변경 3] 전진 조건 반영 (0~9 무작위 값 중 4 이상일 때만 전진) + // Random 대신 전용 Randoms API 활용 + if (Randoms.pickNumberInRange(0, 9) >= 4) { + car.move(); + } + } + + private static void printRoundStatus(List cars) { + for (Car car : cars) { + // 자동차 이름과 함께 전진 거리(-) 출력 + System.out.println(car.getName() + " : " + "-".repeat(car.getPosition())); + } + System.out.println(); + } + + private static void printWinner(List cars) { + int maxPos = getMaxPosition(cars); + List winners = findWinners(cars, maxPos); + // [변경 4] 우승자가 여러 명일 경우 쉼표(,)로 구분 출력 요구사항 반영 + System.out.println("최종 우승자 : " + String.join(", ", winners)); + } + + private static int getMaxPosition(List cars) { + int max = 0; + for (Car car : cars) { + // [변경 5] 3항 연산자 사용 금지 요구사항 반영 + max = Math.max(max, car.getPosition()); + } + return max; + } + + private static List findWinners(List cars, int maxPos) { + List winners = new ArrayList<>(); + for (Car car : cars) { + addIfWinner(winners, car, maxPos); + } + return winners; + } + + private static void addIfWinner(List winners, Car car, int maxPos) { + if (car.getPosition() == maxPos) { + winners.add(car.getName()); + } + } } + + +