From 44f4a596f4426115ec40e50d6ebed26aaa0ac495 Mon Sep 17 00:00:00 2001 From: Jayde1012 Date: Sat, 1 Nov 2025 22:21:11 +0900 Subject: [PATCH 1/6] =?UTF-8?q?(docs)=20=EA=B5=AC=ED=98=84=ED=95=A0=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) 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 From 1ba59f02712ea055b2f8b4d938c1dc6783d7fca6 Mon Sep 17 00:00:00 2001 From: Jayde1012 Date: Sat, 1 Nov 2025 22:30:13 +0900 Subject: [PATCH 2/6] =?UTF-8?q?(feat)=20=EC=9E=90=EB=8F=99=EC=B0=A8=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 --- src/main/java/racingcar/Car.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/main/java/racingcar/Car.java diff --git a/src/main/java/racingcar/Car.java b/src/main/java/racingcar/Car.java new file mode 100644 index 0000000000..5c3ca784d1 --- /dev/null +++ b/src/main/java/racingcar/Car.java @@ -0,0 +1,15 @@ +package racingcar; + +public class Car { + private String name; + private int movement; + + public Car (String name) { + this.name = name; + this.movement = 0; + } + + public void moveForward() { + this.movement++; + } +} \ No newline at end of file From 479068b58c0174b8d7e581de610e7eb9a473c31b Mon Sep 17 00:00:00 2001 From: Jayde1012 Date: Sat, 1 Nov 2025 22:33:46 +0900 Subject: [PATCH 3/6] =?UTF-8?q?(feat)=20=EC=9E=85=EB=A0=A5=20view=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 --- src/main/java/racingcar/view/InputView.java | 28 +++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/main/java/racingcar/view/InputView.java diff --git a/src/main/java/racingcar/view/InputView.java b/src/main/java/racingcar/view/InputView.java new file mode 100644 index 0000000000..475f21cf4c --- /dev/null +++ b/src/main/java/racingcar/view/InputView.java @@ -0,0 +1,28 @@ +package racingcar.view; + +import java.util.Arrays; +import java.util.List; +import camp.nextstep.edu.missionutils.Console; + +public class InputView { + public static List readCarNames() { + System.out.println("κ²½μ£Όλ₯Ό μ§„ν–‰ν•  μžλ™μ°¨ λͺ©λ‘μ„ μ μ–΄μ£Όμ„Έμš”.(`,`둜 ꡬ뢄)"); + String input = Console.readLine(); + // TODO: Validator μΆ”κ°€(빈 값인지 확인) + return parseCarNames(input); + } + + private static List parseCarNames(String inputString) { + List parseList = Arrays.asList(inputString.split(",")); + // TODO: Validator μΆ”κ°€(쀑볡 확인) + return parseList; + } + + public static Integer readRounds() { + System.out.println("총 λͺ‡ λΌμš΄λ“œλ₯Ό μ§„ν–‰ν• κΉŒμš”?"); + String input = Console.readLine(); + + // TODO: Validator μΆ”κ°€(μžμ—°μˆ˜μΈμ§€) + return Integer.parseInt(input); + } +} From 367b688ad0ff841a00bf6cdc0eacfbe50846245e Mon Sep 17 00:00:00 2001 From: Jayde1012 Date: Sat, 1 Nov 2025 23:37:35 +0900 Subject: [PATCH 4/6] =?UTF-8?q?(feat)=20=EB=A0=88=EC=9D=B4=EC=8B=B1=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 --- src/main/java/racingcar/Race.java | 14 +++++++ src/main/java/racingcar/RacingGame.java | 40 +++++++++++++++++++ .../racingcar/controller/RaceController.java | 27 +++++++++++++ src/main/java/racingcar/{ => model}/Car.java | 12 +++++- src/main/java/racingcar/model/Cars.java | 21 ++++++++++ .../utils/RandomNumberGenerator.java | 12 ++++++ src/main/java/racingcar/view/OutputView.java | 16 ++++++++ 7 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 src/main/java/racingcar/Race.java create mode 100644 src/main/java/racingcar/RacingGame.java create mode 100644 src/main/java/racingcar/controller/RaceController.java rename src/main/java/racingcar/{ => model}/Car.java (52%) create mode 100644 src/main/java/racingcar/model/Cars.java create mode 100644 src/main/java/racingcar/utils/RandomNumberGenerator.java create mode 100644 src/main/java/racingcar/view/OutputView.java 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..7674f6962e --- /dev/null +++ b/src/main/java/racingcar/controller/RaceController.java @@ -0,0 +1,27 @@ +package racingcar.controller; + +import racingcar.Race; +import racingcar.RacingGame; +import racingcar.model.Cars; +import racingcar.view.InputView; +import racingcar.view.OutputView; + +import java.util.List; + +public class RaceController { + private InputView inputView; + private 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/Car.java b/src/main/java/racingcar/model/Car.java similarity index 52% rename from src/main/java/racingcar/Car.java rename to src/main/java/racingcar/model/Car.java index 5c3ca784d1..5b08a9839a 100644 --- a/src/main/java/racingcar/Car.java +++ b/src/main/java/racingcar/model/Car.java @@ -1,8 +1,8 @@ -package racingcar; +package racingcar.model; public class Car { private String name; - private int movement; + private Integer movement; public Car (String name) { this.name = name; @@ -12,4 +12,12 @@ public Car (String name) { 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/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/view/OutputView.java b/src/main/java/racingcar/view/OutputView.java new file mode 100644 index 0000000000..65eb5abb94 --- /dev/null +++ b/src/main/java/racingcar/view/OutputView.java @@ -0,0 +1,16 @@ +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); + } +} From 20f2f01300e3d80bfe98c27bd71bc81b771dbdbc Mon Sep 17 00:00:00 2001 From: Jayde1012 Date: Sat, 1 Nov 2025 23:53:25 +0900 Subject: [PATCH 5/6] =?UTF-8?q?(feat)=20validator=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/utils/Validator.java | 42 ++++++++++++++++++++ src/main/java/racingcar/view/InputView.java | 11 ++--- 2 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 src/main/java/racingcar/utils/Validator.java diff --git a/src/main/java/racingcar/utils/Validator.java b/src/main/java/racingcar/utils/Validator.java new file mode 100644 index 0000000000..2cd29846f8 --- /dev/null +++ b/src/main/java/racingcar/utils/Validator.java @@ -0,0 +1,42 @@ +package racingcar.utils; + +import java.util.List; + +public class Validator { + public void isCarNameBlank(String input) { + if (input.isBlank()) { throw new IllegalArgumentException(); } + } + + public void hasDuplicateName(List inputNames) { + long distinctCount = inputNames.stream().distinct().count(); + if (inputNames.size() != distinctCount) { throw new IllegalArgumentException(); } + } + + public Integer isValidRound(String round) { + if (round == null || round.isEmpty()) { + throw new IllegalArgumentException(); + } + + int roundInt; + if (isNumber(round)) { + roundInt = Integer.parseInt(round); + } else { + throw new IllegalArgumentException(); + } + + if (roundInt <= 0) { + throw new IllegalArgumentException(); + } + + return roundInt; + } + + private 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 index 475f21cf4c..d101baa47b 100644 --- a/src/main/java/racingcar/view/InputView.java +++ b/src/main/java/racingcar/view/InputView.java @@ -3,26 +3,27 @@ import java.util.Arrays; import java.util.List; import camp.nextstep.edu.missionutils.Console; +import racingcar.utils.Validator; public class InputView { + private static final Validator validator = new Validator(); + public static List readCarNames() { System.out.println("κ²½μ£Όλ₯Ό μ§„ν–‰ν•  μžλ™μ°¨ λͺ©λ‘μ„ μ μ–΄μ£Όμ„Έμš”.(`,`둜 ꡬ뢄)"); String input = Console.readLine(); - // TODO: Validator μΆ”κ°€(빈 값인지 확인) + validator.isCarNameBlank(input); return parseCarNames(input); } private static List parseCarNames(String inputString) { List parseList = Arrays.asList(inputString.split(",")); - // TODO: Validator μΆ”κ°€(쀑볡 확인) + validator.hasDuplicateName(parseList); return parseList; } public static Integer readRounds() { System.out.println("총 λͺ‡ λΌμš΄λ“œλ₯Ό μ§„ν–‰ν• κΉŒμš”?"); String input = Console.readLine(); - - // TODO: Validator μΆ”κ°€(μžμ—°μˆ˜μΈμ§€) - return Integer.parseInt(input); + return validator.isValidRound(input); } } From 2773589c25e830f16364194667198d8bb21457a3 Mon Sep 17 00:00:00 2001 From: Jayde1012 Date: Sun, 2 Nov 2025 03:24:14 +0900 Subject: [PATCH 6/6] =?UTF-8?q?(feat)=20=EC=97=90=EB=9F=AC=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80,=20=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=EA=B8=B8=EC=9D=B4=20validator=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 | 10 ++++++- .../racingcar/controller/RaceController.java | 9 +++---- src/main/java/racingcar/utils/ErrorCode.java | 8 ++++++ src/main/java/racingcar/utils/Validator.java | 26 ++++++++++++------- src/main/java/racingcar/view/InputView.java | 14 +++++----- src/main/java/racingcar/view/OutputView.java | 6 ++--- 6 files changed, 47 insertions(+), 26 deletions(-) create mode 100644 src/main/java/racingcar/utils/ErrorCode.java 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/controller/RaceController.java b/src/main/java/racingcar/controller/RaceController.java index 7674f6962e..3c0a1de8f5 100644 --- a/src/main/java/racingcar/controller/RaceController.java +++ b/src/main/java/racingcar/controller/RaceController.java @@ -1,6 +1,5 @@ package racingcar.controller; -import racingcar.Race; import racingcar.RacingGame; import racingcar.model.Cars; import racingcar.view.InputView; @@ -9,17 +8,17 @@ import java.util.List; public class RaceController { - private InputView inputView; - private OutputView outputView; + 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(); + List inputCarNameList = inputView.readCarNames(); Cars cars = new Cars(inputCarNameList); - Integer round = InputView.readRounds(); + Integer round = inputView.readRounds(); RacingGame racingGame = new RacingGame(outputView); racingGame.run(cars, round); 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/Validator.java b/src/main/java/racingcar/utils/Validator.java index 2cd29846f8..7cca74087d 100644 --- a/src/main/java/racingcar/utils/Validator.java +++ b/src/main/java/racingcar/utils/Validator.java @@ -3,35 +3,43 @@ import java.util.List; public class Validator { - public void isCarNameBlank(String input) { - if (input.isBlank()) { throw new IllegalArgumentException(); } + public static void isCarNameBlank(String input) { + if (input.isBlank()) { throw new IllegalArgumentException(ErrorCode.INPUT_CANT_BLANK); } } - public void hasDuplicateName(List inputNames) { + 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(); } + if (inputNames.size() != distinctCount) { throw new IllegalArgumentException(ErrorCode.DUPLICATE_NOT_ALLOWED); } } - public Integer isValidRound(String round) { + public static Integer isValidRound(String round) { if (round == null || round.isEmpty()) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException(ErrorCode.INPUT_CANT_BLANK); } int roundInt; if (isNumber(round)) { roundInt = Integer.parseInt(round); } else { - throw new IllegalArgumentException(); + throw new IllegalArgumentException(ErrorCode.INVALID_ROUND); } if (roundInt <= 0) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException(ErrorCode.INVALID_ROUND); } return roundInt; } - private Boolean isNumber(String round) { + private static Boolean isNumber(String round) { try { Integer.parseInt(round); return true; diff --git a/src/main/java/racingcar/view/InputView.java b/src/main/java/racingcar/view/InputView.java index d101baa47b..44648e3b6f 100644 --- a/src/main/java/racingcar/view/InputView.java +++ b/src/main/java/racingcar/view/InputView.java @@ -6,24 +6,24 @@ import racingcar.utils.Validator; public class InputView { - private static final Validator validator = new Validator(); - public static List readCarNames() { + public List readCarNames() { System.out.println("κ²½μ£Όλ₯Ό μ§„ν–‰ν•  μžλ™μ°¨ λͺ©λ‘μ„ μ μ–΄μ£Όμ„Έμš”.(`,`둜 ꡬ뢄)"); String input = Console.readLine(); - validator.isCarNameBlank(input); + Validator.isCarNameBlank(input); return parseCarNames(input); } - private static List parseCarNames(String inputString) { + private List parseCarNames(String inputString) { List parseList = Arrays.asList(inputString.split(",")); - validator.hasDuplicateName(parseList); + Validator.isNameLengthValid(parseList); + Validator.hasDuplicateName(parseList); return parseList; } - public static Integer readRounds() { + public Integer readRounds() { System.out.println("총 λͺ‡ λΌμš΄λ“œλ₯Ό μ§„ν–‰ν• κΉŒμš”?"); String input = Console.readLine(); - return validator.isValidRound(input); + return Validator.isValidRound(input); } } diff --git a/src/main/java/racingcar/view/OutputView.java b/src/main/java/racingcar/view/OutputView.java index 65eb5abb94..ae0441630c 100644 --- a/src/main/java/racingcar/view/OutputView.java +++ b/src/main/java/racingcar/view/OutputView.java @@ -5,12 +5,10 @@ public class OutputView { public void printRaceResult(Cars cars) { cars.getCarList() - .forEach(car -> { - System.out.println(car.getName() + " : " + "-".repeat(car.getMovement())); - }); + .forEach(car -> System.out.println(car.getName() + " : " + "-".repeat(car.getMovement()))); } public void printWinner(String result) { - System.out.println(result); + System.out.println("μ΅œμ’… 우승자 : " + result); } }