diff --git a/README.md b/README.md index d0286c8..04ce620 100644 --- a/README.md +++ b/README.md @@ -1 +1,89 @@ -# java-racingcar-precourse +# 2주차 미션 : 자동차 경주 +
+ 과제 세부 내용 + +## 과제 +- 초간단 자동차 경주 게임을 구현한다. + - 주어진 횟수 동안 n대의 자동차는 전진 또는 멈출 수 있다. + - 각 자동차에 이름을 부여할 수 있다. 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다. + - 자동차 이름은 쉼표(,)를 기준으로 구분하며 이름은 5자 이하만 가능하다. + - 사용자는 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다. + - 전진하는 조건은 0에서 9 사이에서 무작위 값을 구한 후 무작위 값이 4 이상일 경우이다. + - 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한 명 이상일 수 있다. + - 우승자가 여러 명일 경우 쉼표(,)를 이용하여 구분한다. + - 사용자가 잘못된 값을 입력할 경우 `IllegalArgumentException`을 발생시킨 후 애플리케이션은 종료되어야 한다. +### 입출력 +- 경주 할 자동차 이름(이름은 쉽표(,) 기준으로 구분) + + pobi,woni,jun + +- 시도할 횟수 + + 5 + +- 각 차수별 실행 결과 + + pobi : -- + woni : ---- + jun : --- + +- 단독 우승자 안내 문구 + + 최종 우승자 : pobi + +- 공동 우승자 안내 문구 + + 최종 우승자 : pobi, jun + +### 실행 결과 예시 + 경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분) + pobi,woni,jun + 시도할 회수는 몇회인가요? + 5 + + 실행 결과 + pobi : - + woni : + jun : - + + pobi : -- + woni : - + jun : -- + + pobi : --- + woni : -- + jun : --- + + pobi : ---- + woni : --- + jun : ---- + + pobi : ----- + woni : ---- + jun : ----- + + 최종 우승자 : pobi, jun + +
+ +## 구현할 기능 목록 +### Model + Car() // Class + - name + - count + - getName() + - getCount() + - forward() + - printResult() +### Service + - sliceName() + - getWinner() + - checkInput() +### View + - input() + - inputTimes() + - interimTally() + - outputResult() + - output() +### Controller + - startRace() \ No newline at end of file diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java index a17a52e..964db17 100644 --- a/src/main/java/racingcar/Application.java +++ b/src/main/java/racingcar/Application.java @@ -1,7 +1,9 @@ package racingcar; +import racingcar.controller.RaceController; + public class Application { public static void main(String[] args) { - // TODO: 프로그램 구현 + RaceController.startRace(); } } diff --git a/src/main/java/racingcar/controller/RaceController.java b/src/main/java/racingcar/controller/RaceController.java new file mode 100644 index 0000000..d8a2931 --- /dev/null +++ b/src/main/java/racingcar/controller/RaceController.java @@ -0,0 +1,26 @@ +package racingcar.controller; + +import racingcar.model.Car; +import racingcar.service.CheckInput; +import racingcar.service.GetWinner; +import racingcar.service.SliceName; +import racingcar.view.RaceView; + +import java.util.List; + +public class RaceController { + public static void startRace() { + String p = RaceView.inputCars(); + int times = CheckInput.checkNumber(RaceView.inputTimes()); + + List participant = CheckInput.checkName(p); + + for (String s : participant) { + Car.cars.add(new Car(s)); + } + + RaceView.outputResult(times); + + RaceView.outputWinner(GetWinner.getWinner(Car.cars.stream(), GetWinner.getMax(Car.cars.stream()))); + } +} diff --git a/src/main/java/racingcar/model/Car.java b/src/main/java/racingcar/model/Car.java new file mode 100644 index 0000000..e701b8e --- /dev/null +++ b/src/main/java/racingcar/model/Car.java @@ -0,0 +1,36 @@ +package racingcar.model; + +import camp.nextstep.edu.missionutils.Randoms; + +import java.util.ArrayList; +import java.util.List; + +public class Car { + public static List cars = new ArrayList<>(); + + String name; + int count; + + public Car(String name) { + this.name = name; + this.count = 0; + } + + public String getName() { + return name; + } + + public int getCount() { + return count; + } + + public void forward() { + if (Randoms.pickNumberInRange(0, 9) >= 4) { + count++; + } + } + + public void printResult() { + System.out.println(name + " : " + "-".repeat(count)); + } +} diff --git a/src/main/java/racingcar/service/CheckInput.java b/src/main/java/racingcar/service/CheckInput.java new file mode 100644 index 0000000..6d4aa25 --- /dev/null +++ b/src/main/java/racingcar/service/CheckInput.java @@ -0,0 +1,35 @@ +package racingcar.service; + +import java.util.List; +import java.util.regex.Pattern; + +public class CheckInput { + public static List checkName(String s) { + if (s.isEmpty()) throw new IllegalArgumentException("자동차 이름들이 비어있습니다."); + + if (s.split(",").length < 2) throw new IllegalArgumentException("자동차 이름이 부족하거나 구분자가 없습니다."); + + List l = SliceName.slice(s); + + for (String p : l) { + if (Pattern.matches("\\s+", p)) throw new IllegalArgumentException("자동차 이름이 비어있습니다."); + if (p.length() > 5) throw new IllegalArgumentException("자동차 이름이 5자 초과입니다."); + } + + return l; + } + + public static int checkNumber(String s) { + if (s.isEmpty()) throw new IllegalArgumentException("횟수값이 비어있습니다."); + + try { + Integer.parseInt(s); + }catch (NumberFormatException e) { + throw new IllegalArgumentException("횟수값이 숫자가 아니거나 너무 많습니다."); + } + + if (Integer.parseInt(s) <= 0) throw new IllegalArgumentException("횟수값이 양수가 아닙니다."); + + return Integer.parseInt(s); + } +} diff --git a/src/main/java/racingcar/service/GetWinner.java b/src/main/java/racingcar/service/GetWinner.java new file mode 100644 index 0000000..799e26e --- /dev/null +++ b/src/main/java/racingcar/service/GetWinner.java @@ -0,0 +1,17 @@ +package racingcar.service; + +import racingcar.model.Car; + +import java.util.List; +import java.util.stream.Stream; + +public class GetWinner { + public static int getMax(Stream c) { + return c.map(Car::getCount).max(Integer::compare).get(); + } + + public static String getWinner(Stream c, int max) { + List result = c.filter(car -> car.getCount() == max).map(Car::getName).toList(); + return String.join(", ", result); + } +} diff --git a/src/main/java/racingcar/service/SliceName.java b/src/main/java/racingcar/service/SliceName.java new file mode 100644 index 0000000..a6a32ed --- /dev/null +++ b/src/main/java/racingcar/service/SliceName.java @@ -0,0 +1,10 @@ +package racingcar.service; + +import java.util.Arrays; +import java.util.List; + +public class SliceName { + public static List slice(String s) { + return Arrays.asList(s.split(",")); + } +} diff --git a/src/main/java/racingcar/view/RaceView.java b/src/main/java/racingcar/view/RaceView.java new file mode 100644 index 0000000..e0f297e --- /dev/null +++ b/src/main/java/racingcar/view/RaceView.java @@ -0,0 +1,36 @@ +package racingcar.view; + +import camp.nextstep.edu.missionutils.Console; +import racingcar.model.Car; + +import java.util.List; + +public class RaceView { + public static String inputCars() { + System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"); + return Console.readLine(); + } + public static String inputTimes() { + System.out.println("시도할 회수는 몇회인가요?"); + return Console.readLine(); + } + + public static void interimTally(List c) { + for (Car car : c ) { + car.forward(); + car.printResult(); + } + System.out.println(); + } + + public static void outputResult(int t) { + System.out.println("실행 결과"); + for (int i = 0; i < t; i++) { + RaceView.interimTally(Car.cars); + } + } + + public static void outputWinner(String winner) { + System.out.println("최종 우승자 : " + winner); + } +} diff --git a/src/test/java/racingcar/ApplicationTest.java b/src/test/java/racingcar/ApplicationTest.java index 1d35fc3..5a12b44 100644 --- a/src/test/java/racingcar/ApplicationTest.java +++ b/src/test/java/racingcar/ApplicationTest.java @@ -13,7 +13,7 @@ class ApplicationTest extends NsTest { private static final int STOP = 3; @Test - void 기능_테스트() { + void functionTest() { assertRandomNumberInRangeTest( () -> { run("pobi,woni", "1"); @@ -24,10 +24,42 @@ class ApplicationTest extends NsTest { } @Test - void 예외_테스트() { + void isEmpty1() { assertSimpleTest(() -> - assertThatThrownBy(() -> runException("pobi,javaji", "1")) - .isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy(() -> runException("", "1")) + .isInstanceOf(IllegalArgumentException.class) + ); + } + + @Test + void isEmpty2() { + assertSimpleTest(() -> + assertThatThrownBy(() -> runException("pobi,woni", " ")) + .isInstanceOf(IllegalArgumentException.class) + ); + } + + @Test + void isEmpty3() { + assertSimpleTest(() -> + assertThatThrownBy(() -> runException("pobi, ", "1")) + .isInstanceOf(IllegalArgumentException.class) + ); + } + + @Test + void overFlow() { + assertSimpleTest(() -> + assertThatThrownBy(() -> runException("pobi,woni ", "10000000000000000000")) + .isInstanceOf(IllegalArgumentException.class) + ); + } + + @Test + void notPositiveNumber() { + assertSimpleTest(() -> + assertThatThrownBy(() -> runException("pobi,woni ", "-1")) + .isInstanceOf(IllegalArgumentException.class) ); }