From 4c39ef58134f25205986a6f025daf575b5488ed4 Mon Sep 17 00:00:00 2001 From: Hyoungmin Kim Date: Mon, 30 Mar 2026 21:39:38 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=EC=9E=90=EB=8F=99=EC=B0=A8=20?= =?UTF-8?q?=EA=B2=BD=EC=A3=BC=20=EA=B2=8C=EC=9E=84=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) 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 From 6509c0195b29bc26746814f5f80e6b3d123b9462 Mon Sep 17 00:00:00 2001 From: Hyoungmin Kim Date: Mon, 30 Mar 2026 21:55:33 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=EC=9E=90=EB=8F=99=EC=B0=A8=20?= =?UTF-8?q?=EA=B2=BD=EC=A3=BC=20=EA=B2=8C=EC=9E=84=20=EB=B0=8F=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/racingcar/Application.java | 165 ++++++++++++++++++++++- 1 file changed, 164 insertions(+), 1 deletion(-) diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java index a17a52e..a725e40 100644 --- a/src/main/java/racingcar/Application.java +++ b/src/main/java/racingcar/Application.java @@ -1,7 +1,170 @@ -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. 자동차 이름 입력 및 객체 생성 + System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"); + String inputNames = Console.readLine(); + List cars = createCars(inputNames); + + // 2. 시도 횟수 입력 + System.out.println("시도할 회수는 몇회인가요?"); + int tryCount = parseTryCount(Console.readLine()); + + // 3. 경주 진행 및 결과 출력 + System.out.println("\n실행 결과"); + for (int i = 0; i < tryCount; i++) { + playRound(cars); // 한 라운드 진행 + printRoundResult(cars); // 결과 출력 + } + + // 4. 최종 우승자 판별 및 출력 + printFinalWinner(cars); + } + + /** + * 입력받은 문자열을 쉼표 기준으로 나누어 자동차 리스트를 만듭니다. + */ + private static List createCars(String input) { + String[] names = input.split(","); + List cars = new ArrayList<>(); + for (String name : names) { + String trimmedName = name.trim(); + validateName(trimmedName); // 이름 유효성 검사 + cars.add(new Car(trimmedName)); + } + return cars; + } + + /** + * 자동차 이름이 5자를 초과하거나 비어있는지 확인합니다. + */ + private static void validateName(String name) { + if (name.isEmpty() || name.length() > 5) { + // 요구 사항: 잘못된 값 입력 시 IllegalArgumentException 발생 + throw new IllegalArgumentException("이름은 1자 이상, 5자 이하만 가능합니다."); + } + } + + /** + * 입력받은 시도 횟수를 정수로 변환하며 예외를 처리합니다. + */ + private static int parseTryCount(String input) { + try { + int count = Integer.parseInt(input); + if (count < 0) { + throw new IllegalArgumentException("시도 횟수는 0 이상이어야 합니다."); + } + return count; + } catch (NumberFormatException e) { + throw new IllegalArgumentException("시도 횟수는 숫자여야 합니다."); + } + } + + /** + * 모든 자동차에 대해 무작위 값을 구하고 전진 여부를 결정합니다. + */ + private static void playRound(List cars) { + for (Car car : cars) { + // 요구 사항: 0에서 9 사이의 무작위 값 구하기 + int randomNumber = Randoms.pickNumberInRange(0, 9); + // 요구 사항: 무작위 값이 4 이상일 경우 전진 + if (randomNumber >= 4) { + car.move(); + } + } + } + + /** + * 현재 라운드에서 각 자동차의 위치를 '-' 기호로 시각화하여 출력합니다. + */ + private static void printRoundResult(List cars) { + for (Car car : cars) { + // repeat() 메서드를 사용해 위치만큼 '-'를 반복 출력합니다. + System.out.println(car.getName() + " : " + "-".repeat(car.getPosition())); + } + System.out.println(); // 라운드 구분을 위한 줄바꿈 + } + + /** + * 경주가 끝난 후 가장 멀리 간 우승자들을 찾아 출력합니다. + */ + private static void printFinalWinner(List cars) { + int maxPosition = getMaxPosition(cars); // 1. 최고 기록 찾기 + List winners = new ArrayList<>(); + + for (Car car : cars) { + // 2. 최고 기록과 일치하는 우승자 선별 + addIfWinner(winners, car, maxPosition); + } + // 요구 사항: 우승자가 여러 명일 경우 쉼표(,)로 구분 + System.out.println("최종 우승자 : " + String.join(", ", winners)); + } + + /** + * 자동차들 중 가장 높은 위치 값을 반환합니다. + */ + private static int getMaxPosition(List cars) { + int max = 0; + for (Car car : cars) { + // 3항 연산자를 쓰지 않기 위해 Math.max 사용 + max = Math.max(max, car.getPosition()); + } + return max; + } + + /** + * 자동차의 위치가 최고 기록과 같다면 우승자 명단에 추가합니다. + * (들여쓰기 깊이를 줄이기 위해 메서드로 분리) + */ + private static void addIfWinner(List winners, Car car, int maxPosition) { + if (car.getPosition() == maxPosition) { + winners.add(car.getName()); + } + } +} + +/** + * 자동차의 정보를 담는 클래스입니다. + * 이름(name)과 위치(position) 데이터를 가집니다. + */ +class Car { + private final String name; + private int position = 0; + + public Car(String name) { + this.name = name; + } + + // 자동차를 한 칸 전진시킵니다. + public void move() { + this.position++; + } + + public String getName() { + return name; + } + + public int getPosition() { + return position; + } } + + + + + From 63d2d3a51859c07f0ec3e33f177382a4ff43315b Mon Sep 17 00:00:00 2001 From: Hyoungmin Kim Date: Mon, 6 Apr 2026 22:12:27 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=EC=9E=90=EB=8F=99=EC=B0=A8=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81=20=EC=A7=84?= =?UTF-8?q?=ED=96=89=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=9E=85=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/racingcar/Application.java | 162 +++++++++-------------- 1 file changed, 65 insertions(+), 97 deletions(-) diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java index a725e40..535d0ef 100644 --- a/src/main/java/racingcar/Application.java +++ b/src/main/java/racingcar/Application.java @@ -5,7 +5,6 @@ public static void main(String[] args) { // TODO: 프로그램 구현 } }*/ - package racingcar; import camp.nextstep.edu.missionutils.Console; @@ -16,155 +15,124 @@ public static void main(String[] args) { public class Application { public static void main(String[] args) { - // 1. 자동차 이름 입력 및 객체 생성 - System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"); - String inputNames = Console.readLine(); - List cars = createCars(inputNames); + // [변경 1] 예외 발생 시 애플리케이션 종료 요구 반영 + try { + runRacingGame(); + } catch (IllegalArgumentException e) { + throw e; // 잘못된 값 입력 시 예외 발생 후 종료 + } + } - // 2. 시도 횟수 입력 - System.out.println("시도할 회수는 몇회인가요?"); - int tryCount = parseTryCount(Console.readLine()); + private static void runRacingGame() { + List cars = setupCars(); + int tryCount = readTryCount(); - // 3. 경주 진행 및 결과 출력 System.out.println("\n실행 결과"); for (int i = 0; i < tryCount; i++) { - playRound(cars); // 한 라운드 진행 - printRoundResult(cars); // 결과 출력 + playOneRound(cars); + printRoundStatus(cars); } + printWinner(cars); + } - // 4. 최종 우승자 판별 및 출력 - printFinalWinner(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 createCars(String input) { - String[] names = input.split(","); + private static List createCarList(String input) { List cars = new ArrayList<>(); - for (String name : names) { + for (String name : input.split(",")) { // 쉼표(,) 기준 구분 요구사항 반영 String trimmedName = name.trim(); - validateName(trimmedName); // 이름 유효성 검사 + validateName(trimmedName); // 이름은 5자 이하만 가능하다는 규칙 검증 cars.add(new Car(trimmedName)); } return cars; } - /** - * 자동차 이름이 5자를 초과하거나 비어있는지 확인합니다. - */ private static void validateName(String name) { if (name.isEmpty() || name.length() > 5) { - // 요구 사항: 잘못된 값 입력 시 IllegalArgumentException 발생 - throw new IllegalArgumentException("이름은 1자 이상, 5자 이하만 가능합니다."); + throw new IllegalArgumentException("이름은 5자 이하만 가능합니다."); } } - /** - * 입력받은 시도 횟수를 정수로 변환하며 예외를 처리합니다. - */ - private static int parseTryCount(String input) { + 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); - if (count < 0) { - throw new IllegalArgumentException("시도 횟수는 0 이상이어야 합니다."); - } + validatePositive(count); return count; } catch (NumberFormatException e) { - throw new IllegalArgumentException("시도 횟수는 숫자여야 합니다."); + throw new IllegalArgumentException("숫자만 입력 가능합니다."); } } - /** - * 모든 자동차에 대해 무작위 값을 구하고 전진 여부를 결정합니다. - */ - private static void playRound(List cars) { - for (Car car : cars) { - // 요구 사항: 0에서 9 사이의 무작위 값 구하기 - int randomNumber = Randoms.pickNumberInRange(0, 9); - // 요구 사항: 무작위 값이 4 이상일 경우 전진 - if (randomNumber >= 4) { - car.move(); - } + private static void validatePositive(int count) { + if (count < 0) { + throw new IllegalArgumentException("시도 횟수는 0 이상이어야 합니다."); } } - /** - * 현재 라운드에서 각 자동차의 위치를 '-' 기호로 시각화하여 출력합니다. - */ - private static void printRoundResult(List cars) { + private static void playOneRound(List cars) { for (Car car : cars) { - // repeat() 메서드를 사용해 위치만큼 '-'를 반복 출력합니다. - System.out.println(car.getName() + " : " + "-".repeat(car.getPosition())); + moveIfLucky(car); } - System.out.println(); // 라운드 구분을 위한 줄바꿈 } - /** - * 경주가 끝난 후 가장 멀리 간 우승자들을 찾아 출력합니다. - */ - private static void printFinalWinner(List cars) { - int maxPosition = getMaxPosition(cars); // 1. 최고 기록 찾기 - List winners = new ArrayList<>(); + 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) { - // 2. 최고 기록과 일치하는 우승자 선별 - addIfWinner(winners, car, maxPosition); + // 자동차 이름과 함께 전진 거리(-) 출력 + 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) { - // 3항 연산자를 쓰지 않기 위해 Math.max 사용 + // [변경 5] 3항 연산자 사용 금지 요구사항 반영 max = Math.max(max, car.getPosition()); } return max; } - /** - * 자동차의 위치가 최고 기록과 같다면 우승자 명단에 추가합니다. - * (들여쓰기 깊이를 줄이기 위해 메서드로 분리) - */ - private static void addIfWinner(List winners, Car car, int maxPosition) { - if (car.getPosition() == maxPosition) { - winners.add(car.getName()); + private static List findWinners(List cars, int maxPos) { + List winners = new ArrayList<>(); + for (Car car : cars) { + addIfWinner(winners, car, maxPos); } - } -} - -/** - * 자동차의 정보를 담는 클래스입니다. - * 이름(name)과 위치(position) 데이터를 가집니다. - */ -class Car { - private final String name; - private int position = 0; - - public Car(String name) { - this.name = name; + return winners; } - // 자동차를 한 칸 전진시킵니다. - public void move() { - this.position++; - } - - public String getName() { - return name; - } - - public int getPosition() { - return position; + private static void addIfWinner(List winners, Car car, int maxPos) { + if (car.getPosition() == maxPos) { + winners.add(car.getName()); + } } } - -