Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Step3 - 3단계 : 자동차 경주 #1662

Merged
merged 10 commits into from
Dec 7, 2020
Merged
38 changes: 37 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,40 @@
- [X] 결과 값은 정수로 떨어지는 값으로 한정
- [X] 0으로 나눌경우 IllegalArgumentException throw
- [X] 사칙 연산을 모두 포함하는 기능 구현 :: Calculator 클래스 구현
- [X] 사칙 연산 수행
- [X] 사칙 연산 수행

# 3단계 - 자동차 경주
## 기능 요구사항
* 초간단 자동차 경주 게임을 구현한다.
* 주어진 횟수 동안 n대의 자동차는 전진 또는 멈출 수 있다.
* 사용자는 몇 대의 자동차로 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다.
* 전진하는 조건은 0에서 9 사이에서 random 값을 구한 후 random 값이 4이상일 경우이다.
* 자동차의 상태를 화면에 출력한다. 어느 시점에 출력할 것인지에 대한 제약은 없다.

## 프로그래밍 요구사항
* 모든 로직에 단위 테스트를 구현한다. 단, UI(System.out, System.in) 로직은 제외
* 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다.
* UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다.
* 자바 코드 컨벤션을 지키면서 프로그래밍한다.
* 참고문서: https://google.github.io/styleguide/javaguide.html 또는 https://myeonguni.tistory.com/1596
* else 예약어를 쓰지 않는다.
* 힌트: if 조건절에서 값을 return하는 방식으로 구현하면 else를 사용하지 않아도 된다.
* else를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다.

## To do

### UI
- [X] 입력값을 받는 InputView 클래스 구현
- [X] 사용자에게 적절한 UI 메세지를 출력한다
- [X] 입력값을 받아서 메인 기능 클래스로 위임한다
- [X] 결과를 출력 할 ResultView 클래스 구현
- [X] 자동차의 상태를 화면에 출력한다

### 기능
- [X] 자동차는 전진 하거나 멈출 수 있다
- [X] 0 ~ 9 사이의 random 값을 구한 후 random 값이 4이상일 경우 전진한다
- [X] 자동차 여러대가 경주를 한다
- [X] 경기에 참가하는 자동차의 대수는 사용자가 정한다
- [X] 여러대의 자동차가 이동 요구사항을 만족하면서 이동한다
- [X] 자동차가 몇 번의 이동을 할지는 사용자가 정한다
- [X] 각 이동 시점마다 자동차의 상태를 ResultView 클래스를 통해 출력한다
21 changes: 21 additions & 0 deletions src/main/java/racing/Car.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package racing;

public class Car {
private static final int MOVING_CONDITION_COUNT = 3;
private static final int MOVING_DISTANCE = 1;
private final MovingCondition movingCondition;

private int position;

public Car(MovingCondition condition) {
movingCondition = condition;
}

public void move() {
position = movingCondition.getCondition() > MOVING_CONDITION_COUNT ? position + MOVING_DISTANCE : position;
}

public int getPosition() {
return position;
}
}
23 changes: 23 additions & 0 deletions src/main/java/racing/Cars.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package racing;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Cars {
private final List<Car> cars;

public Cars(int count, MovingCondition condition) {
cars = Stream.generate(() -> new Car(condition))
.limit(count)
.collect(Collectors.toList());
}

public List<Car> getCars() {
return cars;
}

public void move() {
cars.forEach(Car::move);
}
}
14 changes: 14 additions & 0 deletions src/main/java/racing/FixedCondition.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package racing;

public class FixedCondition implements MovingCondition {
private final int possibleCondition;

public FixedCondition(int possibleCondition) {
this.possibleCondition = possibleCondition;
}

@Override
public int getCondition() {
return possibleCondition;
}
}
19 changes: 19 additions & 0 deletions src/main/java/racing/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package racing;

import java.util.Scanner;

public class InputView {
private static final Scanner SCANNER = new Scanner(System.in);
private static final String NUMBER_OF_CARS = "자동차 대수는 몇 대 인가요?";
private static final String TRY_TIMES = "시도할 회수는 몇 회 인가요?";

public static int numberOfCars() {
System.out.println(NUMBER_OF_CARS);
return SCANNER.nextInt();
}

public static int tryTimes() {
System.out.println(TRY_TIMES);
return SCANNER.nextInt();
}
}
5 changes: 5 additions & 0 deletions src/main/java/racing/MovingCondition.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package racing;

