Skip to content

Commit 20fa1fb

Browse files
authored
고생하셨습니다.
🎉 PR 머지 완료! 🎉
1 parent 3a8cf14 commit 20fa1fb

24 files changed

+642
-0
lines changed

README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
### 1단계
2+
- 자동차는 이름을 갖는다.
3+
- 자동차는 0-9 사이 랜덤 값을 구한 후 4이상이면 전진, 3이하면 멈춘다.
4+
- 3항 연산자를 쓰지 않는다.
5+
- else 예약어, switch/case 허용하지 않는다.
6+
- 메소드 길이가 15라인이 넘어가지 않도록 구현한다
7+
- 메인 메소드를 만들지 않는다.
8+
- 테스트 코드 작성한다.
9+
10+
### 2단계
11+
- n대의 자동차가 참여가능하다.
12+
- 주어진 횟수동안 자동차 경주 게임을 완료한 후 누가 우승했는지 알 수 있다.
13+
- 우승자는 한 명 이상일 수 있다.
14+
- 나머진 1단계와 유사하다.
15+
16+
### 3단계
17+
- 자동차에 이름 부여가능하고, 전진하는 자동차 출력할 때 자동차 이름을 같이 출력한다.
18+
- 자동차 이름은 , 기준으로 구분하며 이름은 5자 이하만 가능하다.
19+
- 메인 메소드를 추가한다.
20+
21+
### 4단계
22+
- 모든 로직에 단위 테스트를 구현한다.
23+
- mvc 패턴으로 리팩터링한다.
24+
25+
### 개인적 목표
26+
1. 주석이 없어도 읽기 좋은 코드를 짜보자.
27+
2. 메서드가 한가지 기능만 갖도록 분리하다가 따로 관리하는게 좋을 것 같으면 클래스로 구현하자.
28+
3. 단위 테스트 핵심 원칙을 따르자.
29+
4. 개념에 머무르고 있었던 객체 지향적 개념을 활용하여 코드를 작성해보자.
30+
5. 발생할 수 있는 예외 케이스를 고려하여 방어적인 코드를 작성하고, 이를 테스트 코드로 확인하자.
31+
32+

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ dependencies {
1414
testImplementation platform('org.assertj:assertj-bom:3.25.1')
1515
testImplementation('org.junit.jupiter:junit-jupiter')
1616
testImplementation('org.assertj:assertj-core')
17+
developmentOnly('org.springframework.boot:spring-boot-devtools')
1718
}
1819

