From cf4b68efba1762b451a99c2ef28bc7192cf334f4 Mon Sep 17 00:00:00 2001 From: yun6882 Date: Mon, 30 Mar 2026 21:40:32 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat:=201=EC=A3=BC=EC=B0=A8=20=EB=B0=B1?= =?UTF-8?q?=EC=97=94=EB=93=9C=20=EA=B3=BC=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 26 ++++++++ src/main/java/racingcar/Application.java | 64 +++++++++++++++++++- src/main/java/racingcar/Car.java | 34 +++++++++++ src/main/java/racingcar/Validator.java | 49 +++++++++++++++ src/test/java/racingcar/ApplicationTest.java | 2 +- 5 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 src/main/java/racingcar/Car.java create mode 100644 src/main/java/racingcar/Validator.java diff --git a/docs/README.md b/docs/README.md index e69de29..dadf7b3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,26 @@ +1. 주어진 횟수 동안 n대의 자동차는 전진 또는 멈출 수 있다. +2. 각 자동차에 이름을 부여할 수 있다. 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다. +3. 자동차 이름은 쉼표(,)를 기준으로 구분하며 이름은 5자 이하만 가능하다. +4. 사용자는 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다. +5. 전진하는 조건은 0에서 9 사이에서 무작위 값을 구한 후 무작위 값이 4 이상일 경우이다. +6. 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한 명 이상일 수 있다. +7. 우승자가 여러 명일 경우 쉼표(,)를 이용하여 구분한다. +8. 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시킨 후 애플리케이션은 종료되어야 한다. + + +Car class / Validator class / main(사용자 입출력/게임 실행) +1. Car +- 이름/위치 정보 +- move, getter 메서드 + +2. Validator +- 자동차 이름 입력값 검사 +- 횟수 입력값 검사 + +3. main +- 사용자로부터 입력받음 +- Validator로 검사 +- Car 객체 생성-> 레이스 동작 +- 결과 출력 + + diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java index a17a52e..272d047 100644 --- a/src/main/java/racingcar/Application.java +++ b/src/main/java/racingcar/Application.java @@ -1,7 +1,69 @@ package racingcar; +import java.util.ArrayList; +import java.util.List; +import camp.nextstep.edu.missionutils.Console; + + +//3. main +//- 입력받음 -> Validator로 검사 +//- Car 객체 생성/레이스 동작 +//- 결과 출력 public class Application { public static void main(String[] args) { - // TODO: 프로그램 구현 + //1.사용자로부터 이름/횟수 입력받기 -> 검사 + System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"); + String names = Console.readLine(); //내부적으로 Scanner.nextLine()과 동일하게 작동 + Validator.validateCarName(names); + + System.out.println("시도할 회수는 몇회인가요?"); + String times = Console.readLine(); + int tryCount = Validator.validateTry(times); + + //2.Car 객체 리스트 생성 + String[] nameList = names.split(",",-1); + List racingCars= new ArrayList<>(); + for (String name: nameList){ + racingCars.add(new Car(name)); + } + //4. 결과 출력(실행 결과, 최종 우승자) + System.out.println("\n실행 결과"); + for (int i = 0; i maxPosition) { + maxPosition = car.getPosition(); //최고 거리 갱신 + } + } + List winners = new ArrayList<>(); + for (Car car : racingCars) { + if (car.getPosition() == maxPosition) { + winners.add(car.getName()); + } + } + System.out.println("최종 우승자 : " + String.join(", ", winners)); + + + + + + + + + + + } } diff --git a/src/main/java/racingcar/Car.java b/src/main/java/racingcar/Car.java new file mode 100644 index 0000000..bd645ac --- /dev/null +++ b/src/main/java/racingcar/Car.java @@ -0,0 +1,34 @@ +package racingcar; + +import camp.nextstep.edu.missionutils.Randoms; + +/*Car +- 이름/위치 정보 +- move, getter 메서드*/ + +public class Car { + private final String name; + private int position; + + //정보를 넘겨받아 필드에 저장(생성자) + public Car(String name){ + this.name = name; + this.position = 0; + } + + //동작: move 메서드 + public int move(){ + if (Randoms.pickNumberInRange(0,9) >=4){ + position++; + } + return position; + } + + //현재 이름/위치 반환: getter 메서드 넘겨주기 위해 + public String getName(){ + return name; + } + public int getPosition(){ + return position; + } +} diff --git a/src/main/java/racingcar/Validator.java b/src/main/java/racingcar/Validator.java new file mode 100644 index 0000000..ab75826 --- /dev/null +++ b/src/main/java/racingcar/Validator.java @@ -0,0 +1,49 @@ +package racingcar; +import java.util.HashSet; +import java.util.Set; + +/*2. Validator +- 자동차 이름 입력값 검사 +- 횟수 입력값 검사*/ + + +public class Validator { + //이름 입력 검사 + public static String validateCarName(String names){ + if(names.isBlank()){ //1. 전체 검사 + throw new IllegalArgumentException("이름 입력값이 공백이거나 존재하지 않습니다."); + } + //입력을 ,를 기준으로 자른다. 배열로 저장. + String [] nameList = names.split(",",-1); + int name_max = 5; + Set equalNames = new HashSet<>(); //자바에서 문자열 중복 검사는 HashSet을 사용하면 편리하다. + //2. 개별 입력에 대한 검사 + for(String name:nameList){ + if(name.length() > 5) { //2.1 이름 길이 + throw new IllegalArgumentException("자동차 이름은 5자 이하로 입력해주세요."); + } + if(name.isBlank() || name.contains(" ")){ //2.2 이름 빈 값/공백 + throw new IllegalArgumentException(); + }if(!equalNames.add(name)){ //2.3 이름 중복 검사 + throw new IllegalArgumentException("자동차 이름은 중복될 수 없습니다."); + } + } + return names; + + } + + //시도 횟수 검사 + public static int validateTry(String times){ + int count; + try{ + count = Integer.parseInt(times); //Integer.parseInt(문자)일 경우, NumberException 에러 발생 ->try/catch + }catch(NumberFormatException e){ + throw new IllegalArgumentException("시도 횟수를 숫자로 입력해주세요."); + } + if (count < 1) { + throw new IllegalArgumentException("시도 횟수는 1 이상이어야 합니다."); + } + return count; + } + +} diff --git a/src/test/java/racingcar/ApplicationTest.java b/src/test/java/racingcar/ApplicationTest.java index 03aa74b..d89d605 100644 --- a/src/test/java/racingcar/ApplicationTest.java +++ b/src/test/java/racingcar/ApplicationTest.java @@ -19,7 +19,7 @@ class ApplicationTest extends NsTest { run("pobi,woni", "1"); assertThat(output()).contains("pobi : -", "woni : ", "최종 우승자 : pobi"); }, - MOVING_FORWARD, STOP + MOVING_FORWARD, STOP //난수 반환 설정 ); } From f0cd4722ac7a9155b24dc8bdeeb89a616b0e2743 Mon Sep 17 00:00:00 2001 From: yun6882 Date: Mon, 6 Apr 2026 23:29:24 +0900 Subject: [PATCH 2/4] =?UTF-8?q?docs:=202=EC=A3=BC=EC=B0=A8=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81=20=EC=A3=BC=EC=9A=94=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=EC=82=AC=ED=95=AD=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index dadf7b3..a2f2a6b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -17,10 +17,26 @@ Car class / Validator class / main(사용자 입출력/게임 실행) - 자동차 이름 입력값 검사 - 횟수 입력값 검사 -3. main +3. Application(main) - 사용자로부터 입력받음 - Validator로 검사 - Car 객체 생성-> 레이스 동작 - 결과 출력 +2주차_리팩토링(주요 변경사항) +1. Application +main() 안에 로직이 많음 ->>> 메서드 분리 +- getCarNames(): 이름 입력,검사 +- getTryCount(): 횟수 입력,검사 +- setupCars(String names): 입력받은 이름으로 car 리스트 만듦 +- runRace(List racingCars, int tryCount): 경주 진행(자동차 움직임, 핵심) +- void printCarStatus(Car car): 차 위치(position)에 따른 - 출력 +- void printWinners(List racingCars): 최종 우승자 출력 +- main(): 위의 메서드 사용 -> 실행! + +2. Validator +- int name_max 상수 선언했지만, 사용하지 않았음 -> 사용 +- 이름 검사: 2.2 이름 빈값/공백 감지 시, 메세지 출력하도록 수정 + + From 02d201b64a1a7a202807c4a886140a3ed4a7fc96 Mon Sep 17 00:00:00 2001 From: yun6882 Date: Mon, 6 Apr 2026 23:40:00 +0900 Subject: [PATCH 3/4] =?UTF-8?q?refactor:=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/racingcar/Application.java | 76 +++++++++++++----------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java index 272d047..244f8be 100644 --- a/src/main/java/racingcar/Application.java +++ b/src/main/java/racingcar/Application.java @@ -4,47 +4,60 @@ import java.util.List; import camp.nextstep.edu.missionutils.Console; - -//3. main -//- 입력받음 -> Validator로 검사 -//- Car 객체 생성/레이스 동작 -//- 결과 출력 public class Application { public static void main(String[] args) { - //1.사용자로부터 이름/횟수 입력받기 -> 검사 + String names = getCarNames(); // 입력 및 검증 + int tryCount = getTryCount(); + List racingCars = setupCarsList(names); // 자동차(객체) 생성 + runRace(racingCars, tryCount); // 경주 진행/출력 + printWinners(racingCars); // 최종 우승자 출력 + } + + //메서드 분리 + private static String getCarNames() { System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"); String names = Console.readLine(); //내부적으로 Scanner.nextLine()과 동일하게 작동 - Validator.validateCarName(names); + return Validator.validateCarName(names); //반환값 단순화 + } + private static int getTryCount() { System.out.println("시도할 회수는 몇회인가요?"); String times = Console.readLine(); - int tryCount = Validator.validateTry(times); + return Validator.validateTry(times); + } - //2.Car 객체 리스트 생성 - String[] nameList = names.split(",",-1); - List racingCars= new ArrayList<>(); - for (String name: nameList){ + private static List setupCarsList(String names) { + String[] nameList = names.split(",", -1); //문자열을 , 을 구분으로 슬라이싱 + List racingCars = new ArrayList<>(); + for (String name : nameList) { //이름으로 자동차 리스트 racingCars.add(new Car(name)); } - //4. 결과 출력(실행 결과, 최종 우승자) + return racingCars; + } + + private static void runRace(List racingCars, int tryCount) { System.out.println("\n실행 결과"); - for (int i = 0; i racingCars) { + int maxPosition = 0; + for (Car car : racingCars) { if (car.getPosition() > maxPosition) { - maxPosition = car.getPosition(); //최고 거리 갱신 + maxPosition = car.getPosition(); } } List winners = new ArrayList<>(); @@ -54,16 +67,7 @@ public static void main(String[] args) { } } System.out.println("최종 우승자 : " + String.join(", ", winners)); - - - - - - - - - - - } } + + From 093cca6a5a9c23ab00cf59af267439f2e9742e14 Mon Sep 17 00:00:00 2001 From: yun6882 Date: Mon, 6 Apr 2026 23:41:47 +0900 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20=EC=B6=9C=EB=A0=A5=20=EB=A9=94?= =?UTF-8?q?=EC=84=B8=EC=A7=80=20=EC=B6=94=EA=B0=80,=20=EC=83=81=EC=88=98?= =?UTF-8?q?=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/racingcar/Validator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/racingcar/Validator.java b/src/main/java/racingcar/Validator.java index ab75826..46b4f7a 100644 --- a/src/main/java/racingcar/Validator.java +++ b/src/main/java/racingcar/Validator.java @@ -19,11 +19,11 @@ public static String validateCarName(String names){ Set equalNames = new HashSet<>(); //자바에서 문자열 중복 검사는 HashSet을 사용하면 편리하다. //2. 개별 입력에 대한 검사 for(String name:nameList){ - if(name.length() > 5) { //2.1 이름 길이 + if(name.length() > name_max) { //2.1 이름 길이 throw new IllegalArgumentException("자동차 이름은 5자 이하로 입력해주세요."); } if(name.isBlank() || name.contains(" ")){ //2.2 이름 빈 값/공백 - throw new IllegalArgumentException(); + throw new IllegalArgumentException("자동차 이름을 입력하지 않았습니다."); }if(!equalNames.add(name)){ //2.3 이름 중복 검사 throw new IllegalArgumentException("자동차 이름은 중복될 수 없습니다."); }