From 41c1cc83fb2d5e6371f5aa33e1b75e0af79e0b1a Mon Sep 17 00:00:00 2001
From: Kim Chaewon <101501925+Dim-chae@users.noreply.github.com>
Date: Sun, 27 Oct 2024 15:20:27 +0900
Subject: [PATCH 01/14] =?UTF-8?q?docs:=20=EA=B8=B0=EB=8A=A5=20=EC=9A=94?=
=?UTF-8?q?=EA=B5=AC=20=EC=82=AC=ED=95=AD,=20=EC=98=88=EC=99=B8=20?=
=?UTF-8?q?=EC=BC=80=EC=9D=B4=EC=8A=A4=20=EC=A0=95=EB=A6=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
[기능 요구 사항]
자동차 경주 문제에 대한 로직을 기능 별로 분리 및 순차 정리
- 초기 입력
- 전진에 따른 난수 생성 및 전진 여부 판별
- 1회 시도마다 전진 현황 출력
- 우승자 선정, 최종 우승자 출력
[예외 케이스]
- 자동차 이름
문자열이 쉼표로 구분되지 않을 경우
구분 시 5자 이하가 아닐 경우
- 시도할 횟수
양의 정수가 아닌 경우
---
README.md | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/README.md b/README.md
index d0286c859f..c55a254be7 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,36 @@
# java-racingcar-precourse
+
+## 기능 요구 사항
+1. 경주할 **자동차 이름**과 **시도할 횟수**를 입력받는다.
+ 1-1. 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시킨 후 종료되어야 한다.
+
+
+2. 각 자동차마다 **0에서 9** 사이의 난수를 생성한다.
+3. 생성된 난수가 **4 이상**이면 해당 자동차를 **전진**시킨다.
+4. 모든 자동차의 1회 시도가 끝나면, 자동차 이름과 함께 **누적 전진**한 칸만큼 "-"를 출력한다.
+ (출력 형식 → chae : ---)
+
+
+*(입력받은 시도 횟수만큼 **2, 3, 4**의 과정을 반복한다.)*
+
+
+5. 경주한 자동차 중 최종적으로 **전진한 값**이 가장 높은 자동차를 우승자로 선정한다.
+ 5-1. 여러 자동차가 동시에 가장 높은 값을 가졌을 경우 **공동 우승자**로 선정한다.
+
+
+6. 우승한 자동차의 이름을 **우승자 안내** 문구와 함께 출력한다.
+ (출력 형식 → 최종 우승자 : chae, morol)
+
+
+## 예외 케이스
+
+**[자동차 이름 입력]**
+- 쉼표가 포함되지 않은 문자열
+- 구분한 결과가 5자 초과
+- 비어 있는 값
+
+**[시도할 횟수 입력]**
+- 0 또는 음수
+- 정수가 아닌 모든 수
+- 문자, 문자열 등 숫자가 아닌 값
+- 비어 있는 값
\ No newline at end of file
From a6574ca42d2014e33c0e369c6f1e3317ffbb63c2 Mon Sep 17 00:00:00 2001
From: Kim Chaewon <101501925+Dim-chae@users.noreply.github.com>
Date: Sun, 27 Oct 2024 16:30:29 +0900
Subject: [PATCH 02/14] =?UTF-8?q?feat:=20=EC=9E=90=EB=8F=99=EC=B0=A8=20?=
=?UTF-8?q?=EC=9D=B4=EB=A6=84,=20=EC=8B=9C=EB=8F=84=20=ED=9A=9F=EC=88=98?=
=?UTF-8?q?=20=EC=9E=85=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 경주할 자동차의 이름과 시도할 횟수를 입력 받음
- 시도할 횟수를 숫자로 포맷하는 과정에서 에러가 날 경우 Exception 발생
---
src/main/java/racingcar/Application.java | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java
index a17a52e724..d5ca58c531 100644
--- a/src/main/java/racingcar/Application.java
+++ b/src/main/java/racingcar/Application.java
@@ -1,7 +1,16 @@
package racingcar;
+import camp.nextstep.edu.missionutils.Console;
+
public class Application {
public static void main(String[] args) {
- // TODO: 프로그램 구현
+ System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)");
+ String carsName = Console.readLine();
+ System.out.println("시도할 횟수는 몇 회인가요?");
+ try {
+ int raceRoundCount = Integer.parseInt(Console.readLine());
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException();
+ }
}
}
From 3c22f8874fdf69721bb2a601b04263b7facab0bd Mon Sep 17 00:00:00 2001
From: Kim Chaewon <101501925+Dim-chae@users.noreply.github.com>
Date: Mon, 28 Oct 2024 14:54:39 +0900
Subject: [PATCH 03/14] =?UTF-8?q?feat:=20=EA=B0=9C=EB=B3=84=20=EC=9E=90?=
=?UTF-8?q?=EB=8F=99=EC=B0=A8=20=EC=BB=A8=ED=85=8C=EC=9D=B4=EB=84=88=20?=
=?UTF-8?q?=EC=A0=95=EC=9D=98=20=EB=B0=8F=20=EC=B4=88=EA=B8=B0=20=EC=9E=85?=
=?UTF-8?q?=EB=A0=A5=EC=97=90=20=EB=8C=80=ED=95=9C=20split=20=EA=B8=B0?=
=?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 개별 자동차에 대한 컨테이너를 Map 형태로 선언
- 초기 입력 문자열에 split 함수를 이용하여 String 배열 저장
- String 배열 검사, 5 이하일 경우에만 cars 컨테이너에 입력 값 저장
---
src/main/java/racingcar/Application.java | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java
index d5ca58c531..f049a4a732 100644
--- a/src/main/java/racingcar/Application.java
+++ b/src/main/java/racingcar/Application.java
@@ -1,16 +1,30 @@
package racingcar;
import camp.nextstep.edu.missionutils.Console;
+import java.util.HashMap;
+import java.util.Map;
public class Application {
public static void main(String[] args) {
System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)");
- String carsName = Console.readLine();
+ String carsInput = Console.readLine();
System.out.println("시도할 횟수는 몇 회인가요?");
+ int raceRoundCount;
try {
- int raceRoundCount = Integer.parseInt(Console.readLine());
+ raceRoundCount = Integer.parseInt(Console.readLine());
} catch (NumberFormatException e) {
throw new IllegalArgumentException();
}
+
+ Map cars = new HashMap<>();
+
+ String[] carsName = carsInput.split(",");
+
+ for (String car : carsName) {
+ if (car.length() > 5) {
+ throw new IllegalArgumentException();
+ }
+ cars.put(car, 0);
+ }
}
}
From 21820b48a6806a10c55bcc8af6255ea6dbb143b2 Mon Sep 17 00:00:00 2001
From: Kim Chaewon <101501925+Dim-chae@users.noreply.github.com>
Date: Mon, 28 Oct 2024 15:02:30 +0900
Subject: [PATCH 04/14] =?UTF-8?q?feat:=20=EA=B0=81=20=EC=9E=90=EB=8F=99?=
=?UTF-8?q?=EC=B0=A8=EB=A7=88=EB=8B=A4=20=EB=82=9C=EC=88=98=20=EC=83=9D?=
=?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20=EC=A0=84=EC=A7=84=20=EC=97=AC=EB=B6=80?=
=?UTF-8?q?=20=ED=8C=90=EB=B3=84=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20?=
=?UTF-8?q?=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 각 자동차마다 pickNumberInRange() 메소드로 난수 생성
- 4 이상일 경우에만 car 컨테이너의 value 값에 1을 더함
- 입력 받은 시도 횟수(경기를 진행하는 수)만큼 반복 수행
---
src/main/java/racingcar/Application.java | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java
index f049a4a732..04890393bf 100644
--- a/src/main/java/racingcar/Application.java
+++ b/src/main/java/racingcar/Application.java
@@ -1,6 +1,7 @@
package racingcar;
import camp.nextstep.edu.missionutils.Console;
+import camp.nextstep.edu.missionutils.Randoms;
import java.util.HashMap;
import java.util.Map;
@@ -26,5 +27,13 @@ public static void main(String[] args) {
}
cars.put(car, 0);
}
+
+ for (int count = 0; count < raceRoundCount; count++) {
+ for (String car : cars.keySet()) {
+ if (Randoms.pickNumberInRange(0, 9) >= 4) {
+ cars.put(car, cars.get(car) + 1);
+ }
+ }
+ }
}
}
From ebb9435442227be362446cb4b4fcbcb5b7bb348f Mon Sep 17 00:00:00 2001
From: Kim Chaewon <101501925+Dim-chae@users.noreply.github.com>
Date: Mon, 28 Oct 2024 16:18:59 +0900
Subject: [PATCH 05/14] =?UTF-8?q?feat:=201=ED=9A=8C=20=EC=8B=9C=EB=8F=84?=
=?UTF-8?q?=EB=A7=88=EB=8B=A4=20=EC=9E=90=EB=8F=99=EC=B0=A8=20=EB=B3=84?=
=?UTF-8?q?=EB=A1=9C=20=EB=88=84=EC=A0=81=20=EC=A0=84=EC=A7=84=ED=95=9C=20?=
=?UTF-8?q?=EC=B9=B8=20=EC=B6=9C=EB=A0=A5=ED=95=98=EB=8A=94=20=EA=B8=B0?=
=?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 각 자동차의 이름과 전진 값을 map 컨테이너 이용하여 출력
- "-" 문자를 출력할 때 repeat() 메소드로 전진 값(value)만큼 반복하도록 함
---
src/main/java/racingcar/Application.java | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java
index 04890393bf..e3c42c7d4c 100644
--- a/src/main/java/racingcar/Application.java
+++ b/src/main/java/racingcar/Application.java
@@ -34,6 +34,10 @@ public static void main(String[] args) {
cars.put(car, cars.get(car) + 1);
}
}
+ for (Map.Entry entry : cars.entrySet()) {
+ System.out.println(entry.getKey() + " : " + "-".repeat(entry.getValue()));
+ }
+ System.out.println();
}
}
-}
+}
\ No newline at end of file
From b3501afa95b1114756f683f5b82458bd3c2a1a4b Mon Sep 17 00:00:00 2001
From: Kim Chaewon <101501925+Dim-chae@users.noreply.github.com>
Date: Mon, 28 Oct 2024 16:50:39 +0900
Subject: [PATCH 06/14] =?UTF-8?q?feat:=20=EC=B5=9C=EC=A2=85=20=EC=A0=84?=
=?UTF-8?q?=EC=A7=84=20=EA=B1=B0=EB=A6=AC=EC=97=90=20=EB=94=B0=EB=A5=B8=20?=
=?UTF-8?q?=EC=9A=B0=EC=8A=B9=EC=9E=90=20=EC=84=A0=EC=A0=95=20=EA=B8=B0?=
=?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Collections.max()를 사용하여 최대 전진 거리 계산
- Stream API로 최대 전진 거리와 동일한 자동차들을 우승자로 선정
---
src/main/java/racingcar/Application.java | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java
index e3c42c7d4c..53cd99a2fe 100644
--- a/src/main/java/racingcar/Application.java
+++ b/src/main/java/racingcar/Application.java
@@ -2,7 +2,9 @@
import camp.nextstep.edu.missionutils.Console;
import camp.nextstep.edu.missionutils.Randoms;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
public class Application {
@@ -39,5 +41,12 @@ public static void main(String[] args) {
}
System.out.println();
}
+
+ int maxValue = Collections.max(cars.values());
+
+ List winners = cars.entrySet().stream()
+ .filter(entry -> entry.getValue() == maxValue)
+ .map(Map.Entry::getKey)
+ .toList();
}
}
\ No newline at end of file
From 7de07678363c1422ed6e01aa8712dbe64350fa7c Mon Sep 17 00:00:00 2001
From: Kim Chaewon <101501925+Dim-chae@users.noreply.github.com>
Date: Mon, 28 Oct 2024 16:53:21 +0900
Subject: [PATCH 07/14] =?UTF-8?q?feat:=20=EC=B5=9C=EC=A2=85=20=EC=9A=B0?=
=?UTF-8?q?=EC=8A=B9=EC=9E=90=20=EC=B6=9C=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=20?=
=?UTF-8?q?=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 최대 전진 거리를 value로 가지는 자동차(우승자) 리스트 출력
- String.join() 메소드를 통해 우승자가 여러 명일 경우 쉼표로 구분
---
src/main/java/racingcar/Application.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java
index 53cd99a2fe..bd4e37d37b 100644
--- a/src/main/java/racingcar/Application.java
+++ b/src/main/java/racingcar/Application.java
@@ -48,5 +48,7 @@ public static void main(String[] args) {
.filter(entry -> entry.getValue() == maxValue)
.map(Map.Entry::getKey)
.toList();
+
+ System.out.println("최종 우승자 : " + String.join(", ", winners));
}
}
\ No newline at end of file
From 4681a92030a486bd7825a1b73c3934930013579c Mon Sep 17 00:00:00 2001
From: Kim Chaewon <101501925+Dim-chae@users.noreply.github.com>
Date: Mon, 28 Oct 2024 17:34:57 +0900
Subject: [PATCH 08/14] =?UTF-8?q?refactor:=20Main=20=ED=81=B4=EB=9E=98?=
=?UTF-8?q?=EC=8A=A4=EC=97=90=20=EC=9E=91=EC=84=B1=EB=90=9C=20=EC=BD=94?=
=?UTF-8?q?=EB=93=9C=EB=A5=BC=20MVC=20=ED=8C=A8=ED=84=B4=EC=9C=BC=EB=A1=9C?=
=?UTF-8?q?=20=EB=B6=84=EB=A6=AC=20=EB=B0=8F=20=ED=81=B4=EB=9E=98=EC=8A=A4?=
=?UTF-8?q?=20=EC=83=9D=EC=84=B1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
[Main]
- Application 클래스: 메인 로직 실행
[Model]
- Car 클래스: 자동차 객체 생성 및 이동 로직 구현
- RacingGame 클래스: 게임 진행, 자동차 관리, 우승자 결정 로직 구현
[View]
- RacingGameView 클래스: 사용자 입력 프롬프트 및 게임 결과 출력
[Controller]
- RacingGameController 클래스: 사용자 입력 처리, Model과 View 간 상호작용 조정
---
src/main/java/racingcar/Application.java | 53 +++----------------
.../controller/RacingGameController.java | 52 ++++++++++++++++++
src/main/java/racingcar/model/Car.java | 27 ++++++++++
src/main/java/racingcar/model/RacingGame.java | 48 +++++++++++++++++
.../java/racingcar/view/RacingGameView.java | 22 ++++++++
5 files changed, 156 insertions(+), 46 deletions(-)
create mode 100644 src/main/java/racingcar/controller/RacingGameController.java
create mode 100644 src/main/java/racingcar/model/Car.java
create mode 100644 src/main/java/racingcar/model/RacingGame.java
create mode 100644 src/main/java/racingcar/view/RacingGameView.java
diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java
index bd4e37d37b..43d9ba1695 100644
--- a/src/main/java/racingcar/Application.java
+++ b/src/main/java/racingcar/Application.java
@@ -1,54 +1,15 @@
package racingcar;
-import camp.nextstep.edu.missionutils.Console;
-import camp.nextstep.edu.missionutils.Randoms;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import racingcar.controller.RacingGameController;
+import racingcar.model.RacingGame;
+import racingcar.view.RacingGameView;
public class Application {
public static void main(String[] args) {
- System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)");
- String carsInput = Console.readLine();
- System.out.println("시도할 횟수는 몇 회인가요?");
- int raceRoundCount;
- try {
- raceRoundCount = Integer.parseInt(Console.readLine());
- } catch (NumberFormatException e) {
- throw new IllegalArgumentException();
- }
+ RacingGameView view = new RacingGameView();
+ RacingGame model = new RacingGame();
+ RacingGameController controller = new RacingGameController(model, view);
- Map cars = new HashMap<>();
-
- String[] carsName = carsInput.split(",");
-
- for (String car : carsName) {
- if (car.length() > 5) {
- throw new IllegalArgumentException();
- }
- cars.put(car, 0);
- }
-
- for (int count = 0; count < raceRoundCount; count++) {
- for (String car : cars.keySet()) {
- if (Randoms.pickNumberInRange(0, 9) >= 4) {
- cars.put(car, cars.get(car) + 1);
- }
- }
- for (Map.Entry entry : cars.entrySet()) {
- System.out.println(entry.getKey() + " : " + "-".repeat(entry.getValue()));
- }
- System.out.println();
- }
-
- int maxValue = Collections.max(cars.values());
-
- List winners = cars.entrySet().stream()
- .filter(entry -> entry.getValue() == maxValue)
- .map(Map.Entry::getKey)
- .toList();
-
- System.out.println("최종 우승자 : " + String.join(", ", winners));
+ controller.runGame();
}
}
\ No newline at end of file
diff --git a/src/main/java/racingcar/controller/RacingGameController.java b/src/main/java/racingcar/controller/RacingGameController.java
new file mode 100644
index 0000000000..b237dc811c
--- /dev/null
+++ b/src/main/java/racingcar/controller/RacingGameController.java
@@ -0,0 +1,52 @@
+package racingcar.controller;
+
+import racingcar.model.RacingGame;
+import racingcar.view.RacingGameView;
+import camp.nextstep.edu.missionutils.Console;
+
+import java.util.List;
+
+public class RacingGameController {
+ private final RacingGame racingGame;
+ private final RacingGameView racingGameView;
+
+ public RacingGameController(RacingGame racingGame, RacingGameView racingGameView) {
+ this.racingGame = racingGame;
+ this.racingGameView = racingGameView;
+ }
+
+ public void runGame() {
+ initializeGame();
+ playGame();
+ announceWinners();
+ }
+
+ private void initializeGame() {
+ racingGameView.printCarNameInputPrompt();
+ String carNames = Console.readLine();
+ racingGameView.printRoundCountPrompt();
+ int roundCount = getRoundCount();
+
+ racingGame.initialize(carNames, roundCount);
+ }
+
+ private int getRoundCount() {
+ try {
+ return Integer.parseInt(Console.readLine());
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ private void playGame() {
+ for (int round = 0; round < racingGame.getRoundCount(); round++) {
+ racingGame.moveAllCars();
+ racingGameView.printRoundResult(racingGame.getCarStates());
+ }
+ }
+
+ private void announceWinners() {
+ List winners = racingGame.getWinners();
+ racingGameView.printWinners(winners);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/racingcar/model/Car.java b/src/main/java/racingcar/model/Car.java
new file mode 100644
index 0000000000..9ddb1d3fd8
--- /dev/null
+++ b/src/main/java/racingcar/model/Car.java
@@ -0,0 +1,27 @@
+package racingcar.model;
+
+import camp.nextstep.edu.missionutils.Randoms;
+
+public class Car {
+ private final String name;
+ private int position;
+
+ public Car(String name) {
+ this.name = name;
+ this.position = 0;
+ }
+
+ public void move() {
+ if (Randoms.pickNumberInRange(0, 9) >= 4) {
+ position++;
+ }
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getPosition() {
+ return position;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/racingcar/model/RacingGame.java b/src/main/java/racingcar/model/RacingGame.java
new file mode 100644
index 0000000000..235085509a
--- /dev/null
+++ b/src/main/java/racingcar/model/RacingGame.java
@@ -0,0 +1,48 @@
+package racingcar.model;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class RacingGame {
+ private List cars;
+ private int roundCount;
+
+ public void initialize(String carNames, int roundCount) {
+ this.cars = createCars(carNames);
+ this.roundCount = roundCount;
+ }
+
+ private List createCars(String carNames) {
+ return List.of(carNames.split(","))
+ .stream()
+ .map(String::trim)
+ .map(Car::new)
+ .collect(Collectors.toList());
+ }
+
+ public void moveAllCars() {
+ cars.forEach(Car::move);
+ }
+
+ public List getCarStates() {
+ return cars.stream()
+ .map(car -> car.getName() + " : " + "-".repeat(car.getPosition()))
+ .collect(Collectors.toList());
+ }
+
+ public List getWinners() {
+ int maxPosition = cars.stream()
+ .mapToInt(Car::getPosition)
+ .max()
+ .orElse(0);
+
+ return cars.stream()
+ .filter(car -> car.getPosition() == maxPosition)
+ .map(Car::getName)
+ .collect(Collectors.toList());
+ }
+
+ public int getRoundCount() {
+ return roundCount;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/racingcar/view/RacingGameView.java b/src/main/java/racingcar/view/RacingGameView.java
new file mode 100644
index 0000000000..57eb388a8a
--- /dev/null
+++ b/src/main/java/racingcar/view/RacingGameView.java
@@ -0,0 +1,22 @@
+package racingcar.view;
+
+import java.util.List;
+
+public class RacingGameView {
+ public void printCarNameInputPrompt() {
+ System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)");
+ }
+
+ public void printRoundCountPrompt() {
+ System.out.println("시도할 횟수는 몇 회인가요?");
+ }
+
+ public void printRoundResult(List carStates) {
+ carStates.forEach(System.out::println);
+ System.out.println();
+ }
+
+ public void printWinners(List winners) {
+ System.out.println("최종 우승자 : " + String.join(", ", winners));
+ }
+}
\ No newline at end of file
From cdc255c3cbf117e57645668fffca7217e11c0153 Mon Sep 17 00:00:00 2001
From: Kim Chaewon <101501925+Dim-chae@users.noreply.github.com>
Date: Mon, 28 Oct 2024 17:41:11 +0900
Subject: [PATCH 09/14] =?UTF-8?q?refactor:=20=EC=A0=84=EC=A7=84=20?=
=?UTF-8?q?=ED=8C=90=EB=B3=84=20=EC=9E=84=EA=B3=84=EA=B0=92,=20=EB=82=9C?=
=?UTF-8?q?=EC=88=98=20=EC=83=9D=EC=84=B1=20=EB=B2=94=EC=9C=84=20=EC=B5=9C?=
=?UTF-8?q?=EB=8C=93=EA=B0=92=20=EC=83=81=EC=88=98=ED=99=94?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- MOVE_THRESHOLD: 난수를 생성했을 때 전진 여부를 판별하는 임계값(4)에 대한 상수
- RANDOM_BOUND: 난수를 생성할 수 있는 범위의 최댓값(9)에 대한 상수
---
src/main/java/racingcar/model/Car.java | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/main/java/racingcar/model/Car.java b/src/main/java/racingcar/model/Car.java
index 9ddb1d3fd8..ffd6a88b94 100644
--- a/src/main/java/racingcar/model/Car.java
+++ b/src/main/java/racingcar/model/Car.java
@@ -3,6 +3,9 @@
import camp.nextstep.edu.missionutils.Randoms;
public class Car {
+ private static final int MOVE_THRESHOLD = 4;
+ private static final int RANDOM_BOUND = 9;
+
private final String name;
private int position;
@@ -12,7 +15,7 @@ public Car(String name) {
}
public void move() {
- if (Randoms.pickNumberInRange(0, 9) >= 4) {
+ if (Randoms.pickNumberInRange(0, RANDOM_BOUND) >= MOVE_THRESHOLD) {
position++;
}
}
From 9ed302a564d1800d1a2a897e75766f2f18151c66 Mon Sep 17 00:00:00 2001
From: Kim Chaewon <101501925+Dim-chae@users.noreply.github.com>
Date: Mon, 28 Oct 2024 17:47:35 +0900
Subject: [PATCH 10/14] =?UTF-8?q?feat:=20=EC=9E=90=EB=8F=99=EC=B0=A8=20?=
=?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EA=B5=AC=EB=B6=84=20=EA=B2=B0=EA=B3=BC?=
=?UTF-8?q?=EA=B0=80=205=EC=9E=90=20=EC=B4=88=EA=B3=BC=20=EC=8B=9C=20?=
=?UTF-8?q?=EC=98=88=EC=99=B8=20=EB=B0=9C=EC=83=9D=EC=8B=9C=ED=82=A4?=
=?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- validateName(String name) 메소드로 name의 길이 검사
- name의 길이가 5를 초과할 시 IllegalArgumentException 발생
---
src/main/java/racingcar/model/Car.java | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/main/java/racingcar/model/Car.java b/src/main/java/racingcar/model/Car.java
index ffd6a88b94..6906346c25 100644
--- a/src/main/java/racingcar/model/Car.java
+++ b/src/main/java/racingcar/model/Car.java
@@ -10,10 +10,17 @@ public class Car {
private int position;
public Car(String name) {
+ validateName(name);
this.name = name;
this.position = 0;
}
+ private void validateName(String name) {
+ if (name.length() > 5) {
+ throw new IllegalArgumentException();
+ }
+ }
+
public void move() {
if (Randoms.pickNumberInRange(0, RANDOM_BOUND) >= MOVE_THRESHOLD) {
position++;
From c2a4c5ef3028526aacf4acb5f1dac9ce5d4b4295 Mon Sep 17 00:00:00 2001
From: Kim Chaewon <101501925+Dim-chae@users.noreply.github.com>
Date: Mon, 28 Oct 2024 17:49:35 +0900
Subject: [PATCH 11/14] =?UTF-8?q?refactor:=20=EC=9E=90=EB=8F=99=EC=B0=A8?=
=?UTF-8?q?=20=EC=9D=B4=EB=A6=84=20=EA=B8=B8=EC=9D=B4=20=EC=B5=9C=EB=8C=93?=
=?UTF-8?q?=EA=B0=92=20=EC=83=81=EC=88=98=ED=99=94?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- MAX_NAME_LENGTH: 자동차 이름의 길이가 5자가 넘는지 판별 시 최댓값에 대한 상수
---
src/main/java/racingcar/model/Car.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/main/java/racingcar/model/Car.java b/src/main/java/racingcar/model/Car.java
index 6906346c25..eb79738f32 100644
--- a/src/main/java/racingcar/model/Car.java
+++ b/src/main/java/racingcar/model/Car.java
@@ -3,6 +3,7 @@
import camp.nextstep.edu.missionutils.Randoms;
public class Car {
+ private static final int MAX_NAME_LENGTH = 5;
private static final int MOVE_THRESHOLD = 4;
private static final int RANDOM_BOUND = 9;
@@ -16,7 +17,7 @@ public Car(String name) {
}
private void validateName(String name) {
- if (name.length() > 5) {
+ if (name.length() > MAX_NAME_LENGTH) {
throw new IllegalArgumentException();
}
}
From 75ee95b05ac441b90fb6b27c4604673123db9ad4 Mon Sep 17 00:00:00 2001
From: Kim Chaewon <101501925+Dim-chae@users.noreply.github.com>
Date: Mon, 28 Oct 2024 19:37:29 +0900
Subject: [PATCH 12/14] =?UTF-8?q?docs:=20=EC=9E=85=EC=B6=9C=EB=A0=A5=20?=
=?UTF-8?q?=ED=98=95=EC=8B=9D=20=EA=B4=80=EB=A0=A8=20=EA=B5=AC=EC=B2=B4?=
=?UTF-8?q?=EC=A0=81=20=EB=82=B4=EC=9A=A9=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 기능 요구 사항의 입력, 출력 단계에 대해 구체적으로 기술함
---
README.md | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
index c55a254be7..f472898ede 100644
--- a/README.md
+++ b/README.md
@@ -2,14 +2,22 @@
## 기능 요구 사항
1. 경주할 **자동차 이름**과 **시도할 횟수**를 입력받는다.
+
+> **[입력 형식]**
+경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)
+chae,morol
+시도할 횟수는 몇 회인가요?
+3
+
1-1. 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시킨 후 종료되어야 한다.
2. 각 자동차마다 **0에서 9** 사이의 난수를 생성한다.
3. 생성된 난수가 **4 이상**이면 해당 자동차를 **전진**시킨다.
-4. 모든 자동차의 1회 시도가 끝나면, 자동차 이름과 함께 **누적 전진**한 칸만큼 "-"를 출력한다.
- (출력 형식 → chae : ---)
-
+4. 모든 자동차의 1회 시도가 끝나면, 자동차 이름과 함께 **누적 전진**한 칸만큼 "-"를 출력한다.
+> **[출력 형식]**
+chae : ---
+morol : --
*(입력받은 시도 횟수만큼 **2, 3, 4**의 과정을 반복한다.)*
@@ -18,8 +26,9 @@
5-1. 여러 자동차가 동시에 가장 높은 값을 가졌을 경우 **공동 우승자**로 선정한다.
-6. 우승한 자동차의 이름을 **우승자 안내** 문구와 함께 출력한다.
- (출력 형식 → 최종 우승자 : chae, morol)
+6. 우승한 자동차의 이름을 **우승자 안내** 문구와 함께 출력한다.
+> **[출력 형식]**
+최종 우승자 : chae, morol
## 예외 케이스
From bf5feb03d1b0bc8b311424c970c3a2630cb960bd Mon Sep 17 00:00:00 2001
From: Kim Chaewon <101501925+Dim-chae@users.noreply.github.com>
Date: Mon, 28 Oct 2024 23:27:57 +0900
Subject: [PATCH 13/14] =?UTF-8?q?refactor:=20Validator(=EC=98=88=EC=99=B8?=
=?UTF-8?q?=20=EC=B2=98=EB=A6=AC)=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?=
=?UTF-8?q?=EB=B6=84=EB=A6=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- validateInputString 메소드: 입력 문자열에 ","가 없는지 검사
- validateCarName 메소드: 자동차 이름이 비어 있거나 최대 글자수를 넘는지 검사
- validateRoundCount 메소드: 시도 횟수가 0 이하인지 검사
- validateCarPosition 메소드: 자동차의 위치가 음수인지 검사
---
src/main/java/racingcar/model/Car.java | 10 ++-----
src/main/java/racingcar/model/RacingGame.java | 6 ++++
src/main/java/racingcar/model/Validator.java | 29 +++++++++++++++++++
3 files changed, 37 insertions(+), 8 deletions(-)
create mode 100644 src/main/java/racingcar/model/Validator.java
diff --git a/src/main/java/racingcar/model/Car.java b/src/main/java/racingcar/model/Car.java
index eb79738f32..0ba3d23058 100644
--- a/src/main/java/racingcar/model/Car.java
+++ b/src/main/java/racingcar/model/Car.java
@@ -3,7 +3,6 @@
import camp.nextstep.edu.missionutils.Randoms;
public class Car {
- private static final int MAX_NAME_LENGTH = 5;
private static final int MOVE_THRESHOLD = 4;
private static final int RANDOM_BOUND = 9;
@@ -11,18 +10,13 @@ public class Car {
private int position;
public Car(String name) {
- validateName(name);
+ Validator.validateCarName(name);
this.name = name;
this.position = 0;
}
- private void validateName(String name) {
- if (name.length() > MAX_NAME_LENGTH) {
- throw new IllegalArgumentException();
- }
- }
-
public void move() {
+ Validator.validateCarPosition(position);
if (Randoms.pickNumberInRange(0, RANDOM_BOUND) >= MOVE_THRESHOLD) {
position++;
}
diff --git a/src/main/java/racingcar/model/RacingGame.java b/src/main/java/racingcar/model/RacingGame.java
index 235085509a..979047b564 100644
--- a/src/main/java/racingcar/model/RacingGame.java
+++ b/src/main/java/racingcar/model/RacingGame.java
@@ -8,10 +8,16 @@ public class RacingGame {
private int roundCount;
public void initialize(String carNames, int roundCount) {
+ validate(carNames, roundCount);
this.cars = createCars(carNames);
this.roundCount = roundCount;
}
+ private void validate(String carNames, int roundCount) {
+ Validator.validateInputString(carNames);
+ Validator.validateRoundCount(roundCount);
+ }
+
private List createCars(String carNames) {
return List.of(carNames.split(","))
.stream()
diff --git a/src/main/java/racingcar/model/Validator.java b/src/main/java/racingcar/model/Validator.java
new file mode 100644
index 0000000000..d9030bb045
--- /dev/null
+++ b/src/main/java/racingcar/model/Validator.java
@@ -0,0 +1,29 @@
+package racingcar.model;
+
+public class Validator {
+ private static final int MAX_NAME_LENGTH = 5;
+
+ public static void validateInputString(String carNames) {
+ if (!carNames.contains(",")) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public static void validateCarName(String carName) {
+ if (carName.isEmpty() || carName.length() > MAX_NAME_LENGTH) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public static void validateRoundCount(int roundCount) {
+ if (roundCount <= 0) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public static void validateCarPosition(int position) {
+ if (position < 0) {
+ throw new IllegalArgumentException();
+ }
+ }
+}
From 528d2da7a089ca0128557b8f3c4b285d30a160c0 Mon Sep 17 00:00:00 2001
From: Kim Chaewon <101501925+Dim-chae@users.noreply.github.com>
Date: Mon, 28 Oct 2024 23:40:34 +0900
Subject: [PATCH 14/14] =?UTF-8?q?test:=20=EC=98=88=EC=99=B8=20=ED=85=8C?=
=?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BC=80=EC=9D=B4=EC=8A=A4=20=EC=B6=94?=
=?UTF-8?q?=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 이름 길이 초과 예외 테스트: 이름 길이가 5자 초과일 경우
- 빈 이름 예외 테스트: 입력 문자열을 분리한 결과 빈 문자열이 있을 경우
- 시도 횟수 예외 테스트: 시도 횟수를 입력한 값이 문자열일 경우
---
src/test/java/racingcar/ApplicationTest.java | 32 ++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/src/test/java/racingcar/ApplicationTest.java b/src/test/java/racingcar/ApplicationTest.java
index 1d35fc33fe..284c743bc3 100644
--- a/src/test/java/racingcar/ApplicationTest.java
+++ b/src/test/java/racingcar/ApplicationTest.java
@@ -31,6 +31,38 @@ class ApplicationTest extends NsTest {
);
}
+ @Test
+ void 이름_길이_초과_예외_테스트() {
+ assertSimpleTest(() ->
+ assertThatThrownBy(() -> runException("pobi,woni,javaji,longname,tooLongName", "1"))
+ .isInstanceOf(IllegalArgumentException.class)
+ );
+ }
+
+ @Test
+ void 빈_이름_예외_테스트() {
+ assertSimpleTest(() ->
+ assertThatThrownBy(() -> runException("pobi,,woni", "1"))
+ .isInstanceOf(IllegalArgumentException.class)
+ );
+ }
+
+ @Test
+ void 음수_시도_횟수_예외_테스트() {
+ assertSimpleTest(() ->
+ assertThatThrownBy(() -> runException("pobi,woni", "-1"))
+ .isInstanceOf(IllegalArgumentException.class)
+ );
+ }
+
+ @Test
+ void 시도_횟수_예외_테스트() {
+ assertSimpleTest(() ->
+ assertThatThrownBy(() -> runException("pobi,woni", "abc"))
+ .isInstanceOf(IllegalArgumentException.class)
+ );
+ }
+
@Override
public void runMain() {
Application.main(new String[]{});