1920
test {

src/main/java/racinggame/Main.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package racinggame;
2+
3+
import racinggame.controller.RacingGameController;
4+
5+
public class Main {
6+
public static void main(String[] args) {
7+
new RacingGameController().run();
8+
}
9+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package racinggame.controller;
2+
3+
import racinggame.model.RacingGame;
4+
import racinggame.model.car.policy.numbergenerator.ZeroToNineRandomGenerator;
5+
import racinggame.model.car.policy.decider.ThresholdBaseMoveDecider;
6+
import racinggame.model.car.policy.evaluator.GreaterThanOrEqualThresholdEvaluator;
7+
import racinggame.model.car.policy.strategy.MoveStrategy;
8+
import racinggame.model.car.policy.strategy.OneStepMoveStrategy;
9+
import racinggame.view.InputView;
10+
import racinggame.view.OutputView;
11+
12+
import java.util.List;
13+
14+
public class RacingGameController {
15+
public void run(){
16+
List<String> names= InputView.readCarNames();
17+
int moveCount = InputView.readMoveCount();
18+
19+
MoveStrategy strategy = new OneStepMoveStrategy(
20+
new ZeroToNineRandomGenerator(),
21+
new ThresholdBaseMoveDecider(new GreaterThanOrEqualThresholdEvaluator(4)));
22+
23+
RacingGame game = new RacingGame(names,strategy);
24+
25+
for (int i = 0; i < moveCount; i++) {
26+
game.moveOneTurn();
27+
OutputView.printResult(game.getCars());
28+
}
29+
30+
List<String> winners = game.getWinners();
31+
OutputView.printWinner(winners);
32+
}
33+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package racinggame.model;
2+
import racinggame.model.car.Car;
3+
import racinggame.model.car.policy.strategy.MoveStrategy;
4+
5+
import java.util.ArrayList;
6+
import java.util.List;
7+
import java.util.stream.Collectors;
8+
9+
public class RacingGame {
10+
private final List<Car> cars;
11+
12+
public RacingGame(List<String> names,MoveStrategy moveStrategy) {
13+
this.cars = createCars(names,moveStrategy);
14+
}
15+
16+
private List<Car> createCars(List<String> names, MoveStrategy strategy) {
17+
return names.stream()
18+
.map(name -> new Car(name,strategy))
19+
.collect(Collectors.toList());
20+
}
21+
22+
public void moveOneTurn() {
23+
for (Car car : cars) {
24+
car.move();
25+
}
26+
}
27+
28+
public List<Car> getCars() {
29+
return cars;
30+
}
31+
32+
public List<String> getWinners(){
33+
int maxDistance=findMaxDistance();
34+
35+
return cars.stream()
36+
.filter(car->car.getMovedDistance()==maxDistance)
37+
.map(Car::getName).collect(Collectors.toList());
38+
}
39+
40+
private int findMaxDistance(){
41+
return cars.stream()
42+
.mapToInt(Car::getMovedDistance)
43+
.max()
44+
.orElse(0);
45+
}
46+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package racinggame.model;
2+
3+
import racinggame.model.car.Car;
4+
5+
import java.util.List;
6+
import java.util.stream.Collectors;
7+
8+
public class WinnerFinder {
9+
private final List<Car> cars;
10+
private final int moveCount;
11+
public WinnerFinder(List<Car> cars, int moveCount){
12+
this.cars = cars;
13+
this.moveCount = moveCount;
14+
}
15+
16+
public void play(){
17+
for(int i=0;i<moveCount;i++){
18+
moveAllCars();
19+
}
20+
}
21+
public List<String> getWinners(){
22+
int maxDistance=maxDistance();
23+
return cars.stream().filter(car->car.getMovedDistance()==maxDistance).map(Car::getName).collect(Collectors.toList());
24+
}
25+
26+
private void moveAllCars( ){
27+
for (Car car : cars) {
28+
car.move();
29+
}
30+
}
31+
private int maxDistance(){
32+
int max=0;
33+
for (Car car : cars) {
34+
max=Math.max(max,car.getMovedDistance());
35+
}
36+
return max;
37+
}
38+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package racinggame.model.car;
2+
3+
import racinggame.model.car.policy.strategy.MoveStrategy;
4+
5+
import java.util.Objects;
6+
7+
public class Car {
8+
private final String name;
9+
private int movedDistance=0;
10+
11+
private final MoveStrategy moveStrategy;
12+
13+
public Car(String name,MoveStrategy moveStrategy) {
14+
if(name==null){
15+
throw new IllegalArgumentException("이름은 null 일 수 없습니다.");
16+
}
17+
if(name.isBlank()){
18+
throw new IllegalArgumentException("이름은 공백일 수 없습니다.");
19+
}
20+
this.name = name;
21+
this.moveStrategy=moveStrategy;
22+
}
23+
24+
public void move(){
25+
int distance=moveStrategy.addStepSize();
26+
movedDistance+=distance;
27+
}
28+
29+
public int getMovedDistance() {
30+
return movedDistance;
31+
}
32+
public String getName() {
33+
return name;
34+
}
35+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package racinggame.model.car.policy.decider;
2+
3+
public interface MoveDecider {
4+
boolean canMove(int randomNumber);
5+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package racinggame.model.car.policy.decider;
2+
3+
import racinggame.model.car.policy.evaluator.ThresholdEvaluator;
4+
5+
public class ThresholdBaseMoveDecider implements MoveDecider {
6+
private final ThresholdEvaluator evaluator;
7+
8+
public ThresholdBaseMoveDecider(ThresholdEvaluator evaluator) {
9+
this.evaluator = evaluator;
10+
}
11+
12+
@Override
13+
public boolean canMove(int randomNumber){
14+
return evaluator.isSatisfied(randomNumber);
15+
}
16+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package racinggame.model.car.policy.evaluator;
2+
3+
public class GreaterThanOrEqualThresholdEvaluator implements ThresholdEvaluator {
4+
private final int threshold;
5+
6+
public GreaterThanOrEqualThresholdEvaluator(int threshold) {
7+
this.threshold = threshold;
8+
}
9+
@Override
10+
public boolean isSatisfied(int value){
11+
return value >= threshold;
12+
}
13+
}

0 commit comments

Comments
 (0)