diff --git a/README.md b/README.md index 491aece1..af5e8b1a 100644 --- a/README.md +++ b/README.md @@ -1 +1,36 @@ -# java-racingcar-precourse \ No newline at end of file +# 자동차 경주 게임 + +## 기능 요구 사항 +- 주어진 횟수 동안 n대의 자동차는 전진 또는 멈출 수 있다. +- 각 자동차에 이름을 부여할 수 있다. +- 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다. +- 자동차 이름은 쉼표(,)를 기준으로 구분하며 이름은 5자 이하만 가능하다. +- 사용자는 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다. +- 전진하는 조건은 0에서 9 사이에서 무작위 값을 구한 후 무작위 값이 4 이상일 경우이다. +- 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한 명 이상일 수 있다. +- 우승자가 여러 명일 경우 쉼표(,)를 이용하여 구분한다. +- 사용자가 잘못된 값을 입력할 경우 를 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다. + - Exception이 아닌 IllegalArgumentException , IllegalStateException 등과 같은 명확한 유형을 처리한다. + +## 구현 기능 +### Model +* Car + * 이름 및 위치 정보 보유 + * 자동차 전진 +* Race + * 차량 정보 보유 + * 경주 진행 + +### View +* Input + * 자동차 이름 입력 및 검증 + * 시도 회수 입력 및 검증 +* Output + * 경주 결과 출력 + * 우승자 출력 + +### Controller +* Controller + * Car 생성 + * 경주 정보 설정 + * 게임 시작 diff --git a/src/main/java/Application.java b/src/main/java/Application.java new file mode 100644 index 00000000..fcf195be --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,9 @@ +import controller.Controller; + +public class Application { + private static final Controller controller = new Controller(); + + public static void main(String[] args) { + controller.play(); + } +} diff --git a/src/main/java/controller/Controller.java b/src/main/java/controller/Controller.java new file mode 100644 index 00000000..1d769c5f --- /dev/null +++ b/src/main/java/controller/Controller.java @@ -0,0 +1,34 @@ +package controller; + +import java.util.ArrayList; +import java.util.List; +import model.Car; +import model.Race; +import view.Input; +import view.Output; + +public class Controller { + private List createCars() { + while (true) { + try { + String[] names = Input.getCarName(); + List cars = new ArrayList<>(); + for (String carName : names) { + cars.add(new Car(carName)); + } + return cars; + } catch (IllegalArgumentException e){ + System.out.println("[ERROR] " + e.getMessage()); + } + } + } + + public void play() { + List cars = createCars(); + int round = Input.getRound(); + Race race = new Race(cars, round); + + race.start(); + Output.printWinner(race.getWinner()); + } +} diff --git a/src/main/java/model/Car.java b/src/main/java/model/Car.java new file mode 100644 index 00000000..54d513b1 --- /dev/null +++ b/src/main/java/model/Car.java @@ -0,0 +1,29 @@ +package model; + +public class Car { + final private String name; + private int pos; + + public Car(String name) { + if (5 < name.length()) { + throw new IllegalArgumentException("차의 이름은 5글자 이하여야 합니다"); + } + this.name = name; + this.pos = 0; + } + + public String getName() { + return name; + } + + public int getPos() { + return pos; + } + + public void move() { + int randomNumber = (int)(Math.random() * 10); + if (4 <= randomNumber) { + pos++; + } + } +} diff --git a/src/main/java/model/Race.java b/src/main/java/model/Race.java new file mode 100644 index 00000000..4329c9d1 --- /dev/null +++ b/src/main/java/model/Race.java @@ -0,0 +1,38 @@ +package model; + +import java.util.List; +import java.util.ArrayList; +import view.Output; + +public class Race { + private final List cars; + private final int move; + + public Race(List cars, int move) { + this.cars = cars; + this.move = move; + } + + public void start(){ + for(int i = 0; i < move; i++) { + for (Car car : cars) { + car.move(); + } + Output.printResult(cars); + } + } + + public List getWinner() { + int max = 0; + for (Car car : cars) { + max = Math.max(max, car.getPos()); + } + List winners = new ArrayList<>(); + for (Car car : cars) { + if (car.getPos() == max) { + winners.add(car.getName()); + } + } + return winners; + } +} diff --git a/src/main/java/view/Input.java b/src/main/java/view/Input.java new file mode 100644 index 00000000..07c4ab6e --- /dev/null +++ b/src/main/java/view/Input.java @@ -0,0 +1,27 @@ +package view; + +import java.util.Scanner; + +public class Input { + private static final Scanner sc = new Scanner(System.in); + + public static String[] getCarName() { + System.out.println("경주할 자동차 이름을 입력하세요. (이름은 쉼표(,) 기준으로 구분)"); + return sc.nextLine().split(","); + } + + public static int getRound() { + while (true) { + try { + System.out.println("시도할 회수는 몇회인가요?"); + int round = Integer.parseInt(sc.nextLine()); + if (round <= 0) { + throw new IllegalArgumentException("시도 회수는 양의 정수여야 합니다"); + } + return round; + } catch (IllegalArgumentException e) { + System.out.println("[ERROR] " + e.getMessage()); + } + } + } +} diff --git a/src/main/java/view/Output.java b/src/main/java/view/Output.java new file mode 100644 index 00000000..054c1ee7 --- /dev/null +++ b/src/main/java/view/Output.java @@ -0,0 +1,17 @@ +package view; + +import java.util.List; +import model.Car; + +public class Output { + public static void printResult(List cars) { + for (Car car : cars) { + System.out.println(car.getName() + " : " + "-".repeat(car.getPos())); + } + System.out.println(); + } + + public static void printWinner(List winner) { + System.out.println("최종 우승자 : " + String.join(",", winner)); + } +} diff --git a/src/test/java/CarTest.java b/src/test/java/CarTest.java new file mode 100644 index 00000000..88b03294 --- /dev/null +++ b/src/test/java/CarTest.java @@ -0,0 +1,24 @@ +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import model.Car; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class CarTest { + @Test + @DisplayName("차량 이름 검증 테스트") + void carNameLengthTest() { + assertThatThrownBy(() -> new Car("testLongName")).isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("Car.move() 반복 후 이동 여부 테스트") + void carMoveTest(){ + Car car = new Car("car1"); + for (int i = 0; i < 1000; i++){ + car.move(); + } + assertThat(car.getPos()).isNotZero(); + } +} diff --git a/src/test/java/RaceTest.java b/src/test/java/RaceTest.java new file mode 100644 index 00000000..da89ac44 --- /dev/null +++ b/src/test/java/RaceTest.java @@ -0,0 +1,22 @@ +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import model.Car; +import model.Race; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class RaceTest { + @Test + @DisplayName("레이스 우승자 결과 테스트") + void raceWinnerTest() { + ArrayList cars = new ArrayList() {{ + add(new Car("car1")); + add(new Car("car2")); + }}; + Race race = new Race(cars, 10); + race.start(); + + assertThat(race.getWinner().size()).isNotZero(); + } +}