diff --git a/README.md b/README.md index d0286c8..1bba800 100644 --- a/README.md +++ b/README.md @@ -1 +1,22 @@ # java-racingcar-precourse + +# 기능 목록 + +1. 자동차경주 뷰 + - input, output(차수별, 우승자) + +2. 자동차 움직임 뷰 + - 자동차가 움직이면 그걸 출력하는 뷰 + +3. 자동차경주 컨트롤러 + - 입력값 처리 및 자동차 모델에게 전달 및 생성 + - 자동차 경주 게임 진행 + +4. 자동차경주 서비스 + - 예외처리 후 모델에게 전달 + - 우승자 판별 + - 1회차 경기 기능 + +5. 자동차 모델(클래스) + - 이름, 좌표 관련 입출력 + - 좌표 이동 후 뷰에 통보하는 observer \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..656f2e6 --- /dev/null +++ b/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Dfile.encoding=UTF-8 \ No newline at end of file diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java index a17a52e..30ed559 100644 --- a/src/main/java/racingcar/Application.java +++ b/src/main/java/racingcar/Application.java @@ -1,7 +1,24 @@ package racingcar; +import racingcar.controller.RacingGameController; +import racingcar.service.RacingGameService; +import racingcar.view.RacingGameView; + +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; + public class Application { public static void main(String[] args) { - // TODO: 프로그램 구현 + new Application().run(); + } + + public void run(){ + RacingGameService racingGameService = new RacingGameService(); + RacingGameView racingGameView = new RacingGameView(); + RacingGameController racingGameController = new RacingGameController(racingGameView, racingGameService); + + racingGameController.makeCar(); + racingGameController.runGame(); + racingGameController.result(); } } diff --git a/src/main/java/racingcar/controller/RacingGameController.java b/src/main/java/racingcar/controller/RacingGameController.java new file mode 100644 index 0000000..e172da3 --- /dev/null +++ b/src/main/java/racingcar/controller/RacingGameController.java @@ -0,0 +1,42 @@ +package racingcar.controller; + +import racingcar.service.RacingGameService; +import racingcar.util.ErrorMessage; +import racingcar.util.Validator; +import racingcar.view.RacingGameView; + +public class RacingGameController { + + private RacingGameView racingGameView; + private RacingGameService racingGameService; + + public RacingGameController(RacingGameView racingGameView, RacingGameService racingGameService){ + this.racingGameService = racingGameService; + this.racingGameView = racingGameView; + } + + public void makeCar(){ + String[] carNames = racingGameView.readName().split(","); + for(String name : carNames) racingGameService.addCar(name); + racingGameService.addObserver(racingGameView); + } + + public void runGame(){ + String input = racingGameView.readRepeat(); + if(!Validator.isNumber(input)) throw new IllegalArgumentException(ErrorMessage.WRONG_REPEAT_INPUT.getMessage()); + + int repetitionNumber = Integer.parseInt(input); + if(repetitionNumber<1) + racingGameView.printEndGuide(); + for (int i=0;i5) throw new IllegalArgumentException(ErrorMessage.TOO_LONG.getMessage()); + this.name = name; + } + + public int getPosition() { + return position; + } + + public void addPosition(int dice) { + if(dice>3) this.position++; + observer.onCarMove(name, position); + } + + public void setObserver(CarObserver observer) { + this.observer = observer; + } +} diff --git a/src/main/java/racingcar/model/CarObserver.java b/src/main/java/racingcar/model/CarObserver.java new file mode 100644 index 0000000..26e191f --- /dev/null +++ b/src/main/java/racingcar/model/CarObserver.java @@ -0,0 +1,5 @@ +package racingcar.model; + +public interface CarObserver { + void onCarMove(String carName, int position); +} diff --git a/src/main/java/racingcar/service/RacingGameService.java b/src/main/java/racingcar/service/RacingGameService.java new file mode 100644 index 0000000..3c9df7c --- /dev/null +++ b/src/main/java/racingcar/service/RacingGameService.java @@ -0,0 +1,41 @@ +package racingcar.service; + +import racingcar.model.Car; +import racingcar.model.CarObserver; + +import java.net.CacheRequest; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import static camp.nextstep.edu.missionutils.Randoms.pickNumberInRange; + +public class RacingGameService { + private List cars = new ArrayList<>(); + + public void addCar(String carName){ + Car car = new Car(carName); + cars.add(car); + } + + public void addObserver(CarObserver carObserver){ + cars.forEach(car->car.setObserver(carObserver)); + } + + public void playOneGame(){ + for(Car car : cars) car.addPosition(pickNumberInRange(0,9)); + } + + public String checkWinner(){ + Optional maxValue = cars.stream().map(Car::getPosition).max(Integer::compareTo); + + String maxPositionCars = cars.stream() + .filter(n -> maxValue.isPresent() && n.getPosition()==maxValue.get()) + .map(Car::getName) + .collect(Collectors.joining(", ")); + + return maxPositionCars; + } +} diff --git a/src/main/java/racingcar/util/ErrorMessage.java b/src/main/java/racingcar/util/ErrorMessage.java new file mode 100644 index 0000000..e498e21 --- /dev/null +++ b/src/main/java/racingcar/util/ErrorMessage.java @@ -0,0 +1,15 @@ +package racingcar.util; + +public enum ErrorMessage { + TOO_LONG("이름 5자 초과"), + WRONG_REPEAT_INPUT("입력 반복 횟수는 1 이상의 숫자여야합니다."); + + + private String message; + + ErrorMessage(String message){this.message = message;} + + public String getMessage() { + return "Error: "+message; + } +} diff --git a/src/main/java/racingcar/util/SystemMessage.java b/src/main/java/racingcar/util/SystemMessage.java new file mode 100644 index 0000000..07d2d60 --- /dev/null +++ b/src/main/java/racingcar/util/SystemMessage.java @@ -0,0 +1,17 @@ +package racingcar.util; + +public enum SystemMessage { + START_NAME_GUIDE("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"), + START_REPEAT_GUIDE("시도할 회수는 몇 회인가요?"), + RESULT_GUIDE("실행 결과"), + RESULT_WINNER("최종 우승자 : "); + + + private String message; + + SystemMessage(String message){this.message = message;} + + public String getMessage() { + return this.message; + } +} diff --git a/src/main/java/racingcar/util/Validator.java b/src/main/java/racingcar/util/Validator.java new file mode 100644 index 0000000..5afb572 --- /dev/null +++ b/src/main/java/racingcar/util/Validator.java @@ -0,0 +1,10 @@ +package racingcar.util; + +import java.util.regex.Pattern; + +public class Validator { + public static boolean isNumber(String arg){ + if(arg == null || !arg.matches("\\d+")) return false; + return true; + } +} diff --git a/src/main/java/racingcar/view/RacingGameView.java b/src/main/java/racingcar/view/RacingGameView.java new file mode 100644 index 0000000..7fac614 --- /dev/null +++ b/src/main/java/racingcar/view/RacingGameView.java @@ -0,0 +1,37 @@ +package racingcar.view; + +import camp.nextstep.edu.missionutils.Console; +import racingcar.model.CarObserver; +import racingcar.util.SystemMessage; + +public class RacingGameView implements CarObserver { + + public String readName(){ + System.out.println(SystemMessage.START_NAME_GUIDE.getMessage()); + return Console.readLine(); + } + + public String readRepeat(){ + System.out.println(SystemMessage.START_REPEAT_GUIDE.getMessage()); + return Console.readLine(); + } + + public void lineBreak(){ + System.out.println(""); + } + + public void printEndGuide(){ + System.out.println(SystemMessage.RESULT_GUIDE.getMessage()); + } + + public void printFinalWinner(String winner){ + System.out.println(SystemMessage.RESULT_WINNER.getMessage() + winner); + } + + @Override + public void onCarMove(String carName, int position){ + //뷰가 모델과 분리되어야해서 인스턴스 말고 각각 보내는게 좋다 함. + String message = carName + " : " + "-".repeat(position); + System.out.println(message); + } +}