diff --git a/docs/README.md b/docs/README.md index e69de29bb2d..fc0437d6936 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,23 @@ +# 기능 명세서 + +## 자동차 + +- [x] 게임 라운드마다 0-9까지 랜덤 값을 구한다 +- [x] 0부터 3이 나오면 멈추고 4부터 9가 나오면 전진한다 +- [x] 이름을 부여할 수 있다 +- [x] 이름과 거리를 `-`로 출력할 수 있다 + +## 플레이어 + +- [x] 각 자동차에 부여할 이름을 최대 5자까지 입력할 수 있다 + - [x] 이름이 5자 이상 입력된 경우 `IllegalArgumentException`을 발생한다 +- [x] 자동차들이 몇 번의 이동을 할 것 인지 입력할 수 있다 + +## 자동차 경주 게임 + +- [x] 플레이어에게 이름을 입력받으면 받은 수만큼 자동차 객체를 생성한다 +- [x] 플레이어에게 입력받은 라운드 횟수만큼 게임을 실행한다. + - [x] 자동차가 전진 또는 멈춘다. + - [x] 해당 라운드마다 자동차들의 이름과 이동 횟수를 `-`로 출력한다 +- [x] 라운드가 모두 끝나면 최종 우승자를 출력한다 (여러 명일 경우 `,`를 사용해서 모두 출력) + - [x] 모든 라운드 합계 가장 이동한 수가 많은 자동차를 최종 우승자로 선정한다 \ No newline at end of file diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java index a17a52e7242..f67a645a4c2 100644 --- a/src/main/java/racingcar/Application.java +++ b/src/main/java/racingcar/Application.java @@ -1,7 +1,13 @@ package racingcar; +import racingcar.domain.Player; +import racingcar.domain.RacingCarGame; + public class Application { public static void main(String[] args) { // TODO: 프로그램 구현 + Player player = new Player(); + RacingCarGame racingCarGame = new RacingCarGame(player); + racingCarGame.init(); } } diff --git a/src/main/java/racingcar/domain/Player.java b/src/main/java/racingcar/domain/Player.java new file mode 100644 index 00000000000..99786b5193b --- /dev/null +++ b/src/main/java/racingcar/domain/Player.java @@ -0,0 +1,44 @@ +package racingcar.domain; + +import camp.nextstep.edu.missionutils.Console; +import java.util.ArrayList; +import java.util.List; + +public class Player { + public List inputNames() throws IllegalArgumentException { + System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"); + + List names = new ArrayList<>(); + String input = Console.readLine(); + + validateLine(input); + for (String name : input.split(",")) { + validateName(name); + names.add(name); + } + + return names; + } + + private void validateLine(String line) throws IllegalArgumentException { + if (line.substring(line.length() - 1).equals(",")) { + throw new IllegalArgumentException(); + } + } + + private void validateName(String name) throws IllegalArgumentException { + if (name.length() > 5) { + throw new IllegalArgumentException(); + } + } + + public int inputNumberOfRounds() throws IllegalArgumentException { + System.out.println("시도할 회수는 몇회인가요?"); + String input = Console.readLine(); + try { + return Integer.parseInt(input); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(); + } + } +} diff --git a/src/main/java/racingcar/domain/RacingCar.java b/src/main/java/racingcar/domain/RacingCar.java new file mode 100644 index 00000000000..de8d8980a08 --- /dev/null +++ b/src/main/java/racingcar/domain/RacingCar.java @@ -0,0 +1,36 @@ +package racingcar.domain; + +import camp.nextstep.edu.missionutils.Randoms; + +public class RacingCar { + private final String name; + public int randomNumber; + public int distance; + + public RacingCar(String name) { + this.name = name; + } + + private void makeRandomNumber() { + this.randomNumber = Randoms.pickNumberInRange(0, 9); + } + + public void goOrStop() { + makeRandomNumber(); + if (this.randomNumber >= 4) { + this.distance++; + } + } + + public void printDistance() { + System.out.print(this.name + " : "); + for (int i = 0; i < distance; i++) { + System.out.print("-"); + } + System.out.println(); + } + + public String getName() { + return this.name; + } +} diff --git a/src/main/java/racingcar/domain/RacingCarGame.java b/src/main/java/racingcar/domain/RacingCarGame.java new file mode 100644 index 00000000000..913024b12ca --- /dev/null +++ b/src/main/java/racingcar/domain/RacingCarGame.java @@ -0,0 +1,87 @@ +package racingcar.domain; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +public class RacingCarGame { + private final Player player; + + public RacingCarGame(Player player) { + this.player = player; + } + + public List createRacingCars(List carNames) { + List racingCars = new ArrayList<>(); + + for (int i = 0; i < carNames.size(); i++) { + racingCars.add(new RacingCar(carNames.get(i))); + } + + return racingCars; + } + + public void roundStart(List cars) { + for (RacingCar car : cars) { + car.goOrStop(); + } + } + + public void printRoundScore(List cars) { + for (RacingCar car : cars) { + car.printDistance(); + } + } + + public List chooseWinner(List cars) { + List winners = new ArrayList<>(); + int max = getHighestDistance(cars); + + for (RacingCar car : cars) { + if (car.distance == max) { + winners.add(car); + } + } + + return winners; + } + + public int getHighestDistance(List cars) { + cars.sort(new Comparator() { + @Override + public int compare(RacingCar o1, RacingCar o2) { + return o1.distance - o2.distance; + } + }); + + return cars.get(cars.size() - 1).distance; + } + + public void printWinnerName(List winners) { + System.out.print("최종 우승자 : "); + + for (int i = 0; i < winners.size(); i++) { + System.out.print(winners.get(i).getName()); + if (i != winners.size() - 1) { + System.out.print(","); + } + } + } + + public void startGameRounds(List cars, int numberOfRounds) { + for (int i = 0; i < numberOfRounds; i++) { + roundStart(cars); + printRoundScore(cars); + System.out.println(); + } + } + + public void init() { + List cars = createRacingCars(player.inputNames()); + int numberOfRounds = player.inputNumberOfRounds(); + System.out.println(); + System.out.println("실행 결과"); + startGameRounds(cars, numberOfRounds); + printWinnerName(chooseWinner(cars)); + } +} diff --git a/src/test/java/racingcar/ApplicationTest.java b/src/test/java/racingcar/ApplicationTest.java index 764ba4c627e..0896bb0e222 100644 --- a/src/test/java/racingcar/ApplicationTest.java +++ b/src/test/java/racingcar/ApplicationTest.java @@ -1,7 +1,12 @@ package racingcar; import camp.nextstep.edu.missionutils.test.NsTest; +import java.util.ArrayList; +import java.util.List; import org.junit.jupiter.api.Test; +import racingcar.domain.Player; +import racingcar.domain.RacingCar; +import racingcar.domain.RacingCarGame; import static camp.nextstep.edu.missionutils.test.Assertions.assertRandomNumberInRangeTest; import static camp.nextstep.edu.missionutils.test.Assertions.assertSimpleTest; @@ -23,6 +28,63 @@ class ApplicationTest extends NsTest { ); } + @Test + void 전진_정지_5라운드() { + assertRandomNumberInRangeTest( + () -> { + run("pobi,철수,pobi2", "5"); + assertThat(output()).contains("pobi : --", "철수 : -", "pobi2 : --", "최종 우승자 : pobi,pobi2"); + }, + MOVING_FORWARD, STOP, MOVING_FORWARD, + STOP, STOP, MOVING_FORWARD, + MOVING_FORWARD, MOVING_FORWARD, STOP + ); + } + + @Test + void 자동차_이름_확인() { + String name = "pobi"; + RacingCar car = new RacingCar(name); + assertThat(car.getName()).isEqualTo(name); + } + + @Test + void 자동차_전진() { + assertRandomNumberInRangeTest( + () -> { + RacingCar racingCar = new RacingCar("test"); + racingCar.goOrStop(); + assertThat(racingCar.distance).isEqualTo(1); + }, + MOVING_FORWARD + ); + } + + @Test + void 자동차_정지() { + assertRandomNumberInRangeTest( + () -> { + RacingCar racingCar = new RacingCar("test"); + racingCar.goOrStop(); + assertThat(racingCar.distance).isEqualTo(0); + }, + STOP + ); + } + + @Test + void 자동차_이름_거리_출력() { + assertRandomNumberInRangeTest( + () -> { + RacingCar racingCar = new RacingCar("pobi"); + racingCar.goOrStop(); + racingCar.printDistance(); + assertThat(output()).contains("pobi : -"); + }, + MOVING_FORWARD + ); + } + @Test void 이름에_대한_예외_처리() { assertSimpleTest(() -> @@ -31,6 +93,34 @@ class ApplicationTest extends NsTest { ); } + @Test + void 이름에_대한_예외_처리2() { + assertSimpleTest(() -> + assertThatThrownBy(() -> runException("pobi,java,", "1")) + .isInstanceOf(IllegalArgumentException.class) + ); + } + + @Test + void 자동차_객체_생성() { + RacingCarGame racingCarGame = new RacingCarGame(new Player()); + List testNames = new ArrayList<>(); + testNames.add("pobi"); + testNames.add("june"); + List cars = racingCarGame.createRacingCars(testNames); + assertThat(cars.size()).isEqualTo(2); + } + + @Test + void 자동차_게임_라운드_시작_및_결과_출력() { + RacingCarGame racingCarGame = new RacingCarGame(new Player()); + List cars = new ArrayList<>(); + cars.add(new RacingCar("abc")); + cars.add(new RacingCar("def")); + racingCarGame.startGameRounds(cars, 3); + assertThat(output()).contains("abc : ", "def : "); + } + @Override public void runMain() { Application.main(new String[]{});