diff --git a/README.md b/README.md index d0286c859f..2f76b68fe6 100644 --- a/README.md +++ b/README.md @@ -1 +1,45 @@ # java-racingcar-precourse +## πŸ“κ΅¬ν˜„ν•  κΈ°λŠ₯ λͺ©λ‘ +**1. μž…λ ₯** +- μžλ™μ°¨ 이름과 μ‹œλ„ 횟수λ₯Ό μž…λ ₯ λ°›λŠ”λ‹€ + - 빈 κ°’, μ‹œλ„ 횟수 검증 +- `,`을 κΈ°μ€€μœΌλ‘œ μžλ™μ°¨ 이름을 λΆ„λ¦¬ν•œλ‹€ + - μžλ™μ°¨ 이름 길이 검증 + +**2. μžλ™μ°¨** +- μž…λ ₯받은 이름을 μ €μž₯ν•œλ‹€ +- 총 μ›€μ§μž„μ„ μ €μž₯ν•œλ‹€ + +**3. λ‚œμˆ˜ 생성** +- 0μ—μ„œ 9μ‚¬μ΄μ˜ λ‚œμˆ˜λ₯Ό μƒμ„±ν•œλ‹€ + +**4. κ²½μ£Ό** +- μž…λ ₯받은 횟수만큼 λΌμš΄λ“œλ₯Ό μ§„ν–‰ν•œλ‹€ + +**5. 좜λ ₯** +- μ΅œμ’… 우승자λ₯Ό 좜λ ₯ν•œλ‹€ + + \ No newline at end of file diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java index a17a52e724..c1cce46cf2 100644 --- a/src/main/java/racingcar/Application.java +++ b/src/main/java/racingcar/Application.java @@ -1,7 +1,15 @@ package racingcar; +import racingcar.controller.RaceController; +import racingcar.view.InputView; +import racingcar.view.OutputView; + public class Application { public static void main(String[] args) { - // TODO: ν”„λ‘œκ·Έλž¨ κ΅¬ν˜„ + InputView inputView = new InputView(); + OutputView outputView = new OutputView(); + RaceController raceController = new RaceController(inputView, outputView); + + raceController.run(); } } diff --git a/src/main/java/racingcar/Race.java b/src/main/java/racingcar/Race.java new file mode 100644 index 0000000000..0c2ee6fd9a --- /dev/null +++ b/src/main/java/racingcar/Race.java @@ -0,0 +1,14 @@ +package racingcar; + +import racingcar.model.Cars; +import racingcar.utils.RandomNumberGenerator; + +public class Race { + public void run(Cars cars) { + cars.getCarList().forEach((car -> { + if (RandomNumberGenerator.IsMoveable()) { + car.moveForward(); + } + })); + } +} diff --git a/src/main/java/racingcar/RacingGame.java b/src/main/java/racingcar/RacingGame.java new file mode 100644 index 0000000000..aa6fe12a51 --- /dev/null +++ b/src/main/java/racingcar/RacingGame.java @@ -0,0 +1,40 @@ +package racingcar; + +import racingcar.model.Car; +import racingcar.model.Cars; +import racingcar.view.OutputView; + +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +public class RacingGame { + private OutputView outputView; + public RacingGame(OutputView outputView) { + this.outputView = outputView; + } + public void run(Cars cars, Integer round) { + Race race = new Race(); + for(int i = 0; i < round ; i++) { + race.run(cars); + outputView.printRaceResult(cars); + } + + outputView.printWinner(getWinner(cars)); + } + + public String getWinner(Cars cars) { + Integer maxMovement = getMaxMovement(cars); + return cars.getCarList().stream() + .filter((car) -> car.getMovement().equals(maxMovement)) + .map(Car::getName) + .collect(Collectors.joining(",")); + } + + private Integer getMaxMovement(Cars cars) { + return cars.getCarList().stream() + .map(Car::getMovement) + .max(Comparator.naturalOrder()) + .orElse(0); + } +} diff --git a/src/main/java/racingcar/controller/RaceController.java b/src/main/java/racingcar/controller/RaceController.java new file mode 100644 index 0000000000..3c0a1de8f5 --- /dev/null +++ b/src/main/java/racingcar/controller/RaceController.java @@ -0,0 +1,26 @@ +package racingcar.controller; + +import racingcar.RacingGame; +import racingcar.model.Cars; +import racingcar.view.InputView; +import racingcar.view.OutputView; + +import java.util.List; + +public class RaceController { + private final InputView inputView; + private final OutputView outputView; + public RaceController (InputView inputView, OutputView outputView) { + this.inputView = inputView; + this.outputView = outputView; + } + + public void run() { + List inputCarNameList = inputView.readCarNames(); + Cars cars = new Cars(inputCarNameList); + Integer round = inputView.readRounds(); + + RacingGame racingGame = new RacingGame(outputView); + racingGame.run(cars, round); + } +} diff --git a/src/main/java/racingcar/model/Car.java b/src/main/java/racingcar/model/Car.java new file mode 100644 index 0000000000..5b08a9839a --- /dev/null +++ b/src/main/java/racingcar/model/Car.java @@ -0,0 +1,23 @@ +package racingcar.model; + +public class Car { + private String name; + private Integer movement; + + public Car (String name) { + this.name = name; + this.movement = 0; + } + + public void moveForward() { + this.movement++; + } + + public String getName() { + return name; + } + + public Integer getMovement() { + return movement; + } +} \ No newline at end of file diff --git a/src/main/java/racingcar/model/Cars.java b/src/main/java/racingcar/model/Cars.java new file mode 100644 index 0000000000..f649aaf96b --- /dev/null +++ b/src/main/java/racingcar/model/Cars.java @@ -0,0 +1,21 @@ +package racingcar.model; + +import java.util.List; + +public class Cars { + private List cars; + + public Cars (List carNameList) { + this.cars = parseCarList(carNameList); + } + + private List parseCarList(List carNameList) { + return carNameList.stream() + .map(Car::new) + .toList(); + } + + public List getCarList() { + return cars; + } +} diff --git a/src/main/java/racingcar/utils/ErrorCode.java b/src/main/java/racingcar/utils/ErrorCode.java new file mode 100644 index 0000000000..44b9da862b --- /dev/null +++ b/src/main/java/racingcar/utils/ErrorCode.java @@ -0,0 +1,8 @@ +package racingcar.utils; + +public class ErrorCode { + public static final String INPUT_CANT_BLANK = "μž…λ ₯은 λΉ„μ–΄μžˆμ„ 수 μ—†μŠ΅λ‹ˆλ‹€."; + public static final String NAME_TOO_LONG = "μžλ™μ°¨ 이름은 5자 이내여야 ν•©λ‹ˆλ‹€."; + public static final String DUPLICATE_NOT_ALLOWED = "μžλ™μ°¨ 이름은 쀑볡일 수 μ—†μŠ΅λ‹ˆλ‹€."; + public static final String INVALID_ROUND = "λΌμš΄λ“œλŠ” μ–‘μˆ˜λ§Œ ν—ˆμš©λ©λ‹ˆλ‹€."; +} diff --git a/src/main/java/racingcar/utils/RandomNumberGenerator.java b/src/main/java/racingcar/utils/RandomNumberGenerator.java new file mode 100644 index 0000000000..06d7b3f46d --- /dev/null +++ b/src/main/java/racingcar/utils/RandomNumberGenerator.java @@ -0,0 +1,12 @@ +package racingcar.utils; + +import camp.nextstep.edu.missionutils.Randoms; + +public class RandomNumberGenerator { + public static Boolean IsMoveable() { + return randomNumberGenerator() >= 4; + } + private static Integer randomNumberGenerator() { + return Randoms.pickNumberInRange(0, 9); + } +} diff --git a/src/main/java/racingcar/utils/Validator.java b/src/main/java/racingcar/utils/Validator.java new file mode 100644 index 0000000000..7cca74087d --- /dev/null +++ b/src/main/java/racingcar/utils/Validator.java @@ -0,0 +1,50 @@ +package racingcar.utils; + +import java.util.List; + +public class Validator { + public static void isCarNameBlank(String input) { + if (input.isBlank()) { throw new IllegalArgumentException(ErrorCode.INPUT_CANT_BLANK); } + } + + public static void isNameLengthValid(List names) { + names.forEach(name -> { + if (name.length() >= 6) { + throw new IllegalArgumentException(ErrorCode.NAME_TOO_LONG); + } + }); + } + + public static void hasDuplicateName(List inputNames) { + long distinctCount = inputNames.stream().distinct().count(); + if (inputNames.size() != distinctCount) { throw new IllegalArgumentException(ErrorCode.DUPLICATE_NOT_ALLOWED); } + } + + public static Integer isValidRound(String round) { + if (round == null || round.isEmpty()) { + throw new IllegalArgumentException(ErrorCode.INPUT_CANT_BLANK); + } + + int roundInt; + if (isNumber(round)) { + roundInt = Integer.parseInt(round); + } else { + throw new IllegalArgumentException(ErrorCode.INVALID_ROUND); + } + + if (roundInt <= 0) { + throw new IllegalArgumentException(ErrorCode.INVALID_ROUND); + } + + return roundInt; + } + + private static Boolean isNumber(String round) { + try { + Integer.parseInt(round); + return true; + } catch (NumberFormatException e) { + return false; + } + } +} diff --git a/src/main/java/racingcar/view/InputView.java b/src/main/java/racingcar/view/InputView.java new file mode 100644 index 0000000000..44648e3b6f --- /dev/null +++ b/src/main/java/racingcar/view/InputView.java @@ -0,0 +1,29 @@ +package racingcar.view; + +import java.util.Arrays; +import java.util.List; +import camp.nextstep.edu.missionutils.Console; +import racingcar.utils.Validator; + +public class InputView { + + public List readCarNames() { + System.out.println("κ²½μ£Όλ₯Ό μ§„ν–‰ν•  μžλ™μ°¨ λͺ©λ‘μ„ μ μ–΄μ£Όμ„Έμš”.(`,`둜 ꡬ뢄)"); + String input = Console.readLine(); + Validator.isCarNameBlank(input); + return parseCarNames(input); + } + + private List parseCarNames(String inputString) { + List parseList = Arrays.asList(inputString.split(",")); + Validator.isNameLengthValid(parseList); + Validator.hasDuplicateName(parseList); + return parseList; + } + + public Integer readRounds() { + System.out.println("총 λͺ‡ λΌμš΄λ“œλ₯Ό μ§„ν–‰ν• κΉŒμš”?"); + String input = Console.readLine(); + return Validator.isValidRound(input); + } +} diff --git a/src/main/java/racingcar/view/OutputView.java b/src/main/java/racingcar/view/OutputView.java new file mode 100644 index 0000000000..ae0441630c --- /dev/null +++ b/src/main/java/racingcar/view/OutputView.java @@ -0,0 +1,14 @@ +package racingcar.view; + +import racingcar.model.Cars; + +public class OutputView { + public void printRaceResult(Cars cars) { + cars.getCarList() + .forEach(car -> System.out.println(car.getName() + " : " + "-".repeat(car.getMovement()))); + } + + public void printWinner(String result) { + System.out.println("μ΅œμ’… 우승자 : " + result); + } +}