-
Notifications
You must be signed in to change notification settings - Fork 4
[자동차 경주] 이원희 미션 제출합니다. #3
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
2af4445
337987a
6dc5694
2138e02
ca2e608
1d16135
3caef05
d55a56b
a90bd7e
736e045
fd27de6
2b0a3bf
568dd52
64f8dc5
7b8b87c
8ff5c39
1db4406
73f6348
43e48bc
624eb25
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,29 @@ | ||
| ## 기능명세 | ||
| ### 1. 자동차 이름을 입력받기 위한 화면을 구성한다. | ||
| - 자동차 이름 입력받기 | ||
| - 자동차 이름이 5자 이하인 경우에만 입력받기 | ||
| - 자동차 이름에 쉼표(,)로 구분된 이름이 1개 이상인 경우에만 입력받기 | ||
| - 같은 이름의 자동차가 존재하지 않는 경우에만 입력받기 | ||
| - 자동차 이름 저장하기 | ||
| - 자동차 이름을 쉼표(,)로 구분하여 저장하기 | ||
| - 예외 발생 시 에러 던지고 종료 | ||
|
|
||
| ### 2. 시도할 회수를 입력받기 위한 화면을 구성한다. | ||
| - 시도할 회수 입력받기 | ||
| - 시도할 회수가 1 이상인 경우에만 입력받기 | ||
| - 시도할 회수가 숫자인 경우에만 입력받기 | ||
| - 시도할 회수 저장하기 | ||
| - 시도할 회수를 저장하기 | ||
| - 정수로 저장하기 | ||
| - 예외 발생 시 에러 던지고 종료 | ||
|
|
||
| ### 3. 자동차 경주를 진행한다. | ||
| - 시도할 회수를 입력 받은 대로 자동차를 전진시킨다. | ||
| - 차수별 자동차 이름과 전진한 거리를 출력한다. | ||
|
|
||
| ### 4. 경주 결과를 출력한다. | ||
| - 경주 결과를 출력한다. | ||
| - 우승자를 출력한다. | ||
|
|
||
| ### 5. 경주 게임을 종료한다. | ||
| - 경주 게임을 종료한다. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,25 @@ | ||
| package racingcar; | ||
|
|
||
| import racingcar.controller.InputController; | ||
| import racingcar.model.RacingCar; | ||
| import racingcar.view.ResultView; | ||
|
|
||
| public class Application { | ||
|
|
||
| public static void main(String[] args) { | ||
| // TODO: 프로그램 구현 | ||
| startGame(); | ||
| } | ||
|
|
||
| // 게임 시작 | ||
| public static void startGame() { | ||
| InputController.createRacingCar(); | ||
| int round = InputController.setRoundNum(); | ||
| ResultView.printResult(); | ||
| for (int i = 0; i < round; i++) { | ||
| RacingCar.moveCars(); | ||
| System.out.println(); | ||
| } | ||
| RacingCar.getWinners(); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| package racingcar.controller; | ||
| import racingcar.model.NameValid; | ||
| import racingcar.model.NumberVaild; | ||
| import racingcar.model.RacingCar; | ||
| import racingcar.view.InputView; | ||
|
|
||
| public class InputController { | ||
| // 레이싱 자동차를 생성한다. | ||
| public static void createRacingCar() { | ||
| NameValid nameValid = new NameValid(InputView.carNameInput()); | ||
| new RacingCar(nameValid.getNames()); | ||
| } | ||
|
|
||
| public static int setRoundNum() { | ||
| NumberVaild validation = new NumberVaild(Integer.parseInt(InputView.tryCountInput())); | ||
| return validation.getNumber(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| package racingcar.model; | ||
|
|
||
| public class Car{ | ||
| private final String name; | ||
| private int position; | ||
|
|
||
| public Car(String name){ | ||
| this.name = name; | ||
| this.position = 0; | ||
| } | ||
|
|
||
| public void move(){ | ||
| // 매개변수로 랜덤 값을 주면 테스트하기 좋아진다. | ||
| // 랜덤 값이 4 이상이면 전진한다. | ||
| if(RandomNumber.getRandomNumber() >= 4){ | ||
| position++; | ||
| } | ||
| } | ||
|
|
||
| // 최대 위치 반환 | ||
| public int getPosition(){ | ||
| return position; | ||
| } | ||
|
|
||
| public String getName() { | ||
| return name.replace(" ", ""); | ||
| } | ||
| } |
|
Contributor
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. 이 부분은 취향차이일 수도 있는데, Name의 검증과 관련된 부분은 Car 객체를 생성하는 과정에 넣는 게 더 좋지 않나 싶습니다! 그럴 일은 잘 없겠지만 Controller에서 NameValid를 사용하는 것을 까먹고 바로 Car를 생성할 수도 있는 거고, Car에 해당 검증 로직을 넣으면 원터치로 검증이 가능하기 때문에 좋아보입니다.
Member
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. Validation은 Controller에서 제외하는 것이 좋다는 것에 동의합니다. Controller는 Request를 넘겨주는 entry point의 역할만 수행하도록 만드는게 좋다고 생각합니다. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| package racingcar.model; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Arrays; | ||
|
|
||
| public class NameValid { | ||
| final ArrayList<String> names; | ||
|
Contributor
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. 리스트의 불변성 관련 검색 키워드
|
||
|
|
||
| public ArrayList<String> toArrayList(String carsString) { | ||
| String[] carNames = carsString.trim().split(","); | ||
| return new ArrayList<>(Arrays.asList(carNames)); | ||
| } | ||
|
|
||
| public NameValid(String carName) { | ||
| this.names = toArrayList(carName); | ||
| isValid(); | ||
| } | ||
|
|
||
| // 자동차 이름이 5자 이하인지 확인 | ||
| public void isNameValid() { | ||
| for (String name : names) { | ||
| if (name.length() > 5) { | ||
| throw new IllegalArgumentException("자동차 이름은 5자 이하만 가능합니다."); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // 자동차 이름이 중복되는지 확인 | ||
| public void isNameDuplicate() { | ||
| for (int i = 0; i < names.size(); i++) { | ||
| for (int j = i + 1; j < names.size(); j++) { | ||
| if (names.get(i).equals(names.get(j))) { | ||
| // 에러 반환 | ||
| throw new IllegalArgumentException("중복된 이름이 존재합니다."); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
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. 자동차 이름이 중복되는건 생각하지 못했는데 저도 기능 명세를 작성할때 더 생각하는 능력을 길러봐야겠어요!
Author
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. 감사합니당~ |
||
|
|
||
| // 자동차 이름이 유효한지 확인 | ||
| public void isValid() { | ||
| isNameValid(); | ||
| isNameDuplicate(); | ||
| } | ||
|
|
||
| public ArrayList<String> getNames() { | ||
| return names; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| package racingcar.model; | ||
|
|
||
| public class NumberVaild { | ||
| private static int number = 0; | ||
|
|
||
| public NumberVaild(int number) { | ||
| NumberVaild.number = number; | ||
| isValid(); | ||
| } | ||
|
|
||
| // 숫자가 맞는지 확인한다. | ||
| public void isValid() { | ||
| isNumber(); | ||
| isPositiveNumber(); | ||
| } | ||
|
|
||
| // 숫자만 입력했는지 확인한다. | ||
| public void isNumber() { | ||
| if (!String.valueOf(number).matches("^[0-9]*$")) { | ||
| throw new IllegalArgumentException("숫자만 입력해주세요."); | ||
| } | ||
| } | ||
|
|
||
| // 0보다 큰 숫자인지 확인한다. | ||
| public void isPositiveNumber() { | ||
| if (number < 0) { | ||
| throw new IllegalArgumentException("0보다 큰 숫자를 입력해주세요."); | ||
| } | ||
| } | ||
|
|
||
| public int getNumber() { | ||
| return number; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| package racingcar.model; | ||
|
|
||
| import racingcar.view.ResultView; | ||
|
|
||
| import java.util.ArrayList; | ||
|
|
||
| public class RacingCar { | ||
| private static final ArrayList<Car> cars = new ArrayList<>(); | ||
|
Contributor
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. static 키워드를 붙이면 멀티쓰레드 환경에서 필드의 일관성이 보장되지 않기 때문에 당장 생각할 문제는 아니지만 여러 명이 게임을 플레이한다고 가정했을 때 문제가 될 수 있을 것 같습니다! 제거를 고려해보시면 좋을 것 같아유 |
||
|
|
||
| public RacingCar(ArrayList<String> cars) { | ||
| for (String car : cars) { | ||
| RacingCar.cars.add(new Car(car)); | ||
| } | ||
| } | ||
|
|
||
| // 자동차들을 이동시킨다. | ||
| public static void moveCars() { | ||
| for (Car car : cars) { | ||
| car.move(); | ||
| ResultView.printRoundResult(car.getName(), car.getPosition()); | ||
| } | ||
| } | ||
|
|
||
| // 우승자를 반환한다. | ||
| public static void getWinners() { | ||
| ArrayList<String> winners = new ArrayList<>(); | ||
| int maxPosition = getMaxPosition(); | ||
| for (Car car : cars) { | ||
| if (car.getPosition() == maxPosition) { | ||
| winners.add(car.getName()); | ||
| } | ||
| } | ||
| ResultView.printWinner(winners); | ||
| } | ||
|
Comment on lines
+16
to
+34
Member
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. Model에서 View를 호출하지 않고 Controller에서 결합하도록 하는 것이 좋다고 생각합니다!
Author
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. 반영하겠습니다~ |
||
|
|
||
| // 최대 이동값 | ||
| private static int getMaxPosition() { | ||
| int maxPosition = 0; | ||
| for (Car car : cars) { | ||
| maxPosition = Math.max(maxPosition, car.getPosition()); | ||
| } | ||
| return maxPosition; | ||
| } | ||
| } | ||
|
Comment on lines
+36
to
+44
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. 저는 최대값 구하는걸 다른 반복문 안에 같이 집어넣었는데 따로 분리하니까 훨씬 깔끔하고 좋아보이네요
Author
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. 감사합니당~ |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package racingcar.model; | ||
| import camp.nextstep.edu.missionutils.Randoms; | ||
|
|
||
| public class RandomNumber { | ||
| public static int getRandomNumber() { | ||
| return Randoms.pickNumberInRange(0,9); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| package racingcar.view; | ||
| import camp.nextstep.edu.missionutils.Console; | ||
|
|
||
| public class InputView { | ||
|
|
||
| private InputView() { | ||
| } | ||
|
|
||
| // 자동차의 이름을 입력받는다. | ||
| public static String carNameInput() { | ||
| System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"); | ||
| return Console.readLine(); | ||
| } | ||
|
|
||
| // 시도할 회수를 입력받는다. | ||
| public static String tryCountInput() { | ||
| System.out.println("시도할 회수는 몇회인가요?"); | ||
| return Console.readLine(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| package racingcar.view; | ||
|
|
||
| import java.util.ArrayList; | ||
|
|
||
| public class ResultView { | ||
|
|
||
| private ResultView() { | ||
| } | ||
|
|
||
| // 경주 결과를 출력한다. | ||
| public static void printResult() { | ||
| System.out.println("실행 결과"); | ||
| } | ||
|
|
||
| // 라운드 결과 출력 | ||
| public static void printRoundResult(String name, int position) { | ||
| System.out.print(name + " : "); | ||
| System.out.print("-".repeat(position)); | ||
|
Member
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. repeat 메서드를 사용하는 방법이 있다는 것을 처음 알았네요! 좋은 방법 같습니다
Author
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. 감사합니당~ |
||
| System.out.println(); | ||
| } | ||
|
|
||
| // 최종 우승자를 출력한다. | ||
| public static void printWinner(ArrayList<String> winners) { | ||
| System.out.print("최종 우승자 : "); | ||
| for (int i = 0; i < winners.size(); i++) { | ||
| System.out.print(winners.get(i)); | ||
| if (i != winners.size() - 1) { | ||
| System.out.print(", "); | ||
| } | ||
| } | ||
| } | ||
| } | ||
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.
Controller 객체를 만들지 않고 Application.java에서 바로 시작한 이유가 있나요?
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.
가독성과 동작에 크게 영향을 주지 않는다고 생각 했습니다