diff --git a/README.md b/README.md index 491aece1..98f081d5 100644 --- a/README.md +++ b/README.md @@ -1 +1,32 @@ -# java-racingcar-precourse \ No newline at end of file +# java-racingcar-precourse + +## 구현 기능 목록 + +### 자동차의 이름 입력 + + * 이름은 쉼표로 구분하고, 5자 이하만 입력이 가능합니다. + + * 잘못된 입력 시 `IllegalArgumentException`이 발생하고 다시 입력을 받습니다. + +### 이동 횟수 입력 + + * 사용자는 몇 번 이동할 것인지 횟수를 입력 합니다. + + * 마찬가지로 잘못된 입력 시 `IllegalArgumentException`이 발생하고 다시 입력을 받습니다. + +### 난수 생성 + + * 0부터 9까지의 무작위 수를 생성합니다. + +### 자동차 앞으로 전진 + + * 생성된 난수가 4 이상일 시 한 칸 전진합니다. + + * 전진이 끝나면 진행 결과를 출력합니다. + * 이 과정은 사용자로부터 입력 받은 이동 횟수만큼 반복됩니다. + +### 완주 및 우승자 판단 + + * 가장 많이 전진한 자동차가 우승자로 선정됩니다. + + * 최종 우승자를 출력합니다. diff --git a/src/main/java/RacingCarApplication.java b/src/main/java/RacingCarApplication.java new file mode 100644 index 00000000..98b31bb4 --- /dev/null +++ b/src/main/java/RacingCarApplication.java @@ -0,0 +1,10 @@ +import controller.RacingCarController; + +public class RacingCarApplication { + + public static void main(String[] args) { + RacingCarController controller = new RacingCarController(); + controller.startGame(); + } + +} diff --git a/src/main/java/controller/RacingCarController.java b/src/main/java/controller/RacingCarController.java new file mode 100644 index 00000000..6d2ead19 --- /dev/null +++ b/src/main/java/controller/RacingCarController.java @@ -0,0 +1,31 @@ +package controller; + +import java.util.List; +import model.Car; +import model.RacingCarGame; +import view.InputView; +import view.OutputView; + +public class RacingCarController { + + private final InputView inputView = new InputView(); + private final OutputView outputView = new OutputView(); + + public void startGame() { + String[] carNames = inputView.inputCarNames(); + int movementCount = inputView.inputMovementCount(); + + RacingCarGame game = new RacingCarGame(carNames); + + outputView.printResultMessage(); + for (int i = 0; i < movementCount; i++) { + outputView.printProgress(game.playOneRound()); + } + + List winnerCarNames = game.judgeWinners().stream() + .map(Car::getCarName) + .toList(); + outputView.printWinners(winnerCarNames); + } + +} diff --git a/src/main/java/model/Car.java b/src/main/java/model/Car.java new file mode 100644 index 00000000..fa6dceca --- /dev/null +++ b/src/main/java/model/Car.java @@ -0,0 +1,26 @@ +package model; + +public class Car { + + private final String carName; + private int position = 0; + + public Car(String name) { + this.carName = name; + } + + public void move(int randomNumber) { + if (randomNumber >= 4) { + position += 1; + } + } + + public String getCarName() { + return carName; + } + + public int getPosition() { + return position; + } + +} diff --git a/src/main/java/model/RacingCarGame.java b/src/main/java/model/RacingCarGame.java new file mode 100644 index 00000000..5c831471 --- /dev/null +++ b/src/main/java/model/RacingCarGame.java @@ -0,0 +1,39 @@ +package model; + +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; +import util.RandomNumberGenerator; + +public class RacingCarGame { + + private final List cars = new ArrayList<>(); + + private final RandomNumberGenerator generator = new RandomNumberGenerator();; + + public RacingCarGame(String[] carNames) { + for (String carName : carNames) { + cars.add(new Car(carName)); + } + } + + public List playOneRound() { + for (Car car : cars) { + car.move(generator.generateRandomNumber()); + } + + return cars; + } + + public List judgeWinners() { + int winnerPosition = cars.stream() + .mapToInt(Car::getPosition) + .max() + .orElseThrow(NoSuchElementException::new); + + return cars.stream() + .filter(car -> car.getPosition() == winnerPosition) + .toList(); + } + +} diff --git a/src/main/java/util/RandomNumberGenerator.java b/src/main/java/util/RandomNumberGenerator.java new file mode 100644 index 00000000..074b36e8 --- /dev/null +++ b/src/main/java/util/RandomNumberGenerator.java @@ -0,0 +1,13 @@ +package util; + +import java.util.Random; + +public class RandomNumberGenerator { + + private final Random random = new Random(); + + public int generateRandomNumber() { + return random.nextInt(10); + } + +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 00000000..5e5eb927 --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,51 @@ +package view; + +import java.util.Scanner; + +public class InputView { + + private final Scanner scanner = new Scanner(System.in); + + public String[] inputCarNames() { + String[] carNames = null; + boolean isValid = false; + + while(!isValid) { + System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"); + carNames = scanner.nextLine().split(","); + + isValid = isValidCarNames(carNames); + } + + return carNames; + } + + public int inputMovementCount() { + System.out.println("시도할 횟수는 몇회인가요?"); + + return scanner.nextInt(); + } + + private boolean isValidCarNames(String[] carNames) { + for (String carName : carNames) { + if(!isValidCarName(carName)) { + return false; + } + } + return true; + } + + private boolean isValidCarName(String carName) { + try { + if (carName.length() > 5) { + throw new IllegalArgumentException("[ERROR] 자동차 이름은 5자 이하만 입력이 가능합니다."); + } + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + + return false; + } + return true; + } + +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 00000000..99beca91 --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,24 @@ +package view; + +import java.util.List; +import model.Car; + +public class OutputView { + + public void printResultMessage() { + System.out.println(); + System.out.println("실행 결과"); + } + + public void printProgress(List cars) { + for (Car car : cars) { + System.out.println(car.getCarName() + " : " + "-".repeat(car.getPosition())); + } + System.out.println(); + } + + public void printWinners(List carNames) { + System.out.print("최종 우승자 : " + String.join(", ", carNames)); + } + +} diff --git a/src/test/java/model/CarTest.java b/src/test/java/model/CarTest.java new file mode 100644 index 00000000..b3817467 --- /dev/null +++ b/src/test/java/model/CarTest.java @@ -0,0 +1,36 @@ +package model; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class CarTest { + + @DisplayName("자동차를 앞으로 한 칸 전진시킨다.") + @Test + void move() throws Exception { + //given + Car car = new Car("kia"); + + //when + car.move(7); + + //then + assertThat(car.getPosition()).isEqualTo(1); + } + + @DisplayName("자동차를 앞으로 한 칸 전진 시키는데, 주어진 난수가 4 미만이면 전진하지 않는다.") + @Test + void moveWithRandomNumberLessThanFour() throws Exception { + //given + Car car = new Car("kia"); + + //when + car.move(3); + + //then + assertThat(car.getPosition()).isEqualTo(0); + } + +} diff --git a/src/test/java/model/RacingCarGameTest.java b/src/test/java/model/RacingCarGameTest.java new file mode 100644 index 00000000..6a228d39 --- /dev/null +++ b/src/test/java/model/RacingCarGameTest.java @@ -0,0 +1,25 @@ +package model; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class RacingCarGameTest { + + @DisplayName("우승자를 판단하고, 우승자 목록을 반환한다.") + @Test + void judgeWinners() throws Exception { + //given + String[] carNames = {"kia", "good", "test", "hyu"}; + RacingCarGame racingCarGame = new RacingCarGame(carNames); + + //when + List winners = racingCarGame.judgeWinners(); + + //then -> 전진 없이 모두가 같은 위치이므로 모두가 우승자 + assertThat(winners.size()).isEqualTo(carNames.length); + } + +} diff --git a/src/test/java/util/RandomNumberGeneratorTest.java b/src/test/java/util/RandomNumberGeneratorTest.java new file mode 100644 index 00000000..e2c4dc75 --- /dev/null +++ b/src/test/java/util/RandomNumberGeneratorTest.java @@ -0,0 +1,23 @@ +package util; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class RandomNumberGeneratorTest { + + @DisplayName("0부터 9까지 무작위 수를 생성한다.") + @Test + void generateRandomNumber() throws Exception { + //given + RandomNumberGenerator generator = new RandomNumberGenerator(); + + //when + int randomNumber = generator.generateRandomNumber(); + + //then + assertThat(randomNumber).isBetween(0, 9); + } + +}