public interface MovingCondition {
int getCondition();
}
20 changes: 20 additions & 0 deletions src/main/java/racing/Racing.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package racing;

public class Racing {
private final int tryTimes;
private final Cars cars;

public Racing(int movingCount, Cars cars) {
this.tryTimes = movingCount;
this.cars = cars;
}

public void start() {
ResultView.printResultMessage();
for (int i = 0; i < tryTimes; i++) {
ResultView.printLineBreak();
cars.move();
ResultView.printRacingStatus(cars);
}
}
}
9 changes: 9 additions & 0 deletions src/main/java/racing/RacingApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package racing;

public class RacingApplication {
public static void main(String[] args) {
Cars cars = new Cars(InputView.numberOfCars(), new RandomCondition());
Racing racing = new Racing(InputView.tryTimes(), cars);
racing.start();
}
}
16 changes: 16 additions & 0 deletions src/main/java/racing/RandomCondition.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package racing;

import java.util.Random;

public class RandomCondition implements MovingCondition{
private final Random random;

public RandomCondition() {
random = new Random();
}

@Override
public int getCondition() {
return random.nextInt(10);
}
}
23 changes: 23 additions & 0 deletions src/main/java/racing/ResultView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package racing;

public class ResultView {
private static final String EXECUTION_RESULT = "실행 결과";
private static final String CAR_SYMBOL = "-";

public static void printResultMessage() {
System.out.println(EXECUTION_RESULT);
}

public static void printRacingStatus(Cars cars) {
cars.getCars().forEach(car -> {
for (int i = 0; i < car.getPosition(); i++) {
System.out.print(CAR_SYMBOL);
}
printLineBreak();
});
}

public static void printLineBreak() {
System.out.println();
}
}
38 changes: 38 additions & 0 deletions src/test/java/racing/CarTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package racing;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class CarTest {

@DisplayName("자동차는 전진 하거나 멈출 수 있다")
@ParameterizedTest
@CsvSource(value = {"0, 0", "4, 1", "9, 1"})
public void move(int condition, int expected){
//given
Car car = new Car(new FixedCondition(condition));

//when
car.move();

//then
assertEquals(car.getPosition(), expected);
}

@DisplayName("0 ~ 9 사이의 random 값을 구한 후 random 값이 4이상일 경우 전진한다")
@ParameterizedTest
@CsvSource(value = {"0, 0", "4, 1", "9, 1"})
public void movingCar(int condition, int expected) {
//given
Car car = new Car(new FixedCondition(condition));

//when
car.move();

//then
assertEquals(car.getPosition(), expected);
}
}
37 changes: 37 additions & 0 deletions src/test/java/racing/CarsTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package racing;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class CarsTest {

@DisplayName("경기에 참가하는 자동차의 대수는 사용자가 정한다")
@ParameterizedTest
@CsvSource(value = {"3, 3", "5, 5", "7, 7"})
public void numberOfCars(int count, int expected) {
//given
Cars cars = new Cars(count, new RandomCondition());

//then
assertEquals(expected, cars.getCars().size());
}

@DisplayName("여러대의 자동차가 이동 요구사항을 만족하면서 이동한다")
@ParameterizedTest
@CsvSource(value = {"3, 3, 0", "5, 5, 1", "7, 7, 1"})
public void expectedMove(int count, int condition, int expectedPosition) {
//given
Cars cars = new Cars(count, new FixedCondition(condition));

//when
cars.move();

//then
for (Car car : cars.getCars()) {
assertEquals(expectedPosition, car.getPosition());
}
}
}
27 changes: 27 additions & 0 deletions src/test/java/racing/RacingTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package racing;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class RacingTest {

@DisplayName("자동차가 몇 번의 이동을 할지는 사용자가 정한다")
@ParameterizedTest
@CsvSource(value = {"3, 4, 5", " 5, 4, 5"})
public void carsMove(int numberOfCars, int condition, int movingCount) {
//given
Cars cars = new Cars(numberOfCars, new FixedCondition(condition));
Racing racing = new Racing(movingCount, cars);

//when
racing.start();

//then
for (Car car : cars.getCars()) {
assertEquals(movingCount, car.getPosition());
}
}
}