From 04e2c4557587ac1bad29ddf3b6ad47e633770bf2 Mon Sep 17 00:00:00 2001 From: boya-go Date: Thu, 8 May 2025 18:53:47 +0900 Subject: [PATCH 01/16] =?UTF-8?q?docs:=201=EB=8B=A8=EA=B3=84=20=EC=9A=94?= =?UTF-8?q?=EA=B5=AC=EC=82=AC=ED=95=AD=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..0083645a --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# 자동차 경주 - 초간단 애플리케이션 + +## [1] 움직이는 자동차 + +- 자동차에 관한 요구사항 + - [ ] 자동차는 이름을 가지고 있다. + - [ ] 자동차는 움직일 수 있다. + - [ ] 0에서 9 사이의 random 값을 구해 그 값이 **4 이상이면 전진**하고, **3 이하 값이면 멈춘다**. +- 코드 작성 요구사항 + - [ ] 자동차가 움직이는 기능이 의도대로 되는지 테스트한다. + - [ ] 자바 코드 컨벤션 `Java Style Guide` 원칙으로 프로그래밍한다. + - [ ] 3항 연산자를 쓰지 않는다. + - [ ] else 예약어를 쓰지 않는다. + - [ ] switch/case도 사용하지 않는다. + - [ ] 함수(또는 메서드) 길이가 15라인을 넘어가지 않도록 구현한다. + - [ ] 함수(또는 메서드)가 한 가지 일만 하도록 한다. From 884845ce4f5b08c109e7343938cf8346e4c560a5 Mon Sep 17 00:00:00 2001 From: boya-go Date: Fri, 9 May 2025 00:29:43 +0900 Subject: [PATCH 02/16] =?UTF-8?q?feat:=20car=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Car.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/main/java/Car.java diff --git a/src/main/java/Car.java b/src/main/java/Car.java new file mode 100644 index 00000000..fae6f476 --- /dev/null +++ b/src/main/java/Car.java @@ -0,0 +1,18 @@ +public class Car { + + private 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; + } +} From 72129c331b028728da85e56864639b8616f4a4cc Mon Sep 17 00:00:00 2001 From: boya-go Date: Fri, 9 May 2025 00:46:33 +0900 Subject: [PATCH 03/16] =?UTF-8?q?feat:=20=EB=9E=9C=EB=8D=A4=EA=B0=92=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EA=B8=B0=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20?= =?UTF-8?q?car=20=EA=B0=9D=EC=B2=B4=20=EC=A0=95=EB=B3=B4=EC=97=90=20?= =?UTF-8?q?=EC=9B=80=EC=A7=81=EC=9E=84=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Car.java | 9 ++++++++- src/main/java/RandomGenerator.java | 10 ++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/main/java/RandomGenerator.java diff --git a/src/main/java/Car.java b/src/main/java/Car.java index fae6f476..b14d8e4a 100644 --- a/src/main/java/Car.java +++ b/src/main/java/Car.java @@ -1,6 +1,7 @@ + public class Car { - private String name; + private final String name; private int position; public Car(String name) { @@ -15,4 +16,10 @@ public String getName() { public int getPosition() { return position; } + + public void movePosition(RandomGenerator randomGenerator) { + if (randomGenerator.getRandomNumber() > 3) { + position++; + } + } } diff --git a/src/main/java/RandomGenerator.java b/src/main/java/RandomGenerator.java new file mode 100644 index 00000000..b972e108 --- /dev/null +++ b/src/main/java/RandomGenerator.java @@ -0,0 +1,10 @@ +import java.util.Random; + +public class RandomGenerator { + Random random = new Random(); + + public int getRandomNumber() { + return random.nextInt(10); + } + +} From 34fcac480ab3bc5f1e884d7a0f4e6c87ecaea69a Mon Sep 17 00:00:00 2001 From: boya-go Date: Fri, 9 May 2025 02:18:03 +0900 Subject: [PATCH 04/16] =?UTF-8?q?refactor:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EB=A5=BC=20=EC=9C=84=ED=95=B4=20=EB=9E=9C=EB=8D=A4=EC=88=AB?= =?UTF-8?q?=EC=9E=90=20=EC=83=9D=EC=84=B1=EA=B8=B0=EB=8A=A5=EA=B3=BC=20?= =?UTF-8?q?=EC=9B=80=EC=A7=81=EC=9D=B4=EB=8A=94=20=EA=B8=B0=EB=8A=A5=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 --- src/main/java/Car.java | 21 ++++++++++++++++++--- src/main/java/RandomGenerator.java | 10 ---------- 2 files changed, 18 insertions(+), 13 deletions(-) delete mode 100644 src/main/java/RandomGenerator.java diff --git a/src/main/java/Car.java b/src/main/java/Car.java index b14d8e4a..0b767b47 100644 --- a/src/main/java/Car.java +++ b/src/main/java/Car.java @@ -1,10 +1,13 @@ +import java.util.Random; public class Car { - private final String name; + private String name; private int position; + Random random = new Random(); public Car(String name) { + validateNotNull(name); this.name = name; this.position = 0; } @@ -17,8 +20,20 @@ public int getPosition() { return position; } - public void movePosition(RandomGenerator randomGenerator) { - if (randomGenerator.getRandomNumber() > 3) { + private void validateNotNull(String name) { + if (name == null || name.isBlank()) { + throw new IllegalArgumentException("이름은 빈 값이 될 수 없습니다."); + } + } + + public int getRandomNumber() { + int randomNum = random.nextInt(10); + + return randomNum; + } + + public void movePosition(int randomNumber) { + if (randomNumber > 3) { position++; } } diff --git a/src/main/java/RandomGenerator.java b/src/main/java/RandomGenerator.java deleted file mode 100644 index b972e108..00000000 --- a/src/main/java/RandomGenerator.java +++ /dev/null @@ -1,10 +0,0 @@ -import java.util.Random; - -public class RandomGenerator { - Random random = new Random(); - - public int getRandomNumber() { - return random.nextInt(10); - } - -} From fcaa1d5f2a3a000dceff6248616c47fcf09b9217 Mon Sep 17 00:00:00 2001 From: boya-go Date: Fri, 9 May 2025 02:19:45 +0900 Subject: [PATCH 05/16] =?UTF-8?q?test:=20=EC=9B=80=EC=A7=81=EC=9D=B4?= =?UTF-8?q?=EB=8A=94=20=EC=9E=90=EB=8F=99=EC=B0=A8=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/CarTest.java | 65 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 src/test/java/CarTest.java diff --git a/src/test/java/CarTest.java b/src/test/java/CarTest.java new file mode 100644 index 00000000..87598811 --- /dev/null +++ b/src/test/java/CarTest.java @@ -0,0 +1,65 @@ +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class CarTest { + + @Test + void Car_객체생성() { + + // given + Car car = new Car("붕붕이"); + + // when + assertThat(car.getName()).isEqualTo("붕붕이"); + assertThat(car.getPosition()).isEqualTo(0); + } + + @ParameterizedTest + @ValueSource(strings = {"", " "}) + void Car_이름빈값일경우_예외처리(String name) { + + assertThatThrownBy(() -> new Car(name)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("이름은 빈 값이 될 수 없습니다."); + } + + @Test + void getRandomNumber_랜덤숫자기준충족() { + + Car car = new Car("차1"); + assertThat(car.getRandomNumber()) + .isGreaterThanOrEqualTo( 0) + .isLessThanOrEqualTo( 9); + } + + @Test + void movePosition_랜덤숫자4이상일때_1이동() { + + // given + Car car = new Car("차2"); + + // when + car.movePosition(5); + + // then + assertThat(car.getPosition()).isEqualTo(1); + } + + @Test + void movePosition_랜덤숫자3이하일때_정지() { + + // given + Car car = new Car("차3"); + + // when + car.movePosition(2); + + // then + assertThat(car.getPosition()).isEqualTo(0); + } +} + From 0c97bd52758e627c217a1aa3afb7dc23452af946 Mon Sep 17 00:00:00 2001 From: boya-go Date: Fri, 9 May 2025 02:27:49 +0900 Subject: [PATCH 06/16] =?UTF-8?q?docs:=201=EB=8B=A8=EA=B3=84=20=EC=9A=94?= =?UTF-8?q?=EA=B5=AC=EC=82=AC=ED=95=AD=20=EA=B2=B0=EA=B3=BC=20=EB=B0=8F=20?= =?UTF-8?q?2=EB=8B=A8=EA=B3=84=20=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0083645a..a9287be3 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,23 @@ ## [1] 움직이는 자동차 - 자동차에 관한 요구사항 - - [ ] 자동차는 이름을 가지고 있다. - - [ ] 자동차는 움직일 수 있다. - - [ ] 0에서 9 사이의 random 값을 구해 그 값이 **4 이상이면 전진**하고, **3 이하 값이면 멈춘다**. + - [x] 자동차는 이름을 가지고 있다. + - [x] 자동차는 움직일 수 있다. + - [x] 0에서 9 사이의 random 값을 구해 그 값이 **4 이상이면 전진**하고, **3 이하 값이면 멈춘다**. + +--- + +## [2] 우승 자동차 구하기 + +- 기능 요구사항 + - [ ] n대의 자동차 참여 가능 + - [ ] 주어진 횟수동안 n대의 자동차는 전진 또는 멈출 수 있다. + - [ ] 이동 조건은 앞의 [움직이는 자동차]와 동일 + - [ ] 경주 게임 완료 후 우승자를 구할 수 있다. + - [ ] 우승자는 한 명 이상일 수 있다. + +--- + - 코드 작성 요구사항 - [ ] 자동차가 움직이는 기능이 의도대로 되는지 테스트한다. - [ ] 자바 코드 컨벤션 `Java Style Guide` 원칙으로 프로그래밍한다. From 933f644b58b868005bdaec687520beb4f96a4758 Mon Sep 17 00:00:00 2001 From: boya-go Date: Fri, 9 May 2025 23:00:42 +0900 Subject: [PATCH 07/16] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=98=EA=B2=8C=20Random=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EB=90=98=EB=8A=94=20=EA=B2=83=EC=9D=84=20=EB=B0=A9?= =?UTF-8?q?=EC=A7=80=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=B4=20static=20fin?= =?UTF-8?q?al=EB=A1=9C=20=EB=B3=80=EA=B2=BD=ED=95=B4=EC=84=9C=20=EC=84=A0?= =?UTF-8?q?=EC=96=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Car.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/Car.java b/src/main/java/Car.java index 0b767b47..35d3668c 100644 --- a/src/main/java/Car.java +++ b/src/main/java/Car.java @@ -4,7 +4,7 @@ public class Car { private String name; private int position; - Random random = new Random(); + private static final Random random = new Random(); public Car(String name) { validateNotNull(name); From 3a8ff9b69058b76d5d14ca9055efff63c8d942c4 Mon Sep 17 00:00:00 2001 From: boya-go Date: Sat, 10 May 2025 01:10:32 +0900 Subject: [PATCH 08/16] =?UTF-8?q?feat:=20=EA=B2=8C=EC=9E=84=20=EC=8B=A4?= =?UTF-8?q?=ED=96=89=ED=95=B4=20=EC=9A=B0=EC=8A=B9=EC=9E=90=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1,=20=EA=B8=B0=EC=A1=B4=20Car=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=EC=97=90=20=EC=9E=88=EB=8D=98=20=EB=9E=9C=EB=8D=A4?= =?UTF-8?q?=EC=88=AB=EC=9E=90=EC=83=9D=EC=84=B1=EA=B8=B0=EB=A5=BC=20?= =?UTF-8?q?=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=EB=A1=9C=20?= =?UTF-8?q?=EB=A7=8C=EB=93=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Car.java | 17 ++++----- src/main/java/CarRaceGame.java | 48 ++++++++++++++++++++++++ src/main/java/FixedNumberGenerator.java | 14 +++++++ src/main/java/NumberGenerator.java | 3 ++ src/main/java/RandomNumberGenerator.java | 11 ++++++ src/test/java/CarTest.java | 24 ++++++++---- 6 files changed, 99 insertions(+), 18 deletions(-) create mode 100644 src/main/java/CarRaceGame.java create mode 100644 src/main/java/FixedNumberGenerator.java create mode 100644 src/main/java/NumberGenerator.java create mode 100644 src/main/java/RandomNumberGenerator.java diff --git a/src/main/java/Car.java b/src/main/java/Car.java index 35d3668c..8c79fec0 100644 --- a/src/main/java/Car.java +++ b/src/main/java/Car.java @@ -4,12 +4,15 @@ public class Car { private String name; private int position; - private static final Random random = new Random(); + private final NumberGenerator generator; + private static final int MOVE_THRESHOLD = 4; - public Car(String name) { + + public Car(String name, NumberGenerator generator) { validateNotNull(name); this.name = name; this.position = 0; + this.generator = generator; } public String getName() { @@ -26,14 +29,8 @@ private void validateNotNull(String name) { } } - public int getRandomNumber() { - int randomNum = random.nextInt(10); - - return randomNum; - } - - public void movePosition(int randomNumber) { - if (randomNumber > 3) { + public void movePosition() { + if (generator.generate() >= MOVE_THRESHOLD ) { position++; } } diff --git a/src/main/java/CarRaceGame.java b/src/main/java/CarRaceGame.java new file mode 100644 index 00000000..a557ba34 --- /dev/null +++ b/src/main/java/CarRaceGame.java @@ -0,0 +1,48 @@ +import java.util.List; + +public class CarRaceGame { + + private List cars; + private List winners; + + public CarRaceGame(List cars) { + this.cars = cars; + } + + private void validateRoundNumber(int gameRound) { + if (gameRound < 1 ) { + throw new IllegalArgumentException("라운드는 한 번 이상 진행되어야 합니다."); + } + } + + private void carRacing(int gameRound) { + validateRoundNumber(gameRound); + for (int i= 0; i < gameRound; i++) { + cars.forEach(car -> car.movePosition()); + } + } + + private int getMaxDistance() { + int maxDistance = cars.stream().mapToInt(Car::getPosition).max().orElseThrow(); + + return maxDistance; + } + + private List getWinners(int maxDistance) { + List winners = cars.stream().filter(car -> car.getPosition() == maxDistance).map(Car::getName).toList(); + + return winners; + } + + public void playRacingGame(int gameRound) { + carRacing(gameRound); + winners = getWinners(getMaxDistance()); + } + + public List getWinnerNames() { + if (winners == null) { + throw new IllegalStateException("게임이 실행되지 않았습니다."); + } + return winners; + } +} diff --git a/src/main/java/FixedNumberGenerator.java b/src/main/java/FixedNumberGenerator.java new file mode 100644 index 00000000..9c696652 --- /dev/null +++ b/src/main/java/FixedNumberGenerator.java @@ -0,0 +1,14 @@ +public class FixedNumberGenerator implements NumberGenerator { + private final int[] numbers; + private int index = 0; + + public FixedNumberGenerator(int... numbers) { + this.numbers = numbers; + } + + @Override + public int generate() { + return numbers[index++]; + } + +} diff --git a/src/main/java/NumberGenerator.java b/src/main/java/NumberGenerator.java new file mode 100644 index 00000000..aca481b5 --- /dev/null +++ b/src/main/java/NumberGenerator.java @@ -0,0 +1,3 @@ +public interface NumberGenerator { + int generate(); +} diff --git a/src/main/java/RandomNumberGenerator.java b/src/main/java/RandomNumberGenerator.java new file mode 100644 index 00000000..ccd29d96 --- /dev/null +++ b/src/main/java/RandomNumberGenerator.java @@ -0,0 +1,11 @@ +import java.util.Random; + +public class RandomNumberGenerator implements NumberGenerator { + + private static final Random RANDOM = new Random(); + + @Override + public int generate( ) { + return RANDOM.nextInt( 10 ); + } +} diff --git a/src/test/java/CarTest.java b/src/test/java/CarTest.java index 87598811..35881d79 100644 --- a/src/test/java/CarTest.java +++ b/src/test/java/CarTest.java @@ -11,7 +11,8 @@ public class CarTest { void Car_객체생성() { // given - Car car = new Car("붕붕이"); + NumberGenerator generator = new RandomNumberGenerator(); + Car car = new Car("붕붕이", generator); // when assertThat(car.getName()).isEqualTo("붕붕이"); @@ -22,7 +23,9 @@ public class CarTest { @ValueSource(strings = {"", " "}) void Car_이름빈값일경우_예외처리(String name) { - assertThatThrownBy(() -> new Car(name)) + NumberGenerator generator = new RandomNumberGenerator(); + + assertThatThrownBy(() -> new Car(name,generator)) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("이름은 빈 값이 될 수 없습니다."); } @@ -30,8 +33,10 @@ public class CarTest { @Test void getRandomNumber_랜덤숫자기준충족() { - Car car = new Car("차1"); - assertThat(car.getRandomNumber()) + NumberGenerator generator = new RandomNumberGenerator(); + + Car car = new Car("차1",generator); + assertThat(generator.generate()) .isGreaterThanOrEqualTo( 0) .isLessThanOrEqualTo( 9); } @@ -39,11 +44,13 @@ public class CarTest { @Test void movePosition_랜덤숫자4이상일때_1이동() { + NumberGenerator generator = new FixedNumberGenerator(5); + // given - Car car = new Car("차2"); + Car car = new Car("차2", generator); // when - car.movePosition(5); + car.movePosition(); // then assertThat(car.getPosition()).isEqualTo(1); @@ -53,10 +60,11 @@ public class CarTest { void movePosition_랜덤숫자3이하일때_정지() { // given - Car car = new Car("차3"); + NumberGenerator generator = new FixedNumberGenerator(2); + Car car = new Car("차3", generator); // when - car.movePosition(2); + car.movePosition(); // then assertThat(car.getPosition()).isEqualTo(0); From bbb74804e676c04758b1fed52e9e3c355d642724 Mon Sep 17 00:00:00 2001 From: boya-go Date: Sat, 10 May 2025 01:16:08 +0900 Subject: [PATCH 09/16] =?UTF-8?q?test:=20=EC=9A=B0=EC=8A=B9=20=EC=9E=90?= =?UTF-8?q?=EB=8F=99=EC=B0=A8=20=EA=B5=AC=ED=95=98=EA=B8=B0=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/CarRaceGameTest.java | 62 ++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/test/java/CarRaceGameTest.java diff --git a/src/test/java/CarRaceGameTest.java b/src/test/java/CarRaceGameTest.java new file mode 100644 index 00000000..35a3ee4b --- /dev/null +++ b/src/test/java/CarRaceGameTest.java @@ -0,0 +1,62 @@ +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.Assertions.*; +import java.util.List; +import java.util.ArrayList; + +public class CarRaceGameTest { + + private List createCars(NumberGenerator... generators) { + List cars = new ArrayList<>(); + for (int i = 0; i < generators.length; i++) { + cars.add(new Car("차" + (i + 1), generators[i])); + } + return cars; + } + + @ParameterizedTest + @ValueSource(ints = {0, -4}) + void playRacingGame_게임라운드0이하_예외처리(int gameRound) { + List cars = createCars( + new RandomNumberGenerator(), + new RandomNumberGenerator(), + new RandomNumberGenerator() + ); + + CarRaceGame game = new CarRaceGame(cars); + + assertThatThrownBy(() -> game.playRacingGame(gameRound)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("라운드는 한 번 이상 진행되어야 합니다."); + } + + @Test + void playRacingGame_우승자한명_정상출력() { + List cars = createCars( + new FixedNumberGenerator(9, 6, 4, 2, 5), + new FixedNumberGenerator(0, 2, 2, 1, 3), + new FixedNumberGenerator(1, 2, 5, 0, 9) + ); + + CarRaceGame game = new CarRaceGame(cars); + game.playRacingGame(5); + + assertThat(game.getWinnerNames()).containsOnly("차1"); + } + + @Test + void playRacingGame_우승자두명_정상출력() { + List cars = createCars( + new FixedNumberGenerator(1, 8, 7), + new FixedNumberGenerator(0, 9, 2), + new FixedNumberGenerator(7, 2, 5) + ); + + CarRaceGame game = new CarRaceGame(cars); + game.playRacingGame(3); + + assertThat(game.getWinnerNames()).containsOnly("차1", "차3"); + } +} From 8ebd4ee2b52acdcd088866e0073718bf53e066b5 Mon Sep 17 00:00:00 2001 From: boya-go Date: Sat, 10 May 2025 02:08:35 +0900 Subject: [PATCH 10/16] =?UTF-8?q?docs:=202=EB=8B=A8=EA=B3=84=20=EC=9A=94?= =?UTF-8?q?=EA=B5=AC=EC=82=AC=ED=95=AD=20=EA=B2=B0=EA=B3=BC=20=EB=B0=8F=20?= =?UTF-8?q?3=EB=8B=A8=EA=B3=84=20=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a9287be3..1e5949d8 100644 --- a/README.md +++ b/README.md @@ -12,14 +12,24 @@ ## [2] 우승 자동차 구하기 - 기능 요구사항 - - [ ] n대의 자동차 참여 가능 - - [ ] 주어진 횟수동안 n대의 자동차는 전진 또는 멈출 수 있다. - - [ ] 이동 조건은 앞의 [움직이는 자동차]와 동일 - - [ ] 경주 게임 완료 후 우승자를 구할 수 있다. - - [ ] 우승자는 한 명 이상일 수 있다. + - [x] n대의 자동차 참여 가능 + - [x] 주어진 횟수동안 n대의 자동차는 전진 또는 멈출 수 있다. + - [x] 이동 조건은 앞의 [움직이는 자동차]와 동일 + - [x] 경주 게임 완료 후 우승자를 구할 수 있다. + - [x] 우승자는 한 명 이상일 수 있다. --- +## [3] 게임 실행 + +- 기능 요구사항 + - [ ] 자동차 및 게임 방법은 앞의 [움직이는 자동차], [우승 자동차 구하기]와 동일 + - [ ] 사용자로부터 `이름`, `게임횟수` 를 입력받는다. + - [ ] 자동차 이름은 쉼표(,) 기준으로 구분하며, 이름은 5자 이하만 가능하다. + - [ ] 메인 메서드를 추가하여 실행 가능하게 만든다. + +--- + - 코드 작성 요구사항 - [ ] 자동차가 움직이는 기능이 의도대로 되는지 테스트한다. - [ ] 자바 코드 컨벤션 `Java Style Guide` 원칙으로 프로그래밍한다. From 27b851963d23ff623d94cce2be30413449ae80cb Mon Sep 17 00:00:00 2001 From: boya-go Date: Sat, 10 May 2025 06:16:56 +0900 Subject: [PATCH 11/16] =?UTF-8?q?refactor:=20mvc=ED=8C=A8=ED=84=B4?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=20=EC=8B=A4=ED=96=89=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/App.java | 10 ++++ .../java/Controller/RacingGameController.java | 47 +++++++++++++++++++ src/main/java/{ => domain}/Car.java | 15 ++++-- src/main/java/{ => domain}/CarRaceGame.java | 17 +++++-- .../Generator}/FixedNumberGenerator.java | 2 + .../Generator}/NumberGenerator.java | 2 + .../Generator}/RandomNumberGenerator.java | 2 + src/main/java/view/inputView.java | 18 +++++++ src/main/java/view/outputView.java | 26 ++++++++++ src/test/java/CarRaceGameTest.java | 4 ++ src/test/java/CarTest.java | 4 ++ 11 files changed, 139 insertions(+), 8 deletions(-) create mode 100644 src/main/java/App.java create mode 100644 src/main/java/Controller/RacingGameController.java rename src/main/java/{ => domain}/Car.java (72%) rename src/main/java/{ => domain}/CarRaceGame.java (78%) rename src/main/java/{ => domain/Generator}/FixedNumberGenerator.java (91%) rename src/main/java/{ => domain/Generator}/NumberGenerator.java (67%) rename src/main/java/{ => domain/Generator}/RandomNumberGenerator.java (89%) create mode 100644 src/main/java/view/inputView.java create mode 100644 src/main/java/view/outputView.java diff --git a/src/main/java/App.java b/src/main/java/App.java new file mode 100644 index 00000000..40650a95 --- /dev/null +++ b/src/main/java/App.java @@ -0,0 +1,10 @@ +import Controller.RacingGameController; + +public class App { + public static void main(String[] args) { + RacingGameController racingGameController = new RacingGameController(); + + racingGameController.startRacingGame(); + + } +} diff --git a/src/main/java/Controller/RacingGameController.java b/src/main/java/Controller/RacingGameController.java new file mode 100644 index 00000000..16c4b642 --- /dev/null +++ b/src/main/java/Controller/RacingGameController.java @@ -0,0 +1,47 @@ +package Controller; + +import domain.Car; +import domain.CarRaceGame; +import domain.Generator.RandomNumberGenerator; +import view.inputView; +import view.outputView; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class RacingGameController { + + public static final String DELIMITER = ","; + + public void startRacingGame(){ + String names = inputView.enterCarNames(); + int round = inputView.enterRoundNumber(); + + List cars = Arrays.stream(names.split(DELIMITER)) + .map(name -> new Car(name, new RandomNumberGenerator())) + .collect(Collectors.toList()); + + final CarRaceGame carRaceGame = new CarRaceGame(cars); + + outputView.printGameResultTitle(); + + for (int i = 0; i < round; i++) { + + carRaceGame.playOneRound(); + System.out.println(); + outputView.printRoundResult(cars); + + } + + carRaceGame.playRacingGame(round); + + List winnersName = carRaceGame.getWinnerNames(); + + outputView.printGameWinners(winnersName); + + + + + } +} diff --git a/src/main/java/Car.java b/src/main/java/domain/Car.java similarity index 72% rename from src/main/java/Car.java rename to src/main/java/domain/Car.java index 8c79fec0..75874dd2 100644 --- a/src/main/java/Car.java +++ b/src/main/java/domain/Car.java @@ -1,4 +1,6 @@ -import java.util.Random; +package domain; + +import domain.Generator.NumberGenerator; public class Car { @@ -9,7 +11,7 @@ public class Car { public Car(String name, NumberGenerator generator) { - validateNotNull(name); + validateName(name); this.name = name; this.position = 0; this.generator = generator; @@ -23,12 +25,19 @@ public int getPosition() { return position; } - private void validateNotNull(String name) { + private void validateName(String name) { + if (name == null || name.isBlank()) { throw new IllegalArgumentException("이름은 빈 값이 될 수 없습니다."); } + if (name.length() > 5) { + throw new IllegalArgumentException("이름은 5자 이하만 가능합니다."); + + } + } + public void movePosition() { if (generator.generate() >= MOVE_THRESHOLD ) { position++; diff --git a/src/main/java/CarRaceGame.java b/src/main/java/domain/CarRaceGame.java similarity index 78% rename from src/main/java/CarRaceGame.java rename to src/main/java/domain/CarRaceGame.java index a557ba34..0bf69c7f 100644 --- a/src/main/java/CarRaceGame.java +++ b/src/main/java/domain/CarRaceGame.java @@ -1,3 +1,5 @@ +package domain; + import java.util.List; public class CarRaceGame { @@ -15,13 +17,19 @@ private void validateRoundNumber(int gameRound) { } } - private void carRacing(int gameRound) { - validateRoundNumber(gameRound); - for (int i= 0; i < gameRound; i++) { - cars.forEach(car -> car.movePosition()); + public void playOneRound() { + for (Car car : cars) { + car.movePosition(); } } +// private void carRacing(int gameRound) { +// validateRoundNumber(gameRound); +// for (int i= 0; i < gameRound; i++) { +// playOneRound(); +// } +// } + private int getMaxDistance() { int maxDistance = cars.stream().mapToInt(Car::getPosition).max().orElseThrow(); @@ -35,7 +43,6 @@ private List getWinners(int maxDistance) { } public void playRacingGame(int gameRound) { - carRacing(gameRound); winners = getWinners(getMaxDistance()); } diff --git a/src/main/java/FixedNumberGenerator.java b/src/main/java/domain/Generator/FixedNumberGenerator.java similarity index 91% rename from src/main/java/FixedNumberGenerator.java rename to src/main/java/domain/Generator/FixedNumberGenerator.java index 9c696652..c75827e6 100644 --- a/src/main/java/FixedNumberGenerator.java +++ b/src/main/java/domain/Generator/FixedNumberGenerator.java @@ -1,3 +1,5 @@ +package domain.Generator; + public class FixedNumberGenerator implements NumberGenerator { private final int[] numbers; private int index = 0; diff --git a/src/main/java/NumberGenerator.java b/src/main/java/domain/Generator/NumberGenerator.java similarity index 67% rename from src/main/java/NumberGenerator.java rename to src/main/java/domain/Generator/NumberGenerator.java index aca481b5..d058024b 100644 --- a/src/main/java/NumberGenerator.java +++ b/src/main/java/domain/Generator/NumberGenerator.java @@ -1,3 +1,5 @@ +package domain.Generator; + public interface NumberGenerator { int generate(); } diff --git a/src/main/java/RandomNumberGenerator.java b/src/main/java/domain/Generator/RandomNumberGenerator.java similarity index 89% rename from src/main/java/RandomNumberGenerator.java rename to src/main/java/domain/Generator/RandomNumberGenerator.java index ccd29d96..b08e9eb3 100644 --- a/src/main/java/RandomNumberGenerator.java +++ b/src/main/java/domain/Generator/RandomNumberGenerator.java @@ -1,3 +1,5 @@ +package domain.Generator; + import java.util.Random; public class RandomNumberGenerator implements NumberGenerator { diff --git a/src/main/java/view/inputView.java b/src/main/java/view/inputView.java new file mode 100644 index 00000000..bea263cb --- /dev/null +++ b/src/main/java/view/inputView.java @@ -0,0 +1,18 @@ +package view; + +import java.util.Scanner; + +public class inputView { + + private static final Scanner scanner = new Scanner(System.in); + + public static String enterCarNames() { + System.out.println("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분)."); + return scanner.nextLine(); + } + + public static int enterRoundNumber() { + System.out.println("시도할 회수는 몇회인가요?"); + return scanner.nextInt(); + } +} diff --git a/src/main/java/view/outputView.java b/src/main/java/view/outputView.java new file mode 100644 index 00000000..3f7f0a4d --- /dev/null +++ b/src/main/java/view/outputView.java @@ -0,0 +1,26 @@ +package view; + +import domain.Car; + +import java.util.List; + +public class outputView { + + private static final String CAR_POSITION_EXPRESSION = "-"; + private static final String WINNER_NAMES_DELIMITER = ","; + + public static void printGameResultTitle() { + System.out.println("\n실행 결과"); + } + + public static void printRoundResult(List cars) { + for (Car car : cars) { + System.out.println(car.getName() + ": " + CAR_POSITION_EXPRESSION.repeat(car.getPosition())); + } + System.out.println(); + } + + public static void printGameWinners(List winners) { + System.out.println(String.join(WINNER_NAMES_DELIMITER, winners) + "가 최종 우승했습니다."); + } +} diff --git a/src/test/java/CarRaceGameTest.java b/src/test/java/CarRaceGameTest.java index 35a3ee4b..5022e3a5 100644 --- a/src/test/java/CarRaceGameTest.java +++ b/src/test/java/CarRaceGameTest.java @@ -1,3 +1,7 @@ +import domain.*; +import domain.Generator.FixedNumberGenerator; +import domain.Generator.NumberGenerator; +import domain.Generator.RandomNumberGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; diff --git a/src/test/java/CarTest.java b/src/test/java/CarTest.java index 35881d79..42f15b93 100644 --- a/src/test/java/CarTest.java +++ b/src/test/java/CarTest.java @@ -1,3 +1,7 @@ +import domain.Car; +import domain.Generator.FixedNumberGenerator; +import domain.Generator.NumberGenerator; +import domain.Generator.RandomNumberGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; From 1dd8c563cdb2add5fcb6be168453c7eafcc0c698 Mon Sep 17 00:00:00 2001 From: boya-go Date: Sun, 11 May 2025 03:19:14 +0900 Subject: [PATCH 12/16] =?UTF-8?q?refactor:=20=EC=A0=84=EB=B0=98=EC=A0=81?= =?UTF-8?q?=EC=9D=B8=20=EC=BD=94=EB=93=9C=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BC=80?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/App.java | 2 +- .../RacingGameController.java | 15 +++--- src/main/java/domain/Car.java | 6 +-- src/main/java/domain/CarRaceGame.java | 32 ++++++++---- .../java/{ => domain}/CarRaceGameTest.java | 52 ++++++++++++++++++- src/test/java/{ => domain}/CarTest.java | 45 +++++++++++++++- 6 files changed, 125 insertions(+), 27 deletions(-) rename src/main/java/{Controller => controller}/RacingGameController.java (89%) rename src/test/java/{ => domain}/CarRaceGameTest.java (57%) rename src/test/java/{ => domain}/CarTest.java (60%) diff --git a/src/main/java/App.java b/src/main/java/App.java index 40650a95..3000b3c5 100644 --- a/src/main/java/App.java +++ b/src/main/java/App.java @@ -1,4 +1,4 @@ -import Controller.RacingGameController; +import controller.RacingGameController; public class App { public static void main(String[] args) { diff --git a/src/main/java/Controller/RacingGameController.java b/src/main/java/controller/RacingGameController.java similarity index 89% rename from src/main/java/Controller/RacingGameController.java rename to src/main/java/controller/RacingGameController.java index 16c4b642..412ab20d 100644 --- a/src/main/java/Controller/RacingGameController.java +++ b/src/main/java/controller/RacingGameController.java @@ -1,4 +1,4 @@ -package Controller; +package controller; import domain.Car; import domain.CarRaceGame; @@ -6,8 +6,7 @@ import view.inputView; import view.outputView; -import java.util.Arrays; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; public class RacingGameController { @@ -16,7 +15,6 @@ public class RacingGameController { public void startRacingGame(){ String names = inputView.enterCarNames(); - int round = inputView.enterRoundNumber(); List cars = Arrays.stream(names.split(DELIMITER)) .map(name -> new Car(name, new RandomNumberGenerator())) @@ -24,6 +22,10 @@ public void startRacingGame(){ final CarRaceGame carRaceGame = new CarRaceGame(cars); + int round = inputView.enterRoundNumber(); + + carRaceGame.validateRoundNumber(round); + outputView.printGameResultTitle(); for (int i = 0; i < round; i++) { @@ -34,14 +36,9 @@ public void startRacingGame(){ } - carRaceGame.playRacingGame(round); - List winnersName = carRaceGame.getWinnerNames(); outputView.printGameWinners(winnersName); - - - } } diff --git a/src/main/java/domain/Car.java b/src/main/java/domain/Car.java index 75874dd2..c8ebf32c 100644 --- a/src/main/java/domain/Car.java +++ b/src/main/java/domain/Car.java @@ -9,10 +9,9 @@ public class Car { private final NumberGenerator generator; private static final int MOVE_THRESHOLD = 4; - public Car(String name, NumberGenerator generator) { validateName(name); - this.name = name; + this.name = name.trim(); this.position = 0; this.generator = generator; } @@ -32,12 +31,9 @@ private void validateName(String name) { } if (name.length() > 5) { throw new IllegalArgumentException("이름은 5자 이하만 가능합니다."); - } - } - public void movePosition() { if (generator.generate() >= MOVE_THRESHOLD ) { position++; diff --git a/src/main/java/domain/CarRaceGame.java b/src/main/java/domain/CarRaceGame.java index 0bf69c7f..bd9b9560 100644 --- a/src/main/java/domain/CarRaceGame.java +++ b/src/main/java/domain/CarRaceGame.java @@ -1,6 +1,9 @@ package domain; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; public class CarRaceGame { @@ -9,9 +12,23 @@ public class CarRaceGame { public CarRaceGame(List cars) { this.cars = cars; + notAllowDuplicatedCarNames(); } - private void validateRoundNumber(int gameRound) { + private void notAllowDuplicatedCarNames() { + List carNames = cars.stream() + .map(Car::getName) + .collect(Collectors.toList()); + + Set carNameSet = new HashSet<>(carNames); // 중복된 이름은 자동으로 제거됨 + + // 만약 리스트의 크기와 Set의 크기가 다르면 중복이 있다는 의미 + if (carNames.size() != carNameSet.size()) { + throw new IllegalArgumentException("중복된 자동차 이름은 입력할 수 없습니다."); + } + } + + public void validateRoundNumber(int gameRound) { if (gameRound < 1 ) { throw new IllegalArgumentException("라운드는 한 번 이상 진행되어야 합니다."); } @@ -23,13 +40,6 @@ public void playOneRound() { } } -// private void carRacing(int gameRound) { -// validateRoundNumber(gameRound); -// for (int i= 0; i < gameRound; i++) { -// playOneRound(); -// } -// } - private int getMaxDistance() { int maxDistance = cars.stream().mapToInt(Car::getPosition).max().orElseThrow(); @@ -43,10 +53,14 @@ private List getWinners(int maxDistance) { } public void playRacingGame(int gameRound) { - winners = getWinners(getMaxDistance()); + for (int i=0; i < gameRound;i++) { + playOneRound(); + } } public List getWinnerNames() { + winners = getWinners(getMaxDistance()); + if (winners == null) { throw new IllegalStateException("게임이 실행되지 않았습니다."); } diff --git a/src/test/java/CarRaceGameTest.java b/src/test/java/domain/CarRaceGameTest.java similarity index 57% rename from src/test/java/CarRaceGameTest.java rename to src/test/java/domain/CarRaceGameTest.java index 5022e3a5..9879c6e3 100644 --- a/src/test/java/CarRaceGameTest.java +++ b/src/test/java/domain/CarRaceGameTest.java @@ -1,4 +1,5 @@ -import domain.*; +package domain; + import domain.Generator.FixedNumberGenerator; import domain.Generator.NumberGenerator; import domain.Generator.RandomNumberGenerator; @@ -7,6 +8,8 @@ import org.junit.jupiter.params.provider.ValueSource; import static org.assertj.core.api.Assertions.*; + +import java.util.Arrays; import java.util.List; import java.util.ArrayList; @@ -63,4 +66,51 @@ private List createCars(NumberGenerator... generators) { assertThat(game.getWinnerNames()).containsOnly("차1", "차3"); } + + @Test + void playRacingGame_참여자모두가우승자인경우_정상출력() { + List cars = createCars( + new FixedNumberGenerator(3, 1, 7, 9), + new FixedNumberGenerator(0, 4, 2, 8), + new FixedNumberGenerator(7, 2, 5, 1) + ); + + CarRaceGame game = new CarRaceGame(cars); + game.playRacingGame(4); + + assertThat(game.getWinnerNames()).containsOnly("차1", "차2", "차3"); + + } + + @Test + void playRacingGame_모든참여자가전진하지못한경우_정상출력() { + List cars = createCars( + new FixedNumberGenerator(3, 0, 2, 1), + new FixedNumberGenerator(0, 3, 1, 1), + new FixedNumberGenerator(0, 1, 0, 1) + ); + + CarRaceGame game = new CarRaceGame(cars); + game.playRacingGame(4); + + assertThat(game.getWinnerNames()).containsOnly("차1", "차2", "차3"); + + } + + @Test + void notAllowDuplicatedCarNames_중복된차이름_예외처리() { + + NumberGenerator generator = new RandomNumberGenerator(); + + Car car1 = new Car("차1", generator); + Car car2 = new Car("차3", generator); + Car car3 = new Car("차3", generator); + + List cars = Arrays.asList(car1, car2, car3); + + assertThatThrownBy(() -> new CarRaceGame(cars)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("중복된 자동차 이름은 입력할 수 없습니다."); + } + } diff --git a/src/test/java/CarTest.java b/src/test/java/domain/CarTest.java similarity index 60% rename from src/test/java/CarTest.java rename to src/test/java/domain/CarTest.java index 42f15b93..fea178e6 100644 --- a/src/test/java/CarTest.java +++ b/src/test/java/domain/CarTest.java @@ -1,4 +1,5 @@ -import domain.Car; +package domain; + import domain.Generator.FixedNumberGenerator; import domain.Generator.NumberGenerator; import domain.Generator.RandomNumberGenerator; @@ -23,6 +24,17 @@ public class CarTest { assertThat(car.getPosition()).isEqualTo(0); } + @Test + void Car_이름중복제거() { + + String carName = " 붕붕이"; + // given + NumberGenerator generator = new RandomNumberGenerator(); + Car car = new Car(carName, generator); + + assertThat(car.getName()).isEqualTo(carName.trim()); + } + @ParameterizedTest @ValueSource(strings = {"", " "}) void Car_이름빈값일경우_예외처리(String name) { @@ -34,6 +46,35 @@ public class CarTest { .hasMessageContaining("이름은 빈 값이 될 수 없습니다."); } + @Test + void Car_이름null값인경우_예외처리() { + + String name = null; + NumberGenerator generator = new RandomNumberGenerator(); + + assertThatThrownBy(() -> new Car(name,generator)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("이름은 빈 값이 될 수 없습니다."); + } + + @Test + void movePosition_기준값이상인경우_position이1증가한다() { + NumberGenerator generator = new FixedNumberGenerator(5); + Car car = new Car("차1", generator); + car.movePosition(); + + assertThat(car.getPosition()).isEqualTo(1); + } + + @Test + void movePosition_기준값미만인경우_position이변하지않는다() { + NumberGenerator generator = new FixedNumberGenerator(2); + Car car = new Car("차1", generator); + car.movePosition(); + + assertThat(car.getPosition()).isEqualTo(0); + } + @Test void getRandomNumber_랜덤숫자기준충족() { @@ -61,7 +102,7 @@ public class CarTest { } @Test - void movePosition_랜덤숫자3이하일때_정지() { + void movePosition_랜덤숫자4미만일때_정지() { // given NumberGenerator generator = new FixedNumberGenerator(2); From f21a6905e7b84ea776e2352d87541a032da9f991 Mon Sep 17 00:00:00 2001 From: boya-go Date: Sun, 11 May 2025 03:23:35 +0900 Subject: [PATCH 13/16] =?UTF-8?q?docs:=203=EB=8B=A8=EA=B3=84=20=EC=9A=94?= =?UTF-8?q?=EA=B5=AC=EC=82=AC=ED=95=AD=20=EA=B2=B0=EA=B3=BC=20=EB=B0=8F=20?= =?UTF-8?q?4=EB=8B=A8=EA=B3=84=20=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD,=20?= =?UTF-8?q?=EA=B2=B0=EA=B3=BC=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 1e5949d8..2f462c58 100644 --- a/README.md +++ b/README.md @@ -23,18 +23,25 @@ ## [3] 게임 실행 - 기능 요구사항 - - [ ] 자동차 및 게임 방법은 앞의 [움직이는 자동차], [우승 자동차 구하기]와 동일 - - [ ] 사용자로부터 `이름`, `게임횟수` 를 입력받는다. - - [ ] 자동차 이름은 쉼표(,) 기준으로 구분하며, 이름은 5자 이하만 가능하다. - - [ ] 메인 메서드를 추가하여 실행 가능하게 만든다. + - [x] 자동차 및 게임 방법은 앞의 [움직이는 자동차], [우승 자동차 구하기]와 동일 + - [x] 사용자로부터 `이름`, `게임횟수` 를 입력받는다. + - [x] 자동차 이름은 쉼표(,) 기준으로 구분하며, 이름은 5자 이하만 가능하다. + - [x] 메인 메서드를 추가하여 실행 가능하게 만든다. --- +## [4] 리팩터링 + +- 요구사항 + - [x] 단위 테스트를 구현한다. + +--- + - 코드 작성 요구사항 - - [ ] 자동차가 움직이는 기능이 의도대로 되는지 테스트한다. - - [ ] 자바 코드 컨벤션 `Java Style Guide` 원칙으로 프로그래밍한다. - - [ ] 3항 연산자를 쓰지 않는다. - - [ ] else 예약어를 쓰지 않는다. - - [ ] switch/case도 사용하지 않는다. - - [ ] 함수(또는 메서드) 길이가 15라인을 넘어가지 않도록 구현한다. - - [ ] 함수(또는 메서드)가 한 가지 일만 하도록 한다. + - [x] 자동차가 움직이는 기능이 의도대로 되는지 테스트한다. + - [x] 자바 코드 컨벤션 `Java Style Guide` 원칙으로 프로그래밍한다. + - [x] 3항 연산자를 쓰지 않는다. + - [x] else 예약어를 쓰지 않는다. + - [x] switch/case도 사용하지 않는다. + - [x] 함수(또는 메서드) 길이가 15라인을 넘어가지 않도록 구현한다. + - [x] 함수(또는 메서드)가 한 가지 일만 하도록 한다. From 51cd513a19789af04c8ca8935ad6e091cc106a85 Mon Sep 17 00:00:00 2001 From: boya-go Date: Thu, 15 May 2025 00:45:11 +0900 Subject: [PATCH 14/16] =?UTF-8?q?refactor:=20RacingGameController=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/RacingGameController.java | 32 +++++++++---------- src/main/java/domain/Car.java | 4 +-- src/main/java/domain/CarNameParser.java | 17 ++++++++++ src/main/java/domain/CarRaceGame.java | 8 ++--- .../FixedNumberGenerator.java | 2 +- .../NumberGenerator.java | 2 +- .../RandomNumberGenerator.java | 2 +- src/main/java/view/outputView.java | 2 +- src/test/java/domain/CarRaceGameTest.java | 9 +++--- src/test/java/domain/CarTest.java | 6 ++-- 10 files changed, 50 insertions(+), 34 deletions(-) create mode 100644 src/main/java/domain/CarNameParser.java rename src/main/java/domain/{Generator => generator}/FixedNumberGenerator.java (91%) rename src/main/java/domain/{Generator => generator}/NumberGenerator.java (69%) rename src/main/java/domain/{Generator => generator}/RandomNumberGenerator.java (90%) diff --git a/src/main/java/controller/RacingGameController.java b/src/main/java/controller/RacingGameController.java index 412ab20d..7392cd4f 100644 --- a/src/main/java/controller/RacingGameController.java +++ b/src/main/java/controller/RacingGameController.java @@ -1,40 +1,40 @@ package controller; import domain.Car; +import domain.CarNameParser; import domain.CarRaceGame; -import domain.Generator.RandomNumberGenerator; +import java.util.List; import view.inputView; import view.outputView; -import java.util.*; -import java.util.stream.Collectors; - public class RacingGameController { - public static final String DELIMITER = ","; - - public void startRacingGame(){ - String names = inputView.enterCarNames(); + public void startRacingGame() { + String carNames = inputView.enterCarNames(); + List cars = CarNameParser.parseCarName(carNames); + final CarRaceGame carRaceGame = new CarRaceGame(cars); + int round = inputView.enterRoundNumber(); - List cars = Arrays.stream(names.split(DELIMITER)) - .map(name -> new Car(name, new RandomNumberGenerator())) - .collect(Collectors.toList()); + outputView.printGameResultTitle(); - final CarRaceGame carRaceGame = new CarRaceGame(cars); + printGameRounds(carRaceGame, round, cars); - int round = inputView.enterRoundNumber(); + printWinners(carRaceGame); + } + private void printGameRounds(CarRaceGame carRaceGame, int round, List cars) { carRaceGame.validateRoundNumber(round); - outputView.printGameResultTitle(); - for (int i = 0; i < round; i++) { carRaceGame.playOneRound(); System.out.println(); outputView.printRoundResult(cars); - } + } + + + private void printWinners(CarRaceGame carRaceGame) { List winnersName = carRaceGame.getWinnerNames(); diff --git a/src/main/java/domain/Car.java b/src/main/java/domain/Car.java index c8ebf32c..16a01c54 100644 --- a/src/main/java/domain/Car.java +++ b/src/main/java/domain/Car.java @@ -1,10 +1,10 @@ package domain; -import domain.Generator.NumberGenerator; +import domain.generator.NumberGenerator; public class Car { - private String name; + private final String name; private int position; private final NumberGenerator generator; private static final int MOVE_THRESHOLD = 4; diff --git a/src/main/java/domain/CarNameParser.java b/src/main/java/domain/CarNameParser.java new file mode 100644 index 00000000..3602b145 --- /dev/null +++ b/src/main/java/domain/CarNameParser.java @@ -0,0 +1,17 @@ +package domain; + +import domain.generator.RandomNumberGenerator; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class CarNameParser { + + public static final String CAR_NAME_DELIMITER = ","; + + public static List parseCarName(String carNames) { + return Arrays.stream(carNames.split(CAR_NAME_DELIMITER)) + .map(name -> new Car(name, new RandomNumberGenerator())) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/domain/CarRaceGame.java b/src/main/java/domain/CarRaceGame.java index bd9b9560..067cbc85 100644 --- a/src/main/java/domain/CarRaceGame.java +++ b/src/main/java/domain/CarRaceGame.java @@ -7,8 +7,7 @@ public class CarRaceGame { - private List cars; - private List winners; + private final List cars; public CarRaceGame(List cars) { this.cars = cars; @@ -20,9 +19,8 @@ private void notAllowDuplicatedCarNames() { .map(Car::getName) .collect(Collectors.toList()); - Set carNameSet = new HashSet<>(carNames); // 중복된 이름은 자동으로 제거됨 + Set carNameSet = new HashSet<>(carNames); - // 만약 리스트의 크기와 Set의 크기가 다르면 중복이 있다는 의미 if (carNames.size() != carNameSet.size()) { throw new IllegalArgumentException("중복된 자동차 이름은 입력할 수 없습니다."); } @@ -59,7 +57,7 @@ public void playRacingGame(int gameRound) { } public List getWinnerNames() { - winners = getWinners(getMaxDistance()); + List winners = getWinners(getMaxDistance()); if (winners == null) { throw new IllegalStateException("게임이 실행되지 않았습니다."); diff --git a/src/main/java/domain/Generator/FixedNumberGenerator.java b/src/main/java/domain/generator/FixedNumberGenerator.java similarity index 91% rename from src/main/java/domain/Generator/FixedNumberGenerator.java rename to src/main/java/domain/generator/FixedNumberGenerator.java index c75827e6..e6404d07 100644 --- a/src/main/java/domain/Generator/FixedNumberGenerator.java +++ b/src/main/java/domain/generator/FixedNumberGenerator.java @@ -1,4 +1,4 @@ -package domain.Generator; +package domain.generator; public class FixedNumberGenerator implements NumberGenerator { private final int[] numbers; diff --git a/src/main/java/domain/Generator/NumberGenerator.java b/src/main/java/domain/generator/NumberGenerator.java similarity index 69% rename from src/main/java/domain/Generator/NumberGenerator.java rename to src/main/java/domain/generator/NumberGenerator.java index d058024b..8904aa58 100644 --- a/src/main/java/domain/Generator/NumberGenerator.java +++ b/src/main/java/domain/generator/NumberGenerator.java @@ -1,4 +1,4 @@ -package domain.Generator; +package domain.generator; public interface NumberGenerator { int generate(); diff --git a/src/main/java/domain/Generator/RandomNumberGenerator.java b/src/main/java/domain/generator/RandomNumberGenerator.java similarity index 90% rename from src/main/java/domain/Generator/RandomNumberGenerator.java rename to src/main/java/domain/generator/RandomNumberGenerator.java index b08e9eb3..10398566 100644 --- a/src/main/java/domain/Generator/RandomNumberGenerator.java +++ b/src/main/java/domain/generator/RandomNumberGenerator.java @@ -1,4 +1,4 @@ -package domain.Generator; +package domain.generator; import java.util.Random; diff --git a/src/main/java/view/outputView.java b/src/main/java/view/outputView.java index 3f7f0a4d..c1ed5b0d 100644 --- a/src/main/java/view/outputView.java +++ b/src/main/java/view/outputView.java @@ -10,7 +10,7 @@ public class outputView { private static final String WINNER_NAMES_DELIMITER = ","; public static void printGameResultTitle() { - System.out.println("\n실행 결과"); + System.out.print("\n실행 결과"); } public static void printRoundResult(List cars) { diff --git a/src/test/java/domain/CarRaceGameTest.java b/src/test/java/domain/CarRaceGameTest.java index 9879c6e3..6a0aacf8 100644 --- a/src/test/java/domain/CarRaceGameTest.java +++ b/src/test/java/domain/CarRaceGameTest.java @@ -1,13 +1,14 @@ package domain; -import domain.Generator.FixedNumberGenerator; -import domain.Generator.NumberGenerator; -import domain.Generator.RandomNumberGenerator; +import domain.generator.FixedNumberGenerator; +import domain.generator.NumberGenerator; +import domain.generator.RandomNumberGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.util.Arrays; import java.util.List; diff --git a/src/test/java/domain/CarTest.java b/src/test/java/domain/CarTest.java index fea178e6..c0095813 100644 --- a/src/test/java/domain/CarTest.java +++ b/src/test/java/domain/CarTest.java @@ -1,8 +1,8 @@ package domain; -import domain.Generator.FixedNumberGenerator; -import domain.Generator.NumberGenerator; -import domain.Generator.RandomNumberGenerator; +import domain.generator.FixedNumberGenerator; +import domain.generator.NumberGenerator; +import domain.generator.RandomNumberGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; From 960b262f66c818ed0d829d07cf04e371bcc51e62 Mon Sep 17 00:00:00 2001 From: boya-go Date: Thu, 15 May 2025 19:19:04 +0900 Subject: [PATCH 15/16] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EC=97=90=EB=A7=8C=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8A=94=20Fix?= =?UTF-8?q?edNumberGeneraotor=20=EA=B5=AC=ED=98=84=EC=B2=B4=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=ED=8C=A8=ED=82=A4=EC=A7=80=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99,=20@Nested=20=EC=82=AC=EC=9A=A9=ED=95=B4=20?= =?UTF-8?q?=EB=85=BC=EB=A6=AC=EC=A0=81=EC=9D=B8=20=EA=B5=AC=EC=A1=B0?= =?UTF-8?q?=EB=A1=9C=20=EA=B7=B8=EB=A3=B9=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/CarRaceGame.java | 2 + src/test/java/domain/CarRaceGameTest.java | 148 ++++++++++-------- src/test/java/domain/CarTest.java | 148 +++++++++--------- .../generator/FixedNumberGenerator.java | 0 4 files changed, 157 insertions(+), 141 deletions(-) rename src/{main => test}/java/domain/generator/FixedNumberGenerator.java (100%) diff --git a/src/main/java/domain/CarRaceGame.java b/src/main/java/domain/CarRaceGame.java index 067cbc85..6dcd4be8 100644 --- a/src/main/java/domain/CarRaceGame.java +++ b/src/main/java/domain/CarRaceGame.java @@ -51,6 +51,8 @@ private List getWinners(int maxDistance) { } public void playRacingGame(int gameRound) { + validateRoundNumber(gameRound); + for (int i=0; i < gameRound;i++) { playOneRound(); } diff --git a/src/test/java/domain/CarRaceGameTest.java b/src/test/java/domain/CarRaceGameTest.java index 6a0aacf8..b3e82cf2 100644 --- a/src/test/java/domain/CarRaceGameTest.java +++ b/src/test/java/domain/CarRaceGameTest.java @@ -3,6 +3,8 @@ import domain.generator.FixedNumberGenerator; import domain.generator.NumberGenerator; import domain.generator.RandomNumberGenerator; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -24,94 +26,108 @@ private List createCars(NumberGenerator... generators) { return cars; } - @ParameterizedTest - @ValueSource(ints = {0, -4}) - void playRacingGame_게임라운드0이하_예외처리(int gameRound) { - List cars = createCars( - new RandomNumberGenerator(), - new RandomNumberGenerator(), - new RandomNumberGenerator() - ); + @Nested + @DisplayName("게임에 참여한 차들의 이름은 중복이 없어야 한다.") + class CarRaceGameNameTest { - CarRaceGame game = new CarRaceGame(cars); + @Test + void notAllowDuplicatedCarNames_중복된차이름_예외처리() { - assertThatThrownBy(() -> game.playRacingGame(gameRound)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("라운드는 한 번 이상 진행되어야 합니다."); - } + NumberGenerator generator = new RandomNumberGenerator(); - @Test - void playRacingGame_우승자한명_정상출력() { - List cars = createCars( - new FixedNumberGenerator(9, 6, 4, 2, 5), - new FixedNumberGenerator(0, 2, 2, 1, 3), - new FixedNumberGenerator(1, 2, 5, 0, 9) - ); + Car car1 = new Car("차1", generator); + Car car2 = new Car("차3", generator); + Car car3 = new Car("차3", generator); - CarRaceGame game = new CarRaceGame(cars); - game.playRacingGame(5); + List cars = Arrays.asList(car1, car2, car3); - assertThat(game.getWinnerNames()).containsOnly("차1"); + assertThatThrownBy(() -> new CarRaceGame(cars)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("중복된 자동차 이름은 입력할 수 없습니다."); + } } - @Test - void playRacingGame_우승자두명_정상출력() { - List cars = createCars( - new FixedNumberGenerator(1, 8, 7), - new FixedNumberGenerator(0, 9, 2), - new FixedNumberGenerator(7, 2, 5) - ); + @Nested + @DisplayName("게임 라운드는 1 이상의 정수만 입력할 수 있다.") + class CarRaceGameRoundNumberTest { - CarRaceGame game = new CarRaceGame(cars); - game.playRacingGame(3); + @ParameterizedTest + @ValueSource(ints = {0, -4}) + void playRacingGame_게임라운드0이하_예외처리(int gameRound) { + List cars = createCars( + new RandomNumberGenerator(), + new RandomNumberGenerator(), + new RandomNumberGenerator() + ); - assertThat(game.getWinnerNames()).containsOnly("차1", "차3"); + CarRaceGame game = new CarRaceGame(cars); + + assertThatThrownBy(() -> game.playRacingGame(gameRound)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("라운드는 한 번 이상 진행되어야 합니다."); + } } - @Test - void playRacingGame_참여자모두가우승자인경우_정상출력() { - List cars = createCars( - new FixedNumberGenerator(3, 1, 7, 9), - new FixedNumberGenerator(0, 4, 2, 8), - new FixedNumberGenerator(7, 2, 5, 1) - ); + @Nested + @DisplayName("게임이 정상적으로 진행된 경우, 결과도 정상적으로 출력되어야 한다.") + class CarRaceGamePrintResultTest { - CarRaceGame game = new CarRaceGame(cars); - game.playRacingGame(4); + @Test + void playRacingGame_우승자한명_정상출력() { + List cars = createCars( + new FixedNumberGenerator(9, 6, 4, 2, 5), + new FixedNumberGenerator(0, 2, 2, 1, 3), + new FixedNumberGenerator(1, 2, 5, 0, 9) + ); - assertThat(game.getWinnerNames()).containsOnly("차1", "차2", "차3"); + CarRaceGame game = new CarRaceGame(cars); + game.playRacingGame(5); - } + assertThat(game.getWinnerNames()).containsOnly("차1"); + } - @Test - void playRacingGame_모든참여자가전진하지못한경우_정상출력() { - List cars = createCars( - new FixedNumberGenerator(3, 0, 2, 1), - new FixedNumberGenerator(0, 3, 1, 1), - new FixedNumberGenerator(0, 1, 0, 1) - ); + @Test + void playRacingGame_우승자두명_정상출력() { + List cars = createCars( + new FixedNumberGenerator(1, 8, 7), + new FixedNumberGenerator(0, 9, 2), + new FixedNumberGenerator(7, 2, 5) + ); - CarRaceGame game = new CarRaceGame(cars); - game.playRacingGame(4); + CarRaceGame game = new CarRaceGame(cars); + game.playRacingGame(3); - assertThat(game.getWinnerNames()).containsOnly("차1", "차2", "차3"); + assertThat(game.getWinnerNames()).containsOnly("차1", "차3"); + } - } + @Test + void playRacingGame_참여자모두가우승자인경우_정상출력() { + List cars = createCars( + new FixedNumberGenerator(3, 1, 7, 9), + new FixedNumberGenerator(0, 4, 2, 8), + new FixedNumberGenerator(7, 2, 5, 1) + ); - @Test - void notAllowDuplicatedCarNames_중복된차이름_예외처리() { + CarRaceGame game = new CarRaceGame(cars); + game.playRacingGame(4); - NumberGenerator generator = new RandomNumberGenerator(); + assertThat(game.getWinnerNames()).containsOnly("차1", "차2", "차3"); - Car car1 = new Car("차1", generator); - Car car2 = new Car("차3", generator); - Car car3 = new Car("차3", generator); + } - List cars = Arrays.asList(car1, car2, car3); + @Test + void playRacingGame_모든참여자가전진하지못한경우_정상출력() { + List cars = createCars( + new FixedNumberGenerator(3, 0, 2, 1), + new FixedNumberGenerator(0, 3, 1, 1), + new FixedNumberGenerator(0, 1, 0, 1) + ); - assertThatThrownBy(() -> new CarRaceGame(cars)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("중복된 자동차 이름은 입력할 수 없습니다."); - } + CarRaceGame game = new CarRaceGame(cars); + game.playRacingGame(4); + assertThat(game.getWinnerNames()).containsOnly("차1", "차2", "차3"); + + } + } } diff --git a/src/test/java/domain/CarTest.java b/src/test/java/domain/CarTest.java index c0095813..8da45a57 100644 --- a/src/test/java/domain/CarTest.java +++ b/src/test/java/domain/CarTest.java @@ -3,6 +3,8 @@ import domain.generator.FixedNumberGenerator; import domain.generator.NumberGenerator; import domain.generator.RandomNumberGenerator; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -12,107 +14,103 @@ public class CarTest { - @Test - void Car_객체생성() { + @Nested + @DisplayName("Car 객체가 생성된다.") + class CarCreateTest{ - // given - NumberGenerator generator = new RandomNumberGenerator(); - Car car = new Car("붕붕이", generator); + @Test + void Car_객체생성() { - // when - assertThat(car.getName()).isEqualTo("붕붕이"); - assertThat(car.getPosition()).isEqualTo(0); - } - - @Test - void Car_이름중복제거() { - - String carName = " 붕붕이"; - // given - NumberGenerator generator = new RandomNumberGenerator(); - Car car = new Car(carName, generator); + // given + NumberGenerator generator = new RandomNumberGenerator(); + Car car = new Car("붕붕이", generator); - assertThat(car.getName()).isEqualTo(carName.trim()); + // when + assertThat(car.getName()).isEqualTo("붕붕이"); + assertThat(car.getPosition()).isEqualTo(0); + } } - @ParameterizedTest - @ValueSource(strings = {"", " "}) - void Car_이름빈값일경우_예외처리(String name) { + @Nested + @DisplayName("Car 객체의 이름으로 입력된 값을 검증한다.") + class CarNameTest{ - NumberGenerator generator = new RandomNumberGenerator(); + @Test + void Car_이름중복제거() { - assertThatThrownBy(() -> new Car(name,generator)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("이름은 빈 값이 될 수 없습니다."); - } + String carName = " 붕붕이"; + // given + NumberGenerator generator = new RandomNumberGenerator(); + Car car = new Car(carName, generator); - @Test - void Car_이름null값인경우_예외처리() { + assertThat(car.getName()).isEqualTo(carName.trim()); + } - String name = null; - NumberGenerator generator = new RandomNumberGenerator(); + @ParameterizedTest + @ValueSource(strings = {"", " "}) + void Car_이름빈값일경우_예외처리(String name) { - assertThatThrownBy(() -> new Car(name,generator)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("이름은 빈 값이 될 수 없습니다."); - } + NumberGenerator generator = new RandomNumberGenerator(); - @Test - void movePosition_기준값이상인경우_position이1증가한다() { - NumberGenerator generator = new FixedNumberGenerator(5); - Car car = new Car("차1", generator); - car.movePosition(); + assertThatThrownBy(() -> new Car(name,generator)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("이름은 빈 값이 될 수 없습니다."); + } - assertThat(car.getPosition()).isEqualTo(1); - } + @Test + void Car_이름null값인경우_예외처리() { - @Test - void movePosition_기준값미만인경우_position이변하지않는다() { - NumberGenerator generator = new FixedNumberGenerator(2); - Car car = new Car("차1", generator); - car.movePosition(); + String name = null; + NumberGenerator generator = new RandomNumberGenerator(); - assertThat(car.getPosition()).isEqualTo(0); + assertThatThrownBy(() -> new Car(name,generator)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("이름은 빈 값이 될 수 없습니다."); + } } - @Test - void getRandomNumber_랜덤숫자기준충족() { + @Nested + @DisplayName("Car 객체가 요구사항에 맞게 이동한다.") + class CarPositionTest{ - NumberGenerator generator = new RandomNumberGenerator(); + @Test + void getRandomNumber_랜덤숫자기준충족() { - Car car = new Car("차1",generator); - assertThat(generator.generate()) - .isGreaterThanOrEqualTo( 0) - .isLessThanOrEqualTo( 9); - } + NumberGenerator generator = new RandomNumberGenerator(); - @Test - void movePosition_랜덤숫자4이상일때_1이동() { + Car car = new Car("차1",generator); + assertThat(generator.generate()) + .isGreaterThanOrEqualTo( 0) + .isLessThanOrEqualTo( 9); + } - NumberGenerator generator = new FixedNumberGenerator(5); + @Test + void movePosition_랜덤숫자4이상일때_1이동() { - // given - Car car = new Car("차2", generator); + NumberGenerator generator = new FixedNumberGenerator(5); - // when - car.movePosition(); + // given + Car car = new Car("차2", generator); - // then - assertThat(car.getPosition()).isEqualTo(1); - } + // when + car.movePosition(); - @Test - void movePosition_랜덤숫자4미만일때_정지() { + // then + assertThat(car.getPosition()).isEqualTo(1); + } - // given - NumberGenerator generator = new FixedNumberGenerator(2); - Car car = new Car("차3", generator); + @Test + void movePosition_랜덤숫자4미만일때_정지() { - // when - car.movePosition(); + // given + NumberGenerator generator = new FixedNumberGenerator(2); + Car car = new Car("차3", generator); - // then - assertThat(car.getPosition()).isEqualTo(0); + // when + car.movePosition(); + + // then + assertThat(car.getPosition()).isEqualTo(0); + } } } - diff --git a/src/main/java/domain/generator/FixedNumberGenerator.java b/src/test/java/domain/generator/FixedNumberGenerator.java similarity index 100% rename from src/main/java/domain/generator/FixedNumberGenerator.java rename to src/test/java/domain/generator/FixedNumberGenerator.java From f5fe5920857f1375016b98e1a40779678f66cafc Mon Sep 17 00:00:00 2001 From: boya-go Date: Fri, 16 May 2025 00:08:14 +0900 Subject: [PATCH 16/16] =?UTF-8?q?refactor:=20=EB=B3=80=EC=88=98=EC=97=90?= =?UTF-8?q?=20=EA=B0=92=20=ED=95=A0=EB=8B=B9=20=EC=9D=B4=EC=A0=84=EC=97=90?= =?UTF-8?q?=20=EA=B2=80=EC=A6=9D=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/RacingGameController.java | 1 + src/main/java/domain/CarNameParser.java | 22 ++++++- src/main/java/domain/CarRaceGame.java | 28 +++------ src/test/java/domain/CarNameParserTest.java | 59 +++++++++++++++++++ src/test/java/domain/CarRaceGameTest.java | 22 ------- 5 files changed, 88 insertions(+), 44 deletions(-) create mode 100644 src/test/java/domain/CarNameParserTest.java diff --git a/src/main/java/controller/RacingGameController.java b/src/main/java/controller/RacingGameController.java index 7392cd4f..358b39c9 100644 --- a/src/main/java/controller/RacingGameController.java +++ b/src/main/java/controller/RacingGameController.java @@ -13,6 +13,7 @@ public void startRacingGame() { String carNames = inputView.enterCarNames(); List cars = CarNameParser.parseCarName(carNames); final CarRaceGame carRaceGame = new CarRaceGame(cars); + int round = inputView.enterRoundNumber(); outputView.printGameResultTitle(); diff --git a/src/main/java/domain/CarNameParser.java b/src/main/java/domain/CarNameParser.java index 3602b145..19e410af 100644 --- a/src/main/java/domain/CarNameParser.java +++ b/src/main/java/domain/CarNameParser.java @@ -2,7 +2,9 @@ import domain.generator.RandomNumberGenerator; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; public class CarNameParser { @@ -10,8 +12,24 @@ public class CarNameParser { public static final String CAR_NAME_DELIMITER = ","; public static List parseCarName(String carNames) { - return Arrays.stream(carNames.split(CAR_NAME_DELIMITER)) - .map(name -> new Car(name, new RandomNumberGenerator())) + + List carNameList = Arrays.stream(carNames.split(CAR_NAME_DELIMITER)) + .map(String::trim) + .collect(Collectors.toList()); + + validateDuplicateCarName(carNameList); + + return carNameList.stream() + .map(name -> new Car(name.trim(), new RandomNumberGenerator())) .collect(Collectors.toList()); } + + private static void validateDuplicateCarName(List carNameList) { + + Set uniqueCarNames = new HashSet<>(carNameList); + + if (uniqueCarNames.size() != carNameList.size()) { + throw new IllegalArgumentException("중복된 자동차 이름은 입력할 수 없습니다."); + } + } } diff --git a/src/main/java/domain/CarRaceGame.java b/src/main/java/domain/CarRaceGame.java index 6dcd4be8..249c7354 100644 --- a/src/main/java/domain/CarRaceGame.java +++ b/src/main/java/domain/CarRaceGame.java @@ -1,9 +1,6 @@ package domain; -import java.util.HashSet; import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; public class CarRaceGame { @@ -11,19 +8,6 @@ public class CarRaceGame { public CarRaceGame(List cars) { this.cars = cars; - notAllowDuplicatedCarNames(); - } - - private void notAllowDuplicatedCarNames() { - List carNames = cars.stream() - .map(Car::getName) - .collect(Collectors.toList()); - - Set carNameSet = new HashSet<>(carNames); - - if (carNames.size() != carNameSet.size()) { - throw new IllegalArgumentException("중복된 자동차 이름은 입력할 수 없습니다."); - } } public void validateRoundNumber(int gameRound) { @@ -39,15 +23,19 @@ public void playOneRound() { } private int getMaxDistance() { - int maxDistance = cars.stream().mapToInt(Car::getPosition).max().orElseThrow(); + int maxDistance = cars.stream() + .mapToInt(Car::getPosition) + .max() + .orElseThrow(); return maxDistance; } private List getWinners(int maxDistance) { - List winners = cars.stream().filter(car -> car.getPosition() == maxDistance).map(Car::getName).toList(); - - return winners; + return cars.stream() + .filter(car -> car.getPosition() == maxDistance) + .map(Car::getName) + .toList(); } public void playRacingGame(int gameRound) { diff --git a/src/test/java/domain/CarNameParserTest.java b/src/test/java/domain/CarNameParserTest.java new file mode 100644 index 00000000..606374cc --- /dev/null +++ b/src/test/java/domain/CarNameParserTest.java @@ -0,0 +1,59 @@ +package domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +public class CarNameParserTest { + + @Nested + @DisplayName("입력된 문자열은 구분자로 나누어 차의 이름이 된다.") + class ParseCarNameTest { + + @Test + @DisplayName("공백없이 들어왔을 경우") + public void parseCarName_문자열을입력하면_차이름리스트가생성된다() { + + // given + String carNames = "차1,차2,차3"; + + // when + List cars = CarNameParser.parseCarName(carNames); + + // then + assertThat(cars).extracting(Car::getName).containsExactly("차1", "차2", "차3"); + + } + + @Test + @DisplayName("공백 포함해 들어왔을 경우") + public void parseCarName_구분자기준으로공백이포함된경우_공백제거후차이름리스트가생성된다() { + + // given + String carNames = "차1 , 차2,차3 "; + + // when + List cars = CarNameParser.parseCarName(carNames); + + // then + assertThat(cars).extracting(Car::getName).containsExactly("차1", "차2", "차3"); + + } + } + + @Test + @DisplayName("입력된 차들의 이름은 중복이 없어야 한다.") + public void parseCarName_중복된차이름_예외처리() { + // given + CarNameParser carNameParser = new CarNameParser(); + String carNames = "차1,차1,차3"; + + assertThatThrownBy(() -> carNameParser.parseCarName(carNames)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("중복된 자동차 이름은 입력할 수 없습니다."); + } +} diff --git a/src/test/java/domain/CarRaceGameTest.java b/src/test/java/domain/CarRaceGameTest.java index b3e82cf2..d740fffe 100644 --- a/src/test/java/domain/CarRaceGameTest.java +++ b/src/test/java/domain/CarRaceGameTest.java @@ -12,7 +12,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import java.util.Arrays; import java.util.List; import java.util.ArrayList; @@ -26,27 +25,6 @@ private List createCars(NumberGenerator... generators) { return cars; } - @Nested - @DisplayName("게임에 참여한 차들의 이름은 중복이 없어야 한다.") - class CarRaceGameNameTest { - - @Test - void notAllowDuplicatedCarNames_중복된차이름_예외처리() { - - NumberGenerator generator = new RandomNumberGenerator(); - - Car car1 = new Car("차1", generator); - Car car2 = new Car("차3", generator); - Car car3 = new Car("차3", generator); - - List cars = Arrays.asList(car1, car2, car3); - - assertThatThrownBy(() -> new CarRaceGame(cars)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("중복된 자동차 이름은 입력할 수 없습니다."); - } - } - @Nested @DisplayName("게임 라운드는 1 이상의 정수만 입력할 수 있다.") class CarRaceGameRoundNumberTest {