diff --git a/build.gradle b/build.gradle index 3697236..15ad6d1 100644 --- a/build.gradle +++ b/build.gradle @@ -6,6 +6,7 @@ version '1.0-SNAPSHOT' repositories { mavenCentral() + maven { url 'https://jitpack.io' } } dependencies { @@ -13,6 +14,7 @@ dependencies { testImplementation platform('org.assertj:assertj-bom:3.25.1') testImplementation('org.junit.jupiter:junit-jupiter') testImplementation('org.assertj:assertj-core') + implementation 'com.github.woowacourse-projects:mission-utils:1.0.0' } java { diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..1a0075a --- /dev/null +++ b/docs/README.md @@ -0,0 +1,23 @@ +1. 문제에 주어진 요구사항 +- 주어진 횟수 동안 n대의 자동차는 전진 또는 멈출 수 있다. +- 각 자동차에 이름을 부여할 수 있다. 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다. +- 자동차 이름은 쉼표(,)를 기준으로 구분하며 이름은 5자 이하만 가능하다. +- 사용자는 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다. +- 전진하는 조건은 0에서 9 사이에서 random 값을 구한 후 random 값이 4 이상일 경우 전진하고, 3 이하의 값이면 멈춘다. +- 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한 명 이상일 수 있다. + +2. 내가 생각한 구현 아키텍처 +- 우선 MVC 중 view를 먼저 구헌 +- InputView와 OutputView를 만든 후 이를 바탕으로 Controller와 Model 구현 +- 모르거나 헷갈리는 부분은 멘토님 lotto 코드 참조해서 만들어보기 + +3. 구체적인 구현 방법 +- 입력을 받는 부분과 출력이 나오는 부분을 InputView와 OutputView로 나누어 구현 +- Controller에서는 InputView로부터 입력을 받아 Model(domain)에 전달하고 Model로부터 결과를 받아 OutputView로 전달 +- domain에는 자동차 클래스와 자동차 경주 클래스 구현 +- 자동차 클래스에는 자동차 이름, 현재 위치, 자동차가 전진하는 조건을 구현 +- 자동차 경주 클래스에는 경주를 시작하는 메소드와 경주 결과를 반환하는 메소드 구현 +- 최대한 하나의 메소드가 하나의 로직만 담도록 만들어보기 + +4. 추가 구현 사항 +- 단위테스트를 찾아보면서 구현해보고 모르겠으면 질문하기..!(아직 어떻게 하는건지 잘 모르겠다,,) \ No newline at end of file diff --git a/gradlew b/gradlew index 1aa94a4..1b6c787 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,11 +80,13 @@ do esac done -# This is normally unused -# shellcheck disable=SC2034 +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -131,29 +133,22 @@ location of your Java installation." fi else JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." - fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -198,15 +193,11 @@ if "$cygwin" || "$msys" ; then done fi - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ @@ -214,12 +205,6 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/src/main/java/CarRace/RacingMain.java b/src/main/java/CarRace/RacingMain.java new file mode 100644 index 0000000..d735468 --- /dev/null +++ b/src/main/java/CarRace/RacingMain.java @@ -0,0 +1,12 @@ +package CarRace; + +import CarRace.controller.RacingController; + +public class RacingMain { + + public static void main(String[] args) { + // TODO: MVC 패턴을 기반으로 자동차 경주 미션 구현해보기 + RacingController racingController = new RacingController(); + racingController.startRace(); + } +} diff --git a/src/main/java/CarRace/controller/RacingController.java b/src/main/java/CarRace/controller/RacingController.java new file mode 100644 index 0000000..2562a7b --- /dev/null +++ b/src/main/java/CarRace/controller/RacingController.java @@ -0,0 +1,20 @@ +package CarRace.controller; + +import CarRace.domain.RacingGame; +import CarRace.view.InputView; +import CarRace.view.ResultView; + +import java.util.List; + +public class RacingController { + + public void startRace() { + List carNames = InputView.getCarNames(); + int tryCount = InputView.getRaceCount(); // InputView를 통해 차의 이름과 시도 회수를 입력받음 + + RacingGame racingGame = new RacingGame(carNames, tryCount); // 입력받은 차의 이름과 시도 회수를 바탕으로 RacingGame 객체 생성 + racingGame.play(); // 레이스 시작 + + ResultView.printWinners(racingGame.getWinners()); // 우승자 출력 + } +} diff --git a/src/main/java/CarRace/domain/Car.java b/src/main/java/CarRace/domain/Car.java new file mode 100644 index 0000000..e0f111d --- /dev/null +++ b/src/main/java/CarRace/domain/Car.java @@ -0,0 +1,26 @@ +package CarRace.domain; + +public class Car { + private final String name; + private int position; + + public Car(String name) { // 자동차 이름을 받아서 객체 생성 + this.name = name; + this.position = 0; + } + + public String getName() { // 자동차 이름을 반환 + return name; + } + + public int getPosition() { // 자동차의 위치를 반환 + return position; + } + + public void move() { // 전진하는 조건은 0에서 9 사이에서 random 값을 구한 후 random 값이 4 이상일 경우 전진하고, 3 이하의 값이면 멈춤 + int randomValue = (int) (Math.random() * 10); + if (randomValue >= 4) { + position++; + } + } +} diff --git a/src/main/java/CarRace/domain/RacingGame.java b/src/main/java/CarRace/domain/RacingGame.java new file mode 100644 index 0000000..d1d140f --- /dev/null +++ b/src/main/java/CarRace/domain/RacingGame.java @@ -0,0 +1,56 @@ +package CarRace.domain; + +import java.util.ArrayList; +import java.util.List; + +public class RacingGame { + private final List cars; // 자동차 객체를 담을 리스트 + private final int tryCount; // 시도 회수 + private final List winners; // 우승자를 담을 리스트 + + public RacingGame(List carNames, int tryCount) { // 차 이름과 시도 회수를 받아 RacingGame 객체 생성 + this.cars = new ArrayList<>(); + this.tryCount = tryCount; + this.winners = new ArrayList<>(); + for (String carName : carNames) { + cars.add(new Car(carName)); // 입력받은 차 이름을 바탕으로 Car 객체 생성 + } + } + + public void play() { // 레이스를 시작하는 메소드 + for (int i = 0; i < tryCount; i++) { // 시도 회수만큼 레이스를 진행 + playOneRound(); // 한 라운드를 진행하면 + printCurrentPositions(); // 현재 위치 출력 + } + determineWinners(); // 레이스가 끝나면 우승자를 결정 + } + + private void playOneRound() { // 한 라운드를 진행하는 메소드 + for (Car car : cars) { + car.move(); + } + } + + private void printCurrentPositions() { // 현재 위치를 출력하는 메소드 + for (Car car : cars) { + System.out.println(car.getName() + " : " + "-".repeat(car.getPosition())); // 각 자동차 별로 getPosition()을 통해 현재 위치를 받아와서 출력 + } + System.out.println(); + } + + private void determineWinners() { // 우승자를 결정하는 메소드 + int maxPosition = 0; // 가장 멀리 간 자동차의 위치 + for (Car car : cars) { + maxPosition = Math.max(maxPosition, car.getPosition()); // 현재까지 최대 위치와 각 자동차의 위치를 비교하여 최대 위치를 갱신 + } + for (Car car : cars) { + if (car.getPosition() == maxPosition) { + winners.add(car.getName()); // 각 자동차의 위치와 최대위치를 비교하여 같으면 해당 자동차의 이름을 우승자 리스트에 추가 + } + } + } + + public List getWinners() { // 우승자 리스트를 반환하는 메소드 + return winners; + } +} diff --git a/src/main/java/CarRace/view/InputView.java b/src/main/java/CarRace/view/InputView.java new file mode 100644 index 0000000..5680490 --- /dev/null +++ b/src/main/java/CarRace/view/InputView.java @@ -0,0 +1,25 @@ +package CarRace.view; + +import camp.nextstep.edu.missionutils.Console; + +import java.util.Arrays; +import java.util.List; + +public class InputView { + + private static final String RACE_CAR_NAME = "경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분)."; + private static final String RACE_COUNT = "시도할 회수는 몇회인가요?"; + private static final String SEPARATOR_VALUE = ","; + + public static List getCarNames() { // 경주할 자동차 이름을 입력받는 메소드 + System.out.println(RACE_CAR_NAME); + return Arrays.asList(Console.readLine().split(SEPARATOR_VALUE)); + } + + public static int getRaceCount() { // 시도할 회수를 입력받는 메소드 + System.out.println(RACE_COUNT); + return Integer.parseInt(Console.readLine()); + } + + +} diff --git a/src/main/java/CarRace/view/ResultView.java b/src/main/java/CarRace/view/ResultView.java new file mode 100644 index 0000000..8085774 --- /dev/null +++ b/src/main/java/CarRace/view/ResultView.java @@ -0,0 +1,10 @@ +package CarRace.view; + +import java.util.List; + +public class ResultView { + + public static void printWinners(List winners) { + System.out.println(String.join(", ", winners) + "가 최종 우승했습니다"); + } +} diff --git a/src/main/java/RacingMain.java b/src/main/java/RacingMain.java deleted file mode 100644 index 4394287..0000000 --- a/src/main/java/RacingMain.java +++ /dev/null @@ -1,7 +0,0 @@ -public class RacingMain { - - public static void main(String[] args) { - // TODO: MVC 패턴을 기반으로 자동차 경주 미션 구현해보기 - System.out.println("Hello, World!"); - } -} diff --git a/src/test/java/CarRace/RacingMainTest.java b/src/test/java/CarRace/RacingMainTest.java new file mode 100644 index 0000000..5cb2609 --- /dev/null +++ b/src/test/java/CarRace/RacingMainTest.java @@ -0,0 +1,6 @@ +package CarRace; + +import org.junit.jupiter.api.Test; + +public class RacingMainTest { +} diff --git a/src/test/java/CarRace/RacingTest.java b/src/test/java/CarRace/RacingTest.java new file mode 100644 index 0000000..9b6a91a --- /dev/null +++ b/src/test/java/CarRace/RacingTest.java @@ -0,0 +1,6 @@ +package CarRace; + +import org.junit.jupiter.api.Test; + +public class RacingTest { +}