-
Notifications
You must be signed in to change notification settings - Fork 29
[서윤_BackEnd] 2주차 과제 제출합니다. #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| 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. Application(main) | ||
| - 사용자로부터 입력받음 | ||
| - Validator로 검사 | ||
| - Car 객체 생성-> 레이스 동작 | ||
| - 결과 출력 | ||
|
|
||
|
|
||
| 2주차_리팩토링(주요 변경사항) | ||
| 1. Application | ||
| main() 안에 로직이 많음 ->>> 메서드 분리 | ||
| - getCarNames(): 이름 입력,검사 | ||
| - getTryCount(): 횟수 입력,검사 | ||
| - setupCars(String names): 입력받은 이름으로 car 리스트 만듦 | ||
| - runRace(List<Car> racingCars, int tryCount): 경주 진행(자동차 움직임, 핵심) | ||
| - void printCarStatus(Car car): 차 위치(position)에 따른 - 출력 | ||
| - void printWinners(List<Car> racingCars): 최종 우승자 출력 | ||
| - main(): 위의 메서드 사용 -> 실행! | ||
|
|
||
| 2. Validator | ||
| - int name_max 상수 선언했지만, 사용하지 않았음 -> 사용 | ||
| - 이름 검사: 2.2 이름 빈값/공백 감지 시, 메세지 출력하도록 수정 | ||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,73 @@ | ||
| package racingcar; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import camp.nextstep.edu.missionutils.Console; | ||
|
|
||
| public class Application { | ||
| public static void main(String[] args) { | ||
| // TODO: 프로그램 구현 | ||
| String names = getCarNames(); // 입력 및 검증 | ||
| int tryCount = getTryCount(); | ||
| List<Car> racingCars = setupCarsList(names); // 자동차(객체) 생성 | ||
| runRace(racingCars, tryCount); // 경주 진행/출력 | ||
| printWinners(racingCars); // 최종 우승자 출력 | ||
| } | ||
|
|
||
| //메서드 분리 | ||
| private static String getCarNames() { | ||
| System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"); | ||
| String names = Console.readLine(); //내부적으로 Scanner.nextLine()과 동일하게 작동 | ||
| return Validator.validateCarName(names); //반환값 단순화 | ||
| } | ||
|
|
||
| private static int getTryCount() { | ||
| System.out.println("시도할 회수는 몇회인가요?"); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아주 작은 부분이지만 사용자에게 보여지는 문구라서, 회수보다는 횟수로 맞춰주면 더 자연스러울 것 같아요. |
||
| String times = Console.readLine(); | ||
| return Validator.validateTry(times); | ||
| } | ||
|
|
||
| private static List<Car> setupCarsList(String names) { | ||
| String[] nameList = names.split(",", -1); //문자열을 , 을 구분으로 슬라이싱 | ||
| List<Car> racingCars = new ArrayList<>(); | ||
| for (String name : nameList) { //이름으로 자동차 리스트 | ||
| racingCars.add(new Car(name)); | ||
| } | ||
| return racingCars; | ||
| } | ||
|
|
||
| private static void runRace(List<Car> racingCars, int tryCount) { | ||
| System.out.println("\n실행 결과"); | ||
| for (int i = 0; i < tryCount; i++) { | ||
| for (Car car : racingCars) { | ||
| car.move(); | ||
| printCarStatus(car); //- 출력 | ||
| } | ||
| System.out.println(); | ||
| } | ||
| } | ||
| private static void printCarStatus(Car car) { | ||
| System.out.print(car.getName() + " : "); | ||
| for (int j = 0; j < car.getPosition(); j++) { | ||
| System.out.print("-"); | ||
| } | ||
| System.out.println(); | ||
| } | ||
|
|
||
| private static void printWinners(List<Car> racingCars) { | ||
| int maxPosition = 0; | ||
| for (Car car : racingCars) { | ||
| if (car.getPosition() > maxPosition) { | ||
| maxPosition = car.getPosition(); | ||
| } | ||
| } | ||
| List<String> winners = new ArrayList<>(); | ||
| for (Car car : racingCars) { | ||
| if (car.getPosition() == maxPosition) { | ||
| winners.add(car.getName()); | ||
| } | ||
| } | ||
| System.out.println("최종 우승자 : " + String.join(", ", winners)); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| package racingcar; | ||
|
|
||
| import camp.nextstep.edu.missionutils.Randoms; | ||
|
|
||
| /*Car | ||
| - 이름/위치 정보 | ||
| - move, getter 메서드*/ | ||
|
|
||
| public class Car { | ||
| private final String name; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이름을 final로 두고 상태를 private로 감싼 점은 좋아요. 객체가 가져야 할 값을 비교적 안전하게 관리하려는 의도가 잘 보입니다 👍 |
||
| private int position; | ||
|
|
||
| //정보를 넘겨받아 필드에 저장(생성자) | ||
| public Car(String name){ | ||
| this.name = name; | ||
| this.position = 0; | ||
| } | ||
|
|
||
| //동작: move 메서드 | ||
| public int move(){ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 반환값을 사용하는 곳이 보이지 않아서, 이 메서드의 책임이 상태 변경인지 값 반환인지 한 번 더 정리해보면 읽는 입장에서 더 명확해질 것 같아요. |
||
| if (Randoms.pickNumberInRange(0,9) >=4){ | ||
| position++; | ||
| } | ||
| return position; | ||
| } | ||
|
|
||
| //현재 이름/위치 반환: getter 메서드 넘겨주기 위해 | ||
| public String getName(){ | ||
| return name; | ||
| } | ||
| public int getPosition(){ | ||
| return position; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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){ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 현재 호출부에서는 반환값을 사용하지 않고 있어서, 검증만 담당하는 메서드라면 반환형을 조금 더 단순하게 가져갈 수 있을지 고민해봐도 좋을 것 같습니다. |
||
| if(names.isBlank()){ //1. 전체 검사 | ||
| throw new IllegalArgumentException("이름 입력값이 공백이거나 존재하지 않습니다."); | ||
| } | ||
| //입력을 ,를 기준으로 자른다. 배열로 저장. | ||
| String [] nameList = names.split(",",-1); | ||
| int name_max = 5; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 상수로 빼려던 의도는 보입니다만, 실제 검증에서는 다시 5를 직접 쓰고 있어서 이 값을 정말 사용할지 아니면 아예 상수 형태로 정리할지 한 번 맞춰보면 좋겠습니다. |
||
| Set<String> equalNames = new HashSet<>(); //자바에서 문자열 중복 검사는 HashSet을 사용하면 편리하다. | ||
| //2. 개별 입력에 대한 검사 | ||
| for(String name:nameList){ | ||
| if(name.length() > name_max) { //2.1 이름 길이 | ||
| throw new IllegalArgumentException("자동차 이름은 5자 이하로 입력해주세요."); | ||
| } | ||
| if(name.isBlank() || name.contains(" ")){ //2.2 이름 빈 값/공백 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 바로 위아래 예외는 메시지를 같이 주고 있는데 여기만 비어 있어서, 어떤 입력에서 실패했는지 파악하기 조금 어려울 수 있어 보여요. 이 부분도 같은 톤으로 메시지를 맞춰보면 좋겠습니다. |
||
| throw new IllegalArgumentException("자동차 이름을 입력하지 않았습니다."); | ||
| }if(!equalNames.add(name)){ //2.3 이름 중복 검사 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 중복 이름까지 예외 처리하고 있는데, 현재 README 요구사항에 포함된 제약인지 한 번 확인해보면 좋겠습니다. 의도한 추가 규칙이 아니라면 스펙보다 강한 제한이 될 수도 있어 보여요. |
||
| 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; | ||
| } | ||
|
|
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
main()에 입력, 검증, 게임 진행, 결과 출력이 모두 들어가 있어서 역할이 조금 큰 느낌이 있습니다. 메서드로 한 단계 더 나누면 흐름이 더 잘 보일 것 같아요.