diff --git a/src/main/java/car/Car.java b/src/main/java/car/Car.java new file mode 100644 index 000000000..2b5e4b13a --- /dev/null +++ b/src/main/java/car/Car.java @@ -0,0 +1,25 @@ +package car; + +public class Car { + private int location; // 초기값은 0 (primitive) + private final String name; + public Car(String name) { + if (name.length() > 5) throw new IllegalArgumentException(); + this.name = name; + } + public String getName() { + return this.name; + } + + public int getLocation() { + return location; + } + + public void move() { + this.location++; + } + + public void moveByStrategy(int digit, MoveStrategy moveStrategy) { + if (moveStrategy.move(digit)) this.move(); + } +} diff --git a/src/main/java/car/Cars.java b/src/main/java/car/Cars.java new file mode 100644 index 000000000..3871a29d8 --- /dev/null +++ b/src/main/java/car/Cars.java @@ -0,0 +1,44 @@ +package car; + +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.stream.Collectors; + +public class Cars { + private final List cars; + private final Random random = new Random(); // reusable + public Cars(String carNames) { + this.cars = initCarByNames(carNames); + } + + private List initCarByNames(String carNames) { + return Arrays.stream(carNames.split(",")) + .map(String::trim) + .map(Car::new) + .collect(Collectors.toList()); + } + + public List getCarNames() { + return cars.stream().map(Car::getName).collect(Collectors.toList()); + } + + public void moveForTest(int digit){ + cars.forEach(car -> car.moveByStrategy(digit, value -> value >= 5)); + } + + public void move(){ + cars.forEach(car -> car.moveByStrategy(random.nextInt(10), value -> value >= 5)); + } + + public int getLocationByCarName(String carName) { + return cars.stream().filter(car -> car.getName().equals(carName)).map(Car::getLocation).findFirst().orElseThrow( + () -> new IllegalArgumentException("그런 차는 없다") + ); + } + + public List getWinnersNames() { + int maxLocation = cars.stream().mapToInt(Car::getLocation).max().orElse(0); + return cars.stream().filter(car -> car.getLocation() == maxLocation).map(Car::getName).collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/src/main/java/car/Main.java b/src/main/java/car/Main.java new file mode 100644 index 000000000..3b87abbb1 --- /dev/null +++ b/src/main/java/car/Main.java @@ -0,0 +1,15 @@ +package car; + +import view.InputView; +import view.OutputView; + +import java.io.IOException; + +public class Main { + public static void main(String[] args) throws IOException { + InputView inputView = new InputView(); + OutputView outputView = new OutputView(); + RacingGame racingGame = new RacingGame(inputView, outputView); + racingGame.game(); + } +} diff --git a/src/main/java/car/MoveStrategy.java b/src/main/java/car/MoveStrategy.java new file mode 100644 index 000000000..6ad99ee7b --- /dev/null +++ b/src/main/java/car/MoveStrategy.java @@ -0,0 +1,5 @@ +package car; +@FunctionalInterface +public interface MoveStrategy { + boolean move(int value); +} diff --git a/src/main/java/car/RacingGame.java b/src/main/java/car/RacingGame.java new file mode 100644 index 000000000..c0fda9ae2 --- /dev/null +++ b/src/main/java/car/RacingGame.java @@ -0,0 +1,29 @@ +package car; + +import view.InputView; +import view.OutputView; + +import java.io.IOException; + +public class RacingGame { + private final InputView inputView; + private final OutputView outputView; + + public RacingGame(InputView inputView, OutputView outputView) { + this.inputView = inputView; + this.outputView = outputView; + } + + public void game() throws IOException { + outputView.inputName(); + String names = inputView.getInput(); + Cars cars = new Cars(names); + outputView.getTrial(); + int trial = inputView.getNumericInput(); + for (int integer = 0; integer < trial; integer++) { + cars.move(); + outputView.printLocations(cars); + } + outputView.printWinners(cars); + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 000000000..c7951179e --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,17 @@ +package view; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class InputView { + private final BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + public String getInput() throws IOException { + return br.readLine(); + } + + public Integer getNumericInput() throws IOException { + return Integer.parseInt(br.readLine()); + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 000000000..6b330e7cc --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,47 @@ +package view; + +import car.Cars; + +import java.util.List; + +public class OutputView { + private static final String INPUT_NAMES = "경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분)."; + private static final String INPUT_TRIALS = "시도할 회수는 몇회인가요?"; + private static final String IS_WINNER = "가 최종 우승했습니다."; + private static final String LOCATION_EXPRESSION = "-"; + public void inputName(){ + System.out.println(INPUT_NAMES); + } + + public void getTrial(){ + System.out.println(INPUT_TRIALS); + } + + public void printLocations(Cars cars){ + List carNames = cars.getCarNames(); + for (String carName : carNames) { + System.out.println(carName + ":"+ intToMinus(cars.getLocationByCarName(carName))); + } + } + + public void printWinners(Cars cars){ + List winners = cars.getWinnersNames(); + if (winners.size() == 1){ + System.out.println(winners.get(0) + IS_WINNER); + } + if (winners.size() > 1){ + StringBuilder sb = new StringBuilder(); + sb.append(String.join(", ", winners)); + sb.append(IS_WINNER); + System.out.println(sb); + } + } + + private String intToMinus(int location){ + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < location; i++) { + sb.append(LOCATION_EXPRESSION); + } + return sb.toString(); + } +} \ No newline at end of file diff --git a/src/test/java/CarTest.java b/src/test/java/CarTest.java new file mode 100644 index 000000000..c1751bff6 --- /dev/null +++ b/src/test/java/CarTest.java @@ -0,0 +1,55 @@ +import car.Car; +import car.Cars; +import com.sun.tools.javac.util.List; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.*; + +class CarTest { + //## **기능 요구사항** + // + //- 각 자동차에 이름을 부여할 수 있다. **자동차 이름은 5자를 초과**할 수 없다. + //- 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다. + //- 자동차 이름은 쉼표(,)를 기준으로 구분한다. + //- 전진하는 조건은 0에서 9 사이에서 random 값을 구한 후 random 값이 4이상일 경우이다. + //- **자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한명 이상일 수 있다.** + @Test + void carNameTest() { + String name = "car"; + Car car = new Car(name); + assertThat(car.getName()).isEqualTo(name); + } + + @Test + void invalid_car_name_test() { + String name = "more than 5 words"; + assertThatThrownBy(() -> new Car(name)).isInstanceOf(IllegalArgumentException.class); + } + + @Test + void carsTest() { + String carNames = "car1, car2, car3"; // , 기준 split 및 trim 필요 + Cars cars = new Cars(carNames); + assertThat(cars.getCarNames()).isEqualTo(List.of("car1", "car2", "car3")); + } + + @Test + void invalid_cars_name_test() { + String carNames = "less, MoreThan5word, thisIsMoreThan5"; + assertThatThrownBy(() -> new Cars(carNames)).isInstanceOf(IllegalArgumentException.class); + } + + @Test + void justOneCarTest() { + String carNames = "car1"; + Cars cars = new Cars(carNames); + assertThat(cars.getCarNames()).isEqualTo(List.of("car1")); + } + + @Test + void moveTest(){ + Cars cars = new Cars("car1, car2"); + cars.moveForTest(5); + assertThat(cars.getLocationByCarName("car1")).isEqualTo(1); + } +} \ No newline at end of file diff --git a/src/test/java/MovingStrategyTest.java b/src/test/java/MovingStrategyTest.java new file mode 100644 index 000000000..5574a313a --- /dev/null +++ b/src/test/java/MovingStrategyTest.java @@ -0,0 +1,30 @@ +import car.Car; +import car.MoveStrategy; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class MovingStrategyTest { + //- 전진하는 조건은 0에서 9 사이에서 random 값을 구한 후 random 값이 4이상일 경우이다. + private Car car; + + @BeforeEach + void initCar(){ + car = new Car("name"); + } + @Test + void simple_move_test() { + car.move(); + assertThat(car.getLocation()).isOne(); + } + + @Test + void moveByStrategyTest(){ + car.moveByStrategy(3, value -> value >= 5); + assertThat(car.getLocation()).isZero(); + + car.moveByStrategy(9, value -> value > 5); + assertThat(car.getLocation()).isOne(); + } +}