diff --git a/src/main/java/RacingMain.java b/src/main/java/RacingMain.java index 4394287..c97a27a 100644 --- a/src/main/java/RacingMain.java +++ b/src/main/java/RacingMain.java @@ -1,7 +1,15 @@ +import controller.RacingController; + +import java.io.IOException; + public class RacingMain { - public static void main(String[] args) { + public static void main(String[] args) throws IOException { // TODO: MVC 패턴을 기반으로 자동차 경주 미션 구현해보기 - System.out.println("Hello, World!"); + + RacingController rcController = new RacingController(); + + rcController.run(); + } } diff --git a/src/main/java/controller/RacingController.java b/src/main/java/controller/RacingController.java new file mode 100644 index 0000000..d77c19a --- /dev/null +++ b/src/main/java/controller/RacingController.java @@ -0,0 +1,43 @@ +package controller; + +import domain.Car; +import domain.Cars; +import domain.TryCount; +import view.InputView; +import view.OutputView; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.List; + +public class RacingController { + + public void run() throws IOException { + // 차량 이름 입력 + Cars cars = new Cars(InputView.setCarName()); + + // 시도 횟수 입력 + TryCount tryCount = new TryCount(InputView.setTryCount()); + + printResult(cars, tryCount); + + findWinner(cars); + } + + // 결과 출력 + public void printResult(Cars cars, TryCount tryCount){ + for (int i = 0; i < tryCount.getTryCount(); i++){ + for (Car car : cars.getCars()){ + car.moveCar(); + } + + OutputView.printRacing(cars.getCars()); + } + } + + public void findWinner(Cars cars){ + OutputView.printWinner(cars.getCars()); + } +} diff --git a/src/main/java/domain/Car.java b/src/main/java/domain/Car.java new file mode 100644 index 0000000..eb501e5 --- /dev/null +++ b/src/main/java/domain/Car.java @@ -0,0 +1,34 @@ +package domain; + +// 자동차 +public class Car { + private static final int RANDOM_MINIMUM = 4; + private final CarName name; + private final CarPosition position; + + // 차량 초기 설정 + public Car(String name){ + this.name = new CarName(name); + this.position = new CarPosition(); + } + + // 차량 이름 반환 + public String getCarName(){ + return name.getCarName(); + } + + // 차량 위치 반환 + public int getCarPosition(){ + return position.getCarPosition(); + } + + // 차량 한칸 이동 (전진) + public void moveCar(){ + int random_number = (int)(Math.random() * 9); + + if (random_number >= RANDOM_MINIMUM){ + position.movePosition(); + } + + } +} diff --git a/src/main/java/domain/CarName.java b/src/main/java/domain/CarName.java new file mode 100644 index 0000000..036553e --- /dev/null +++ b/src/main/java/domain/CarName.java @@ -0,0 +1,16 @@ +package domain; + +public class CarName { + private final String carName; + + public CarName(String name){ + if (name.length() > 5 || name.length() < 1) + throw new IllegalArgumentException("[ERROR]"); + + this.carName = name; + } + + public String getCarName(){ + return carName; + } +} diff --git a/src/main/java/domain/CarPosition.java b/src/main/java/domain/CarPosition.java new file mode 100644 index 0000000..ba7ca2b --- /dev/null +++ b/src/main/java/domain/CarPosition.java @@ -0,0 +1,21 @@ +package domain; + +public class CarPosition { + private static final int START_POSITION = 0; + private int myPosition; + + public CarPosition(){ + // 자동차 초기 위치 설정 + myPosition = START_POSITION; + } + + // 차량 위치 반환 + public int getCarPosition(){ + return myPosition; + } + + // 차량 전진 + public void movePosition(){ + myPosition++; + } +} diff --git a/src/main/java/domain/Cars.java b/src/main/java/domain/Cars.java new file mode 100644 index 0000000..dbcdeab --- /dev/null +++ b/src/main/java/domain/Cars.java @@ -0,0 +1,36 @@ +package domain; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +// 자동차 모음 +public class Cars { + private final List cars; + + public Cars(List carNames){ + cars = new ArrayList<>(); + + createCarList(carNames); + } + + // 차량 리스트 생성 + public void createCarList(List carNames){ + for (String carName : carNames){ + Car car = new Car(carName); + cars.add(car); + } + } + + // 차량 목록 반환 + public List getCars(){ + return cars; + } + + // 차량 목록 이동 + public void moveCars(){ + for (Car car : cars){ + car.moveCar(); + } + } +} diff --git a/src/main/java/domain/TryCount.java b/src/main/java/domain/TryCount.java new file mode 100644 index 0000000..d9a8d3e --- /dev/null +++ b/src/main/java/domain/TryCount.java @@ -0,0 +1,19 @@ +package domain; + +public class TryCount { + private static final int MINIMUM = 1; + private int tryCount; + + // 시도 횟수 + public TryCount(int count){ + if (count < MINIMUM) + throw new IllegalArgumentException("[ERROR]"); + + this.tryCount = count; + } + + // 시도 횟수 반환 + public int getTryCount(){ + return tryCount; + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 0000000..abef62a --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,30 @@ +package view; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.List; + +public class InputView { + private static final BufferedReader br + = new BufferedReader(new InputStreamReader(System.in)); + + // 차량 이름 입력 + public static List setCarName() throws IOException { + System.out.println("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분)."); + + String str = br.readLine(); + + return Arrays.asList(str.split(",")); + } + + // 시도 횟수 입력 + public static int setTryCount() throws IOException { + System.out.println("시도할 회수는 몇회인가요?"); + + String str = br.readLine(); + + return Integer.parseInt(str); + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 0000000..cea8fb9 --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,41 @@ +package view; + +import domain.Car; +import domain.Cars; + +import java.util.ArrayList; +import java.util.List; + +public class OutputView { + + // 결과 출력 + public static void printRacing(List cars){ + for (Car car : cars){ + System.out.print(car.getCarName() + " : "); + for (int i = 0; i < car.getCarPosition(); i++) + System.out.print("-"); + System.out.println(); + } + System.out.println(); + } + + // 우승자 출력 + public static void printWinner(List cars){ + int max = 0; + List winners = new ArrayList<>(); + + for (Car car : cars){ + if (car.getCarPosition() > max) + max = car.getCarPosition(); + } + + for (Car car : cars){ + if (car.getCarPosition() == max) + winners.add(car.getCarName()); + } + + String winnerResult = String.join(", ", winners); + + System.out.println(winnerResult + "가 최종 우승했습니다."); + } +} diff --git a/src/test/java/domain/CarNameTest.java b/src/test/java/domain/CarNameTest.java new file mode 100644 index 0000000..5c463a6 --- /dev/null +++ b/src/test/java/domain/CarNameTest.java @@ -0,0 +1,30 @@ +package domain; + +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.AssertionsForClassTypes.assertThatCode; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + +public class CarNameTest { + @DisplayName("차량 이름은 1~5자 사이여야 한다") + @ParameterizedTest + @CsvSource(value = {"'', 차량 이름이 존재해야 합니다.", + "123456, 차량 이름은 5글자 이하여야 합니다.", + "123456789, 이름은 5글자 이하여야 합니다."}) + + void 이름_예외_발생(String carName, String errorMessage) { + assertThatThrownBy(() -> new CarName(carName)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(errorMessage); + } + + @DisplayName("1~5글자 이름은 유효") + @ParameterizedTest + @CsvSource(value = {"1", "123", "123", "1234"}) + void 유효한_이름(String carName) { + assertThatCode(() -> new CarName(carName)) + .doesNotThrowAnyException(); + } +} diff --git a/src/test/java/domain/CarTest.java b/src/test/java/domain/CarTest.java new file mode 100644 index 0000000..de39bf5 --- /dev/null +++ b/src/test/java/domain/CarTest.java @@ -0,0 +1,23 @@ +package domain; + +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.FactoryBasedNavigableListAssert.assertThat; + +public class CarTest { + @DisplayName("랜덤 숫자가 0~3일 때는 움직이지 않음") + @ParameterizedTest + @CsvSource(value = {"0,0", "1,0", "2,0", "3,0"}) + void 움직이지_않음(int number, int position) { + + } + + @DisplayName("랜덤 숫자가 4~9일 때는 움직임") + @ParameterizedTest + @CsvSource(value = {"4,1", "5,1", "6,1", "7,1", "8,1", "9,1"}) + void 움직임(int number, int distance) { + + } +} diff --git a/src/test/java/domain/CarsTest.java b/src/test/java/domain/CarsTest.java new file mode 100644 index 0000000..28da1dc --- /dev/null +++ b/src/test/java/domain/CarsTest.java @@ -0,0 +1,19 @@ +package domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + +public class CarsTest { + @DisplayName("자동차 이름이 중복되면 예외 처리") + @ParameterizedTest + @CsvSource(value = {"1", "1", "2"}) + void 차량_이름_중복(int size) { + + } +} diff --git a/src/test/java/domain/TryCountTest.java b/src/test/java/domain/TryCountTest.java new file mode 100644 index 0000000..c37eba4 --- /dev/null +++ b/src/test/java/domain/TryCountTest.java @@ -0,0 +1,24 @@ +package domain; + +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.AssertionsForClassTypes.assertThatCode; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + +public class TryCountTest { + @DisplayName("시도 횟수가 양의 정수면 유효") + @ParameterizedTest + @CsvSource(value = {"1", "10", "100", "1000"}) + void 시도_횟수_양수(int number) { + + } + + @DisplayName("시도 횟수가 0 이하 혹은 음수면 예외를 던진다") + @ParameterizedTest + @CsvSource(value = {"0", "-1", "-100", "-1000"}) + void 시도_횟수_음수(int number) { + + } +}