From 3755dff1dc382fa7bea5192469b720d2f2eda525 Mon Sep 17 00:00:00 2001 From: LeeJin0527 Date: Wed, 19 Mar 2025 21:15:46 +0900 Subject: [PATCH 01/17] =?UTF-8?q?refactor(step3):=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 진입점에 맞추어 main 클래스 package안으로 이동 - 클래스, 인스턴스 변수 공백 추가 - private method static 제거 - 테스트 코드 분리 - util 클래스 객체 생성 방지를 위해 private생성자 추가 --- src/main/java/{ => racingcar}/Main.java | 6 +++- .../java/racingcar/message/ErrorMessage.java | 1 + src/main/java/racingcar/message/Message.java | 1 + src/main/java/racingcar/model/Car.java | 3 +- src/main/java/racingcar/model/Position.java | 3 +- .../java/racingcar/util/InputValidator.java | 4 +++ src/main/java/racingcar/view/InputView.java | 1 + src/main/java/racingcar/view/OutputView.java | 1 + src/main/java/step2/StringAddCalculator.java | 1 + src/test/java/racingcar/model/CarTest.java | 22 +++++++-------- .../java/racingcar/model/PositionTest.java | 28 +++++++++++++++++++ 11 files changed, 57 insertions(+), 14 deletions(-) rename src/main/java/{ => racingcar}/Main.java (87%) create mode 100644 src/test/java/racingcar/model/PositionTest.java diff --git a/src/main/java/Main.java b/src/main/java/racingcar/Main.java similarity index 87% rename from src/main/java/Main.java rename to src/main/java/racingcar/Main.java index 8a2ffc22a77..dd4e1f48a2f 100644 --- a/src/main/java/Main.java +++ b/src/main/java/racingcar/Main.java @@ -1,3 +1,5 @@ +package racingcar; + import racingcar.model.RacingGame; import racingcar.util.InputValidator; import racingcar.view.InputView; @@ -6,9 +8,11 @@ public class Main { public static void main(String[] args) { + InputView inputView = new InputView(); - inputView.printMessage(CAR_COUNT_MESSAGE); + inputView.printMessage( + CAR_COUNT_MESSAGE); int carCount = InputValidator.validatePositiveNumber(inputView.readInput()); inputView.printMessage(ATTEMPT_COUNT_MESSAGE); diff --git a/src/main/java/racingcar/message/ErrorMessage.java b/src/main/java/racingcar/message/ErrorMessage.java index c593bfd2607..9726f5affea 100644 --- a/src/main/java/racingcar/message/ErrorMessage.java +++ b/src/main/java/racingcar/message/ErrorMessage.java @@ -1,6 +1,7 @@ package racingcar.message; public class ErrorMessage { + public static final String INVALID_NUMBER = "숫자를 입력해야 합니다."; public static final String POSITIVE_NUMBER = "양수를 입력해야 합니다."; diff --git a/src/main/java/racingcar/message/Message.java b/src/main/java/racingcar/message/Message.java index 80495302128..57e376be92d 100644 --- a/src/main/java/racingcar/message/Message.java +++ b/src/main/java/racingcar/message/Message.java @@ -1,6 +1,7 @@ package racingcar.message; public class Message { + public static final String RESULT_MESSAGE = "실행 결과"; public static final String CAR_COUNT_MESSAGE = "자동차 대수는 몇 대 인가요?"; public static final String ATTEMPT_COUNT_MESSAGE = "시도할 회수는 몇 회 인가요?"; diff --git a/src/main/java/racingcar/model/Car.java b/src/main/java/racingcar/model/Car.java index ab6eb6cc24b..073a5e775c4 100644 --- a/src/main/java/racingcar/model/Car.java +++ b/src/main/java/racingcar/model/Car.java @@ -4,6 +4,7 @@ public class Car { private final Position position; + private static final int MOVE_CONDITION_NUMBER = 4; public Car() { @@ -20,7 +21,7 @@ public void move(int randomValue) { } } - private static boolean canMove(int randomValue) { + private boolean canMove(int randomValue) { return randomValue >= MOVE_CONDITION_NUMBER; } diff --git a/src/main/java/racingcar/model/Position.java b/src/main/java/racingcar/model/Position.java index 595371bd06e..96cbdf3c251 100644 --- a/src/main/java/racingcar/model/Position.java +++ b/src/main/java/racingcar/model/Position.java @@ -3,6 +3,7 @@ public class Position { private int position; + private static final String DELIMITER = "-"; public Position() { @@ -14,7 +15,7 @@ public Position(int initialPosition) { } public void incrementPosition() { - position += 1; + position ++; } public boolean isSameAs(Position other) { diff --git a/src/main/java/racingcar/util/InputValidator.java b/src/main/java/racingcar/util/InputValidator.java index c12e27e41da..de584dfea48 100644 --- a/src/main/java/racingcar/util/InputValidator.java +++ b/src/main/java/racingcar/util/InputValidator.java @@ -6,9 +6,13 @@ public class InputValidator { + private InputValidator() {} + public static int validatePositiveNumber(String input) { int number = InputView.convertToInt(input); + validatePositive(number); + return number; } diff --git a/src/main/java/racingcar/view/InputView.java b/src/main/java/racingcar/view/InputView.java index 7aa2a86f2c2..024bad97b06 100644 --- a/src/main/java/racingcar/view/InputView.java +++ b/src/main/java/racingcar/view/InputView.java @@ -5,6 +5,7 @@ import java.util.Scanner; public class InputView { + private final Scanner scanner; public InputView() { diff --git a/src/main/java/racingcar/view/OutputView.java b/src/main/java/racingcar/view/OutputView.java index c7ee3a9b25a..331f7016ab4 100644 --- a/src/main/java/racingcar/view/OutputView.java +++ b/src/main/java/racingcar/view/OutputView.java @@ -1,6 +1,7 @@ package racingcar.view; public class OutputView { + public static void print(String message) { System.out.println(message); } diff --git a/src/main/java/step2/StringAddCalculator.java b/src/main/java/step2/StringAddCalculator.java index 8195854793d..851dd7ee72d 100644 --- a/src/main/java/step2/StringAddCalculator.java +++ b/src/main/java/step2/StringAddCalculator.java @@ -5,6 +5,7 @@ import java.util.regex.Pattern; public class StringAddCalculator { + private static final Pattern CUSTOM_SEPERATOR_PATTERN = Pattern.compile("//(.)\n(.*)"); private static final String DEFAULT_SEPERATOR_PATTERN = ",|:"; private static final int CUSTOM_SEPARATOR_GROUP_INDEX = 1; diff --git a/src/test/java/racingcar/model/CarTest.java b/src/test/java/racingcar/model/CarTest.java index 8d2451b77bf..a4d58f13f76 100644 --- a/src/test/java/racingcar/model/CarTest.java +++ b/src/test/java/racingcar/model/CarTest.java @@ -16,14 +16,15 @@ void car_initialPosition_test(int initialPosition) { assertThat(car.isAtPosition(new Position(initialPosition))).isTrue(); } - @DisplayName("자동차가 이동하면 위치가 올바르게 증가한다.") + @DisplayName("랜덤 값이 4이상 이면 이동한다.") @ParameterizedTest @CsvSource({ "0,4,1", - "3,3,3", + "3,5,4", "5,6,6", - "2,9,3", - "1,0,1" + "2,7,3", + "2,8,3", + "1,9,2" }) void car_move_test(int initialPosition, int randomValue, int expectedPosition) { Car car = new Car(initialPosition); @@ -33,19 +34,18 @@ void car_move_test(int initialPosition, int randomValue, int expectedPosition) { assertThat(car.isAtPosition(new Position(expectedPosition))).isTrue(); } - @DisplayName("초기 위치가 5인 자동차가 2번 이동 하면 현재 위치보다 2 증가한다.") + @DisplayName("랜덤 값이 3이하 이면 이동하지 않는다.") @ParameterizedTest @CsvSource({ - "0,1,1,0", - "3,4,4,5", - "5,4,1,6", - "5,1,5,6" + "0,3,0", + "3,2,3", + "5,1,5", + "2,0,2", }) - void move_initial_move(int initialPosition, int randomValue, int randomValue2, int expectedPosition) { + void car_not_move_test(int initialPosition, int randomValue, int expectedPosition) { Car car = new Car(initialPosition); car.move(randomValue); - car.move(randomValue2); assertThat(car.isAtPosition(new Position(expectedPosition))).isTrue(); } diff --git a/src/test/java/racingcar/model/PositionTest.java b/src/test/java/racingcar/model/PositionTest.java new file mode 100644 index 00000000000..568f9631fa9 --- /dev/null +++ b/src/test/java/racingcar/model/PositionTest.java @@ -0,0 +1,28 @@ +package racingcar.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.assertj.core.api.Assertions.assertThat; + +class PositionTest { + + @DisplayName("초기 위치가 5인 자동차가 2번 이동 하면 현재 위치보다 2 증가한다.") + @ParameterizedTest + @CsvSource({ + "0,1,1,0", + "3,4,4,5", + "5,4,1,6", + "5,1,5,6" + }) + void move_initial_move(int initialPosition, int randomValue, int randomValue2, int expectedPosition) { + Car car = new Car(initialPosition); + + car.move(randomValue); + car.move(randomValue2); + + assertThat(car.isAtPosition(new Position(expectedPosition))).isTrue(); + } + +} From 66a7abfbb26d446cd878e6aebe00d9301baa866f Mon Sep 17 00:00:00 2001 From: LeeJin0527 Date: Thu, 20 Mar 2025 09:37:24 +0900 Subject: [PATCH 02/17] =?UTF-8?q?refactor(step3):=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Car, Position 불변 객체로 변경 - RacingGame 접근 범위 private로 제한 - 테스트 케이스 불변객체 적용 - 유틸클래스 private 생성자 추가 - InputView > InputValidator로 변경 --- src/main/java/racingcar/Main.java | 5 +-- src/main/java/racingcar/model/Car.java | 11 ++++-- src/main/java/racingcar/model/Position.java | 8 ++-- src/main/java/racingcar/model/RacingGame.java | 38 +++++++++++++------ src/test/java/racingcar/model/CarTest.java | 32 +++++++++++----- .../java/racingcar/model/PositionTest.java | 8 ++-- .../java/racingcar/model/RacingGameTest.java | 2 +- .../InputValidatorTest.java} | 19 +++------- 8 files changed, 74 insertions(+), 49 deletions(-) rename src/test/java/racingcar/{view/InputViewTest.java => util/InputValidatorTest.java} (75%) diff --git a/src/main/java/racingcar/Main.java b/src/main/java/racingcar/Main.java index dd4e1f48a2f..850782e43ad 100644 --- a/src/main/java/racingcar/Main.java +++ b/src/main/java/racingcar/Main.java @@ -11,14 +11,13 @@ public static void main(String[] args) { InputView inputView = new InputView(); - inputView.printMessage( - CAR_COUNT_MESSAGE); + inputView.printMessage(CAR_COUNT_MESSAGE); int carCount = InputValidator.validatePositiveNumber(inputView.readInput()); inputView.printMessage(ATTEMPT_COUNT_MESSAGE); int attemptCount = InputValidator.validatePositiveNumber(inputView.readInput()); RacingGame racingGame = new RacingGame(carCount); - racingGame.race(attemptCount); + racingGame = racingGame.race(attemptCount); } } diff --git a/src/main/java/racingcar/model/Car.java b/src/main/java/racingcar/model/Car.java index 073a5e775c4..430d1d2c446 100644 --- a/src/main/java/racingcar/model/Car.java +++ b/src/main/java/racingcar/model/Car.java @@ -8,17 +8,22 @@ public class Car { private static final int MOVE_CONDITION_NUMBER = 4; public Car() { - this.position = new Position(); + this(0); } public Car(int initialPosition) { this.position = new Position(initialPosition); } - public void move(int randomValue) { + private Car(Position position) { + this.position = position; + } + + public Car move(int randomValue) { if (canMove(randomValue)) { - position.incrementPosition(); + return new Car(this.position.incrementPosition()); } + return this; } private boolean canMove(int randomValue) { diff --git a/src/main/java/racingcar/model/Position.java b/src/main/java/racingcar/model/Position.java index 96cbdf3c251..31fe148cb9f 100644 --- a/src/main/java/racingcar/model/Position.java +++ b/src/main/java/racingcar/model/Position.java @@ -2,20 +2,20 @@ public class Position { - private int position; + private final int position; private static final String DELIMITER = "-"; public Position() { - this.position = 0; + this(0); } public Position(int initialPosition) { this.position = initialPosition; } - public void incrementPosition() { - position ++; + public Position incrementPosition() { + return new Position(this.position + 1); } public boolean isSameAs(Position other) { diff --git a/src/main/java/racingcar/model/RacingGame.java b/src/main/java/racingcar/model/RacingGame.java index 8937ed5845b..35765060cf2 100644 --- a/src/main/java/racingcar/model/RacingGame.java +++ b/src/main/java/racingcar/model/RacingGame.java @@ -4,29 +4,45 @@ import racingcar.util.RandomNumberGenerator; import racingcar.view.OutputView; +import java.util.Collections; import java.util.List; -import java.util.stream.IntStream; +import java.util.stream.Collectors; public class RacingGame { - List cars; + private final List cars; public RacingGame(int carCount) { this.cars = CarGenerator.createCars(carCount); } - public void race(int attemptCount) { + public List getCars() { + return Collections.unmodifiableList(cars); + } + + private RacingGame(List cars) { + this.cars = cars; + } + + public RacingGame race(int attemptCount) { OutputView.print(Message.RESULT_MESSAGE); - IntStream.range(0, attemptCount) - .forEach(i -> { - moveCars(); - OutputView.print(""); - }); + List updatedCars = cars; + for (int i = 0; i < attemptCount; i++) { + updatedCars = moveCars(updatedCars); + OutputView.print(""); + } + + return new RacingGame(updatedCars); } - private void moveCars() { - cars.forEach(car -> car.move(RandomNumberGenerator.generateNumber())); - cars.forEach(Car::printPosition); + private List moveCars(List currentCars) { + List movedCars = currentCars.stream() + .map(car -> car.move(RandomNumberGenerator.generateNumber())) + .collect(Collectors.toList()); + + movedCars.forEach(Car::printPosition); + + return movedCars; } } diff --git a/src/test/java/racingcar/model/CarTest.java b/src/test/java/racingcar/model/CarTest.java index a4d58f13f76..623ec35b431 100644 --- a/src/test/java/racingcar/model/CarTest.java +++ b/src/test/java/racingcar/model/CarTest.java @@ -1,6 +1,7 @@ package racingcar.model; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; @@ -16,7 +17,7 @@ void car_initialPosition_test(int initialPosition) { assertThat(car.isAtPosition(new Position(initialPosition))).isTrue(); } - @DisplayName("랜덤 값이 4이상 이면 이동한다.") + @DisplayName("랜덤 값이 4이상 이면 이동 한다.") @ParameterizedTest @CsvSource({ "0,4,1", @@ -26,15 +27,15 @@ void car_initialPosition_test(int initialPosition) { "2,8,3", "1,9,2" }) - void car_move_test(int initialPosition, int randomValue, int expectedPosition) { - Car car = new Car(initialPosition); + void car_move_logic_test(int initialPosition, int randomValue, int expectedPosition) { + Car initialCar = new Car(initialPosition); - car.move(randomValue); + Car movedCar = initialCar.move(randomValue); - assertThat(car.isAtPosition(new Position(expectedPosition))).isTrue(); + assertThat(movedCar.isAtPosition(new Position(expectedPosition))).isTrue(); } - @DisplayName("랜덤 값이 3이하 이면 이동하지 않는다.") + @DisplayName("랜덤 값이 3이하 이면 이동 하지 않는다.") @ParameterizedTest @CsvSource({ "0,3,0", @@ -42,11 +43,22 @@ void car_move_test(int initialPosition, int randomValue, int expectedPosition) { "5,1,5", "2,0,2", }) - void car_not_move_test(int initialPosition, int randomValue, int expectedPosition) { - Car car = new Car(initialPosition); + void car_not_move_logic_test(int initialPosition, int randomValue, int expectedPosition) { + Car initialCar = new Car(initialPosition); + + Car movedCar = initialCar.move(randomValue); + + assertThat(movedCar.isAtPosition(new Position(expectedPosition))).isTrue(); + } + + @DisplayName("자동차가 이동해도 기존 객체는 변하지 않는다.(불변 객체 테스트)") + @Test + void car_not_move_immutable_test() { + Car initialCar = new Car(0); - car.move(randomValue); + Car movedCar = initialCar.move(4); - assertThat(car.isAtPosition(new Position(expectedPosition))).isTrue(); + assertThat(initialCar.isAtPosition(new Position(0))).isTrue(); + assertThat(movedCar.isAtPosition(new Position(1))).isTrue(); } } diff --git a/src/test/java/racingcar/model/PositionTest.java b/src/test/java/racingcar/model/PositionTest.java index 568f9631fa9..8f15dafe081 100644 --- a/src/test/java/racingcar/model/PositionTest.java +++ b/src/test/java/racingcar/model/PositionTest.java @@ -17,12 +17,12 @@ class PositionTest { "5,1,5,6" }) void move_initial_move(int initialPosition, int randomValue, int randomValue2, int expectedPosition) { - Car car = new Car(initialPosition); + Car initialCar = new Car(initialPosition); - car.move(randomValue); - car.move(randomValue2); + Car movedOnceCar = initialCar.move(randomValue); + Car movedTwiceCar = movedOnceCar.move(randomValue2); - assertThat(car.isAtPosition(new Position(expectedPosition))).isTrue(); + assertThat(movedTwiceCar.isAtPosition(new Position(expectedPosition))).isTrue(); } } diff --git a/src/test/java/racingcar/model/RacingGameTest.java b/src/test/java/racingcar/model/RacingGameTest.java index 8dc2a53063e..4fe2c523286 100644 --- a/src/test/java/racingcar/model/RacingGameTest.java +++ b/src/test/java/racingcar/model/RacingGameTest.java @@ -13,6 +13,6 @@ void createCarsTest() { int carCount = 3; RacingGame racingGame = new RacingGame(carCount); - assertThat(racingGame.cars).hasSize(carCount); + assertThat(racingGame.getCars()).hasSize(carCount); } } diff --git a/src/test/java/racingcar/view/InputViewTest.java b/src/test/java/racingcar/util/InputValidatorTest.java similarity index 75% rename from src/test/java/racingcar/view/InputViewTest.java rename to src/test/java/racingcar/util/InputValidatorTest.java index a791afc7b21..4348662b08c 100644 --- a/src/test/java/racingcar/view/InputViewTest.java +++ b/src/test/java/racingcar/util/InputValidatorTest.java @@ -1,27 +1,20 @@ -package racingcar.view; +package racingcar.util; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import racingcar.message.ErrorMessage; +import racingcar.view.InputView; import static org.assertj.core.api.Assertions.*; -class InputViewTest { - - private InputView inputView; - - @BeforeEach - void setUp() { - inputView = new InputView(); // 중복 제거 - } +class InputValidatorTest { @DisplayName("숫자 문자열을 입력했을 때 숫자로 변환한다.") @ParameterizedTest @ValueSource(strings = {"123", "42", "9876"}) void convertToInt_문자(String input) { - int result = inputView.convertToInt(input); + int result = InputView.convertToInt(input); assertThat(result).isEqualTo(Integer.parseInt(input)); } @@ -29,7 +22,7 @@ void setUp() { @ParameterizedTest @ValueSource(strings = {" 123 ", " 456 ", "\t789\t"}) void convertToInt_공백_문자(String input) { - int result = inputView.convertToInt(input); + int result = InputView.convertToInt(input); assertThat(result).isEqualTo(Integer.parseInt(input.trim())); } @@ -37,7 +30,7 @@ void setUp() { @ParameterizedTest @ValueSource(strings = {"abc", "123abc", "!@#$", " "}) void convertToInt_예외(String input) { - assertThatThrownBy(() -> inputView.convertToInt(input)) + assertThatThrownBy(() -> InputView.convertToInt(input)) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining(ErrorMessage.INVALID_NUMBER + input); } From 897b8527a13393047984cbf59bc7abc64d67119b Mon Sep 17 00:00:00 2001 From: LeeJin0527 Date: Thu, 20 Mar 2025 13:37:50 +0900 Subject: [PATCH 03/17] =?UTF-8?q?feat(step4):=20=EC=9E=90=EB=8F=99?= =?UTF-8?q?=EC=B0=A8=20=EC=9D=B4=EB=A6=84=20=EC=9E=85=EB=A0=A5=20=EA=B0=92?= =?UTF-8?q?=20=EA=B2=80=EC=A6=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 1자 이상 5자 이하, 공백 및 6자 이상 예외 처리 - 에러메시지 추가 - private 생성자 추가 --- README.md | 23 ++++++++++++ src/main/java/racingcar/Main.java | 34 +++++++++++++++--- .../java/racingcar/message/ErrorMessage.java | 1 + .../java/racingcar/util/InputValidator.java | 36 +++++++++++++++++-- 4 files changed, 87 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index f498458691d..f28259acf45 100644 --- a/README.md +++ b/README.md @@ -50,3 +50,26 @@ - [x] 입력 횟수가 숫자가 아닌 경우 예외를 발생시킨다. - [x] 자동차 댓수가 숫자가 아닌 경우 예외를 발생시킨다. - [x] 음수를 입력한 경우 예외를 발생시킨다. + +## 🚀 4단계 - 자동차 경주(우승자) +- 각 자동차에 이름을 부여할 수 있다. 자동차 이름은 5자를 초과할 수 없다. +- 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다. +- 자동차 이름은 쉼표(,)를 기준으로 구분한다. +- 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한명 이상일 수 있다. + +### 입력 값 검증 +- [x] 이름은 1자 이상 5자 이하이다. + - [x] 이름이 비어있거나 공백일 경우 예외를 발생시킨다. + - [x] 이름이 6자 이상일 경우 예외를 발생시킨다. + +### 자동차 객체 +- [ ] 자동차의 이름을 부여한다. +- [ ] 자동차 이름은 쉼표를 기준으로 구분한다. +- [ ] 자동차 이름이 1자이상 5자이하인지 검증한다. + +### 비즈니스 로직 +- [ ] 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다. +- [ ] 자동차 경주가 끝난 후 쉼표로 구분하여 우승자를 출력한다. + +### 결과 출력 +- [] "a, b가 최종 우승했습니다."로 출력한다. diff --git a/src/main/java/racingcar/Main.java b/src/main/java/racingcar/Main.java index 850782e43ad..de7a6f65814 100644 --- a/src/main/java/racingcar/Main.java +++ b/src/main/java/racingcar/Main.java @@ -1,9 +1,14 @@ package racingcar; +import racingcar.model.Car; import racingcar.model.RacingGame; import racingcar.util.InputValidator; import racingcar.view.InputView; +import racingcar.view.OutputView; +import java.util.List; + +import static racingcar.message.ErrorMessage.INVALID_NAME; import static racingcar.message.Message.*; public class Main { @@ -11,13 +16,32 @@ public static void main(String[] args) { InputView inputView = new InputView(); - inputView.printMessage(CAR_COUNT_MESSAGE); - int carCount = InputValidator.validatePositiveNumber(inputView.readInput()); + final List names = getValidCarNames(inputView); + final int attemptCount = getValidAttemptCount(inputView); + + RacingGame racingGame = RacingGame.createRacingGame(names); + + final RacingGame finalResult = racingGame.race(attemptCount); + + List winners = finalResult.getWinners(); + OutputView.printWinners(winners); + } + + private static List getValidCarNames(InputView inputView) { + while (true) { + try { + inputView.printMessage(CAR_NAME_MESSAGE); + return InputValidator.validateNames(inputView.readInput()); + + } catch (IllegalArgumentException e) { + OutputView.print(INVALID_NAME); + } + } + } + private static int getValidAttemptCount(InputView inputView) { inputView.printMessage(ATTEMPT_COUNT_MESSAGE); - int attemptCount = InputValidator.validatePositiveNumber(inputView.readInput()); - RacingGame racingGame = new RacingGame(carCount); - racingGame = racingGame.race(attemptCount); + return InputValidator.validatePositiveNumber(inputView.readInput()); } } diff --git a/src/main/java/racingcar/message/ErrorMessage.java b/src/main/java/racingcar/message/ErrorMessage.java index 9726f5affea..3ca95417a89 100644 --- a/src/main/java/racingcar/message/ErrorMessage.java +++ b/src/main/java/racingcar/message/ErrorMessage.java @@ -4,6 +4,7 @@ public class ErrorMessage { public static final String INVALID_NUMBER = "숫자를 입력해야 합니다."; public static final String POSITIVE_NUMBER = "양수를 입력해야 합니다."; + public static final String INVALID_NAME = "닉네임은 1자 이상 5자 이하여야 합니다. 다시 입력해주세요."; private ErrorMessage() { } diff --git a/src/main/java/racingcar/util/InputValidator.java b/src/main/java/racingcar/util/InputValidator.java index de584dfea48..b3104ab2515 100644 --- a/src/main/java/racingcar/util/InputValidator.java +++ b/src/main/java/racingcar/util/InputValidator.java @@ -2,11 +2,19 @@ import racingcar.view.InputView; +import java.util.List; + +import static racingcar.message.ErrorMessage.INVALID_NAME; import static racingcar.message.ErrorMessage.POSITIVE_NUMBER; public class InputValidator { - private InputValidator() {} + private static final String SEPERATOR = ","; + private static final int MINIMUM_NAME_LENGTH = 1; + private static final int MAXIMUM_NAME_LENGTH = 5; + + private InputValidator() { + } public static int validatePositiveNumber(String input) { int number = InputView.convertToInt(input); @@ -17,8 +25,32 @@ public static int validatePositiveNumber(String input) { } private static void validatePositive(int number) { - if (number <= 0) { + if (isLessThanMinimumLength(number)) { throw new IllegalArgumentException(POSITIVE_NUMBER); } } + + private static boolean isLessThanMinimumLength(int number) { + return number < MINIMUM_NAME_LENGTH; + } + + public static List validateNames(String input) { + List names = List.of(input.split(SEPERATOR)); + + return validateName(names); + } + + private static List validateName(List names) { + boolean hasInvalidName = checkInvalidName(names); + + if (hasInvalidName) { + throw new IllegalArgumentException(INVALID_NAME); + } + return List.copyOf(names); + } + + private static boolean checkInvalidName(List names) { + return names.stream() + .anyMatch(name -> name.isBlank() || name.length() > MAXIMUM_NAME_LENGTH); + } } From de6c4b835b4a8907242c4152c70190980a4c3f6b Mon Sep 17 00:00:00 2001 From: LeeJin0527 Date: Thu, 20 Mar 2025 13:42:58 +0900 Subject: [PATCH 04/17] =?UTF-8?q?feat(step4):=20=EC=9E=90=EB=8F=99?= =?UTF-8?q?=EC=B0=A8=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20=EC=8B=9C?= =?UTF-8?q?=20=EC=9D=B4=EB=A6=84=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CarGenerator 관련 파일 삭제하고 팩토리 메서드 패턴을 통해 이름 입력으로 차량 객체 생성하도록 수정 - 테스트 코드에 이름 받도록 수정 --- README.md | 6 +-- src/main/java/racingcar/model/Car.java | 43 ++++++++++++++----- .../java/racingcar/model/CarGenerator.java | 14 ------ .../racingcar/model/CarGeneratorTest.java | 17 -------- src/test/java/racingcar/model/CarTest.java | 17 ++++++-- .../java/racingcar/model/PositionTest.java | 3 +- 6 files changed, 51 insertions(+), 49 deletions(-) delete mode 100644 src/main/java/racingcar/model/CarGenerator.java delete mode 100644 src/test/java/racingcar/model/CarGeneratorTest.java diff --git a/README.md b/README.md index f28259acf45..a31e12d442d 100644 --- a/README.md +++ b/README.md @@ -63,9 +63,9 @@ - [x] 이름이 6자 이상일 경우 예외를 발생시킨다. ### 자동차 객체 -- [ ] 자동차의 이름을 부여한다. -- [ ] 자동차 이름은 쉼표를 기준으로 구분한다. -- [ ] 자동차 이름이 1자이상 5자이하인지 검증한다. +- [x] 자동차의 이름을 부여한다. +- [x] 자동차 이름은 쉼표를 기준으로 구분한다. +- [x] 자동차 이름이 1자이상 5자이하인지 검증한다. ### 비즈니스 로직 - [ ] 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다. diff --git a/src/main/java/racingcar/model/Car.java b/src/main/java/racingcar/model/Car.java index 430d1d2c446..5718dc83a56 100644 --- a/src/main/java/racingcar/model/Car.java +++ b/src/main/java/racingcar/model/Car.java @@ -1,27 +1,41 @@ package racingcar.model; +import racingcar.message.ErrorMessage; -public class Car { +public final class Car { + private final String name; private final Position position; private static final int MOVE_CONDITION_NUMBER = 4; + private static final int MAXIMUM_NAME_LENGTH = 5; + private static final String SEPERATOR = ":"; - public Car() { - this(0); + public Car(String name) { + validateName(name); + this.name = name; + this.position = new Position(0); } - public Car(int initialPosition) { - this.position = new Position(initialPosition); + public Car(String name, Position initialPosition) { + validateName(name); + this.name = name; + this.position = initialPosition; } - private Car(Position position) { - this.position = position; + private void validateName(String name) { + if (invalidName(name)) { + throw new IllegalArgumentException(ErrorMessage.INVALID_NAME); + } + } + + private boolean invalidName(String name) { + return name.isBlank() || name.length() > MAXIMUM_NAME_LENGTH; } public Car move(int randomValue) { if (canMove(randomValue)) { - return new Car(this.position.incrementPosition()); + return new Car(this.name, this.position.incrementPosition()); } return this; } @@ -34,7 +48,16 @@ public boolean isAtPosition(Position other) { return position.isSameAs(other); } - public void printPosition() { - System.out.println(position); + public String getName() { + return name; + } + + public int getPosition() { + return position.getPosition(); + } + + @Override + public String toString() { + return name + SEPERATOR + position; } } diff --git a/src/main/java/racingcar/model/CarGenerator.java b/src/main/java/racingcar/model/CarGenerator.java deleted file mode 100644 index 25acd0b8a51..00000000000 --- a/src/main/java/racingcar/model/CarGenerator.java +++ /dev/null @@ -1,14 +0,0 @@ -package racingcar.model; - -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -public class CarGenerator { - - public static List createCars(int carCount) { - return IntStream.range(0, carCount) - .mapToObj(i -> new Car()) - .collect(Collectors.toList()); - } -} diff --git a/src/test/java/racingcar/model/CarGeneratorTest.java b/src/test/java/racingcar/model/CarGeneratorTest.java deleted file mode 100644 index f3a69a1e07c..00000000000 --- a/src/test/java/racingcar/model/CarGeneratorTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package racingcar.model; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -class CarGeneratorTest { - - @Test - @DisplayName("입력한 숫자만큼 차량 객체를 생성하고, 초기 위치는 0이다.") - void createCars() { - assertThat(CarGenerator.createCars(3)) - .hasSize(3) - .allMatch(car -> car.isAtPosition(new Position(0))); - } -} diff --git a/src/test/java/racingcar/model/CarTest.java b/src/test/java/racingcar/model/CarTest.java index 623ec35b431..b2194d38a0a 100644 --- a/src/test/java/racingcar/model/CarTest.java +++ b/src/test/java/racingcar/model/CarTest.java @@ -13,7 +13,11 @@ class CarTest { @CsvSource({"0", "1", "5"}) @DisplayName("자동차는 주어진 위치로 초기화된다.") void car_initialPosition_test(int initialPosition) { - Car car = new Car(initialPosition); + String carName = "car"; + + Car car = new Car(carName, new Position(initialPosition)); + + assertThat(car.getName()).isEqualTo(carName); assertThat(car.isAtPosition(new Position(initialPosition))).isTrue(); } @@ -28,10 +32,12 @@ void car_initialPosition_test(int initialPosition) { "1,9,2" }) void car_move_logic_test(int initialPosition, int randomValue, int expectedPosition) { - Car initialCar = new Car(initialPosition); + String carName = "car"; + Car initialCar = new Car(carName, new Position(initialPosition)); Car movedCar = initialCar.move(randomValue); + assertThat(movedCar.getName()).isEqualTo(carName); assertThat(movedCar.isAtPosition(new Position(expectedPosition))).isTrue(); } @@ -44,17 +50,20 @@ void car_move_logic_test(int initialPosition, int randomValue, int expectedPosit "2,0,2", }) void car_not_move_logic_test(int initialPosition, int randomValue, int expectedPosition) { - Car initialCar = new Car(initialPosition); + String carName = "car"; + Car initialCar = new Car(carName, new Position(initialPosition)); Car movedCar = initialCar.move(randomValue); + assertThat(movedCar.getName()).isEqualTo(carName); assertThat(movedCar.isAtPosition(new Position(expectedPosition))).isTrue(); } @DisplayName("자동차가 이동해도 기존 객체는 변하지 않는다.(불변 객체 테스트)") @Test void car_not_move_immutable_test() { - Car initialCar = new Car(0); + String carName = "car"; + Car initialCar = new Car(carName); Car movedCar = initialCar.move(4); diff --git a/src/test/java/racingcar/model/PositionTest.java b/src/test/java/racingcar/model/PositionTest.java index 8f15dafe081..0e0b1d5d49a 100644 --- a/src/test/java/racingcar/model/PositionTest.java +++ b/src/test/java/racingcar/model/PositionTest.java @@ -17,7 +17,8 @@ class PositionTest { "5,1,5,6" }) void move_initial_move(int initialPosition, int randomValue, int randomValue2, int expectedPosition) { - Car initialCar = new Car(initialPosition); + String carName = "car"; + Car initialCar = new Car(carName, new Position(initialPosition)); Car movedOnceCar = initialCar.move(randomValue); Car movedTwiceCar = movedOnceCar.move(randomValue2); From d0bacbde2fdbaa7b635facb61952f0757528aec4 Mon Sep 17 00:00:00 2001 From: LeeJin0527 Date: Thu, 20 Mar 2025 13:55:09 +0900 Subject: [PATCH 05/17] =?UTF-8?q?feat(step4):=20=EA=B2=BD=EC=A3=BC=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=20=EC=8B=9C=20=EB=A7=A4=20=ED=9A=8C=EC=B0=A8?= =?UTF-8?q?=20=EC=9E=90=EB=8F=99=EC=B0=A8=EB=93=A4=EC=9D=98=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EC=B6=9C=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/racingcar/model/Position.java | 4 ++ src/main/java/racingcar/model/RacingGame.java | 66 +++++++++++++++---- .../java/racingcar/model/RacingGameTest.java | 12 ++-- 3 files changed, 65 insertions(+), 17 deletions(-) diff --git a/src/main/java/racingcar/model/Position.java b/src/main/java/racingcar/model/Position.java index 31fe148cb9f..064756d6cc0 100644 --- a/src/main/java/racingcar/model/Position.java +++ b/src/main/java/racingcar/model/Position.java @@ -22,6 +22,10 @@ public boolean isSameAs(Position other) { return this.position == other.position; } + public int getPosition() { + return position; + } + @Override public String toString() { return DELIMITER.repeat(position); diff --git a/src/main/java/racingcar/model/RacingGame.java b/src/main/java/racingcar/model/RacingGame.java index 35765060cf2..af8c0bf0300 100644 --- a/src/main/java/racingcar/model/RacingGame.java +++ b/src/main/java/racingcar/model/RacingGame.java @@ -3,8 +3,6 @@ import racingcar.message.Message; import racingcar.util.RandomNumberGenerator; import racingcar.view.OutputView; - -import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -12,37 +10,79 @@ public class RacingGame { private final List cars; - public RacingGame(int carCount) { - this.cars = CarGenerator.createCars(carCount); + private RacingGame(List cars) { + this.cars = cars; } - public List getCars() { - return Collections.unmodifiableList(cars); + public static RacingGame createRacingGame(List names) { + List cars = createCars(names); + + return new RacingGame(cars); } - private RacingGame(List cars) { - this.cars = cars; + private static List createCars(List names) { + return names.stream() + .map(Car::new) + .collect(Collectors.toList()); + } + + public boolean hasCarCount(int expectedCount) { + return cars.size() == expectedCount; + } + + public boolean areAllCarsAtPosition(Position position) { + return cars.stream().allMatch(car -> car.isAtPosition(position)); } public RacingGame race(int attemptCount) { OutputView.print(Message.RESULT_MESSAGE); + List updatedCars = getCars(attemptCount); + + return new RacingGame(updatedCars); + } + + private List getCars(int attemptCount) { List updatedCars = cars; + + updatedCars = executeRace(attemptCount, updatedCars); + return updatedCars; + } + + private List executeRace(int attemptCount, List updatedCars) { for (int i = 0; i < attemptCount; i++) { - updatedCars = moveCars(updatedCars); + updatedCars = move(updatedCars); OutputView.print(""); } + return updatedCars; + } - return new RacingGame(updatedCars); + private List move(List currentCars) { + List movedCars = moveCars(currentCars); + + movedCars.forEach(System.out::println); + + return movedCars; } private List moveCars(List currentCars) { - List movedCars = currentCars.stream() + return currentCars.stream() .map(car -> car.move(RandomNumberGenerator.generateNumber())) .collect(Collectors.toList()); + } - movedCars.forEach(Car::printPosition); + public List getWinners() { + int maxPosition = findMaxPosition(); - return movedCars; + return cars.stream() + .filter(car -> car.isAtPosition(new Position(maxPosition))) + .collect(Collectors.toList()); + } + + private int findMaxPosition() { + return cars.stream() + .mapToInt(Car::getPosition) + .max() + .orElse(0); } } diff --git a/src/test/java/racingcar/model/RacingGameTest.java b/src/test/java/racingcar/model/RacingGameTest.java index 4fe2c523286..2d4132b3b03 100644 --- a/src/test/java/racingcar/model/RacingGameTest.java +++ b/src/test/java/racingcar/model/RacingGameTest.java @@ -3,16 +3,20 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.List; + import static org.assertj.core.api.Assertions.assertThat; class RacingGameTest { @Test - @DisplayName("입력한 자동차 대수만큼 자동차 객체를 생성한다.") + @DisplayName("입력한 자동차 대수만큼 자동차 객체를 생성하고 초기 위치는 0이다.") void createCarsTest() { - int carCount = 3; - RacingGame racingGame = new RacingGame(carCount); + List carNames = List.of("car1", "car2", "car3"); + + RacingGame racingGame = RacingGame.createRacingGame(carNames); - assertThat(racingGame.getCars()).hasSize(carCount); + assertThat(racingGame.hasCarCount(carNames.size())).isTrue(); + assertThat(racingGame.areAllCarsAtPosition(new Position(0))).isTrue(); } } From c535ddfd0b20bee0bd71dfe1b036f47d1bae30f3 Mon Sep 17 00:00:00 2001 From: LeeJin0527 Date: Thu, 20 Mar 2025 13:55:23 +0900 Subject: [PATCH 06/17] =?UTF-8?q?feat(step4):=20=EC=B5=9C=EC=A2=85=20?= =?UTF-8?q?=EC=9A=B0=EC=8A=B9=EC=9E=90=20=EC=B6=9C=EB=A0=A5=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=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/message/Message.java | 3 ++- src/main/java/racingcar/view/OutputView.java | 23 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/main/java/racingcar/message/Message.java b/src/main/java/racingcar/message/Message.java index 57e376be92d..8ab3d0ac445 100644 --- a/src/main/java/racingcar/message/Message.java +++ b/src/main/java/racingcar/message/Message.java @@ -3,8 +3,9 @@ public class Message { public static final String RESULT_MESSAGE = "실행 결과"; - public static final String CAR_COUNT_MESSAGE = "자동차 대수는 몇 대 인가요?"; public static final String ATTEMPT_COUNT_MESSAGE = "시도할 회수는 몇 회 인가요?"; + public static final String CAR_NAME_MESSAGE = "경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분)."; + public static final String WINNING_MESSAGE = "가 최종 우승했습니다."; private Message() { } diff --git a/src/main/java/racingcar/view/OutputView.java b/src/main/java/racingcar/view/OutputView.java index 331f7016ab4..30b00b4865c 100644 --- a/src/main/java/racingcar/view/OutputView.java +++ b/src/main/java/racingcar/view/OutputView.java @@ -1,8 +1,31 @@ package racingcar.view; +import racingcar.model.Car; + +import java.util.List; +import java.util.stream.Collectors; + +import static racingcar.message.Message.WINNING_MESSAGE; + public class OutputView { + private OutputView() {} + + private static final String SEPERATOR = ", "; + public static void print(String message) { System.out.println(message); } + + public static void printWinners(List winners) { + String winnerNames = formatWinnersName(winners); + + print(winnerNames + WINNING_MESSAGE); + } + + private static String formatWinnersName(List winners) { + return winners.stream() + .map(Car::getName) + .collect(Collectors.joining(SEPERATOR)); + } } From 5b22668b08e83634c8b19c847abc87f73c7c4203 Mon Sep 17 00:00:00 2001 From: LeeJin0527 Date: Thu, 20 Mar 2025 14:01:13 +0900 Subject: [PATCH 07/17] =?UTF-8?q?docs(step4):=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=20md=20=EC=99=84=EB=A3=8C?= =?UTF-8?q?=20=ED=95=AD=EB=AA=A9=20=EC=B2=B4=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a31e12d442d..2570bc2cae6 100644 --- a/README.md +++ b/README.md @@ -68,8 +68,8 @@ - [x] 자동차 이름이 1자이상 5자이하인지 검증한다. ### 비즈니스 로직 -- [ ] 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다. -- [ ] 자동차 경주가 끝난 후 쉼표로 구분하여 우승자를 출력한다. +- [x] 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다. +- [x] 자동차 경주가 끝난 후 쉼표로 구분하여 우승자를 출력한다. ### 결과 출력 -- [] "a, b가 최종 우승했습니다."로 출력한다. +- [x] "a, b가 최종 우승했습니다."로 출력한다. From 06dbad0a1537ae059d80fd531e75ac7792545381 Mon Sep 17 00:00:00 2001 From: LeeJin0527 Date: Wed, 26 Mar 2025 09:08:34 +0900 Subject: [PATCH 08/17] =?UTF-8?q?refactor(step4)=20:=20final=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/racingcar/Main.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/racingcar/Main.java b/src/main/java/racingcar/Main.java index de7a6f65814..4c74570fa23 100644 --- a/src/main/java/racingcar/Main.java +++ b/src/main/java/racingcar/Main.java @@ -14,16 +14,16 @@ public class Main { public static void main(String[] args) { - InputView inputView = new InputView(); + final InputView inputView = new InputView(); final List names = getValidCarNames(inputView); final int attemptCount = getValidAttemptCount(inputView); - RacingGame racingGame = RacingGame.createRacingGame(names); + final RacingGame racingGame = RacingGame.createRacingGame(names); final RacingGame finalResult = racingGame.race(attemptCount); - List winners = finalResult.getWinners(); + final List winners = finalResult.getWinners(); OutputView.printWinners(winners); } From 75f3c15194cab5eba51a920d0964a478dad6c62b Mon Sep 17 00:00:00 2001 From: LeeJin0527 Date: Wed, 26 Mar 2025 09:16:38 +0900 Subject: [PATCH 09/17] =?UTF-8?q?refactor(step4)=20:=20=EC=9E=90=EB=8F=99?= =?UTF-8?q?=EC=B0=A8=EB=AA=85=20=EC=9B=90=EC=8B=9C=20=EA=B0=92=20=ED=8F=AC?= =?UTF-8?q?=EC=9E=A5=20&=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/racingcar/model/Car.java | 23 ++------- src/main/java/racingcar/model/CarName.java | 48 +++++++++++++++++++ src/main/java/racingcar/model/RacingGame.java | 3 +- src/main/java/racingcar/view/OutputView.java | 5 +- .../java/racingcar/model/CarNameTest.java | 36 ++++++++++++++ src/test/java/racingcar/model/CarTest.java | 14 +++--- .../java/racingcar/model/PositionTest.java | 3 +- 7 files changed, 101 insertions(+), 31 deletions(-) create mode 100644 src/main/java/racingcar/model/CarName.java create mode 100644 src/test/java/racingcar/model/CarNameTest.java diff --git a/src/main/java/racingcar/model/Car.java b/src/main/java/racingcar/model/Car.java index 5718dc83a56..4f4c48eb533 100644 --- a/src/main/java/racingcar/model/Car.java +++ b/src/main/java/racingcar/model/Car.java @@ -1,38 +1,23 @@ package racingcar.model; -import racingcar.message.ErrorMessage; - public final class Car { - private final String name; + private final CarName name; private final Position position; private static final int MOVE_CONDITION_NUMBER = 4; - private static final int MAXIMUM_NAME_LENGTH = 5; private static final String SEPERATOR = ":"; - public Car(String name) { - validateName(name); + public Car(CarName name) { this.name = name; this.position = new Position(0); } - public Car(String name, Position initialPosition) { - validateName(name); + public Car(CarName name, Position initialPosition) { this.name = name; this.position = initialPosition; } - private void validateName(String name) { - if (invalidName(name)) { - throw new IllegalArgumentException(ErrorMessage.INVALID_NAME); - } - } - - private boolean invalidName(String name) { - return name.isBlank() || name.length() > MAXIMUM_NAME_LENGTH; - } - public Car move(int randomValue) { if (canMove(randomValue)) { return new Car(this.name, this.position.incrementPosition()); @@ -48,7 +33,7 @@ public boolean isAtPosition(Position other) { return position.isSameAs(other); } - public String getName() { + public CarName getName() { return name; } diff --git a/src/main/java/racingcar/model/CarName.java b/src/main/java/racingcar/model/CarName.java new file mode 100644 index 00000000000..81b81cb3411 --- /dev/null +++ b/src/main/java/racingcar/model/CarName.java @@ -0,0 +1,48 @@ +package racingcar.model; + +import static racingcar.message.ErrorMessage.INVALID_CAR_NAME_LENGTH; +import static racingcar.message.ErrorMessage.INVALID_NAME; + +public class CarName { + + private final String name; + + private static final int MAXIMUM_NAME_LENGTH = 5; + + public CarName(String value) { + validate(value); + this.name = value; + } + + private void validate(String value) { + if (value == null || value.isBlank()) { + throw new IllegalArgumentException(INVALID_NAME); + } + + if (value.length() > MAXIMUM_NAME_LENGTH) { + throw new IllegalArgumentException(INVALID_CAR_NAME_LENGTH); + } + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CarName)) return false; + CarName carName = (CarName) o; + return name.equals(carName.name); + } + + @Override + public int hashCode() { + return name.hashCode(); + } +} diff --git a/src/main/java/racingcar/model/RacingGame.java b/src/main/java/racingcar/model/RacingGame.java index af8c0bf0300..eeb234a2ad7 100644 --- a/src/main/java/racingcar/model/RacingGame.java +++ b/src/main/java/racingcar/model/RacingGame.java @@ -3,6 +3,7 @@ import racingcar.message.Message; import racingcar.util.RandomNumberGenerator; import racingcar.view.OutputView; + import java.util.List; import java.util.stream.Collectors; @@ -22,7 +23,7 @@ public static RacingGame createRacingGame(List names) { private static List createCars(List names) { return names.stream() - .map(Car::new) + .map(name -> new Car(new CarName(name))) .collect(Collectors.toList()); } diff --git a/src/main/java/racingcar/view/OutputView.java b/src/main/java/racingcar/view/OutputView.java index 30b00b4865c..5cfcbba1c3d 100644 --- a/src/main/java/racingcar/view/OutputView.java +++ b/src/main/java/racingcar/view/OutputView.java @@ -9,7 +9,8 @@ public class OutputView { - private OutputView() {} + private OutputView() { + } private static final String SEPERATOR = ", "; @@ -25,7 +26,7 @@ public static void printWinners(List winners) { private static String formatWinnersName(List winners) { return winners.stream() - .map(Car::getName) + .map(car -> car.getName().getName()) .collect(Collectors.joining(SEPERATOR)); } } diff --git a/src/test/java/racingcar/model/CarNameTest.java b/src/test/java/racingcar/model/CarNameTest.java new file mode 100644 index 00000000000..946135f5b09 --- /dev/null +++ b/src/test/java/racingcar/model/CarNameTest.java @@ -0,0 +1,36 @@ +package racingcar.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.params.provider.ValueSource; +import racingcar.message.ErrorMessage; + +class CarNameTest { + + @DisplayName("자동차명은 1자에서 5자 이하이다.") + @ParameterizedTest + @ValueSource(strings = {"a", "ab", "abc", "abcd", "abcde"}) + void valid_car_name(String carName) { + assertThatCode(() -> new Car(new CarName(carName))) + .doesNotThrowAnyException(); + } + + @DisplayName("자동차명이 null이면 exception을 발생시킨다.") + @Test + void car_name_with_blank() { + assertThatThrownBy(() -> new Car(new CarName(""))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(ErrorMessage.INVALID_NAME); + } + + @DisplayName("자동차명이 5자를 초과하면 exception을 발생시킨다.") + @Test + void car_name_exceed_max_length() { + assertThatThrownBy(() -> new Car(new CarName("abcdef"))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(ErrorMessage.INVALID_CAR_NAME_LENGTH); + } +} diff --git a/src/test/java/racingcar/model/CarTest.java b/src/test/java/racingcar/model/CarTest.java index b2194d38a0a..7bcbcae3800 100644 --- a/src/test/java/racingcar/model/CarTest.java +++ b/src/test/java/racingcar/model/CarTest.java @@ -15,9 +15,9 @@ class CarTest { void car_initialPosition_test(int initialPosition) { String carName = "car"; - Car car = new Car(carName, new Position(initialPosition)); + Car car = new Car(new CarName(carName), new Position(initialPosition)); - assertThat(car.getName()).isEqualTo(carName); + assertThat(car.getName().getName()).isEqualTo(carName); assertThat(car.isAtPosition(new Position(initialPosition))).isTrue(); } @@ -33,11 +33,11 @@ void car_initialPosition_test(int initialPosition) { }) void car_move_logic_test(int initialPosition, int randomValue, int expectedPosition) { String carName = "car"; - Car initialCar = new Car(carName, new Position(initialPosition)); + Car initialCar = new Car(new CarName(carName), new Position(initialPosition)); Car movedCar = initialCar.move(randomValue); - assertThat(movedCar.getName()).isEqualTo(carName); + assertThat(movedCar.getName().getName()).isEqualTo(carName); assertThat(movedCar.isAtPosition(new Position(expectedPosition))).isTrue(); } @@ -51,11 +51,11 @@ void car_move_logic_test(int initialPosition, int randomValue, int expectedPosit }) void car_not_move_logic_test(int initialPosition, int randomValue, int expectedPosition) { String carName = "car"; - Car initialCar = new Car(carName, new Position(initialPosition)); + Car initialCar = new Car(new CarName(carName), new Position(initialPosition)); Car movedCar = initialCar.move(randomValue); - assertThat(movedCar.getName()).isEqualTo(carName); + assertThat(movedCar.getName().getName()).isEqualTo(carName); assertThat(movedCar.isAtPosition(new Position(expectedPosition))).isTrue(); } @@ -63,7 +63,7 @@ void car_not_move_logic_test(int initialPosition, int randomValue, int expectedP @Test void car_not_move_immutable_test() { String carName = "car"; - Car initialCar = new Car(carName); + Car initialCar = new Car(new CarName(carName)); Car movedCar = initialCar.move(4); diff --git a/src/test/java/racingcar/model/PositionTest.java b/src/test/java/racingcar/model/PositionTest.java index 0e0b1d5d49a..6136bd8c458 100644 --- a/src/test/java/racingcar/model/PositionTest.java +++ b/src/test/java/racingcar/model/PositionTest.java @@ -17,8 +17,7 @@ class PositionTest { "5,1,5,6" }) void move_initial_move(int initialPosition, int randomValue, int randomValue2, int expectedPosition) { - String carName = "car"; - Car initialCar = new Car(carName, new Position(initialPosition)); + Car initialCar = new Car(new CarName("test"), new Position(initialPosition)); Car movedOnceCar = initialCar.move(randomValue); Car movedTwiceCar = movedOnceCar.move(randomValue2); From df07b2fc2a3c1dcde437e479c463fb04a2f151f3 Mon Sep 17 00:00:00 2001 From: LeeJin0527 Date: Wed, 26 Mar 2025 09:39:25 +0900 Subject: [PATCH 10/17] =?UTF-8?q?refactor(step4)=20:=20=EB=B6=80=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9E=90=EB=A5=BC=20=EC=A3=BC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EC=9E=90=EB=A5=BC=20=ED=98=B8=EC=B6=9C=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 생성자 테스트 코드 작성 --- .../java/racingcar/message/ErrorMessage.java | 1 + src/main/java/racingcar/model/Car.java | 3 +-- src/test/java/racingcar/model/CarTest.java | 17 +++++++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/main/java/racingcar/message/ErrorMessage.java b/src/main/java/racingcar/message/ErrorMessage.java index 3ca95417a89..e1ec83b8547 100644 --- a/src/main/java/racingcar/message/ErrorMessage.java +++ b/src/main/java/racingcar/message/ErrorMessage.java @@ -5,6 +5,7 @@ public class ErrorMessage { public static final String INVALID_NUMBER = "숫자를 입력해야 합니다."; public static final String POSITIVE_NUMBER = "양수를 입력해야 합니다."; public static final String INVALID_NAME = "닉네임은 1자 이상 5자 이하여야 합니다. 다시 입력해주세요."; + public static final String INVALID_CAR_NAME_LENGTH = "자동차 이름은 5자 이하만 가능합니다."; private ErrorMessage() { } diff --git a/src/main/java/racingcar/model/Car.java b/src/main/java/racingcar/model/Car.java index 4f4c48eb533..457cadd818b 100644 --- a/src/main/java/racingcar/model/Car.java +++ b/src/main/java/racingcar/model/Car.java @@ -9,8 +9,7 @@ public final class Car { private static final String SEPERATOR = ":"; public Car(CarName name) { - this.name = name; - this.position = new Position(0); + this(name, new Position(0)); } public Car(CarName name, Position initialPosition) { diff --git a/src/test/java/racingcar/model/CarTest.java b/src/test/java/racingcar/model/CarTest.java index 7bcbcae3800..ea90da7228c 100644 --- a/src/test/java/racingcar/model/CarTest.java +++ b/src/test/java/racingcar/model/CarTest.java @@ -9,6 +9,23 @@ class CarTest { + @Test + @DisplayName("자동차의 이름과 초기 위치를 가지고 생성할 수 있다.") + void car_creation_test() { + Car car = new Car(new CarName("test"), new Position(5)); + + assertThat(car.getName().getName()).isEqualTo("test"); + assertThat(car.isAtPosition(new Position(5))).isTrue(); + } + + @Test + @DisplayName("자동차 기본 생성시 초기 위치는 0이다.") + void car_initialPosition_test() { + Car car = new Car(new CarName("test")); + + assertThat(car.isAtPosition(new Position(0))).isTrue(); + } + @ParameterizedTest(name = "초기 위치 {0}으로 생성된 자동차의 위치는 {0}이어야 한다.") @CsvSource({"0", "1", "5"}) @DisplayName("자동차는 주어진 위치로 초기화된다.") From b5e3e938160f6ed73d2bd0807e180ac3a6244e52 Mon Sep 17 00:00:00 2001 From: LeeJin0527 Date: Wed, 26 Mar 2025 09:48:56 +0900 Subject: [PATCH 11/17] =?UTF-8?q?refactor(step4)=20:=20=EC=B6=9C=EB=A0=A5?= =?UTF-8?q?=EA=B3=BC=20=EA=B4=80=EB=A0=A8=EB=90=9C=20=EC=83=81=EC=88=98=20?= =?UTF-8?q?OutputView=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/racingcar/model/Car.java | 5 +++-- src/main/java/racingcar/model/Position.java | 6 +++--- src/main/java/racingcar/util/InputValidator.java | 2 +- src/main/java/racingcar/view/OutputView.java | 7 +++++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/main/java/racingcar/model/Car.java b/src/main/java/racingcar/model/Car.java index 457cadd818b..1f84f321d63 100644 --- a/src/main/java/racingcar/model/Car.java +++ b/src/main/java/racingcar/model/Car.java @@ -1,12 +1,13 @@ package racingcar.model; +import static racingcar.view.OutputView.NAME_POSITION_SEPERATOR; + public final class Car { private final CarName name; private final Position position; private static final int MOVE_CONDITION_NUMBER = 4; - private static final String SEPERATOR = ":"; public Car(CarName name) { this(name, new Position(0)); @@ -42,6 +43,6 @@ public int getPosition() { @Override public String toString() { - return name + SEPERATOR + position; + return name + NAME_POSITION_SEPERATOR + position; } } diff --git a/src/main/java/racingcar/model/Position.java b/src/main/java/racingcar/model/Position.java index 064756d6cc0..ed2d24b4035 100644 --- a/src/main/java/racingcar/model/Position.java +++ b/src/main/java/racingcar/model/Position.java @@ -1,11 +1,11 @@ package racingcar.model; +import static racingcar.view.OutputView.MOVE; + public class Position { private final int position; - private static final String DELIMITER = "-"; - public Position() { this(0); } @@ -28,6 +28,6 @@ public int getPosition() { @Override public String toString() { - return DELIMITER.repeat(position); + return MOVE.repeat(position); } } diff --git a/src/main/java/racingcar/util/InputValidator.java b/src/main/java/racingcar/util/InputValidator.java index b3104ab2515..77668ecc0ea 100644 --- a/src/main/java/racingcar/util/InputValidator.java +++ b/src/main/java/racingcar/util/InputValidator.java @@ -6,10 +6,10 @@ import static racingcar.message.ErrorMessage.INVALID_NAME; import static racingcar.message.ErrorMessage.POSITIVE_NUMBER; +import static racingcar.view.OutputView.SEPERATOR; public class InputValidator { - private static final String SEPERATOR = ","; private static final int MINIMUM_NAME_LENGTH = 1; private static final int MAXIMUM_NAME_LENGTH = 5; diff --git a/src/main/java/racingcar/view/OutputView.java b/src/main/java/racingcar/view/OutputView.java index 5cfcbba1c3d..e3b20ec9891 100644 --- a/src/main/java/racingcar/view/OutputView.java +++ b/src/main/java/racingcar/view/OutputView.java @@ -12,7 +12,10 @@ public class OutputView { private OutputView() { } - private static final String SEPERATOR = ", "; + private static final String WINNER_NAME_SEPERATOR = ", "; + public static final String NAME_POSITION_SEPERATOR = ":"; + public static final String MOVE = "-"; + public static final String SEPERATOR = ","; public static void print(String message) { System.out.println(message); @@ -27,6 +30,6 @@ public static void printWinners(List winners) { private static String formatWinnersName(List winners) { return winners.stream() .map(car -> car.getName().getName()) - .collect(Collectors.joining(SEPERATOR)); + .collect(Collectors.joining(WINNER_NAME_SEPERATOR)); } } From d8def67e2f63e9e1c1964e0a934669ac67da4292 Mon Sep 17 00:00:00 2001 From: LeeJin0527 Date: Wed, 26 Mar 2025 09:50:59 +0900 Subject: [PATCH 12/17] =?UTF-8?q?test(step4)=20:=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?=EA=B0=92=20=EB=B9=84=EA=B5=90=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/racingcar/model/CarTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/racingcar/model/CarTest.java b/src/test/java/racingcar/model/CarTest.java index ea90da7228c..440382322de 100644 --- a/src/test/java/racingcar/model/CarTest.java +++ b/src/test/java/racingcar/model/CarTest.java @@ -56,6 +56,7 @@ void car_move_logic_test(int initialPosition, int randomValue, int expectedPosit assertThat(movedCar.getName().getName()).isEqualTo(carName); assertThat(movedCar.isAtPosition(new Position(expectedPosition))).isTrue(); + assertThat(initialCar).isNotEqualTo(movedCar); } @DisplayName("랜덤 값이 3이하 이면 이동 하지 않는다.") @@ -86,5 +87,6 @@ void car_not_move_immutable_test() { assertThat(initialCar.isAtPosition(new Position(0))).isTrue(); assertThat(movedCar.isAtPosition(new Position(1))).isTrue(); + assertThat(initialCar).isNotEqualTo(movedCar); } } From 7c551d11db1e2bd313418ff99ef0bcdd07c870db Mon Sep 17 00:00:00 2001 From: LeeJin0527 Date: Wed, 26 Mar 2025 09:58:09 +0900 Subject: [PATCH 13/17] =?UTF-8?q?test(step4)=20:=20PositionTest=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=EA=B8=B0=EB=B0=98=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/racingcar/model/PositionTest.java | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/test/java/racingcar/model/PositionTest.java b/src/test/java/racingcar/model/PositionTest.java index 6136bd8c458..0e77371edd2 100644 --- a/src/test/java/racingcar/model/PositionTest.java +++ b/src/test/java/racingcar/model/PositionTest.java @@ -1,6 +1,7 @@ package racingcar.model; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; @@ -8,21 +9,19 @@ class PositionTest { - @DisplayName("초기 위치가 5인 자동차가 2번 이동 하면 현재 위치보다 2 증가한다.") + @DisplayName("incrementPosition() 호출시 1 증가된 Position이 반환된다.") @ParameterizedTest @CsvSource({ - "0,1,1,0", - "3,4,4,5", - "5,4,1,6", - "5,1,5,6" + "0, 1", + "1, 2", + "2, 3", + "3, 4", }) - void move_initial_move(int initialPosition, int randomValue, int randomValue2, int expectedPosition) { - Car initialCar = new Car(new CarName("test"), new Position(initialPosition)); + void incrementPosition(int initialPosition, int expectedPosition) { + Position position = new Position(initialPosition); - Car movedOnceCar = initialCar.move(randomValue); - Car movedTwiceCar = movedOnceCar.move(randomValue2); + Position movedPosition = position.incrementPosition(); - assertThat(movedTwiceCar.isAtPosition(new Position(expectedPosition))).isTrue(); + assertThat(movedPosition.getPosition()).isEqualTo(expectedPosition); } - } From 722e61c40af34acc2be00553d1a0b45169c70107 Mon Sep 17 00:00:00 2001 From: LeeJin0527 Date: Wed, 26 Mar 2025 10:10:13 +0900 Subject: [PATCH 14/17] =?UTF-8?q?test(step4)=20:=20=EC=9A=B0=EC=8A=B9?= =?UTF-8?q?=EC=9E=90=20=EC=B6=9C=EB=A0=A5=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=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/model/RacingGame.java | 4 +++ .../java/racingcar/model/RacingGameTest.java | 28 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/main/java/racingcar/model/RacingGame.java b/src/main/java/racingcar/model/RacingGame.java index eeb234a2ad7..696a51e0c70 100644 --- a/src/main/java/racingcar/model/RacingGame.java +++ b/src/main/java/racingcar/model/RacingGame.java @@ -21,6 +21,10 @@ public static RacingGame createRacingGame(List names) { return new RacingGame(cars); } + public static RacingGame ofCars(List cars) { + return new RacingGame(cars); + } + private static List createCars(List names) { return names.stream() .map(name -> new Car(new CarName(name))) diff --git a/src/test/java/racingcar/model/RacingGameTest.java b/src/test/java/racingcar/model/RacingGameTest.java index 2d4132b3b03..659d1a4ec34 100644 --- a/src/test/java/racingcar/model/RacingGameTest.java +++ b/src/test/java/racingcar/model/RacingGameTest.java @@ -19,4 +19,32 @@ void createCarsTest() { assertThat(racingGame.hasCarCount(carNames.size())).isTrue(); assertThat(racingGame.areAllCarsAtPosition(new Position(0))).isTrue(); } + + @Test + @DisplayName("우승자를 정확히 추출할 수 있다") + void get_winner_cars() { + + Car win = new Car(new CarName("win"), new Position(3)); + Car lose = new Car(new CarName("lose"), new Position(1)); + + RacingGame game = RacingGame.ofCars(List.of(win, lose)); + + List winners = game.getWinners(); + + assertThat(winners).containsExactly(win); + } + + @Test + @DisplayName("최대 위치를 정확히 찾는다") + void find_max_position_test() { + Car a = new Car(new CarName("a"), new Position(2)); + Car b = new Car(new CarName("b"), new Position(5)); + Car c = new Car(new CarName("c"), new Position(1)); + + RacingGame game = RacingGame.ofCars(List.of(a, b, c)); + + List winners = game.getWinners(); + + assertThat(winners).containsExactly(b); + } } From 53ec369488bc06bb22c499808b138b4c3cf6cf4c Mon Sep 17 00:00:00 2001 From: LeeJin0527 Date: Thu, 27 Mar 2025 19:23:00 +0900 Subject: [PATCH 15/17] =?UTF-8?q?test(step4)=20:=20=EC=B0=A8=EB=9F=89=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EA=B0=9D=EC=B2=B4=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 차량 이름만 테스트 하도록 Car 객체 생성하는 코드 제거 --- src/test/java/racingcar/model/CarNameTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/racingcar/model/CarNameTest.java b/src/test/java/racingcar/model/CarNameTest.java index 946135f5b09..612b16d8866 100644 --- a/src/test/java/racingcar/model/CarNameTest.java +++ b/src/test/java/racingcar/model/CarNameTest.java @@ -10,18 +10,18 @@ class CarNameTest { - @DisplayName("자동차명은 1자에서 5자 이하이다.") + @DisplayName("자동차명은 1자에서 5자 이하이면 예외가 발생하지 않는다.") @ParameterizedTest @ValueSource(strings = {"a", "ab", "abc", "abcd", "abcde"}) void valid_car_name(String carName) { - assertThatCode(() -> new Car(new CarName(carName))) + assertThatCode(() -> new CarName(carName)) .doesNotThrowAnyException(); } @DisplayName("자동차명이 null이면 exception을 발생시킨다.") @Test void car_name_with_blank() { - assertThatThrownBy(() -> new Car(new CarName(""))) + assertThatThrownBy(() -> new CarName("")) .isInstanceOf(IllegalArgumentException.class) .hasMessage(ErrorMessage.INVALID_NAME); } @@ -29,7 +29,7 @@ void car_name_with_blank() { @DisplayName("자동차명이 5자를 초과하면 exception을 발생시킨다.") @Test void car_name_exceed_max_length() { - assertThatThrownBy(() -> new Car(new CarName("abcdef"))) + assertThatThrownBy(() -> new CarName("abcdef")) .isInstanceOf(IllegalArgumentException.class) .hasMessage(ErrorMessage.INVALID_CAR_NAME_LENGTH); } From ddb70759230e1c9f42885f85daf2d3bd5cf802a1 Mon Sep 17 00:00:00 2001 From: LeeJin0527 Date: Thu, 27 Mar 2025 19:28:27 +0900 Subject: [PATCH 16/17] =?UTF-8?q?test(step4)=20:=20=EC=B0=A8=EB=9F=89=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EA=B2=BD?= =?UTF-8?q?=EA=B3=84=EA=B0=92=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/racingcar/message/ErrorMessage.java | 2 +- src/main/java/racingcar/model/CarName.java | 3 +-- src/test/java/racingcar/model/CarNameTest.java | 12 +++++++++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/racingcar/message/ErrorMessage.java b/src/main/java/racingcar/message/ErrorMessage.java index e1ec83b8547..948a9a2c2aa 100644 --- a/src/main/java/racingcar/message/ErrorMessage.java +++ b/src/main/java/racingcar/message/ErrorMessage.java @@ -5,7 +5,7 @@ public class ErrorMessage { public static final String INVALID_NUMBER = "숫자를 입력해야 합니다."; public static final String POSITIVE_NUMBER = "양수를 입력해야 합니다."; public static final String INVALID_NAME = "닉네임은 1자 이상 5자 이하여야 합니다. 다시 입력해주세요."; - public static final String INVALID_CAR_NAME_LENGTH = "자동차 이름은 5자 이하만 가능합니다."; + public static final String INVALID_CAR_NAME_LENGTH = "자동차 이름은 1자 이상 5자 이하만 가능합니다."; private ErrorMessage() { } diff --git a/src/main/java/racingcar/model/CarName.java b/src/main/java/racingcar/model/CarName.java index 81b81cb3411..dbc924f9925 100644 --- a/src/main/java/racingcar/model/CarName.java +++ b/src/main/java/racingcar/model/CarName.java @@ -1,7 +1,6 @@ package racingcar.model; import static racingcar.message.ErrorMessage.INVALID_CAR_NAME_LENGTH; -import static racingcar.message.ErrorMessage.INVALID_NAME; public class CarName { @@ -16,7 +15,7 @@ public CarName(String value) { private void validate(String value) { if (value == null || value.isBlank()) { - throw new IllegalArgumentException(INVALID_NAME); + throw new IllegalArgumentException(INVALID_CAR_NAME_LENGTH); } if (value.length() > MAXIMUM_NAME_LENGTH) { diff --git a/src/test/java/racingcar/model/CarNameTest.java b/src/test/java/racingcar/model/CarNameTest.java index 612b16d8866..a214512901d 100644 --- a/src/test/java/racingcar/model/CarNameTest.java +++ b/src/test/java/racingcar/model/CarNameTest.java @@ -3,6 +3,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; + import static org.assertj.core.api.Assertions.*; import org.junit.jupiter.params.provider.ValueSource; @@ -18,12 +19,21 @@ void valid_car_name(String carName) { .doesNotThrowAnyException(); } + @DisplayName("자동차명이 0자 이하 6자 이상이면 예외가 발생한다.") + @ParameterizedTest + @ValueSource(strings = {"", "abcdef", "abddklajgkljgaskfjaklsjfksjf"}) + void invalid_car_name(String carName) { + assertThatThrownBy(() -> new CarName(carName)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(ErrorMessage.INVALID_CAR_NAME_LENGTH); + } + @DisplayName("자동차명이 null이면 exception을 발생시킨다.") @Test void car_name_with_blank() { assertThatThrownBy(() -> new CarName("")) .isInstanceOf(IllegalArgumentException.class) - .hasMessage(ErrorMessage.INVALID_NAME); + .hasMessage(ErrorMessage.INVALID_CAR_NAME_LENGTH); } @DisplayName("자동차명이 5자를 초과하면 exception을 발생시킨다.") From 928e4f54364ce06f322a38d27b4d13e243ae2858 Mon Sep 17 00:00:00 2001 From: LeeJin0527 Date: Thu, 27 Mar 2025 22:55:51 +0900 Subject: [PATCH 17/17] =?UTF-8?q?refactor(step4):=20=EB=94=94=EB=AF=B8?= =?UTF-8?q?=ED=84=B0=20=EB=B2=95=EC=B9=99=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/racingcar/model/Car.java | 4 ++++ src/main/java/racingcar/model/CarName.java | 4 ---- src/main/java/racingcar/view/OutputView.java | 4 +++- src/test/java/racingcar/model/CarTest.java | 8 ++++---- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/main/java/racingcar/model/Car.java b/src/main/java/racingcar/model/Car.java index 1f84f321d63..1276e072eaf 100644 --- a/src/main/java/racingcar/model/Car.java +++ b/src/main/java/racingcar/model/Car.java @@ -29,6 +29,10 @@ private boolean canMove(int randomValue) { return randomValue >= MOVE_CONDITION_NUMBER; } + public boolean matches(CarName carName) { + return this.name.equals(carName); + } + public boolean isAtPosition(Position other) { return position.isSameAs(other); } diff --git a/src/main/java/racingcar/model/CarName.java b/src/main/java/racingcar/model/CarName.java index dbc924f9925..e8f383664ee 100644 --- a/src/main/java/racingcar/model/CarName.java +++ b/src/main/java/racingcar/model/CarName.java @@ -23,10 +23,6 @@ private void validate(String value) { } } - public String getName() { - return name; - } - @Override public String toString() { return name; diff --git a/src/main/java/racingcar/view/OutputView.java b/src/main/java/racingcar/view/OutputView.java index e3b20ec9891..3d67e127b32 100644 --- a/src/main/java/racingcar/view/OutputView.java +++ b/src/main/java/racingcar/view/OutputView.java @@ -1,6 +1,7 @@ package racingcar.view; import racingcar.model.Car; +import racingcar.model.CarName; import java.util.List; import java.util.stream.Collectors; @@ -29,7 +30,8 @@ public static void printWinners(List winners) { private static String formatWinnersName(List winners) { return winners.stream() - .map(car -> car.getName().getName()) + .map(Car::getName) + .map(CarName::toString) .collect(Collectors.joining(WINNER_NAME_SEPERATOR)); } } diff --git a/src/test/java/racingcar/model/CarTest.java b/src/test/java/racingcar/model/CarTest.java index 440382322de..849df3453e9 100644 --- a/src/test/java/racingcar/model/CarTest.java +++ b/src/test/java/racingcar/model/CarTest.java @@ -14,7 +14,7 @@ class CarTest { void car_creation_test() { Car car = new Car(new CarName("test"), new Position(5)); - assertThat(car.getName().getName()).isEqualTo("test"); + assertThat(car.matches(new CarName("test"))).isTrue(); assertThat(car.isAtPosition(new Position(5))).isTrue(); } @@ -34,7 +34,7 @@ void car_initialPosition_test(int initialPosition) { Car car = new Car(new CarName(carName), new Position(initialPosition)); - assertThat(car.getName().getName()).isEqualTo(carName); + assertThat(car.matches(new CarName(carName))).isTrue(); assertThat(car.isAtPosition(new Position(initialPosition))).isTrue(); } @@ -54,7 +54,7 @@ void car_move_logic_test(int initialPosition, int randomValue, int expectedPosit Car movedCar = initialCar.move(randomValue); - assertThat(movedCar.getName().getName()).isEqualTo(carName); + assertThat(movedCar.matches(new CarName("car"))).isTrue(); assertThat(movedCar.isAtPosition(new Position(expectedPosition))).isTrue(); assertThat(initialCar).isNotEqualTo(movedCar); } @@ -73,7 +73,7 @@ void car_not_move_logic_test(int initialPosition, int randomValue, int expectedP Car movedCar = initialCar.move(randomValue); - assertThat(movedCar.getName().getName()).isEqualTo(carName); + assertThat(movedCar.matches(new CarName(carName))).isTrue(); assertThat(movedCar.isAtPosition(new Position(expectedPosition))).isTrue(); }