diff --git a/README-HS.md b/README-HS.md new file mode 100644 index 0000000..6b606fe --- /dev/null +++ b/README-HS.md @@ -0,0 +1,23 @@ +## 요구사항 +1. depth 는 3이 넘지 않도록 구현 +2. else 사용 불가 +3. 3항 연산자 불가 +4. 메소드는 한가지 일만 하도록 구현 +5. 모든 원시 값과 문자열을 포장 +6. 일급 컬렉션 사용 + +**Scanner 를 사용한 입력은 구현하지 않고 도메인만 구현** + +--- + +## 구현 내용 +1. 자동차 이름 입력 + - 5자 초과 불가 + - 쉼표로 구분 +2. 시도 횟수 입력 + - 숫자 입력만 가능 +3. 시도 횟수 만큼 실행 + 1. 랜덤 값 생성 + 2. 랜덤 값 4 이상일 경우 전진 + 3. 실행 결과 출력 +4. 최종 레이싱 결과와 우승자 출력 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0f80bbf..d2880ba 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/RacingCarApplication.java b/src/main/java/RacingCarApplication.java new file mode 100644 index 0000000..d5ed30d --- /dev/null +++ b/src/main/java/RacingCarApplication.java @@ -0,0 +1,13 @@ +import racingcar.domain.Race; +import racingcar.domain.Cars; +import racingcar.view.RaceResult; + +public class RacingCarApplication { + public static void main(String[] args) { + Cars cars = new Cars("red,blue,pink"); + Race race = new Race(cars, 3); + + RaceResult raceResult = race.raceStart(); + raceResult.printWinner(); + } +} diff --git a/src/main/java/racingcar/domain/Car.java b/src/main/java/racingcar/domain/Car.java new file mode 100644 index 0000000..d65f365 --- /dev/null +++ b/src/main/java/racingcar/domain/Car.java @@ -0,0 +1,40 @@ +package racingcar.domain; + +public class Car { + private static final int FORWARD_NUM = 4; + + private Name name; + private Location location; + + public Car(String name) { + this.name = new Name(name); + this.location = new Location(); + } + + public void move(int randomNum) { + if (randomNum >= FORWARD_NUM){ + location.forward(); + } + } + + public boolean isWinner(Location maxLocation){ + return location.equals(maxLocation); + } + + public Location getMaxLocation(Location maxLocation) { + return location.lessThan(maxLocation); + } + + public Name getName(){ + return name; + } + + public Location getLocation() { + return location; + } + + @Override + public String toString() { + return name.toString() + " : " + location.toString(); + } +} diff --git a/src/main/java/racingcar/domain/Cars.java b/src/main/java/racingcar/domain/Cars.java new file mode 100644 index 0000000..23285b4 --- /dev/null +++ b/src/main/java/racingcar/domain/Cars.java @@ -0,0 +1,57 @@ +package racingcar.domain; + +import racingcar.exception.CarException; +import racingcar.exception.messages.ErrorMessages; +import racingcar.util.RacingCarUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class Cars { + private final List cars; + + public Cars(String carNameStr) { + this.cars = new ArrayList<>(); + createCar(carNameStr); + } + + public void createCar(String carNameStr) { + String[] carNames = RacingCarUtil.splitName(carNameStr); + + for (String carName : carNames){ + if(!Name.isNameLengthLessThanFive(carName)){ + throw new CarException(ErrorMessages.CAR_NAME_OVER_FIVE); + } + cars.add(new Car(carName)); + } + } + + public String getWinnerName(){ + Location maxLocation = getMaxLocation(); + + return cars.stream() + .filter(car -> car.isWinner(maxLocation)) + .map(car -> car.getName().toString()) + .collect(Collectors.joining(", ")); + + } + + public Location getMaxLocation(){ + Location maxLocation = new Location(); + + for(Car car : cars){ + maxLocation = car.getMaxLocation(maxLocation); + } + + return maxLocation; + + } + + public List getCars(){ + return List.copyOf(cars); + } + + + +} diff --git a/src/main/java/racingcar/domain/Location.java b/src/main/java/racingcar/domain/Location.java new file mode 100644 index 0000000..673929e --- /dev/null +++ b/src/main/java/racingcar/domain/Location.java @@ -0,0 +1,44 @@ +package racingcar.domain; + +import java.util.Objects; + +public class Location { + private int location; + + public Location(){ + this.location = 0; + } + + public Location(int location){ + this.location = location; + } + + public void forward(){ + location++; + } + + public Location lessThan(Location maxLocation) { + if (location > maxLocation.location){ + return this; + } + return maxLocation; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Location location1 = (Location) o; + return location == location1.location; + } + + @Override + public int hashCode() { + return Objects.hashCode(location); + } + + @Override + public String toString() { + return "-".repeat(location); + } +} diff --git a/src/main/java/racingcar/domain/Name.java b/src/main/java/racingcar/domain/Name.java new file mode 100644 index 0000000..0e9f1db --- /dev/null +++ b/src/main/java/racingcar/domain/Name.java @@ -0,0 +1,35 @@ +package racingcar.domain; + +import java.util.Objects; + +public class Name { + private static final int CAR_NAME_MAX = 5; + + private String name; + + public Name(String name){ + this.name = name; + } + + public static boolean isNameLengthLessThanFive(String name) { + return name.length() < CAR_NAME_MAX; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Name name1 = (Name) o; + return Objects.equals(name, name1.name); + } + + @Override + public int hashCode() { + return Objects.hashCode(name); + } + + @Override + public String toString() { + return name; + } +} diff --git a/src/main/java/racingcar/domain/Race.java b/src/main/java/racingcar/domain/Race.java new file mode 100644 index 0000000..5f8b2f6 --- /dev/null +++ b/src/main/java/racingcar/domain/Race.java @@ -0,0 +1,32 @@ +package racingcar.domain; + +import racingcar.util.RacingCarUtil; +import racingcar.view.RaceResult; + +public class Race { + private final Cars cars; + private final int repeatNum; + private final RaceResult raceResult; + + public Race(Cars cars, int repeatNum){ + this.cars = cars; + this.repeatNum = repeatNum; + this.raceResult = new RaceResult(cars); + } + + public RaceResult raceStart(){ + for(int i=0; i response = cars.getCars(); + + // then + assertThat(response.size()).isEqualTo(2); + assertThat(response).extracting(Car::getName).contains(red, blue); + } + + @Test + @DisplayName("자동차 이름이 5자 초과로 예외 발생") + void createCar_exception(){ + // given, when + CarException fail = assertThrows(CarException.class, () -> new Cars("red, blue, green")); + + // then + assertThat(fail.getMessage()).isEqualTo(ErrorMessages.CAR_NAME_OVER_FIVE); + + } + + + @Test + @DisplayName("우승자 이름 반환") + void getWinnerName(){ + // given + Cars cars = new Cars("red,blue,pink"); + + Car car1 = cars.getCars().get(0); + car1.move(4); + Car car2 = cars.getCars().get(1); + car2.move(4); + + // when + String response = cars.getWinnerName(); + + // then + assertThat(response).isEqualTo(car1.getName().toString()+ ", " + car2.getName().toString()); + } + + @Test + @DisplayName("레이싱 가장 큰 위치 반환") + void getMaxLocation(){ + // given + Cars cars = new Cars("red,blue,pink"); + Car car = cars.getCars().get(0); + car.move(4); + car.move(4); + + // when + Location response = cars.getMaxLocation(); + + // then + assertThat(response).isEqualTo(car.getLocation()); + } + + @Test + @DisplayName("자동차 리스트에 객체 추가 시도로 에러 발생") + void getCars(){ + Cars cars = new Cars("red,blue,pink"); + + assertThrows(UnsupportedOperationException.class, () -> cars.getCars().add(new Car("test"))); + } + + + +} diff --git a/src/test/java/racingcar/domain/LocationTest.java b/src/test/java/racingcar/domain/LocationTest.java new file mode 100644 index 0000000..fcc9545 --- /dev/null +++ b/src/test/java/racingcar/domain/LocationTest.java @@ -0,0 +1,43 @@ +package racingcar.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class LocationTest { + + @Test + @DisplayName("Location 비교") + void lessThan(){ + // given + Location maxLocation = new Location(3); + Location lessLocation = new Location(2); + + // when + Location response = lessLocation.lessThan(maxLocation); + + // then + assertThat(response).isEqualTo(maxLocation); + } + + @Test + @DisplayName("자동차 이름이 5글자가 넘지 않아 true 반환") + void isNameLengthLessThanFive_true(){ + // given, when + boolean response = Name.isNameLengthLessThanFive("blue"); + + // then + assertThat(response).isTrue(); + } + + @Test + @DisplayName("자동차 이름이 5글자가 넘어 false 반환") + void isNameLengthLessThanFive_false(){ + // given, when + boolean response = Name.isNameLengthLessThanFive("green"); + + // then + assertThat(response).isFalse(); + } +} \ No newline at end of file diff --git a/src/test/java/racingcar/util/RacingCarUtilTest.java b/src/test/java/racingcar/util/RacingCarUtilTest.java new file mode 100644 index 0000000..092f12b --- /dev/null +++ b/src/test/java/racingcar/util/RacingCarUtilTest.java @@ -0,0 +1,51 @@ +package racingcar.util; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class RacingCarUtilTest { + + @RepeatedTest(10) + @DisplayName("랜덤 값 생성") + void createRandomNumber(){ + // given, when + int response = RacingCarUtil.createRandomNumber(); + + // then + assertTrue(response > 0); + assertTrue(response < 10); + } + + @Test + @DisplayName("문자열 쉼표 기준으로 분리") + void splitName(){ + // given, when + String[] response = RacingCarUtil.splitName("red,blue,pink"); + + assertThat(response).isEqualTo(new String[]{"red", "blue", "pink"}); + } + + @Test + @DisplayName("문자열 쉼표 기준으로 분리 시 공백 포함되어 있는 경우") + void splitNameContainsSpace(){ + // given, when + String[] response = RacingCarUtil.splitName("red, blue,pink"); + + assertThat(response).isEqualTo(new String[]{"red", "blue", "pink"}); + } + + @Test + @DisplayName("문자열 쉼표 기준으로 분리 시 쉼표 없는 경우") + void splitNameNotContainsComma(){ + // given, when + String[] response = RacingCarUtil.splitName("racingCar^^"); + + assertThat(response).isEqualTo(new String[]{"racingCar^^"}); + } + +}