From 559a968acc753277811fd74dd4f4901c08113976 Mon Sep 17 00:00:00 2001 From: yhkee0404 Date: Mon, 28 Oct 2024 20:10:48 +0900 Subject: [PATCH 1/7] docs(app): import TODO --- README.md | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/README.md b/README.md index d0286c859f..7b8f12b413 100644 --- a/README.md +++ b/README.md @@ -1 +1,93 @@ # java-racingcar-precourse + +## 초간단 자동차 경주 게임을 구현한다. + +> 이 문서의 작성 양식은 [프리코스 과제 가이드](https://github.com/woowacourse/woowacourse-docs/blob/e2f102b97f6b65f5ba8da09944ee8cb9b33b696a/precourse/README.md)를 참고했습니다. + +* 취소선 처리한 내용을 검색하면 다른 항목에서 찾을 수 있습니다. + +--- + +### 1. 주어진 횟수 동안 n대의 자동차는 ~~전진 또는 멈출 수 있다~~ 전진할 수 있다. + +> 예: +> +> 2 +> +> \- +> \- +> \- +> +> \-- +> \-- +> \-- + +* 1-1. 사용자는 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다. + +* 1-2. 전진하며 출력한다. + +--- + +### 2. 각 자동차에 이름을 부여할 수 있다. 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다. + +> 예: +> +> pobi,woni,jun +> +> pobi : \- +> woni : \- +> jun : \- +> +> pobi : \-\- +> woni : \-\- +> jun : \-\- + +* 2-1. 이름을 입력한다. 자동차 이름은 쉼표(,)를 기준으로 구분한다. + +* 2-2. 이름을 출력한다. + +--- + +### 3. ~~자동차 이름은 쉼표(,)를 기준으로 구분하며~~ ~~이름은 5자 이하만 가능하다.~~ + +--- + +### 4. ~~사용자는 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다.~~ + +--- + +### 5. 전진하는 조건은 0에서 9 사이에서 무작위 값을 구한 후 무작위 값이 4 이상일 경우이다. + +> 예: +> +> pobi,woni,jun +> +> pobi : \- +> woni : +> jun : \- +> +> pobi : \-- +> woni : \- +> jun : \-- + +* 4 미만일 경우에 멈출 수 있다. + +--- + +### 6. 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한 명 이상일 수 있다. + +> 예: +> +> pobi, jun + +* 우승자가 여러 명일 경우 쉼표(,)를 이용하여 구분한다. + +--- + +### 7. ~~우승자가 여러 명일 경우 쉼표(,)를 이용하여 구분한다.~~ + +--- + +### 8. 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시킨 후 애플리케이션은 종료되어야 한다. + +* 이름은 5자 이하만 가능하다. From 420cb543a610070242cf3f6c5e0b6a2651100bdd Mon Sep 17 00:00:00 2001 From: yhkee0404 Date: Mon, 28 Oct 2024 21:08:13 +0900 Subject: [PATCH 2/7] feat(racingcar): add RacingCar --- src/main/java/racingcar/RacingCar.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/main/java/racingcar/RacingCar.java diff --git a/src/main/java/racingcar/RacingCar.java b/src/main/java/racingcar/RacingCar.java new file mode 100644 index 0000000000..98d0a4664b --- /dev/null +++ b/src/main/java/racingcar/RacingCar.java @@ -0,0 +1,13 @@ +package racingcar; + +public class RacingCar { + public void move() { + mileage++; + } + + public int getMileage() { + return mileage; + } + + private int mileage; +} From 6e9cd81d150d6ea459d08c2d6ef053354406a4bc Mon Sep 17 00:00:00 2001 From: yhkee0404 Date: Mon, 28 Oct 2024 21:11:15 +0900 Subject: [PATCH 3/7] feat(app): move RacingCar and get mileage --- src/main/java/racingcar/Application.java | 28 +++++++++++++++++++- src/test/java/racingcar/ApplicationTest.java | 11 ++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java index a17a52e724..3e5a87a4ad 100644 --- a/src/main/java/racingcar/Application.java +++ b/src/main/java/racingcar/Application.java @@ -1,7 +1,33 @@ package racingcar; +import static camp.nextstep.edu.missionutils.Console.readLine; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + public class Application { public static void main(String[] args) { - // TODO: 프로그램 구현 + final PrintWriter pw = new PrintWriter(System.out); + + final int numUsers = Integer.parseInt(readLine()); + + final List racingCars = Stream.generate(RacingCar::new) + .limit(numUsers) + .collect(Collectors + .toCollection(ArrayList::new)); + + for (int i = 0; i != numUsers; i++) { + racingCars.parallelStream() + .forEach(RacingCar::move); + + racingCars.stream() + .forEach(racingCar -> + pw.println("-".repeat(racingCar.getMileage())) + ); + + pw.flush(); + } } } diff --git a/src/test/java/racingcar/ApplicationTest.java b/src/test/java/racingcar/ApplicationTest.java index 1d35fc33fe..d8a9a6d34b 100644 --- a/src/test/java/racingcar/ApplicationTest.java +++ b/src/test/java/racingcar/ApplicationTest.java @@ -1,6 +1,7 @@ package racingcar; import camp.nextstep.edu.missionutils.test.NsTest; +import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; import static camp.nextstep.edu.missionutils.test.Assertions.assertRandomNumberInRangeTest; @@ -12,6 +13,16 @@ class ApplicationTest extends NsTest { private static final int MOVING_FORWARD = 4; private static final int STOP = 3; + @Test + void 전진_테스트() { + assertSimpleTest( + () -> { + run("2"); + assertEquals("-\n-\n--\n--", output()); + } + ); + } + @Test void 기능_테스트() { assertRandomNumberInRangeTest( From 8b52f7b337e3c3515382ff92e7500445f64ac14b Mon Sep 17 00:00:00 2001 From: yhkee0404 Date: Mon, 28 Oct 2024 21:34:37 +0900 Subject: [PATCH 4/7] feat(racingcar): add name --- src/main/java/racingcar/RacingCar.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/racingcar/RacingCar.java b/src/main/java/racingcar/RacingCar.java index 98d0a4664b..6721252da1 100644 --- a/src/main/java/racingcar/RacingCar.java +++ b/src/main/java/racingcar/RacingCar.java @@ -1,6 +1,10 @@ package racingcar; public class RacingCar { + public RacingCar(final String name) { + this.name = name; + } + public void move() { mileage++; } @@ -9,5 +13,10 @@ public int getMileage() { return mileage; } + public String getName() { + return name; + } + private int mileage; + private String name; } From 014f668b6e96e6b322b4b1ba28067d87af03ab0d Mon Sep 17 00:00:00 2001 From: yhkee0404 Date: Mon, 28 Oct 2024 21:36:08 +0900 Subject: [PATCH 5/7] feat(app): input RacingCar name --- src/main/java/racingcar/Application.java | 21 ++++++++++---------- src/test/java/racingcar/ApplicationTest.java | 11 ++++++++-- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java index 3e5a87a4ad..6afd828894 100644 --- a/src/main/java/racingcar/Application.java +++ b/src/main/java/racingcar/Application.java @@ -3,30 +3,31 @@ import static camp.nextstep.edu.missionutils.Console.readLine; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; -import java.util.stream.Stream; public class Application { public static void main(String[] args) { final PrintWriter pw = new PrintWriter(System.out); - final int numUsers = Integer.parseInt(readLine()); + final String[] carNames = readLine().split(","); + final List racingCars = Arrays.stream(carNames) + .parallel() + .map(RacingCar::new) + .collect(Collectors.toCollection(ArrayList::new)); - final List racingCars = Stream.generate(RacingCar::new) - .limit(numUsers) - .collect(Collectors - .toCollection(ArrayList::new)); - - for (int i = 0; i != numUsers; i++) { + final int numRounds = Integer.parseInt(readLine()); + for (int i = 0; i != numRounds; i++) { racingCars.parallelStream() .forEach(RacingCar::move); racingCars.stream() .forEach(racingCar -> - pw.println("-".repeat(racingCar.getMileage())) + pw.println(racingCar.getName() + ": " + "-".repeat(racingCar.getMileage())) ); - + + pw.println(); pw.flush(); } } diff --git a/src/test/java/racingcar/ApplicationTest.java b/src/test/java/racingcar/ApplicationTest.java index d8a9a6d34b..8c8852daaf 100644 --- a/src/test/java/racingcar/ApplicationTest.java +++ b/src/test/java/racingcar/ApplicationTest.java @@ -17,8 +17,15 @@ class ApplicationTest extends NsTest { void 전진_테스트() { assertSimpleTest( () -> { - run("2"); - assertEquals("-\n-\n--\n--", output()); + run("pobi,woni,jun", "2"); + assertEquals(""" + pobi: - + woni: - + jun: - + + pobi: -- + woni: -- + jun: --""", output()); } ); } From 87056d6ef2323d52623ad6ee4cc491fde85537b2 Mon Sep 17 00:00:00 2001 From: yhkee0404 Date: Mon, 28 Oct 2024 22:23:12 +0900 Subject: [PATCH 6/7] feat(app): move racing car randomly --- src/main/java/racingcar/Application.java | 5 +- src/test/java/racingcar/ApplicationTest.java | 48 ++++++++++++++------ 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java index 6afd828894..122ede67d5 100644 --- a/src/main/java/racingcar/Application.java +++ b/src/main/java/racingcar/Application.java @@ -1,6 +1,7 @@ package racingcar; import static camp.nextstep.edu.missionutils.Console.readLine; +import static camp.nextstep.edu.missionutils.Randoms.pickNumberInRange; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; @@ -20,11 +21,11 @@ public static void main(String[] args) { final int numRounds = Integer.parseInt(readLine()); for (int i = 0; i != numRounds; i++) { racingCars.parallelStream() - .forEach(RacingCar::move); + .forEach(racingCar -> racingCar.move(pickNumberInRange(0, 9))); racingCars.stream() .forEach(racingCar -> - pw.println(racingCar.getName() + ": " + "-".repeat(racingCar.getMileage())) + pw.println(racingCar.getName() + " : " + "-".repeat(racingCar.getMileage())) ); pw.println(); diff --git a/src/test/java/racingcar/ApplicationTest.java b/src/test/java/racingcar/ApplicationTest.java index 8c8852daaf..4d1ebd48f7 100644 --- a/src/test/java/racingcar/ApplicationTest.java +++ b/src/test/java/racingcar/ApplicationTest.java @@ -1,13 +1,16 @@ package racingcar; -import camp.nextstep.edu.missionutils.test.NsTest; -import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.jupiter.api.Test; - import static camp.nextstep.edu.missionutils.test.Assertions.assertRandomNumberInRangeTest; import static camp.nextstep.edu.missionutils.test.Assertions.assertSimpleTest; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import camp.nextstep.edu.missionutils.test.NsTest; class ApplicationTest extends NsTest { private static final int MOVING_FORWARD = 4; @@ -15,17 +18,36 @@ class ApplicationTest extends NsTest { @Test void 전진_테스트() { + final List carNames = List.of("pobi", "woni", "jun"); + final int numRounds = 2; + assertSimpleTest( () -> { - run("pobi,woni,jun", "2"); - assertEquals(""" - pobi: - - woni: - - jun: - - - pobi: -- - woni: -- - jun: --""", output()); + run(String.join(",", carNames), String.valueOf(numRounds)); + + final List mileages = Stream.generate(() -> 0) + .limit(carNames.size()) + .collect(Collectors.toCollection(ArrayList::new)); + + final String[] lines = output().split("\n"); + for (int i = 0, j = 0; i != lines.length; i++, j = i % (carNames.size() + 1)) { + final String line = lines[i]; + + if (j == carNames.size()) { + assertThat(line.isBlank()); + continue; + } + + final String[] words = line.split(" : "); + assertEquals(2, words.length); + + assertEquals(carNames.get(j), words[0]); + + assertEquals("-".repeat(words[1].length()), words[1]); + assertThat(mileages.get(j) <= words[1].length()); + mileages.set(j, words[1].length()); + } + assertEquals(numRounds * (carNames.size() + 1) - 1, lines.length); } ); } From be4f84879fb6cb825de2360002b2a9d10bc7b828 Mon Sep 17 00:00:00 2001 From: yhkee0404 Date: Mon, 28 Oct 2024 23:56:58 +0900 Subject: [PATCH 7/7] feat(app): return winners --- src/main/java/racingcar/Application.java | 44 ++++++++++++++---- src/main/java/racingcar/RacingCar.java | 6 ++- src/test/java/racingcar/ApplicationTest.java | 48 +++++++++++++++++--- 3 files changed, 82 insertions(+), 16 deletions(-) diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java index 122ede67d5..8b18862bb3 100644 --- a/src/main/java/racingcar/Application.java +++ b/src/main/java/racingcar/Application.java @@ -1,35 +1,61 @@ package racingcar; import static camp.nextstep.edu.missionutils.Console.readLine; -import static camp.nextstep.edu.missionutils.Randoms.pickNumberInRange; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; public class Application { - public static void main(String[] args) { + public static final String lastPrefix = "최종 우승자 : "; + + public static void main(String[] args) throws IllegalArgumentException { final PrintWriter pw = new PrintWriter(System.out); + String line; - final String[] carNames = readLine().split(","); + line = readLine(); + if (line == null || line.isBlank()) { + throw new IllegalArgumentException(); + } + final String[] carNames = line.split(","); final List racingCars = Arrays.stream(carNames) .parallel() + .map(String::trim) .map(RacingCar::new) .collect(Collectors.toCollection(ArrayList::new)); + + racingCars.parallelStream() + .allMatch(racingCar -> racingCar.getName().length() <= 5); - final int numRounds = Integer.parseInt(readLine()); + line = readLine(); + if (line == null || line.isBlank()) { + throw new IllegalArgumentException(); + } + final int numRounds = Integer.parseInt(line.trim()); for (int i = 0; i != numRounds; i++) { - racingCars.parallelStream() - .forEach(racingCar -> racingCar.move(pickNumberInRange(0, 9))); - racingCars.stream() - .forEach(racingCar -> - pw.println(racingCar.getName() + " : " + "-".repeat(racingCar.getMileage())) + .forEach( + racingCar -> { + racingCar.move(); + pw.println(racingCar.getName() + " : " + "-".repeat(racingCar.getMileage())); + } ); pw.println(); pw.flush(); } + + final int maxMileage = racingCars.parallelStream() + .max(Comparator.comparing(RacingCar::getMileage)) + .get() + .getMileage(); + pw.println(lastPrefix + racingCars.stream() + .filter(racingCar -> racingCar.getMileage() == maxMileage) + .map(RacingCar::getName) + .collect(Collectors.joining(", ")) + ); + pw.flush(); } } diff --git a/src/main/java/racingcar/RacingCar.java b/src/main/java/racingcar/RacingCar.java index 6721252da1..55f723d4db 100644 --- a/src/main/java/racingcar/RacingCar.java +++ b/src/main/java/racingcar/RacingCar.java @@ -1,12 +1,16 @@ package racingcar; +import static camp.nextstep.edu.missionutils.Randoms.pickNumberInRange; + public class RacingCar { public RacingCar(final String name) { this.name = name; } public void move() { - mileage++; + if (pickNumberInRange(0, 9) >= 4) { + mileage++; + } } public int getMileage() { diff --git a/src/test/java/racingcar/ApplicationTest.java b/src/test/java/racingcar/ApplicationTest.java index 4d1ebd48f7..56a8c3b905 100644 --- a/src/test/java/racingcar/ApplicationTest.java +++ b/src/test/java/racingcar/ApplicationTest.java @@ -19,7 +19,7 @@ class ApplicationTest extends NsTest { @Test void 전진_테스트() { final List carNames = List.of("pobi", "woni", "jun"); - final int numRounds = 2; + final int numRounds = 10; assertSimpleTest( () -> { @@ -30,7 +30,8 @@ class ApplicationTest extends NsTest { .collect(Collectors.toCollection(ArrayList::new)); final String[] lines = output().split("\n"); - for (int i = 0, j = 0; i != lines.length; i++, j = i % (carNames.size() + 1)) { + for (int i = 0, j = 0; i < lines.length - 1; i++, j = i % (carNames.size() + 1)) { + assertThat(i <= 5); final String line = lines[i]; if (j == carNames.size()) { @@ -39,15 +40,50 @@ class ApplicationTest extends NsTest { } final String[] words = line.split(" : "); - assertEquals(2, words.length); - assertEquals(carNames.get(j), words[0]); + if (words.length == 1) { + assertEquals(mileages.get(j), 0); + continue; + } + assertThat(words.length == 2); assertEquals("-".repeat(words[1].length()), words[1]); - assertThat(mileages.get(j) <= words[1].length()); + assertThat(words[1].length() - mileages.get(j) >= 0); mileages.set(j, words[1].length()); } - assertEquals(numRounds * (carNames.size() + 1) - 1, lines.length); + assertEquals(numRounds * (carNames.size() + 1) + 1, lines.length); + + final String lastLine = lines[lines.length - 1]; + assertThat(lastLine.startsWith(Application.lastPrefix)); + + final String[] winnerNames = lastLine.substring(Application.lastPrefix.length()) + .split(", "); + + int maxMileage = -1; + for (int i = 0, j = 0; i != carNames.size(); i++) { + final String carName = carNames.get(i); + + if (j == winnerNames.length || ! carName.equals(winnerNames[j])) { + continue; + } + j++; + + if (maxMileage == -1) { + maxMileage = mileages.get(i); + } + assertThat(maxMileage == mileages.get(i)); + } + + for (int i = 0, j = 0; i != carNames.size(); i++) { + final String carName = carNames.get(i); + + if (j != winnerNames.length && carName.equals(winnerNames[j])) { + j++; + continue; + } + assertThat(maxMileage > mileages.get(i)); + } + } ); }