diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..03478cd --- /dev/null +++ b/docs/README.md @@ -0,0 +1,9 @@ +

구현할 기능 목록

+ +- ### 사용자로부터 자동차 이름 입력받고 유효성 검사하기 +- ### 사용자로부터 시도할 횟수 입력받고 유효성 검사하기 +- ### 시도할 횟수만큼 라운드 반복하기 +- ### 모든 자동차 전진 또는 정지하기 +- ### 자동차의 상태 출력하기 +- ### 최종 우승자 찾기 +- ### 최종 우승자 출력하기 diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java index b9ed045..8b8ecad 100644 --- a/src/main/java/racingcar/Application.java +++ b/src/main/java/racingcar/Application.java @@ -1,7 +1,17 @@ package racingcar; +import racingcar.game.Car; +import racingcar.game.Game; +import racingcar.tool.InputUtils; + +import java.util.List; + public class Application { public static void main(String[] args) { - // TODO 구현 진행 + List cars = InputUtils.getCarListFromInput(); + int totalRound = InputUtils.getTotalRoundFromInput(); + Game game = new Game(cars, totalRound); + + game.start(); } } diff --git a/src/main/java/racingcar/Car.java b/src/main/java/racingcar/Car.java deleted file mode 100644 index ab3df94..0000000 --- a/src/main/java/racingcar/Car.java +++ /dev/null @@ -1,12 +0,0 @@ -package racingcar; - -public class Car { - private final String name; - private int position = 0; - - public Car(String name) { - this.name = name; - } - - // 추가 기능 구현 -} diff --git a/src/main/java/racingcar/game/Car.java b/src/main/java/racingcar/game/Car.java new file mode 100644 index 0000000..4b32685 --- /dev/null +++ b/src/main/java/racingcar/game/Car.java @@ -0,0 +1,51 @@ +package racingcar.game; + +import camp.nextstep.edu.missionutils.Randoms; + +import racingcar.tool.StringValidator; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + + +public class Car { + private final String name; + private int position = 0; + + public Car(String name) { + this.name = name; + } + + public static Car createCar(String carName) { + StringValidator.cannotUseCarName(carName); + + return new Car(carName); + } + + public int getPosition() { + return this.position; + } + + public String getName() { + return this.name; + } + + public String toString() { + return String.format("%s : %s",this.name, getMovingPositionLine()); + } + + public void move() { + if (Randoms.pickNumberInRange(0, 9) >= 4) { + this.position += 1; + } + } + + private String getMovingPositionLine() { + List movingPositions = Arrays.stream(new String[this.position]) + .map(s -> "-") + .collect(Collectors.toList()); + + return String.join("", movingPositions); + } +} diff --git a/src/main/java/racingcar/game/Game.java b/src/main/java/racingcar/game/Game.java new file mode 100644 index 0000000..4ad41d0 --- /dev/null +++ b/src/main/java/racingcar/game/Game.java @@ -0,0 +1,45 @@ +package racingcar.game; + +import racingcar.tool.PrintManager; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class Game { + + private final List cars; + private final int totalRound; + + public Game(List cars, int totalRound) { + this.cars = cars; + this.totalRound = totalRound; + } + + public void start() { + Round round = new Round(cars); + + PrintManager.printGameResultHead(); + while (round.getCurrentRound() <= totalRound) { + round.play(); + } + + List winningCars = findWinningCars(); + PrintManager.printWinningCarsName(winningCars); + } + + private List findWinningCars() { + if (cars.size() == 0) { + return Collections.emptyList(); + } + + int maxPosition = cars.stream() + .map(Car::getPosition) + .max(Integer::compareTo) + .get(); + + return cars.stream() + .filter(car -> car.getPosition() == maxPosition) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/racingcar/game/Round.java b/src/main/java/racingcar/game/Round.java new file mode 100644 index 0000000..e1252fe --- /dev/null +++ b/src/main/java/racingcar/game/Round.java @@ -0,0 +1,30 @@ +package racingcar.game; + +import racingcar.tool.PrintManager; + +import java.util.List; + +public class Round { + private int currentRound; + private final List cars; + + public Round(List cars) { + this.currentRound = 1; + this.cars = cars; + } + + public int getCurrentRound() { + return this.currentRound; + } + + public void play() { + moveAllCars(); + PrintManager.printAllCarsStatus(cars); + this.currentRound += 1; + } + + private void moveAllCars() { + cars.forEach(Car::move); + } + +} diff --git a/src/main/java/racingcar/tool/InputUtils.java b/src/main/java/racingcar/tool/InputUtils.java new file mode 100644 index 0000000..48def9b --- /dev/null +++ b/src/main/java/racingcar/tool/InputUtils.java @@ -0,0 +1,40 @@ +package racingcar.tool; + +import camp.nextstep.edu.missionutils.Console; + +import racingcar.game.Car; + +import java.util.List; + +public class InputUtils { + + private InputUtils() {} + + public static List getCarListFromInput() { + while (true) { + PrintManager.printCarNameInputDescription(); + + //for to split last comma, ' ' is going to be removed by trim func. + String carNames = Console.readLine() + ' '; + try { + return StringConvertor.convertIntoCars(carNames); + } catch (IllegalArgumentException exception) { + PrintManager.printErrorMessage(exception.getMessage()); + } + } + } + + public static int getTotalRoundFromInput() { + while (true) { + PrintManager.printTotalRoundInputDescription(); + + String roundInput = Console.readLine(); + try { + return StringConvertor.convertIntoNaturalNumber(roundInput); + } catch (IllegalArgumentException exception) { + PrintManager.printErrorMessage(exception.getMessage()); + } + } + } + +} diff --git a/src/main/java/racingcar/tool/ListConvertor.java b/src/main/java/racingcar/tool/ListConvertor.java new file mode 100644 index 0000000..d7d9cf3 --- /dev/null +++ b/src/main/java/racingcar/tool/ListConvertor.java @@ -0,0 +1,20 @@ +package racingcar.tool; + +import racingcar.game.Car; + +import java.util.List; +import java.util.stream.Collectors; + +public class ListConvertor { + + private ListConvertor() {} + + public static String joinCarsName(String delimiter, List cars) { + List names = cars.stream() + .map(Car::getName) + .collect(Collectors.toList()); + + return String.join(delimiter, names); + } + +} diff --git a/src/main/java/racingcar/tool/PrintManager.java b/src/main/java/racingcar/tool/PrintManager.java new file mode 100644 index 0000000..5f65b9f --- /dev/null +++ b/src/main/java/racingcar/tool/PrintManager.java @@ -0,0 +1,37 @@ +package racingcar.tool; + +import racingcar.game.Car; + +import java.util.List; + +public class PrintManager { + + private PrintManager() {} + + public static void printCarNameInputDescription() { + System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"); + } + + public static void printTotalRoundInputDescription() { + System.out.println("시도할 회수는 몇회인가요?"); + } + + public static void printAllCarsStatus(List cars) { + cars.forEach(System.out::println); + System.out.println(); + } + + public static void printWinningCarsName(List winningCars) { + String winningCarsName = ListConvertor.joinCarsName(", ", winningCars); + + System.out.printf("최종 우승자 : %s", winningCarsName); + } + + public static void printGameResultHead() { + System.out.println("\n실행 결과"); + } + + public static void printErrorMessage(String message) { + System.out.printf("[ERROR] %s\n", message); + } +} diff --git a/src/main/java/racingcar/tool/StringConvertor.java b/src/main/java/racingcar/tool/StringConvertor.java new file mode 100644 index 0000000..a6f7acf --- /dev/null +++ b/src/main/java/racingcar/tool/StringConvertor.java @@ -0,0 +1,33 @@ +package racingcar.tool; + +import racingcar.game.Car; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class StringConvertor { + + private StringConvertor() {} + + public static List convertIntoCars(String carNames) throws IllegalArgumentException { + return Arrays.stream(carNames.split(",")) + .map(String::trim) + .map(Car::createCar) + .collect(Collectors.toList()); + } + + public static Integer convertIntoNaturalNumber(String targetString) throws IllegalArgumentException { + try { + int number = Integer.parseInt(targetString); + + if (number < 1) { + throw new NumberFormatException(); + } + + return number; + } catch (NumberFormatException exception) { + throw new IllegalArgumentException("자연수가 아닌 값은 입력할 수 없습니다."); + } + } +} diff --git a/src/main/java/racingcar/tool/StringValidator.java b/src/main/java/racingcar/tool/StringValidator.java new file mode 100644 index 0000000..a322b19 --- /dev/null +++ b/src/main/java/racingcar/tool/StringValidator.java @@ -0,0 +1,14 @@ +package racingcar.tool; + +public class StringValidator { + + private StringValidator() {} + + public static void cannotUseCarName(String carName) throws IllegalArgumentException { + if (carName.length() == 0) { + throw new IllegalArgumentException("자동차 이름은 공백일 수 없습니다."); + } else if (carName.length() > 5) { + throw new IllegalArgumentException("자동차 이름은 최대 5자리입니다. 불가능한 이름: " + carName); + } + } +}