From d9f9463ce2a0aec8c59f7790ace496b14f71b124 Mon Sep 17 00:00:00 2001 From: qkrcodus Date: Thu, 8 May 2025 17:48:48 +0900 Subject: [PATCH 01/13] =?UTF-8?q?feat=20:=201=EB=8B=A8=EA=B3=84=20?= =?UTF-8?q?=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 --- src/main/java/car/Car.java | 26 +++++++++++++++++++ .../generator/random/RandomGenerator.java | 5 ++++ .../random/ZeroToNineRandomGenerator.java | 11 ++++++++ .../decider/GreaterThanFourMoveDecider.java | 14 ++++++++++ src/main/java/move/decider/MoveDecider.java | 5 ++++ src/main/java/move/strategy/MoveStrategy.java | 5 ++++ .../move/strategy/OneStepMoveStrategy.java | 10 +++++++ 7 files changed, 76 insertions(+) create mode 100644 src/main/java/car/Car.java create mode 100644 src/main/java/generator/random/RandomGenerator.java create mode 100644 src/main/java/generator/random/ZeroToNineRandomGenerator.java create mode 100644 src/main/java/move/decider/GreaterThanFourMoveDecider.java create mode 100644 src/main/java/move/decider/MoveDecider.java create mode 100644 src/main/java/move/strategy/MoveStrategy.java create mode 100644 src/main/java/move/strategy/OneStepMoveStrategy.java diff --git a/src/main/java/car/Car.java b/src/main/java/car/Car.java new file mode 100644 index 00000000..f2d7fe80 --- /dev/null +++ b/src/main/java/car/Car.java @@ -0,0 +1,26 @@ +package car; + +import move.strategy.MoveStrategy; + +public class Car { + private final String name; + private int movedDistance=0; + private final MoveStrategy moveStrategy; + + public Car(String name,MoveStrategy moveStrategy) { + this.name=name; + this.moveStrategy=moveStrategy; + } + + public void move(){ + int distance=moveStrategy.addStepSize(); + movedDistance+=distance; + } + + public int getMovedDistance() { + return movedDistance; + } + public String getName() { + return name; + } +} diff --git a/src/main/java/generator/random/RandomGenerator.java b/src/main/java/generator/random/RandomGenerator.java new file mode 100644 index 00000000..9eca1d64 --- /dev/null +++ b/src/main/java/generator/random/RandomGenerator.java @@ -0,0 +1,5 @@ +package generator.random; + +public interface RandomGenerator { + int generate(); +} diff --git a/src/main/java/generator/random/ZeroToNineRandomGenerator.java b/src/main/java/generator/random/ZeroToNineRandomGenerator.java new file mode 100644 index 00000000..6f4f7a2b --- /dev/null +++ b/src/main/java/generator/random/ZeroToNineRandomGenerator.java @@ -0,0 +1,11 @@ +package generator.random; +import java.util.Random; + +public class ZeroToNineRandomGenerator implements RandomGenerator { + private final Random random=new Random(); + + @Override + public int generate() { + return random.nextInt(10); + } +} diff --git a/src/main/java/move/decider/GreaterThanFourMoveDecider.java b/src/main/java/move/decider/GreaterThanFourMoveDecider.java new file mode 100644 index 00000000..b550cde4 --- /dev/null +++ b/src/main/java/move/decider/GreaterThanFourMoveDecider.java @@ -0,0 +1,14 @@ +package move.decider; + +public class GreaterThanFourMoveDecider implements MoveDecider { + private static final int MOVE_THRESHOLD = 4; + + @Override + public boolean canMove(int randomNumber){ + return isGreaterThanOrEqualToThreshold(randomNumber); + } + + private boolean isGreaterThanOrEqualToThreshold(int randomNumber){ + return randomNumber >= MOVE_THRESHOLD; + } +} diff --git a/src/main/java/move/decider/MoveDecider.java b/src/main/java/move/decider/MoveDecider.java new file mode 100644 index 00000000..7583c5a6 --- /dev/null +++ b/src/main/java/move/decider/MoveDecider.java @@ -0,0 +1,5 @@ +package move.decider; + +public interface MoveDecider { + public boolean canMove(int randomNumber); +} diff --git a/src/main/java/move/strategy/MoveStrategy.java b/src/main/java/move/strategy/MoveStrategy.java new file mode 100644 index 00000000..7c616a35 --- /dev/null +++ b/src/main/java/move/strategy/MoveStrategy.java @@ -0,0 +1,5 @@ +package move.strategy; + +public interface MoveStrategy { + int addStepSize(); +} diff --git a/src/main/java/move/strategy/OneStepMoveStrategy.java b/src/main/java/move/strategy/OneStepMoveStrategy.java new file mode 100644 index 00000000..678efb58 --- /dev/null +++ b/src/main/java/move/strategy/OneStepMoveStrategy.java @@ -0,0 +1,10 @@ +package move.strategy; + +public class OneStepMoveStrategy implements MoveStrategy { + private static final int STEP_SIZE = 1; + + @Override + public int addStepSize(){ + return STEP_SIZE; + } +} From 6fe844e93b2a05ee38efd2db6ba478812367c859 Mon Sep 17 00:00:00 2001 From: qkrcodus Date: Thu, 8 May 2025 17:53:33 +0900 Subject: [PATCH 02/13] =?UTF-8?q?fix=20:=20OneStepMoveStrategy=20=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=A1=B0=EA=B1=B4=20=EB=A7=8C=EC=A1=B1=ED=95=A0?= =?UTF-8?q?=EB=95=8C=20=EC=9E=90=EB=8F=99=EC=B0=A8=EA=B0=80=20=EC=9B=80?= =?UTF-8?q?=EC=A7=81=EC=9D=BC=20=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/move/strategy/OneStepMoveStrategy.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/move/strategy/OneStepMoveStrategy.java b/src/main/java/move/strategy/OneStepMoveStrategy.java index 678efb58..9bbb7772 100644 --- a/src/main/java/move/strategy/OneStepMoveStrategy.java +++ b/src/main/java/move/strategy/OneStepMoveStrategy.java @@ -1,10 +1,23 @@ package move.strategy; +import generator.random.RandomGenerator; +import move.decider.MoveDecider; + public class OneStepMoveStrategy implements MoveStrategy { private static final int STEP_SIZE = 1; + private final RandomGenerator randomGenerator; + private final MoveDecider moveDecider; + + public OneStepMoveStrategy(RandomGenerator randomGenerator, MoveDecider moveDecider) { + this.randomGenerator = randomGenerator; + this.moveDecider = moveDecider; + } @Override public int addStepSize(){ - return STEP_SIZE; + int randomNumber=randomGenerator.generate(); + if(moveDecider.canMove(randomNumber)){ + return STEP_SIZE; + }else return 0; } } From 86787ab82c193d741e4b43160a07593f822f3760 Mon Sep 17 00:00:00 2001 From: qkrcodus Date: Thu, 8 May 2025 20:01:32 +0900 Subject: [PATCH 03/13] =?UTF-8?q?fix=20:=20else=20=EC=98=88=EC=95=BD?= =?UTF-8?q?=EC=96=B4=20=EC=97=86=EC=95=A0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/move/strategy/OneStepMoveStrategy.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/move/strategy/OneStepMoveStrategy.java b/src/main/java/move/strategy/OneStepMoveStrategy.java index 9bbb7772..81ff89db 100644 --- a/src/main/java/move/strategy/OneStepMoveStrategy.java +++ b/src/main/java/move/strategy/OneStepMoveStrategy.java @@ -18,6 +18,7 @@ public int addStepSize(){ int randomNumber=randomGenerator.generate(); if(moveDecider.canMove(randomNumber)){ return STEP_SIZE; - }else return 0; + } + return 0; } } From 1439fb346fc5e59c2364d923c4d28ee37f88cb4e Mon Sep 17 00:00:00 2001 From: qkrcodus Date: Fri, 9 May 2025 14:52:54 +0900 Subject: [PATCH 04/13] =?UTF-8?q?refactor=20:=20MoveDecider=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=EC=B2=B4=20=EC=B1=85=EC=9E=84=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../move/decider/GreaterThanFourMoveDecider.java | 14 -------------- src/main/java/move/decider/MoveDecider.java | 2 +- .../move/decider/ThresholdBaseMoveDecider.java | 16 ++++++++++++++++ .../evalutaor/GreaterThanOrEqualThreshold.java | 13 +++++++++++++ .../java/move/evalutaor/ThresholdEvaluator.java | 5 +++++ 5 files changed, 35 insertions(+), 15 deletions(-) delete mode 100644 src/main/java/move/decider/GreaterThanFourMoveDecider.java create mode 100644 src/main/java/move/decider/ThresholdBaseMoveDecider.java create mode 100644 src/main/java/move/evalutaor/GreaterThanOrEqualThreshold.java create mode 100644 src/main/java/move/evalutaor/ThresholdEvaluator.java diff --git a/src/main/java/move/decider/GreaterThanFourMoveDecider.java b/src/main/java/move/decider/GreaterThanFourMoveDecider.java deleted file mode 100644 index b550cde4..00000000 --- a/src/main/java/move/decider/GreaterThanFourMoveDecider.java +++ /dev/null @@ -1,14 +0,0 @@ -package move.decider; - -public class GreaterThanFourMoveDecider implements MoveDecider { - private static final int MOVE_THRESHOLD = 4; - - @Override - public boolean canMove(int randomNumber){ - return isGreaterThanOrEqualToThreshold(randomNumber); - } - - private boolean isGreaterThanOrEqualToThreshold(int randomNumber){ - return randomNumber >= MOVE_THRESHOLD; - } -} diff --git a/src/main/java/move/decider/MoveDecider.java b/src/main/java/move/decider/MoveDecider.java index 7583c5a6..8439badd 100644 --- a/src/main/java/move/decider/MoveDecider.java +++ b/src/main/java/move/decider/MoveDecider.java @@ -1,5 +1,5 @@ package move.decider; public interface MoveDecider { - public boolean canMove(int randomNumber); + boolean canMove(int randomNumber); } diff --git a/src/main/java/move/decider/ThresholdBaseMoveDecider.java b/src/main/java/move/decider/ThresholdBaseMoveDecider.java new file mode 100644 index 00000000..cacbd987 --- /dev/null +++ b/src/main/java/move/decider/ThresholdBaseMoveDecider.java @@ -0,0 +1,16 @@ +package move.decider; + +import move.evalutaor.ThresholdEvaluator; + +public class ThresholdBaseMoveDecider implements MoveDecider { + private final ThresholdEvaluator evaluator; + + public ThresholdBaseMoveDecider(ThresholdEvaluator evaluator) { + this.evaluator = evaluator; + } + + @Override + public boolean canMove(int randomNumber){ + return evaluator.isSatisfied(randomNumber); + } +} diff --git a/src/main/java/move/evalutaor/GreaterThanOrEqualThreshold.java b/src/main/java/move/evalutaor/GreaterThanOrEqualThreshold.java new file mode 100644 index 00000000..dfafc509 --- /dev/null +++ b/src/main/java/move/evalutaor/GreaterThanOrEqualThreshold.java @@ -0,0 +1,13 @@ +package move.evalutaor; + +public class GreaterThanOrEqualThreshold implements ThresholdEvaluator { + private final int threshold; + + public GreaterThanOrEqualThreshold(int threshold) { + this.threshold = threshold; + } + @Override + public boolean isSatisfied(int value){ + return value >= threshold; + } +} diff --git a/src/main/java/move/evalutaor/ThresholdEvaluator.java b/src/main/java/move/evalutaor/ThresholdEvaluator.java new file mode 100644 index 00000000..18675a15 --- /dev/null +++ b/src/main/java/move/evalutaor/ThresholdEvaluator.java @@ -0,0 +1,5 @@ +package move.evalutaor; + +public interface ThresholdEvaluator { + boolean isSatisfied(int value); +} From 03c00c6d33ece6b102574f764f905e3045e8dc11 Mon Sep 17 00:00:00 2001 From: qkrcodus Date: Fri, 9 May 2025 14:55:05 +0900 Subject: [PATCH 05/13] =?UTF-8?q?test=20:=20Car=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EB=8B=A8=EC=9C=84=20=ED=85=8C=EC=8A=A4=ED=8A=B8=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/test/java/CarTest.java | 57 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 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..02055f7a --- /dev/null +++ b/src/test/java/CarTest.java @@ -0,0 +1,57 @@ +import car.Car; +import generator.random.RandomGenerator; +import move.decider.MoveDecider; +import move.strategy.MoveStrategy; +import move.strategy.OneStepMoveStrategy; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CarTest { + + @DisplayName("랜덤값이 조건을 만족할 경우 자동차는 1칸 전진한다") + @Test + void 움직일_수_있을_때_1칸_전진() { + // given + RandomGenerator fixedGenerator = () -> 7; // 7을 반환 + MoveDecider alwaysTrueDecider = (number) -> true; // 항상 움직임 + MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, alwaysTrueDecider); + Car car = new Car("car1", strategy); + + // when + car.move(); + + // then + assertThat(car.getMovedDistance()).isEqualTo(1); + } + + + @DisplayName("랜덤값이 조건을 만족하지 않을 경우 자동차는 전진하지 않는다") + @Test + void 움직일_수_없을_때_전진_하지_않음() { + RandomGenerator fixedGenerator = () -> 2; + MoveDecider alwaysFalseDecider = (number) -> false; + MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, alwaysFalseDecider); + Car car = new Car("car2", strategy); + + car.move(); + + assertThat(car.getMovedDistance()).isEqualTo(0); + } + + @DisplayName("자동차는 여러 번 움직일 경우 이동 거리가 누적된다") + @Test + void 여러번_움직이면_누적됨() { + RandomGenerator fixedGenerator = () -> 8; + MoveDecider alwaysTrueDecider = (number) -> true; + MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, alwaysTrueDecider); + Car car = new Car("car3", strategy); + + car.move(); + car.move(); + car.move(); + + assertThat(car.getMovedDistance()).isEqualTo(3); + } +} From e6a63bedbc9dc1a6b7f8fdbd1bb5e2fd4e3f606a Mon Sep 17 00:00:00 2001 From: qkrcodus Date: Fri, 9 May 2025 15:56:21 +0900 Subject: [PATCH 06/13] =?UTF-8?q?refactor=20:=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=EC=97=90=EC=84=9C=20ThresholdBas?= =?UTF-8?q?eMoveDecider,=20GreaterThanOrEqualThreshold=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=EC=B2=B4=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/car/Car.java | 1 + .../decider/ThresholdBaseMoveDecider.java | 2 +- .../GreaterThanOrEqualThreshold.java | 2 +- .../ThresholdEvaluator.java | 2 +- src/test/java/CarTest.java | 20 ++++++++++++------- 5 files changed, 17 insertions(+), 10 deletions(-) rename src/main/java/move/{evalutaor => evaluator}/GreaterThanOrEqualThreshold.java (92%) rename src/main/java/move/{evalutaor => evaluator}/ThresholdEvaluator.java (76%) diff --git a/src/main/java/car/Car.java b/src/main/java/car/Car.java index f2d7fe80..4e4b0b00 100644 --- a/src/main/java/car/Car.java +++ b/src/main/java/car/Car.java @@ -5,6 +5,7 @@ public class Car { private final String name; private int movedDistance=0; + private final MoveStrategy moveStrategy; public Car(String name,MoveStrategy moveStrategy) { diff --git a/src/main/java/move/decider/ThresholdBaseMoveDecider.java b/src/main/java/move/decider/ThresholdBaseMoveDecider.java index cacbd987..efb5e32f 100644 --- a/src/main/java/move/decider/ThresholdBaseMoveDecider.java +++ b/src/main/java/move/decider/ThresholdBaseMoveDecider.java @@ -1,6 +1,6 @@ package move.decider; -import move.evalutaor.ThresholdEvaluator; +import move.evaluator.ThresholdEvaluator; public class ThresholdBaseMoveDecider implements MoveDecider { private final ThresholdEvaluator evaluator; diff --git a/src/main/java/move/evalutaor/GreaterThanOrEqualThreshold.java b/src/main/java/move/evaluator/GreaterThanOrEqualThreshold.java similarity index 92% rename from src/main/java/move/evalutaor/GreaterThanOrEqualThreshold.java rename to src/main/java/move/evaluator/GreaterThanOrEqualThreshold.java index dfafc509..3d357492 100644 --- a/src/main/java/move/evalutaor/GreaterThanOrEqualThreshold.java +++ b/src/main/java/move/evaluator/GreaterThanOrEqualThreshold.java @@ -1,4 +1,4 @@ -package move.evalutaor; +package move.evaluator; public class GreaterThanOrEqualThreshold implements ThresholdEvaluator { private final int threshold; diff --git a/src/main/java/move/evalutaor/ThresholdEvaluator.java b/src/main/java/move/evaluator/ThresholdEvaluator.java similarity index 76% rename from src/main/java/move/evalutaor/ThresholdEvaluator.java rename to src/main/java/move/evaluator/ThresholdEvaluator.java index 18675a15..d11df755 100644 --- a/src/main/java/move/evalutaor/ThresholdEvaluator.java +++ b/src/main/java/move/evaluator/ThresholdEvaluator.java @@ -1,4 +1,4 @@ -package move.evalutaor; +package move.evaluator; public interface ThresholdEvaluator { boolean isSatisfied(int value); diff --git a/src/test/java/CarTest.java b/src/test/java/CarTest.java index 02055f7a..5370a553 100644 --- a/src/test/java/CarTest.java +++ b/src/test/java/CarTest.java @@ -1,6 +1,9 @@ import car.Car; import generator.random.RandomGenerator; import move.decider.MoveDecider; +import move.decider.ThresholdBaseMoveDecider; +import move.evaluator.GreaterThanOrEqualThreshold; +import move.evaluator.ThresholdEvaluator; import move.strategy.MoveStrategy; import move.strategy.OneStepMoveStrategy; import org.junit.jupiter.api.DisplayName; @@ -14,9 +17,10 @@ public class CarTest { @Test void 움직일_수_있을_때_1칸_전진() { // given - RandomGenerator fixedGenerator = () -> 7; // 7을 반환 - MoveDecider alwaysTrueDecider = (number) -> true; // 항상 움직임 - MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, alwaysTrueDecider); + RandomGenerator fixedGenerator = () -> 7; + ThresholdEvaluator evaluator=new GreaterThanOrEqualThreshold(4); + MoveDecider decider= new ThresholdBaseMoveDecider(evaluator); + MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, decider); Car car = new Car("car1", strategy); // when @@ -31,8 +35,9 @@ public class CarTest { @Test void 움직일_수_없을_때_전진_하지_않음() { RandomGenerator fixedGenerator = () -> 2; - MoveDecider alwaysFalseDecider = (number) -> false; - MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, alwaysFalseDecider); + ThresholdEvaluator evaluator=new GreaterThanOrEqualThreshold(4); + MoveDecider decider= new ThresholdBaseMoveDecider(evaluator); + MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, decider); Car car = new Car("car2", strategy); car.move(); @@ -44,8 +49,9 @@ public class CarTest { @Test void 여러번_움직이면_누적됨() { RandomGenerator fixedGenerator = () -> 8; - MoveDecider alwaysTrueDecider = (number) -> true; - MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, alwaysTrueDecider); + ThresholdEvaluator evaluator=new GreaterThanOrEqualThreshold(4); + MoveDecider decider= new ThresholdBaseMoveDecider(evaluator); + MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, decider); Car car = new Car("car3", strategy); car.move(); From ed438b1568d7d19ee27eedfe4c5a32c8749cf76a Mon Sep 17 00:00:00 2001 From: qkrcodus Date: Fri, 9 May 2025 16:17:25 +0900 Subject: [PATCH 07/13] =?UTF-8?q?refactor=20:=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=EC=97=90=20getName()=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 --- src/test/java/CarTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/java/CarTest.java b/src/test/java/CarTest.java index 5370a553..11bf69f9 100644 --- a/src/test/java/CarTest.java +++ b/src/test/java/CarTest.java @@ -28,6 +28,7 @@ public class CarTest { // then assertThat(car.getMovedDistance()).isEqualTo(1); + assertThat(car.getName()).isEqualTo("car1"); } @@ -43,6 +44,7 @@ public class CarTest { car.move(); assertThat(car.getMovedDistance()).isEqualTo(0); + assertThat(car.getName()).isEqualTo("car2"); } @DisplayName("자동차는 여러 번 움직일 경우 이동 거리가 누적된다") @@ -59,5 +61,6 @@ public class CarTest { car.move(); assertThat(car.getMovedDistance()).isEqualTo(3); + assertThat(car.getName()).isEqualTo("car3"); } } From 86900bb3e0a6162a9b7a735427856e9cc0261fc3 Mon Sep 17 00:00:00 2001 From: qkrcodus Date: Fri, 9 May 2025 21:58:24 +0900 Subject: [PATCH 08/13] =?UTF-8?q?feat=20:=203=EB=8B=A8=EA=B3=84=20?= =?UTF-8?q?=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 --- build.gradle | 1 + src/main/java/car/Car.java | 2 +- .../generator/random/RandomGenerator.java | 2 +- .../random/ZeroToNineRandomGenerator.java | 2 +- .../{ => car}/move/decider/MoveDecider.java | 2 +- .../decider/ThresholdBaseMoveDecider.java | 4 +- ...GreaterThanOrEqualThresholdEvaluator.java} | 6 +- .../move/evaluator/ThresholdEvaluator.java | 2 +- .../{ => car}/move/strategy/MoveStrategy.java | 2 +- .../move/strategy/OneStepMoveStrategy.java | 6 +- src/main/java/racinggame/RacingGame.java | 84 +++++++++++++++++++ src/test/java/CarTest.java | 20 ++--- 12 files changed, 109 insertions(+), 24 deletions(-) rename src/main/java/{ => car}/generator/random/RandomGenerator.java (65%) rename src/main/java/{ => car}/generator/random/ZeroToNineRandomGenerator.java (88%) rename src/main/java/{ => car}/move/decider/MoveDecider.java (73%) rename src/main/java/{ => car}/move/decider/ThresholdBaseMoveDecider.java (82%) rename src/main/java/{move/evaluator/GreaterThanOrEqualThreshold.java => car/move/evaluator/GreaterThanOrEqualThresholdEvaluator.java} (50%) rename src/main/java/{ => car}/move/evaluator/ThresholdEvaluator.java (73%) rename src/main/java/{ => car}/move/strategy/MoveStrategy.java (68%) rename src/main/java/{ => car}/move/strategy/OneStepMoveStrategy.java (84%) create mode 100644 src/main/java/racinggame/RacingGame.java diff --git a/build.gradle b/build.gradle index 239f9e78..1b83bdf0 100644 --- a/build.gradle +++ b/build.gradle @@ -14,6 +14,7 @@ dependencies { testImplementation platform('org.assertj:assertj-bom:3.25.1') testImplementation('org.junit.jupiter:junit-jupiter') testImplementation('org.assertj:assertj-core') + developmentOnly('org.springframework.boot:spring-boot-devtools') } test { diff --git a/src/main/java/car/Car.java b/src/main/java/car/Car.java index 4e4b0b00..f5b627c6 100644 --- a/src/main/java/car/Car.java +++ b/src/main/java/car/Car.java @@ -1,6 +1,6 @@ package car; -import move.strategy.MoveStrategy; +import car.move.strategy.MoveStrategy; public class Car { private final String name; diff --git a/src/main/java/generator/random/RandomGenerator.java b/src/main/java/car/generator/random/RandomGenerator.java similarity index 65% rename from src/main/java/generator/random/RandomGenerator.java rename to src/main/java/car/generator/random/RandomGenerator.java index 9eca1d64..095b8648 100644 --- a/src/main/java/generator/random/RandomGenerator.java +++ b/src/main/java/car/generator/random/RandomGenerator.java @@ -1,4 +1,4 @@ -package generator.random; +package car.generator.random; public interface RandomGenerator { int generate(); diff --git a/src/main/java/generator/random/ZeroToNineRandomGenerator.java b/src/main/java/car/generator/random/ZeroToNineRandomGenerator.java similarity index 88% rename from src/main/java/generator/random/ZeroToNineRandomGenerator.java rename to src/main/java/car/generator/random/ZeroToNineRandomGenerator.java index 6f4f7a2b..4429f004 100644 --- a/src/main/java/generator/random/ZeroToNineRandomGenerator.java +++ b/src/main/java/car/generator/random/ZeroToNineRandomGenerator.java @@ -1,4 +1,4 @@ -package generator.random; +package car.generator.random; import java.util.Random; public class ZeroToNineRandomGenerator implements RandomGenerator { diff --git a/src/main/java/move/decider/MoveDecider.java b/src/main/java/car/move/decider/MoveDecider.java similarity index 73% rename from src/main/java/move/decider/MoveDecider.java rename to src/main/java/car/move/decider/MoveDecider.java index 8439badd..794c6400 100644 --- a/src/main/java/move/decider/MoveDecider.java +++ b/src/main/java/car/move/decider/MoveDecider.java @@ -1,4 +1,4 @@ -package move.decider; +package car.move.decider; public interface MoveDecider { boolean canMove(int randomNumber); diff --git a/src/main/java/move/decider/ThresholdBaseMoveDecider.java b/src/main/java/car/move/decider/ThresholdBaseMoveDecider.java similarity index 82% rename from src/main/java/move/decider/ThresholdBaseMoveDecider.java rename to src/main/java/car/move/decider/ThresholdBaseMoveDecider.java index efb5e32f..cdb68143 100644 --- a/src/main/java/move/decider/ThresholdBaseMoveDecider.java +++ b/src/main/java/car/move/decider/ThresholdBaseMoveDecider.java @@ -1,6 +1,6 @@ -package move.decider; +package car.move.decider; -import move.evaluator.ThresholdEvaluator; +import car.move.evaluator.ThresholdEvaluator; public class ThresholdBaseMoveDecider implements MoveDecider { private final ThresholdEvaluator evaluator; diff --git a/src/main/java/move/evaluator/GreaterThanOrEqualThreshold.java b/src/main/java/car/move/evaluator/GreaterThanOrEqualThresholdEvaluator.java similarity index 50% rename from src/main/java/move/evaluator/GreaterThanOrEqualThreshold.java rename to src/main/java/car/move/evaluator/GreaterThanOrEqualThresholdEvaluator.java index 3d357492..c3044fc7 100644 --- a/src/main/java/move/evaluator/GreaterThanOrEqualThreshold.java +++ b/src/main/java/car/move/evaluator/GreaterThanOrEqualThresholdEvaluator.java @@ -1,9 +1,9 @@ -package move.evaluator; +package car.move.evaluator; -public class GreaterThanOrEqualThreshold implements ThresholdEvaluator { +public class GreaterThanOrEqualThresholdEvaluator implements ThresholdEvaluator { private final int threshold; - public GreaterThanOrEqualThreshold(int threshold) { + public GreaterThanOrEqualThresholdEvaluator(int threshold) { this.threshold = threshold; } @Override diff --git a/src/main/java/move/evaluator/ThresholdEvaluator.java b/src/main/java/car/move/evaluator/ThresholdEvaluator.java similarity index 73% rename from src/main/java/move/evaluator/ThresholdEvaluator.java rename to src/main/java/car/move/evaluator/ThresholdEvaluator.java index d11df755..e457055b 100644 --- a/src/main/java/move/evaluator/ThresholdEvaluator.java +++ b/src/main/java/car/move/evaluator/ThresholdEvaluator.java @@ -1,4 +1,4 @@ -package move.evaluator; +package car.move.evaluator; public interface ThresholdEvaluator { boolean isSatisfied(int value); diff --git a/src/main/java/move/strategy/MoveStrategy.java b/src/main/java/car/move/strategy/MoveStrategy.java similarity index 68% rename from src/main/java/move/strategy/MoveStrategy.java rename to src/main/java/car/move/strategy/MoveStrategy.java index 7c616a35..e93e1010 100644 --- a/src/main/java/move/strategy/MoveStrategy.java +++ b/src/main/java/car/move/strategy/MoveStrategy.java @@ -1,4 +1,4 @@ -package move.strategy; +package car.move.strategy; public interface MoveStrategy { int addStepSize(); diff --git a/src/main/java/move/strategy/OneStepMoveStrategy.java b/src/main/java/car/move/strategy/OneStepMoveStrategy.java similarity index 84% rename from src/main/java/move/strategy/OneStepMoveStrategy.java rename to src/main/java/car/move/strategy/OneStepMoveStrategy.java index 81ff89db..bbf234ec 100644 --- a/src/main/java/move/strategy/OneStepMoveStrategy.java +++ b/src/main/java/car/move/strategy/OneStepMoveStrategy.java @@ -1,7 +1,7 @@ -package move.strategy; +package car.move.strategy; -import generator.random.RandomGenerator; -import move.decider.MoveDecider; +import car.generator.random.RandomGenerator; +import car.move.decider.MoveDecider; public class OneStepMoveStrategy implements MoveStrategy { private static final int STEP_SIZE = 1; diff --git a/src/main/java/racinggame/RacingGame.java b/src/main/java/racinggame/RacingGame.java new file mode 100644 index 00000000..36368c4b --- /dev/null +++ b/src/main/java/racinggame/RacingGame.java @@ -0,0 +1,84 @@ +package racinggame; + +import car.Car; +import car.generator.random.ZeroToNineRandomGenerator; +import car.move.decider.ThresholdBaseMoveDecider; +import car.move.evaluator.GreaterThanOrEqualThresholdEvaluator; +import car.move.strategy.MoveStrategy; +import car.move.strategy.OneStepMoveStrategy; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Scanner; +import java.util.stream.Collectors; + +public class RacingGame { + private final List cars; + private final int moveCount; + + public RacingGame(List names, int moveCount, MoveStrategy moveStrategy) { + this.cars = createCars(names,moveStrategy); + this.moveCount = moveCount; + } + + private void moveAllCars( ){ + for (Car car : cars) { + car.move(); + } + } + public void play(){ + for(int i=0;i getWinners(){ + int maxDistance=findMaxDistance(); + return cars.stream().filter(car->car.getMovedDistance()==maxDistance).map(Car::getName).collect(Collectors.toList()); + } + + private List createCars(List names, MoveStrategy strategy) { + List cars = new ArrayList<>(); + for(String name : names){ + cars.add(new Car(name,strategy)); + } + return cars; + } + private int findMaxDistance(){ + int max=0; + for (Car car : cars) { + max=Math.max(max,car.getMovedDistance()); + } + return max; + } + private void printStatus() { + for (Car car : cars) { + System.out.println(car.getName() + " : " + "-".repeat(car.getMovedDistance())); + } + System.out.println(); + } + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + System.out.println("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분)."); + String[] inputNames = scanner.nextLine().split(","); + List names = Arrays.stream(inputNames) + .map(String::trim) + .collect(Collectors.toList()); + + System.out.println("시도할 회수는 몇회인가요?"); + int moveCount = scanner.nextInt(); + + MoveStrategy strategy = new OneStepMoveStrategy( + new ZeroToNineRandomGenerator(), + new ThresholdBaseMoveDecider(new GreaterThanOrEqualThresholdEvaluator(4))); + + RacingGame game = new RacingGame(names,moveCount,strategy); + System.out.println("\n실행 결과"); + game.play(); + + List winners = game.getWinners(); + System.out.println(String.join(", ", winners) + "가 최종 우승했습니다."); + } + +} diff --git a/src/test/java/CarTest.java b/src/test/java/CarTest.java index 11bf69f9..c47931f3 100644 --- a/src/test/java/CarTest.java +++ b/src/test/java/CarTest.java @@ -1,11 +1,11 @@ import car.Car; -import generator.random.RandomGenerator; -import move.decider.MoveDecider; -import move.decider.ThresholdBaseMoveDecider; -import move.evaluator.GreaterThanOrEqualThreshold; -import move.evaluator.ThresholdEvaluator; -import move.strategy.MoveStrategy; -import move.strategy.OneStepMoveStrategy; +import car.generator.random.RandomGenerator; +import car.move.decider.MoveDecider; +import car.move.decider.ThresholdBaseMoveDecider; +import car.move.evaluator.GreaterThanOrEqualThresholdEvaluator; +import car.move.evaluator.ThresholdEvaluator; +import car.move.strategy.MoveStrategy; +import car.move.strategy.OneStepMoveStrategy; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -18,7 +18,7 @@ public class CarTest { void 움직일_수_있을_때_1칸_전진() { // given RandomGenerator fixedGenerator = () -> 7; - ThresholdEvaluator evaluator=new GreaterThanOrEqualThreshold(4); + ThresholdEvaluator evaluator=new GreaterThanOrEqualThresholdEvaluator(4); MoveDecider decider= new ThresholdBaseMoveDecider(evaluator); MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, decider); Car car = new Car("car1", strategy); @@ -36,7 +36,7 @@ public class CarTest { @Test void 움직일_수_없을_때_전진_하지_않음() { RandomGenerator fixedGenerator = () -> 2; - ThresholdEvaluator evaluator=new GreaterThanOrEqualThreshold(4); + ThresholdEvaluator evaluator=new GreaterThanOrEqualThresholdEvaluator(4); MoveDecider decider= new ThresholdBaseMoveDecider(evaluator); MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, decider); Car car = new Car("car2", strategy); @@ -51,7 +51,7 @@ public class CarTest { @Test void 여러번_움직이면_누적됨() { RandomGenerator fixedGenerator = () -> 8; - ThresholdEvaluator evaluator=new GreaterThanOrEqualThreshold(4); + ThresholdEvaluator evaluator=new GreaterThanOrEqualThresholdEvaluator(4); MoveDecider decider= new ThresholdBaseMoveDecider(evaluator); MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, decider); Car car = new Car("car3", strategy); From 499696127cfd715541cbe82f3f9809db8fc23192 Mon Sep 17 00:00:00 2001 From: qkrcodus Date: Sat, 10 May 2025 16:08:54 +0900 Subject: [PATCH 09/13] =?UTF-8?q?feat=20:=202=EB=8B=A8=EA=B3=84=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5,=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/racinggame/WinnerFinder.java | 38 ++++++++++++++++ src/test/java/WinnerFinderTest.java | 53 ++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 src/main/java/racinggame/WinnerFinder.java create mode 100644 src/test/java/WinnerFinderTest.java diff --git a/src/main/java/racinggame/WinnerFinder.java b/src/main/java/racinggame/WinnerFinder.java new file mode 100644 index 00000000..55e4193b --- /dev/null +++ b/src/main/java/racinggame/WinnerFinder.java @@ -0,0 +1,38 @@ +package racinggame; + +import car.Car; + +import java.util.List; +import java.util.stream.Collectors; + +public class WinnerFinder { + private final List cars; + private final int moveCount; + public WinnerFinder(List cars, int moveCount){ + this.cars = cars; + this.moveCount = moveCount; + } + + public void play(){ + for(int i=0;i getWinners(){ + int maxDistance=maxDistance(); + return cars.stream().filter(car->car.getMovedDistance()==maxDistance).map(Car::getName).collect(Collectors.toList()); + } + + private void moveAllCars( ){ + for (Car car : cars) { + car.move(); + } + } + private int maxDistance(){ + int max=0; + for (Car car : cars) { + max=Math.max(max,car.getMovedDistance()); + } + return max; + } +} diff --git a/src/test/java/WinnerFinderTest.java b/src/test/java/WinnerFinderTest.java new file mode 100644 index 00000000..0fc36ed4 --- /dev/null +++ b/src/test/java/WinnerFinderTest.java @@ -0,0 +1,53 @@ +import car.Car; +import car.move.strategy.MoveStrategy; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import racinggame.WinnerFinder; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + + +public class WinnerFinderTest { + + @Test + @DisplayName("우승자 1명일 경우 car1") + public void singleWinner(){ + List cars = createCarsForTest(new int[]{3,2,1},new String[]{"car1","car2","car3"}); + WinnerFinder winner=new WinnerFinder(cars,1); + winner.play(); + + List winners = winner.getWinners(); + assertThat(winners).containsExactly("car1"); + } + + @Test + @DisplayName("우승자 여러명일 경우 car1 car2") + public void multipleWinners(){ + List cars = createCarsForTest(new int[]{3,3,1},new String[]{"car1","car2","car3"}); + WinnerFinder winner=new WinnerFinder(cars,1); + winner.play(); + + List winners = winner.getWinners(); + assertThat(winners).containsExactly("car1", "car2"); + } + + // 이름과 이동 거리를 갖는 Car 리스트 생성하기 + private List createCarsForTest(int[] distances,String[] names){ + List cars = new ArrayList<>(); + for (int i = 0; i < names.length; i++) { + cars.add(new Car(names[i],fixedStrategy(distances[i]))); + } + return cars; + } + + // 테스트 코드에만 존재하면 되므로 배포되지 않는 test 패키지안에 구현 + // MoveStrategy 은 addStepSize( ) 하나의 메소드만 있다. + // 함수형 인터페이스를 사용한다. + private MoveStrategy fixedStrategy(int distance){ + return ()->distance; + } + +} \ No newline at end of file From 6f767b54f9446fba1a5812637f8aafb42350341f Mon Sep 17 00:00:00 2001 From: qkrcodus Date: Sun, 11 May 2025 15:09:16 +0900 Subject: [PATCH 10/13] =?UTF-8?q?feat=20:=204=EB=8B=A8=EA=B3=84=20?= =?UTF-8?q?=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 --- src/main/java/racinggame/Main.java | 9 ++ src/main/java/racinggame/RacingGame.java | 84 ------------------- .../controller/RacingController.java | 32 +++++++ .../java/{car => racinggame/model}/Car.java | 4 +- .../java/racinggame/model/RacingGame.java | 50 +++++++++++ .../racinggame/{ => model}/WinnerFinder.java | 4 +- .../policy}/decider/MoveDecider.java | 2 +- .../decider/ThresholdBaseMoveDecider.java | 4 +- .../GreaterThanOrEqualThresholdEvaluator.java | 2 +- .../policy}/evaluator/ThresholdEvaluator.java | 2 +- .../numbergenerator}/RandomGenerator.java | 2 +- .../ZeroToNineRandomGenerator.java | 2 +- .../policy}/strategy/MoveStrategy.java | 2 +- .../policy}/strategy/OneStepMoveStrategy.java | 9 +- src/main/java/racinggame/view/InputView.java | 29 +++++++ src/main/java/racinggame/view/OutputView.java | 20 +++++ src/test/java/CarTest.java | 16 ++-- src/test/java/WinnerFinderTest.java | 6 +- 18 files changed, 166 insertions(+), 113 deletions(-) create mode 100644 src/main/java/racinggame/Main.java delete mode 100644 src/main/java/racinggame/RacingGame.java create mode 100644 src/main/java/racinggame/controller/RacingController.java rename src/main/java/{car => racinggame/model}/Car.java (87%) create mode 100644 src/main/java/racinggame/model/RacingGame.java rename src/main/java/racinggame/{ => model}/WinnerFinder.java (95%) rename src/main/java/{car/move => racinggame/policy}/decider/MoveDecider.java (67%) rename src/main/java/{car/move => racinggame/policy}/decider/ThresholdBaseMoveDecider.java (79%) rename src/main/java/{car/move => racinggame/policy}/evaluator/GreaterThanOrEqualThresholdEvaluator.java (89%) rename src/main/java/{car/move => racinggame/policy}/evaluator/ThresholdEvaluator.java (67%) rename src/main/java/{car/generator/random => racinggame/policy/numbergenerator}/RandomGenerator.java (57%) rename src/main/java/{car/generator/random => racinggame/policy/numbergenerator}/ZeroToNineRandomGenerator.java (84%) rename src/main/java/{car/move => racinggame/policy}/strategy/MoveStrategy.java (61%) rename src/main/java/{car/move => racinggame/policy}/strategy/OneStepMoveStrategy.java (60%) create mode 100644 src/main/java/racinggame/view/InputView.java create mode 100644 src/main/java/racinggame/view/OutputView.java diff --git a/src/main/java/racinggame/Main.java b/src/main/java/racinggame/Main.java new file mode 100644 index 00000000..f1ad8a80 --- /dev/null +++ b/src/main/java/racinggame/Main.java @@ -0,0 +1,9 @@ +package racinggame; + +import racinggame.controller.RacingController; + +public class Main { + public static void main(String[] args) { + new RacingController().run(); + } +} diff --git a/src/main/java/racinggame/RacingGame.java b/src/main/java/racinggame/RacingGame.java deleted file mode 100644 index 36368c4b..00000000 --- a/src/main/java/racinggame/RacingGame.java +++ /dev/null @@ -1,84 +0,0 @@ -package racinggame; - -import car.Car; -import car.generator.random.ZeroToNineRandomGenerator; -import car.move.decider.ThresholdBaseMoveDecider; -import car.move.evaluator.GreaterThanOrEqualThresholdEvaluator; -import car.move.strategy.MoveStrategy; -import car.move.strategy.OneStepMoveStrategy; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Scanner; -import java.util.stream.Collectors; - -public class RacingGame { - private final List cars; - private final int moveCount; - - public RacingGame(List names, int moveCount, MoveStrategy moveStrategy) { - this.cars = createCars(names,moveStrategy); - this.moveCount = moveCount; - } - - private void moveAllCars( ){ - for (Car car : cars) { - car.move(); - } - } - public void play(){ - for(int i=0;i getWinners(){ - int maxDistance=findMaxDistance(); - return cars.stream().filter(car->car.getMovedDistance()==maxDistance).map(Car::getName).collect(Collectors.toList()); - } - - private List createCars(List names, MoveStrategy strategy) { - List cars = new ArrayList<>(); - for(String name : names){ - cars.add(new Car(name,strategy)); - } - return cars; - } - private int findMaxDistance(){ - int max=0; - for (Car car : cars) { - max=Math.max(max,car.getMovedDistance()); - } - return max; - } - private void printStatus() { - for (Car car : cars) { - System.out.println(car.getName() + " : " + "-".repeat(car.getMovedDistance())); - } - System.out.println(); - } - public static void main(String[] args) { - Scanner scanner = new Scanner(System.in); - System.out.println("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분)."); - String[] inputNames = scanner.nextLine().split(","); - List names = Arrays.stream(inputNames) - .map(String::trim) - .collect(Collectors.toList()); - - System.out.println("시도할 회수는 몇회인가요?"); - int moveCount = scanner.nextInt(); - - MoveStrategy strategy = new OneStepMoveStrategy( - new ZeroToNineRandomGenerator(), - new ThresholdBaseMoveDecider(new GreaterThanOrEqualThresholdEvaluator(4))); - - RacingGame game = new RacingGame(names,moveCount,strategy); - System.out.println("\n실행 결과"); - game.play(); - - List winners = game.getWinners(); - System.out.println(String.join(", ", winners) + "가 최종 우승했습니다."); - } - -} diff --git a/src/main/java/racinggame/controller/RacingController.java b/src/main/java/racinggame/controller/RacingController.java new file mode 100644 index 00000000..e3b5dc46 --- /dev/null +++ b/src/main/java/racinggame/controller/RacingController.java @@ -0,0 +1,32 @@ +package racinggame.controller; + +import racinggame.model.RacingGame; +import racinggame.policy.decider.ThresholdBaseMoveDecider; +import racinggame.policy.evaluator.GreaterThanOrEqualThresholdEvaluator; +import racinggame.policy.strategy.MoveStrategy; +import racinggame.policy.strategy.OneStepMoveStrategy; +import racinggame.view.InputView; +import racinggame.view.OutputView; + +import java.util.List; + +public class RacingController { + public void run(){ + List names= InputView.readCarNames(); + int moveCount = InputView.readMoveCount(); + + MoveStrategy strategy = new OneStepMoveStrategy( + new racinggame.policy.numbergenerator.ZeroToNineRandomGenerator(), + new ThresholdBaseMoveDecider(new GreaterThanOrEqualThresholdEvaluator(4))); + + RacingGame game = new RacingGame(names,moveCount,strategy); + + for (int i = 0; i < moveCount; i++) { + game.moveOneTurn(); + OutputView.printResult(game.getCars()); + } + + List winners = game.getWinners(); + OutputView.printWinner(winners); + } +} diff --git a/src/main/java/car/Car.java b/src/main/java/racinggame/model/Car.java similarity index 87% rename from src/main/java/car/Car.java rename to src/main/java/racinggame/model/Car.java index f5b627c6..4af78d4e 100644 --- a/src/main/java/car/Car.java +++ b/src/main/java/racinggame/model/Car.java @@ -1,6 +1,6 @@ -package car; +package racinggame.model; -import car.move.strategy.MoveStrategy; +import racinggame.policy.strategy.MoveStrategy; public class Car { private final String name; diff --git a/src/main/java/racinggame/model/RacingGame.java b/src/main/java/racinggame/model/RacingGame.java new file mode 100644 index 00000000..618e4c76 --- /dev/null +++ b/src/main/java/racinggame/model/RacingGame.java @@ -0,0 +1,50 @@ +package racinggame.model; +import racinggame.policy.strategy.MoveStrategy; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class RacingGame { + private final List cars; + private final int moveCount; + + public RacingGame(List names, int moveCount, MoveStrategy moveStrategy) { + this.cars = createCars(names,moveStrategy); + this.moveCount = moveCount; + } + + private void moveAllCars( ){ + for (Car car : cars) { + car.move(); + } + } + + public void moveOneTurn() { + moveAllCars(); + } + + public List getCars() { + return cars; + } + + public List getWinners(){ + int maxDistance=findMaxDistance(); + return cars.stream().filter(car->car.getMovedDistance()==maxDistance).map(Car::getName).collect(Collectors.toList()); + } + + private List createCars(List names, MoveStrategy strategy) { + List cars = new ArrayList<>(); + for(String name : names){ + cars.add(new Car(name,strategy)); + } + return cars; + } + private int findMaxDistance(){ + int max=0; + for (Car car : cars) { + max=Math.max(max,car.getMovedDistance()); + } + return max; + } +} diff --git a/src/main/java/racinggame/WinnerFinder.java b/src/main/java/racinggame/model/WinnerFinder.java similarity index 95% rename from src/main/java/racinggame/WinnerFinder.java rename to src/main/java/racinggame/model/WinnerFinder.java index 55e4193b..0e3e3e75 100644 --- a/src/main/java/racinggame/WinnerFinder.java +++ b/src/main/java/racinggame/model/WinnerFinder.java @@ -1,6 +1,4 @@ -package racinggame; - -import car.Car; +package racinggame.model; import java.util.List; import java.util.stream.Collectors; diff --git a/src/main/java/car/move/decider/MoveDecider.java b/src/main/java/racinggame/policy/decider/MoveDecider.java similarity index 67% rename from src/main/java/car/move/decider/MoveDecider.java rename to src/main/java/racinggame/policy/decider/MoveDecider.java index 794c6400..24d75583 100644 --- a/src/main/java/car/move/decider/MoveDecider.java +++ b/src/main/java/racinggame/policy/decider/MoveDecider.java @@ -1,4 +1,4 @@ -package car.move.decider; +package racinggame.policy.decider; public interface MoveDecider { boolean canMove(int randomNumber); diff --git a/src/main/java/car/move/decider/ThresholdBaseMoveDecider.java b/src/main/java/racinggame/policy/decider/ThresholdBaseMoveDecider.java similarity index 79% rename from src/main/java/car/move/decider/ThresholdBaseMoveDecider.java rename to src/main/java/racinggame/policy/decider/ThresholdBaseMoveDecider.java index cdb68143..c50f70ec 100644 --- a/src/main/java/car/move/decider/ThresholdBaseMoveDecider.java +++ b/src/main/java/racinggame/policy/decider/ThresholdBaseMoveDecider.java @@ -1,6 +1,6 @@ -package car.move.decider; +package racinggame.policy.decider; -import car.move.evaluator.ThresholdEvaluator; +import racinggame.policy.evaluator.ThresholdEvaluator; public class ThresholdBaseMoveDecider implements MoveDecider { private final ThresholdEvaluator evaluator; diff --git a/src/main/java/car/move/evaluator/GreaterThanOrEqualThresholdEvaluator.java b/src/main/java/racinggame/policy/evaluator/GreaterThanOrEqualThresholdEvaluator.java similarity index 89% rename from src/main/java/car/move/evaluator/GreaterThanOrEqualThresholdEvaluator.java rename to src/main/java/racinggame/policy/evaluator/GreaterThanOrEqualThresholdEvaluator.java index c3044fc7..8f1f9973 100644 --- a/src/main/java/car/move/evaluator/GreaterThanOrEqualThresholdEvaluator.java +++ b/src/main/java/racinggame/policy/evaluator/GreaterThanOrEqualThresholdEvaluator.java @@ -1,4 +1,4 @@ -package car.move.evaluator; +package racinggame.policy.evaluator; public class GreaterThanOrEqualThresholdEvaluator implements ThresholdEvaluator { private final int threshold; diff --git a/src/main/java/car/move/evaluator/ThresholdEvaluator.java b/src/main/java/racinggame/policy/evaluator/ThresholdEvaluator.java similarity index 67% rename from src/main/java/car/move/evaluator/ThresholdEvaluator.java rename to src/main/java/racinggame/policy/evaluator/ThresholdEvaluator.java index e457055b..35b7d219 100644 --- a/src/main/java/car/move/evaluator/ThresholdEvaluator.java +++ b/src/main/java/racinggame/policy/evaluator/ThresholdEvaluator.java @@ -1,4 +1,4 @@ -package car.move.evaluator; +package racinggame.policy.evaluator; public interface ThresholdEvaluator { boolean isSatisfied(int value); diff --git a/src/main/java/car/generator/random/RandomGenerator.java b/src/main/java/racinggame/policy/numbergenerator/RandomGenerator.java similarity index 57% rename from src/main/java/car/generator/random/RandomGenerator.java rename to src/main/java/racinggame/policy/numbergenerator/RandomGenerator.java index 095b8648..a6bda932 100644 --- a/src/main/java/car/generator/random/RandomGenerator.java +++ b/src/main/java/racinggame/policy/numbergenerator/RandomGenerator.java @@ -1,4 +1,4 @@ -package car.generator.random; +package racinggame.policy.numbergenerator; public interface RandomGenerator { int generate(); diff --git a/src/main/java/car/generator/random/ZeroToNineRandomGenerator.java b/src/main/java/racinggame/policy/numbergenerator/ZeroToNineRandomGenerator.java similarity index 84% rename from src/main/java/car/generator/random/ZeroToNineRandomGenerator.java rename to src/main/java/racinggame/policy/numbergenerator/ZeroToNineRandomGenerator.java index 4429f004..d5a22640 100644 --- a/src/main/java/car/generator/random/ZeroToNineRandomGenerator.java +++ b/src/main/java/racinggame/policy/numbergenerator/ZeroToNineRandomGenerator.java @@ -1,4 +1,4 @@ -package car.generator.random; +package racinggame.policy.numbergenerator; import java.util.Random; public class ZeroToNineRandomGenerator implements RandomGenerator { diff --git a/src/main/java/car/move/strategy/MoveStrategy.java b/src/main/java/racinggame/policy/strategy/MoveStrategy.java similarity index 61% rename from src/main/java/car/move/strategy/MoveStrategy.java rename to src/main/java/racinggame/policy/strategy/MoveStrategy.java index e93e1010..64f4c32f 100644 --- a/src/main/java/car/move/strategy/MoveStrategy.java +++ b/src/main/java/racinggame/policy/strategy/MoveStrategy.java @@ -1,4 +1,4 @@ -package car.move.strategy; +package racinggame.policy.strategy; public interface MoveStrategy { int addStepSize(); diff --git a/src/main/java/car/move/strategy/OneStepMoveStrategy.java b/src/main/java/racinggame/policy/strategy/OneStepMoveStrategy.java similarity index 60% rename from src/main/java/car/move/strategy/OneStepMoveStrategy.java rename to src/main/java/racinggame/policy/strategy/OneStepMoveStrategy.java index bbf234ec..2dc8d097 100644 --- a/src/main/java/car/move/strategy/OneStepMoveStrategy.java +++ b/src/main/java/racinggame/policy/strategy/OneStepMoveStrategy.java @@ -1,15 +1,14 @@ -package car.move.strategy; +package racinggame.policy.strategy; -import car.generator.random.RandomGenerator; -import car.move.decider.MoveDecider; +import racinggame.policy.decider.MoveDecider; public class OneStepMoveStrategy implements MoveStrategy { private static final int STEP_SIZE = 1; - private final RandomGenerator randomGenerator; + private final racinggame.policy.numbergenerator.RandomGenerator randomGenerator; private final MoveDecider moveDecider; - public OneStepMoveStrategy(RandomGenerator randomGenerator, MoveDecider moveDecider) { + public OneStepMoveStrategy(racinggame.policy.numbergenerator.RandomGenerator randomGenerator, MoveDecider moveDecider) { this.randomGenerator = randomGenerator; this.moveDecider = moveDecider; } diff --git a/src/main/java/racinggame/view/InputView.java b/src/main/java/racinggame/view/InputView.java new file mode 100644 index 00000000..13945fdc --- /dev/null +++ b/src/main/java/racinggame/view/InputView.java @@ -0,0 +1,29 @@ +package racinggame.view; + +import java.util.Arrays; +import java.util.List; +import java.util.Scanner; +import java.util.stream.Collectors; + +public class InputView { + // scanner는 공유자원 + private static final Scanner scanner = new Scanner(System.in); + + public static List readCarNames() { + System.out.println("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분)."); + String[] inputNames = scanner.nextLine().split(","); + List names = Arrays.stream(inputNames) + .map(String::trim) + .collect(Collectors.toList()); + return names; + } + + public static int readMoveCount() { + System.out.println("시도할 회수는 몇회인가요?"); + int moveCount = scanner.nextInt(); + if (moveCount <= 0) { + throw new IllegalArgumentException("moveCount must be positive"); + } + return moveCount; + } +} diff --git a/src/main/java/racinggame/view/OutputView.java b/src/main/java/racinggame/view/OutputView.java new file mode 100644 index 00000000..6040923e --- /dev/null +++ b/src/main/java/racinggame/view/OutputView.java @@ -0,0 +1,20 @@ +package racinggame.view; + +import racinggame.model.Car; + +import java.util.List; + +public class OutputView { + public static void printResult(List cars) { + System.out.println("\n실행 결과"); + for (Car car : cars) { + System.out.println(car.getName() + " : " + "-".repeat(car.getMovedDistance())); + } + System.out.println(); + } + + public static void printWinner(List winners) { + System.out.println(String.join(", ", winners) + "가 최종 우승했습니다."); + } + +} diff --git a/src/test/java/CarTest.java b/src/test/java/CarTest.java index c47931f3..32cd44b0 100644 --- a/src/test/java/CarTest.java +++ b/src/test/java/CarTest.java @@ -1,11 +1,11 @@ -import car.Car; -import car.generator.random.RandomGenerator; -import car.move.decider.MoveDecider; -import car.move.decider.ThresholdBaseMoveDecider; -import car.move.evaluator.GreaterThanOrEqualThresholdEvaluator; -import car.move.evaluator.ThresholdEvaluator; -import car.move.strategy.MoveStrategy; -import car.move.strategy.OneStepMoveStrategy; +import racinggame.model.Car; +import racinggame.policy.numbergenerator.RandomGenerator; +import racinggame.policy.decider.MoveDecider; +import racinggame.policy.decider.ThresholdBaseMoveDecider; +import racinggame.policy.evaluator.GreaterThanOrEqualThresholdEvaluator; +import racinggame.policy.evaluator.ThresholdEvaluator; +import racinggame.policy.strategy.MoveStrategy; +import racinggame.policy.strategy.OneStepMoveStrategy; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/WinnerFinderTest.java b/src/test/java/WinnerFinderTest.java index 0fc36ed4..daceb704 100644 --- a/src/test/java/WinnerFinderTest.java +++ b/src/test/java/WinnerFinderTest.java @@ -1,8 +1,8 @@ -import car.Car; -import car.move.strategy.MoveStrategy; +import racinggame.model.Car; +import racinggame.policy.strategy.MoveStrategy; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import racinggame.WinnerFinder; +import racinggame.model.WinnerFinder; import java.util.ArrayList; import java.util.List; From 9879f8c5eb23071fa2684baed8ee2ea73220d727 Mon Sep 17 00:00:00 2001 From: qkrcodus Date: Sun, 11 May 2025 16:06:26 +0900 Subject: [PATCH 11/13] =?UTF-8?q?feat=20:=204=EB=8B=A8=EA=B3=84=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=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/racinggame/Main.java | 4 +- ...troller.java => RacingGameController.java} | 2 +- .../java/racinggame/model/RacingGame.java | 4 ++ src/main/java/racinggame/view/InputView.java | 2 +- src/test/java/RacingGameTest.java | 70 +++++++++++++++++++ 5 files changed, 78 insertions(+), 4 deletions(-) rename src/main/java/racinggame/controller/{RacingController.java => RacingGameController.java} (96%) create mode 100644 src/test/java/RacingGameTest.java diff --git a/src/main/java/racinggame/Main.java b/src/main/java/racinggame/Main.java index f1ad8a80..90474f98 100644 --- a/src/main/java/racinggame/Main.java +++ b/src/main/java/racinggame/Main.java @@ -1,9 +1,9 @@ package racinggame; -import racinggame.controller.RacingController; +import racinggame.controller.RacingGameController; public class Main { public static void main(String[] args) { - new RacingController().run(); + new RacingGameController().run(); } } diff --git a/src/main/java/racinggame/controller/RacingController.java b/src/main/java/racinggame/controller/RacingGameController.java similarity index 96% rename from src/main/java/racinggame/controller/RacingController.java rename to src/main/java/racinggame/controller/RacingGameController.java index e3b5dc46..ffdb0fb2 100644 --- a/src/main/java/racinggame/controller/RacingController.java +++ b/src/main/java/racinggame/controller/RacingGameController.java @@ -10,7 +10,7 @@ import java.util.List; -public class RacingController { +public class RacingGameController { public void run(){ List names= InputView.readCarNames(); int moveCount = InputView.readMoveCount(); diff --git a/src/main/java/racinggame/model/RacingGame.java b/src/main/java/racinggame/model/RacingGame.java index 618e4c76..53ba9117 100644 --- a/src/main/java/racinggame/model/RacingGame.java +++ b/src/main/java/racinggame/model/RacingGame.java @@ -9,7 +9,11 @@ public class RacingGame { private final List cars; private final int moveCount; + public RacingGame(List names, int moveCount, MoveStrategy moveStrategy) { + if (moveCount <= 0) { + throw new IllegalArgumentException("moveCount는 0보다 큰 값이여야 합니다."); + } this.cars = createCars(names,moveStrategy); this.moveCount = moveCount; } diff --git a/src/main/java/racinggame/view/InputView.java b/src/main/java/racinggame/view/InputView.java index 13945fdc..a12995fc 100644 --- a/src/main/java/racinggame/view/InputView.java +++ b/src/main/java/racinggame/view/InputView.java @@ -22,7 +22,7 @@ public static int readMoveCount() { System.out.println("시도할 회수는 몇회인가요?"); int moveCount = scanner.nextInt(); if (moveCount <= 0) { - throw new IllegalArgumentException("moveCount must be positive"); + throw new IllegalArgumentException("moveCount는 0보다 큰 값이여야 합니다."); } return moveCount; } diff --git a/src/test/java/RacingGameTest.java b/src/test/java/RacingGameTest.java new file mode 100644 index 00000000..ee7a7ebf --- /dev/null +++ b/src/test/java/RacingGameTest.java @@ -0,0 +1,70 @@ +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import racinggame.model.RacingGame; +import racinggame.policy.decider.MoveDecider; +import racinggame.policy.decider.ThresholdBaseMoveDecider; +import racinggame.policy.evaluator.GreaterThanOrEqualThresholdEvaluator; +import racinggame.policy.evaluator.ThresholdEvaluator; +import racinggame.policy.numbergenerator.RandomGenerator; +import racinggame.policy.strategy.MoveStrategy; +import racinggame.policy.strategy.OneStepMoveStrategy; + +import java.util.List; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; + +public class RacingGameTest { + @Test + @DisplayName("0이하 값을 이동 횟수로 입력하면 표준 예외를 출력한다.") + void invalidInputMoveCount(){ + RandomGenerator fixedGenerator = () -> 7; + ThresholdEvaluator evaluator=new GreaterThanOrEqualThresholdEvaluator(4); + MoveDecider decider= new ThresholdBaseMoveDecider(evaluator); + MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, decider); + assertThatThrownBy(() -> new RacingGame(List.of("car1", "car2"), 0,strategy)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("moveCount는 0보다 큰 값이여야 합니다."); + } + + @Test + @DisplayName("공동 우승자 발생한 경우 -> car1 car2 ") + void getWinners_multipleWinners() { + RandomGenerator fixedGenerator = () -> 7; + ThresholdEvaluator evaluator=new GreaterThanOrEqualThresholdEvaluator(4); + MoveDecider decider= new ThresholdBaseMoveDecider(evaluator); + MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, decider); + RacingGame game = new RacingGame(List.of("car1", "car2"), 1, strategy); + game.moveOneTurn(); + List winners = game.getWinners(); + assertThat(winners).containsExactlyInAnyOrder("car1", "car2"); + } + + @Test + @DisplayName("랜덤값이 threshold 값 이상일 때 자동차가 잘 움직이는지 확인한다.") + void carMovesWhenRandomValueIsAboveThreshold() { + RandomGenerator fixedGenerator = () -> 7; + ThresholdEvaluator evaluator=new GreaterThanOrEqualThresholdEvaluator(4); + MoveDecider decider= new ThresholdBaseMoveDecider(evaluator); + MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, decider); + + RacingGame game = new RacingGame(List.of("neo"), 1, strategy); + game.moveOneTurn(); + assertThat(game.getCars().get(0).getMovedDistance()).isEqualTo(1); + } + + @Test + @DisplayName("랜덤값이 threshold 값 초과일 때 자동차가 멈추는지 확인한다.") + void carStopsWhenRandomValueIsBelowThreshold() { + RandomGenerator fixedGenerator = () -> 2; + ThresholdEvaluator evaluator=new GreaterThanOrEqualThresholdEvaluator(4); + MoveDecider decider= new ThresholdBaseMoveDecider(evaluator); + MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, decider); + + RacingGame game = new RacingGame(List.of("car1"), 1, strategy); + game.moveOneTurn(); + assertThat(game.getCars().get(0).getMovedDistance()).isEqualTo(0); + } + + +} From 4820e8a1b6e3d1216e344d3ca6dbefd9fd0f44ca Mon Sep 17 00:00:00 2001 From: qkrcodus Date: Sun, 11 May 2025 16:17:29 +0900 Subject: [PATCH 12/13] =?UTF-8?q?docs=20:=20=EB=A6=AC=EB=93=9C=EB=AF=B8=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 --- README.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..7cad491c --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +### 1단계 +- 자동차는 이름을 갖는다. +- 자동차는 0-9 사이 랜덤 값을 구한 후 4이상이면 전진, 3이하면 멈춘다. +- 3항 연산자를 쓰지 않는다. +- else 예약어, switch/case 허용하지 않는다. +- 메소드 길이가 15라인이 넘어가지 않도록 구현한다 +- 메인 메소드를 만들지 않는다. +- 테스트 코드 작성한다. + +### 2단계 +- n대의 자동차가 참여가능하다. +- 주어진 횟수동안 자동차 경주 게임을 완료한 후 누가 우승했는지 알 수 있다. +- 우승자는 한 명 이상일 수 있다. +- 나머진 1단계와 유사하다. + +### 3단계 +- 자동차에 이름 부여가능하고, 전진하는 자동차 출력할 때 자동차 이름을 같이 출력한다. +- 자동차 이름은 , 기준으로 구분하며 이름은 5자 이하만 가능하다. +- 메인 메소드를 추가한다. + +### 4단계 +- 모든 로직에 단위 테스트를 구현한다. +- mvc 패턴으로 리팩터링한다. + +### 개인적 목표 +1. 주석이 없어도 읽기 좋은 코드를 짜보자. +2. 메서드가 한가지 기능만 갖도록 분리하다가 따로 관리하는게 좋을 것 같으면 클래스로 구현하자. +3. 단위 테스트 핵심 원칙을 따르자. +4. 개념에 머무르고 있었던 객체 지향적 개념을 활용하여 코드를 작성해보자. +5. 발생할 수 있는 예외 케이스를 고려하여 방어적인 코드를 작성하고, 이를 테스트 코드로 확인하자. + + From cb561b271244c241ac5eaebe743756e531dd6a35 Mon Sep 17 00:00:00 2001 From: qkrcodus Date: Thu, 15 May 2025 16:20:18 +0900 Subject: [PATCH 13/13] =?UTF-8?q?refactor=20:=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/RacingGameController.java | 13 +-- .../java/racinggame/model/RacingGame.java | 44 +++++----- .../java/racinggame/model/WinnerFinder.java | 2 + .../java/racinggame/model/{ => car}/Car.java | 14 +++- .../car}/policy/decider/MoveDecider.java | 2 +- .../decider/ThresholdBaseMoveDecider.java | 4 +- .../GreaterThanOrEqualThresholdEvaluator.java | 2 +- .../policy/evaluator/ThresholdEvaluator.java | 2 +- .../numbergenerator/RandomGenerator.java | 2 +- .../ZeroToNineRandomGenerator.java | 2 +- .../car}/policy/strategy/MoveStrategy.java | 2 +- .../policy/strategy/OneStepMoveStrategy.java | 9 ++- src/main/java/racinggame/view/InputView.java | 27 +++++-- src/main/java/racinggame/view/OutputView.java | 2 +- src/test/java/CarTest.java | 80 +++++++++---------- ...aterThanOrEqualThresholdEvaluatorTest.java | 37 +++++++++ src/test/java/InputViewTest.java | 54 +++++++++++++ src/test/java/OneStepMoveStrategyTest.java | 35 ++++++++ src/test/java/RacingGameTest.java | 64 +++------------ .../java/ThresholdBaseMoveDeciderTest.java | 29 +++++++ src/test/java/WinnerFinderTest.java | 14 +++- 21 files changed, 285 insertions(+), 155 deletions(-) rename src/main/java/racinggame/model/{ => car}/Car.java (55%) rename src/main/java/racinggame/{ => model/car}/policy/decider/MoveDecider.java (61%) rename src/main/java/racinggame/{ => model/car}/policy/decider/ThresholdBaseMoveDecider.java (75%) rename src/main/java/racinggame/{ => model/car}/policy/evaluator/GreaterThanOrEqualThresholdEvaluator.java (87%) rename src/main/java/racinggame/{ => model/car}/policy/evaluator/ThresholdEvaluator.java (62%) rename src/main/java/racinggame/{ => model/car}/policy/numbergenerator/RandomGenerator.java (52%) rename src/main/java/racinggame/{ => model/car}/policy/numbergenerator/ZeroToNineRandomGenerator.java (81%) rename src/main/java/racinggame/{ => model/car}/policy/strategy/MoveStrategy.java (55%) rename src/main/java/racinggame/{ => model/car}/policy/strategy/OneStepMoveStrategy.java (59%) create mode 100644 src/test/java/GreaterThanOrEqualThresholdEvaluatorTest.java create mode 100644 src/test/java/InputViewTest.java create mode 100644 src/test/java/OneStepMoveStrategyTest.java create mode 100644 src/test/java/ThresholdBaseMoveDeciderTest.java diff --git a/src/main/java/racinggame/controller/RacingGameController.java b/src/main/java/racinggame/controller/RacingGameController.java index ffdb0fb2..0cfbf028 100644 --- a/src/main/java/racinggame/controller/RacingGameController.java +++ b/src/main/java/racinggame/controller/RacingGameController.java @@ -1,10 +1,11 @@ package racinggame.controller; import racinggame.model.RacingGame; -import racinggame.policy.decider.ThresholdBaseMoveDecider; -import racinggame.policy.evaluator.GreaterThanOrEqualThresholdEvaluator; -import racinggame.policy.strategy.MoveStrategy; -import racinggame.policy.strategy.OneStepMoveStrategy; +import racinggame.model.car.policy.numbergenerator.ZeroToNineRandomGenerator; +import racinggame.model.car.policy.decider.ThresholdBaseMoveDecider; +import racinggame.model.car.policy.evaluator.GreaterThanOrEqualThresholdEvaluator; +import racinggame.model.car.policy.strategy.MoveStrategy; +import racinggame.model.car.policy.strategy.OneStepMoveStrategy; import racinggame.view.InputView; import racinggame.view.OutputView; @@ -16,10 +17,10 @@ public void run(){ int moveCount = InputView.readMoveCount(); MoveStrategy strategy = new OneStepMoveStrategy( - new racinggame.policy.numbergenerator.ZeroToNineRandomGenerator(), + new ZeroToNineRandomGenerator(), new ThresholdBaseMoveDecider(new GreaterThanOrEqualThresholdEvaluator(4))); - RacingGame game = new RacingGame(names,moveCount,strategy); + RacingGame game = new RacingGame(names,strategy); for (int i = 0; i < moveCount; i++) { game.moveOneTurn(); diff --git a/src/main/java/racinggame/model/RacingGame.java b/src/main/java/racinggame/model/RacingGame.java index 53ba9117..5c6d6fe0 100644 --- a/src/main/java/racinggame/model/RacingGame.java +++ b/src/main/java/racinggame/model/RacingGame.java @@ -1,5 +1,6 @@ package racinggame.model; -import racinggame.policy.strategy.MoveStrategy; +import racinggame.model.car.Car; +import racinggame.model.car.policy.strategy.MoveStrategy; import java.util.ArrayList; import java.util.List; @@ -7,25 +8,21 @@ public class RacingGame { private final List cars; - private final int moveCount; - - public RacingGame(List names, int moveCount, MoveStrategy moveStrategy) { - if (moveCount <= 0) { - throw new IllegalArgumentException("moveCount는 0보다 큰 값이여야 합니다."); - } + public RacingGame(List names,MoveStrategy moveStrategy) { this.cars = createCars(names,moveStrategy); - this.moveCount = moveCount; } - private void moveAllCars( ){ - for (Car car : cars) { - car.move(); - } + private List createCars(List names, MoveStrategy strategy) { + return names.stream() + .map(name -> new Car(name,strategy)) + .collect(Collectors.toList()); } public void moveOneTurn() { - moveAllCars(); + for (Car car : cars) { + car.move(); + } } public List getCars() { @@ -34,21 +31,16 @@ public List getCars() { public List getWinners(){ int maxDistance=findMaxDistance(); - return cars.stream().filter(car->car.getMovedDistance()==maxDistance).map(Car::getName).collect(Collectors.toList()); + + return cars.stream() + .filter(car->car.getMovedDistance()==maxDistance) + .map(Car::getName).collect(Collectors.toList()); } - private List createCars(List names, MoveStrategy strategy) { - List cars = new ArrayList<>(); - for(String name : names){ - cars.add(new Car(name,strategy)); - } - return cars; - } private int findMaxDistance(){ - int max=0; - for (Car car : cars) { - max=Math.max(max,car.getMovedDistance()); - } - return max; + return cars.stream() + .mapToInt(Car::getMovedDistance) + .max() + .orElse(0); } } diff --git a/src/main/java/racinggame/model/WinnerFinder.java b/src/main/java/racinggame/model/WinnerFinder.java index 0e3e3e75..0638477c 100644 --- a/src/main/java/racinggame/model/WinnerFinder.java +++ b/src/main/java/racinggame/model/WinnerFinder.java @@ -1,5 +1,7 @@ package racinggame.model; +import racinggame.model.car.Car; + import java.util.List; import java.util.stream.Collectors; diff --git a/src/main/java/racinggame/model/Car.java b/src/main/java/racinggame/model/car/Car.java similarity index 55% rename from src/main/java/racinggame/model/Car.java rename to src/main/java/racinggame/model/car/Car.java index 4af78d4e..1ca461cf 100644 --- a/src/main/java/racinggame/model/Car.java +++ b/src/main/java/racinggame/model/car/Car.java @@ -1,6 +1,8 @@ -package racinggame.model; +package racinggame.model.car; -import racinggame.policy.strategy.MoveStrategy; +import racinggame.model.car.policy.strategy.MoveStrategy; + +import java.util.Objects; public class Car { private final String name; @@ -9,7 +11,13 @@ public class Car { private final MoveStrategy moveStrategy; public Car(String name,MoveStrategy moveStrategy) { - this.name=name; + if(name==null){ + throw new IllegalArgumentException("이름은 null 일 수 없습니다."); + } + if(name.isBlank()){ + throw new IllegalArgumentException("이름은 공백일 수 없습니다."); + } + this.name = name; this.moveStrategy=moveStrategy; } diff --git a/src/main/java/racinggame/policy/decider/MoveDecider.java b/src/main/java/racinggame/model/car/policy/decider/MoveDecider.java similarity index 61% rename from src/main/java/racinggame/policy/decider/MoveDecider.java rename to src/main/java/racinggame/model/car/policy/decider/MoveDecider.java index 24d75583..77e2ab20 100644 --- a/src/main/java/racinggame/policy/decider/MoveDecider.java +++ b/src/main/java/racinggame/model/car/policy/decider/MoveDecider.java @@ -1,4 +1,4 @@ -package racinggame.policy.decider; +package racinggame.model.car.policy.decider; public interface MoveDecider { boolean canMove(int randomNumber); diff --git a/src/main/java/racinggame/policy/decider/ThresholdBaseMoveDecider.java b/src/main/java/racinggame/model/car/policy/decider/ThresholdBaseMoveDecider.java similarity index 75% rename from src/main/java/racinggame/policy/decider/ThresholdBaseMoveDecider.java rename to src/main/java/racinggame/model/car/policy/decider/ThresholdBaseMoveDecider.java index c50f70ec..1436575e 100644 --- a/src/main/java/racinggame/policy/decider/ThresholdBaseMoveDecider.java +++ b/src/main/java/racinggame/model/car/policy/decider/ThresholdBaseMoveDecider.java @@ -1,6 +1,6 @@ -package racinggame.policy.decider; +package racinggame.model.car.policy.decider; -import racinggame.policy.evaluator.ThresholdEvaluator; +import racinggame.model.car.policy.evaluator.ThresholdEvaluator; public class ThresholdBaseMoveDecider implements MoveDecider { private final ThresholdEvaluator evaluator; diff --git a/src/main/java/racinggame/policy/evaluator/GreaterThanOrEqualThresholdEvaluator.java b/src/main/java/racinggame/model/car/policy/evaluator/GreaterThanOrEqualThresholdEvaluator.java similarity index 87% rename from src/main/java/racinggame/policy/evaluator/GreaterThanOrEqualThresholdEvaluator.java rename to src/main/java/racinggame/model/car/policy/evaluator/GreaterThanOrEqualThresholdEvaluator.java index 8f1f9973..3e0e5509 100644 --- a/src/main/java/racinggame/policy/evaluator/GreaterThanOrEqualThresholdEvaluator.java +++ b/src/main/java/racinggame/model/car/policy/evaluator/GreaterThanOrEqualThresholdEvaluator.java @@ -1,4 +1,4 @@ -package racinggame.policy.evaluator; +package racinggame.model.car.policy.evaluator; public class GreaterThanOrEqualThresholdEvaluator implements ThresholdEvaluator { private final int threshold; diff --git a/src/main/java/racinggame/policy/evaluator/ThresholdEvaluator.java b/src/main/java/racinggame/model/car/policy/evaluator/ThresholdEvaluator.java similarity index 62% rename from src/main/java/racinggame/policy/evaluator/ThresholdEvaluator.java rename to src/main/java/racinggame/model/car/policy/evaluator/ThresholdEvaluator.java index 35b7d219..ac40b49d 100644 --- a/src/main/java/racinggame/policy/evaluator/ThresholdEvaluator.java +++ b/src/main/java/racinggame/model/car/policy/evaluator/ThresholdEvaluator.java @@ -1,4 +1,4 @@ -package racinggame.policy.evaluator; +package racinggame.model.car.policy.evaluator; public interface ThresholdEvaluator { boolean isSatisfied(int value); diff --git a/src/main/java/racinggame/policy/numbergenerator/RandomGenerator.java b/src/main/java/racinggame/model/car/policy/numbergenerator/RandomGenerator.java similarity index 52% rename from src/main/java/racinggame/policy/numbergenerator/RandomGenerator.java rename to src/main/java/racinggame/model/car/policy/numbergenerator/RandomGenerator.java index a6bda932..5c28be53 100644 --- a/src/main/java/racinggame/policy/numbergenerator/RandomGenerator.java +++ b/src/main/java/racinggame/model/car/policy/numbergenerator/RandomGenerator.java @@ -1,4 +1,4 @@ -package racinggame.policy.numbergenerator; +package racinggame.model.car.policy.numbergenerator; public interface RandomGenerator { int generate(); diff --git a/src/main/java/racinggame/policy/numbergenerator/ZeroToNineRandomGenerator.java b/src/main/java/racinggame/model/car/policy/numbergenerator/ZeroToNineRandomGenerator.java similarity index 81% rename from src/main/java/racinggame/policy/numbergenerator/ZeroToNineRandomGenerator.java rename to src/main/java/racinggame/model/car/policy/numbergenerator/ZeroToNineRandomGenerator.java index d5a22640..750a06d4 100644 --- a/src/main/java/racinggame/policy/numbergenerator/ZeroToNineRandomGenerator.java +++ b/src/main/java/racinggame/model/car/policy/numbergenerator/ZeroToNineRandomGenerator.java @@ -1,4 +1,4 @@ -package racinggame.policy.numbergenerator; +package racinggame.model.car.policy.numbergenerator; import java.util.Random; public class ZeroToNineRandomGenerator implements RandomGenerator { diff --git a/src/main/java/racinggame/policy/strategy/MoveStrategy.java b/src/main/java/racinggame/model/car/policy/strategy/MoveStrategy.java similarity index 55% rename from src/main/java/racinggame/policy/strategy/MoveStrategy.java rename to src/main/java/racinggame/model/car/policy/strategy/MoveStrategy.java index 64f4c32f..c1bfb5fa 100644 --- a/src/main/java/racinggame/policy/strategy/MoveStrategy.java +++ b/src/main/java/racinggame/model/car/policy/strategy/MoveStrategy.java @@ -1,4 +1,4 @@ -package racinggame.policy.strategy; +package racinggame.model.car.policy.strategy; public interface MoveStrategy { int addStepSize(); diff --git a/src/main/java/racinggame/policy/strategy/OneStepMoveStrategy.java b/src/main/java/racinggame/model/car/policy/strategy/OneStepMoveStrategy.java similarity index 59% rename from src/main/java/racinggame/policy/strategy/OneStepMoveStrategy.java rename to src/main/java/racinggame/model/car/policy/strategy/OneStepMoveStrategy.java index 2dc8d097..64133cb2 100644 --- a/src/main/java/racinggame/policy/strategy/OneStepMoveStrategy.java +++ b/src/main/java/racinggame/model/car/policy/strategy/OneStepMoveStrategy.java @@ -1,14 +1,15 @@ -package racinggame.policy.strategy; +package racinggame.model.car.policy.strategy; -import racinggame.policy.decider.MoveDecider; +import racinggame.model.car.policy.numbergenerator.RandomGenerator; +import racinggame.model.car.policy.decider.MoveDecider; public class OneStepMoveStrategy implements MoveStrategy { private static final int STEP_SIZE = 1; - private final racinggame.policy.numbergenerator.RandomGenerator randomGenerator; + private final RandomGenerator randomGenerator; private final MoveDecider moveDecider; - public OneStepMoveStrategy(racinggame.policy.numbergenerator.RandomGenerator randomGenerator, MoveDecider moveDecider) { + public OneStepMoveStrategy(RandomGenerator randomGenerator, MoveDecider moveDecider) { this.randomGenerator = randomGenerator; this.moveDecider = moveDecider; } diff --git a/src/main/java/racinggame/view/InputView.java b/src/main/java/racinggame/view/InputView.java index a12995fc..210f3301 100644 --- a/src/main/java/racinggame/view/InputView.java +++ b/src/main/java/racinggame/view/InputView.java @@ -3,27 +3,42 @@ import java.util.Arrays; import java.util.List; import java.util.Scanner; +import java.util.Set; import java.util.stream.Collectors; public class InputView { - // scanner는 공유자원 - private static final Scanner scanner = new Scanner(System.in); + private static final String DELIMITER = ","; + private static final String CAR_NAME_INPUT_PROMPT ="경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분)."; public static List readCarNames() { - System.out.println("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분)."); - String[] inputNames = scanner.nextLine().split(","); - List names = Arrays.stream(inputNames) + Scanner scanner = new Scanner(System.in); + System.out.println(CAR_NAME_INPUT_PROMPT); + + List names = Arrays.stream(scanner.nextLine().split(DELIMITER)) .map(String::trim) - .collect(Collectors.toList()); + .toList(); + + if (names.stream().anyMatch(name -> name.length() > 5)) { + throw new IllegalArgumentException("이름은 5자 이하만 가능합니다."); + } + + Set unique = names.stream().collect(Collectors.toSet()); + if (unique.size() != names.size()) { + throw new IllegalArgumentException("자동차 이름은 모두 고유해야 합니다."); + } + return names; } public static int readMoveCount() { + Scanner scanner = new Scanner(System.in); System.out.println("시도할 회수는 몇회인가요?"); + int moveCount = scanner.nextInt(); if (moveCount <= 0) { throw new IllegalArgumentException("moveCount는 0보다 큰 값이여야 합니다."); } + return moveCount; } } diff --git a/src/main/java/racinggame/view/OutputView.java b/src/main/java/racinggame/view/OutputView.java index 6040923e..1f0662bf 100644 --- a/src/main/java/racinggame/view/OutputView.java +++ b/src/main/java/racinggame/view/OutputView.java @@ -1,6 +1,6 @@ package racinggame.view; -import racinggame.model.Car; +import racinggame.model.car.Car; import java.util.List; diff --git a/src/test/java/CarTest.java b/src/test/java/CarTest.java index 32cd44b0..4ea2164d 100644 --- a/src/test/java/CarTest.java +++ b/src/test/java/CarTest.java @@ -1,66 +1,60 @@ -import racinggame.model.Car; -import racinggame.policy.numbergenerator.RandomGenerator; -import racinggame.policy.decider.MoveDecider; -import racinggame.policy.decider.ThresholdBaseMoveDecider; -import racinggame.policy.evaluator.GreaterThanOrEqualThresholdEvaluator; -import racinggame.policy.evaluator.ThresholdEvaluator; -import racinggame.policy.strategy.MoveStrategy; -import racinggame.policy.strategy.OneStepMoveStrategy; +import racinggame.model.car.Car; +import racinggame.model.car.policy.numbergenerator.RandomGenerator; +import racinggame.model.car.policy.decider.MoveDecider; +import racinggame.model.car.policy.decider.ThresholdBaseMoveDecider; +import racinggame.model.car.policy.evaluator.GreaterThanOrEqualThresholdEvaluator; +import racinggame.model.car.policy.evaluator.ThresholdEvaluator; +import racinggame.model.car.policy.strategy.MoveStrategy; +import racinggame.model.car.policy.strategy.OneStepMoveStrategy; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.Objects; + import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; public class CarTest { - @DisplayName("랜덤값이 조건을 만족할 경우 자동차는 1칸 전진한다") @Test - void 움직일_수_있을_때_1칸_전진() { - // given - RandomGenerator fixedGenerator = () -> 7; - ThresholdEvaluator evaluator=new GreaterThanOrEqualThresholdEvaluator(4); - MoveDecider decider= new ThresholdBaseMoveDecider(evaluator); - MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, decider); - Car car = new Car("car1", strategy); + @DisplayName("moveStrategy에 따라 누적 이동 거리가 쌓인다") + void moveStrategy_따라_누적되는지_확인한다 () { + // give + MoveStrategy alwaysOne = () -> 1; + Car car = new Car("car1", alwaysOne); // when car.move(); + car.move(); // then - assertThat(car.getMovedDistance()).isEqualTo(1); - assertThat(car.getName()).isEqualTo("car1"); + assertThat(car.getMovedDistance()).isEqualTo(2); + assertThat(car.getName()).isEqualTo("car2"); } - - @DisplayName("랜덤값이 조건을 만족하지 않을 경우 자동차는 전진하지 않는다") + @DisplayName("이름을 null로 둔다면 에러를 던지는지 확인한다.") @Test - void 움직일_수_없을_때_전진_하지_않음() { - RandomGenerator fixedGenerator = () -> 2; - ThresholdEvaluator evaluator=new GreaterThanOrEqualThresholdEvaluator(4); - MoveDecider decider= new ThresholdBaseMoveDecider(evaluator); - MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, decider); - Car car = new Car("car2", strategy); - - car.move(); + void 이름을_null로_둘_수_없음(){ + // given + MoveStrategy dummystrategy=()->0; - assertThat(car.getMovedDistance()).isEqualTo(0); - assertThat(car.getName()).isEqualTo("car2"); + // when & then + assertThatThrownBy(()->new Car(null, dummystrategy)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("이름은 null 일 수 없습니다."); } - @DisplayName("자동차는 여러 번 움직일 경우 이동 거리가 누적된다") + @DisplayName("이름을 공백으로 둔다면 에러를 던지는지 확인한다.") @Test - void 여러번_움직이면_누적됨() { - RandomGenerator fixedGenerator = () -> 8; - ThresholdEvaluator evaluator=new GreaterThanOrEqualThresholdEvaluator(4); - MoveDecider decider= new ThresholdBaseMoveDecider(evaluator); - MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, decider); - Car car = new Car("car3", strategy); - - car.move(); - car.move(); - car.move(); + void 이름을_공백으로_둘_수_없음(){ + // given + MoveStrategy dummystrategy=()->0; - assertThat(car.getMovedDistance()).isEqualTo(3); - assertThat(car.getName()).isEqualTo("car3"); + // when & then + assertThatThrownBy(()->new Car(" ", dummystrategy)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("이름은 공백일 수 없습니다."); } + + } diff --git a/src/test/java/GreaterThanOrEqualThresholdEvaluatorTest.java b/src/test/java/GreaterThanOrEqualThresholdEvaluatorTest.java new file mode 100644 index 00000000..304aeb2e --- /dev/null +++ b/src/test/java/GreaterThanOrEqualThresholdEvaluatorTest.java @@ -0,0 +1,37 @@ +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import racinggame.model.car.policy.evaluator.GreaterThanOrEqualThresholdEvaluator; +import racinggame.model.car.policy.evaluator.ThresholdEvaluator; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +public class GreaterThanOrEqualThresholdEvaluatorTest { + @Test + @DisplayName("value가 threshold 이상이면 true") + void threshold_이상이면_크면_참() { + // given + ThresholdEvaluator evaluator = new GreaterThanOrEqualThresholdEvaluator(4); + + // when + boolean atThreshold=evaluator.isSatisfied(4); + boolean aboveThreshold=evaluator.isSatisfied(5); + + // then + assertThat(atThreshold).isTrue(); + assertThat(aboveThreshold).isTrue(); + } + + @Test + @DisplayName("value가 threshold 미만이면 false") + void threshold_미만이면_거짓() { + // given + ThresholdEvaluator evaluator = new GreaterThanOrEqualThresholdEvaluator(4); + + // when + boolean belowThreshold=evaluator.isSatisfied(2); + + // then + assertThat(belowThreshold).isFalse(); + + } +} diff --git a/src/test/java/InputViewTest.java b/src/test/java/InputViewTest.java new file mode 100644 index 00000000..c9fecb88 --- /dev/null +++ b/src/test/java/InputViewTest.java @@ -0,0 +1,54 @@ +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import racinggame.view.InputView; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + +public class InputViewTest { + private final InputStream systemIn = System.in; + + @AfterEach + void restore() { + System.setIn(systemIn); + } + @Test + @DisplayName("0 이하 입력 시 IllegalArgumentException 발생") + void invalidMoveCount(){ + // given + String testInput ="0\n"; + System.setIn(new ByteArrayInputStream(testInput.getBytes())); + + // when & then + assertThatThrownBy(()-> InputView.readMoveCount()) + .isInstanceOf(IllegalArgumentException.class).hasMessage("moveCount는 0보다 큰 값이여야 합니다."); + } + + @Test + @DisplayName("이름이 5자 초과일 경우 예외를 던진다") + void nameTooLong_throwsException() { + // given + System.setIn(new ByteArrayInputStream("123456\n".getBytes())); + + // when & then + assertThatThrownBy(InputView::readCarNames) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("이름은 5자 이하만 가능합니다."); + } + + @Test + @DisplayName("중복된 이름이 있을 경우 예외를 던진다") + void duplicateName_throwsException() { + // given + System.setIn(new ByteArrayInputStream("aa,bb,aa\n".getBytes())); + + // when & then + assertThatThrownBy(InputView::readCarNames) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("자동차 이름은 모두 고유해야 합니다."); + } + +} diff --git a/src/test/java/OneStepMoveStrategyTest.java b/src/test/java/OneStepMoveStrategyTest.java new file mode 100644 index 00000000..a87b0dfd --- /dev/null +++ b/src/test/java/OneStepMoveStrategyTest.java @@ -0,0 +1,35 @@ + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import racinggame.model.car.policy.decider.MoveDecider; +import racinggame.model.car.policy.numbergenerator.RandomGenerator; +import racinggame.model.car.policy.strategy.OneStepMoveStrategy; + +import static org.assertj.core.api.Assertions.assertThat; + +class OneStepMoveStrategyTest { + + @Test + @DisplayName("Decider가 true일 때는 STEP_SIZE 만큼 반환") + void returnsStepSizeWhenDeciderTrue() { + // given + RandomGenerator fixedGenerator = () -> 8; + MoveDecider alwaysTrue = num -> true; + OneStepMoveStrategy strat = new OneStepMoveStrategy(fixedGenerator, alwaysTrue); + + // when & then + assertThat(strat.addStepSize()).isEqualTo(1); + } + + @Test + @DisplayName("Decider가 false일 때는 0 반환") + void returnsZeroWhenDeciderFalse() { + // given + RandomGenerator fixedGenerator = () -> 2; + MoveDecider alwaysFalse = num -> false; + OneStepMoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, alwaysFalse); + + // when & then + assertThat(strategy.addStepSize()).isZero(); + } +} diff --git a/src/test/java/RacingGameTest.java b/src/test/java/RacingGameTest.java index ee7a7ebf..c911377d 100644 --- a/src/test/java/RacingGameTest.java +++ b/src/test/java/RacingGameTest.java @@ -1,70 +1,24 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import racinggame.model.RacingGame; -import racinggame.policy.decider.MoveDecider; -import racinggame.policy.decider.ThresholdBaseMoveDecider; -import racinggame.policy.evaluator.GreaterThanOrEqualThresholdEvaluator; -import racinggame.policy.evaluator.ThresholdEvaluator; -import racinggame.policy.numbergenerator.RandomGenerator; -import racinggame.policy.strategy.MoveStrategy; -import racinggame.policy.strategy.OneStepMoveStrategy; +import racinggame.model.car.policy.strategy.MoveStrategy; import java.util.List; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; public class RacingGameTest { @Test - @DisplayName("0이하 값을 이동 횟수로 입력하면 표준 예외를 출력한다.") - void invalidInputMoveCount(){ - RandomGenerator fixedGenerator = () -> 7; - ThresholdEvaluator evaluator=new GreaterThanOrEqualThresholdEvaluator(4); - MoveDecider decider= new ThresholdBaseMoveDecider(evaluator); - MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, decider); - assertThatThrownBy(() -> new RacingGame(List.of("car1", "car2"), 0,strategy)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("moveCount는 0보다 큰 값이여야 합니다."); - } + @DisplayName("공동 우승자 발생한 경우 -> car1 car2") + void 공동_우승자_발생 () { + // given + MoveStrategy dummystrategy=()->1; + RacingGame game = new RacingGame(List.of("car1", "car2"), dummystrategy); - @Test - @DisplayName("공동 우승자 발생한 경우 -> car1 car2 ") - void getWinners_multipleWinners() { - RandomGenerator fixedGenerator = () -> 7; - ThresholdEvaluator evaluator=new GreaterThanOrEqualThresholdEvaluator(4); - MoveDecider decider= new ThresholdBaseMoveDecider(evaluator); - MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, decider); - RacingGame game = new RacingGame(List.of("car1", "car2"), 1, strategy); + // when game.moveOneTurn(); + + // then List winners = game.getWinners(); assertThat(winners).containsExactlyInAnyOrder("car1", "car2"); } - - @Test - @DisplayName("랜덤값이 threshold 값 이상일 때 자동차가 잘 움직이는지 확인한다.") - void carMovesWhenRandomValueIsAboveThreshold() { - RandomGenerator fixedGenerator = () -> 7; - ThresholdEvaluator evaluator=new GreaterThanOrEqualThresholdEvaluator(4); - MoveDecider decider= new ThresholdBaseMoveDecider(evaluator); - MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, decider); - - RacingGame game = new RacingGame(List.of("neo"), 1, strategy); - game.moveOneTurn(); - assertThat(game.getCars().get(0).getMovedDistance()).isEqualTo(1); - } - - @Test - @DisplayName("랜덤값이 threshold 값 초과일 때 자동차가 멈추는지 확인한다.") - void carStopsWhenRandomValueIsBelowThreshold() { - RandomGenerator fixedGenerator = () -> 2; - ThresholdEvaluator evaluator=new GreaterThanOrEqualThresholdEvaluator(4); - MoveDecider decider= new ThresholdBaseMoveDecider(evaluator); - MoveStrategy strategy = new OneStepMoveStrategy(fixedGenerator, decider); - - RacingGame game = new RacingGame(List.of("car1"), 1, strategy); - game.moveOneTurn(); - assertThat(game.getCars().get(0).getMovedDistance()).isEqualTo(0); - } - - } diff --git a/src/test/java/ThresholdBaseMoveDeciderTest.java b/src/test/java/ThresholdBaseMoveDeciderTest.java new file mode 100644 index 00000000..ef2bd6b6 --- /dev/null +++ b/src/test/java/ThresholdBaseMoveDeciderTest.java @@ -0,0 +1,29 @@ +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import racinggame.model.car.policy.decider.MoveDecider; +import racinggame.model.car.policy.decider.ThresholdBaseMoveDecider; +import racinggame.model.car.policy.evaluator.ThresholdEvaluator; + +import static org.assertj.core.api.Assertions.assertThat; + + +class ThresholdBaseMoveDeciderTest { + + @Test + @DisplayName("Evaluator 결과를 그대로 리턴한다") + void evaluator_결과_리턴 () { + // given + ThresholdEvaluator evaluator = new ThresholdEvaluator() { + @Override + public boolean isSatisfied(int value) { + return value == 7; + } + }; + MoveDecider decider = new ThresholdBaseMoveDecider(evaluator); + + // when & then + assertThat(decider.canMove(7)).isTrue(); + assertThat(decider.canMove(2)).isFalse(); + + } +} diff --git a/src/test/java/WinnerFinderTest.java b/src/test/java/WinnerFinderTest.java index daceb704..fa238077 100644 --- a/src/test/java/WinnerFinderTest.java +++ b/src/test/java/WinnerFinderTest.java @@ -1,5 +1,5 @@ -import racinggame.model.Car; -import racinggame.policy.strategy.MoveStrategy; +import racinggame.model.car.Car; +import racinggame.model.car.policy.strategy.MoveStrategy; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import racinggame.model.WinnerFinder; @@ -15,10 +15,14 @@ public class WinnerFinderTest { @Test @DisplayName("우승자 1명일 경우 car1") public void singleWinner(){ + // given List cars = createCarsForTest(new int[]{3,2,1},new String[]{"car1","car2","car3"}); WinnerFinder winner=new WinnerFinder(cars,1); + + // when winner.play(); + // then List winners = winner.getWinners(); assertThat(winners).containsExactly("car1"); } @@ -26,15 +30,19 @@ public void singleWinner(){ @Test @DisplayName("우승자 여러명일 경우 car1 car2") public void multipleWinners(){ + // given List cars = createCarsForTest(new int[]{3,3,1},new String[]{"car1","car2","car3"}); WinnerFinder winner=new WinnerFinder(cars,1); + + // when winner.play(); + // then List winners = winner.getWinners(); assertThat(winners).containsExactly("car1", "car2"); } - // 이름과 이동 거리를 갖는 Car 리스트 생성하기 + private List createCarsForTest(int[] distances,String[] names){ List cars = new ArrayList<>(); for (int i = 0; i < names.length; i++) {