Skip to content

Commit 0a80371

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

File tree

15 files changed

+466
-0
lines changed

15 files changed

+466
-0
lines changed

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#자동차 경주 미션
2+
3+
##기능
4+
5+
- 자동차 이름 입력: 쉼표(,)로 구분된, 1자 이상 5자 이하의 자동차 이름을 입력받는다.
6+
- 시도 횟수 입력: 경주를 진행할 총 라운드 수를 입력받는다.
7+
- 전진 또는 정지: 각 자동차는 매 라운드마다 0~9 사이의 무작위 값을 생성하여, 4 이상일 경우 전진한다.
8+
- 라운드별 결과 출력: 매 라운드가 끝날 때마다 모든 자동차의 현재 위치를 출력한다.
9+
- 최종 우승자 발표: 경주가 끝난 후, 가장 멀리 전진한 자동차를 최종 우승자로 발표한다. (공동 우승 가능)
10+
11+
##조건
12+
13+
- MVC 패턴을 적용하여 역할을 분리한다.
14+
- 모든 로직에 단위 테스트를 구현한다.
15+
- indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다.
16+
- 3항 연산자를 쓰지 않는다.
17+
- else 예약어를 쓰지 않는다.
18+
- 함수(또는 메소드)의 길이가 15라인을 넘어가지 않도록 구현한다.
19+
- 함수(또는 메소드)가 한 가지 일만 잘 하도록 구현한다.
20+
21+
##프로젝트 구조
22+
23+
- model
24+
* Car.java: 자동차 객체 (이름, 위치 상태 및 유효성 검사)
25+
* Cars.java: 자동차 목록을 관리하는 일급 컬렉션
26+
* MoveCarStrategy.java: NumberGenerator에 따라 자동차 이동 여부를 결정하는 전략.
27+
* Race.java: 경주 상태 및 로직 관리
28+
* NumberGenerator: 숫자 생성을 위한 인터페이스
29+
* RandomNumberGenerator:NumberGenerator의 구현체
30+
- controller
31+
* RacingGameController.java: 게임 전체 흐름 관리
32+
- view
33+
* InputView.java: 사용자 입력 담당
34+
* OutputView.java: 결과 출력 담당

src/main/java/RaceMain.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import controller.RacingGameController;
2+
import model.strategy.NumberGenerator;
3+
import model.strategy.RandomNumberGenerator;
4+
5+
public class RaceMain {
6+
public static void main(String[] args) {
7+
NumberGenerator numberGenerator = new RandomNumberGenerator();
8+
RacingGameController controller = new RacingGameController(numberGenerator);
9+
controller.run();
10+
}
11+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package controller;
2+
3+
import model.domain.Car;
4+
import model.domain.Cars;
5+
import model.strategy.MoveCarStrategy;
6+
import model.strategy.NumberGenerator;
7+
import model.domain.Race;
8+
import view.InputView;
9+
import view.OutputView;
10+
11+
import java.util.List;
12+
13+
public class RacingGameController {
14+
15+
private final NumberGenerator numberGenerator;
16+
17+
public RacingGameController(NumberGenerator numberGenerator) {
18+
this.numberGenerator = numberGenerator;
19+
}
20+
21+
public void run() {
22+
Cars cars = setupCars();
23+
Race race = new Race(cars, new MoveCarStrategy(numberGenerator));
24+
25+
int rounds = InputView.readRounds();
26+
runRace(race, rounds);
27+
OutputView.printWinners(race.getWinners());
28+
29+
InputView.close();
30+
}
31+
32+
private Cars setupCars() {
33+
String[] carNames = InputView.readCarNames();
34+
return Cars.fromNames(List.of(carNames));
35+
}
36+
37+
private void runRace(Race race, int rounds) {
38+
OutputView.printRaceStartMessage();
39+
for (int i = 0; i < rounds; i++) {
40+
race.runRound();
41+
printCurrentPositions(race.getCars()); }
42+
}
43+
44+
private void printCurrentPositions(List<Car> cars) {
45+
for (Car car : cars) {
46+
OutputView.printSingleCarStatus(car.getCarName(), car.getPosition());
47+
}
48+
OutputView.printNewLine();
49+
}
50+
51+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package model.domain;
2+
3+
public class Car {
4+
5+
private static final int MOVE_DISTANCE = 1;
6+
private static final int MAX_NAME_LENGTH = 5;
7+
8+
private final String carName;
9+
private int position;
10+
11+
private Car(String name) {
12+
this.carName = name;
13+
this.position = 0;
14+
}
15+
16+
public static Car fromName(String name) {
17+
String trimmedName = name.trim();
18+
validateName(trimmedName);
19+
return new Car(trimmedName);
20+
}
21+
22+
private static void validateName(String name) {
23+
if (name.length() > MAX_NAME_LENGTH) {
24+
throw new IllegalArgumentException("자동차 이름은 5자 이하만 가능합니다.");
25+
}
26+
}
27+
28+
public void moveForward() {
29+
position += MOVE_DISTANCE;
30+
}
31+
32+
public String getCarName() {
33+
return carName;
34+
}
35+
36+
public int getPosition() {
37+
return position;
38+
}
39+
40+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package model.domain;
2+
3+
import model.strategy.MoveCarStrategy;
4+
5+
import java.util.Collections;
6+
import java.util.List;
7+
import java.util.stream.Collectors;
8+
9+
public class Cars {
10+
11+
private final List<Car> cars;
12+
13+
public Cars(List<Car> cars) {
14+
this.cars = cars;
15+
}
16+
17+
public static Cars fromNames(List<String> carNames) {
18+
List<Car> carList = carNames.stream()
19+
.map(Car::fromName)
20+
.collect(Collectors.toList());
21+
return new Cars(carList);
22+
}
23+
24+
public void moveEachCar(MoveCarStrategy moveCarStrategy) {
25+
for (Car car : cars) {
26+
moveCarStrategy.tryMove(car);
27+
}
28+
}
29+
30+
public List<String> findWinners() {
31+
int maxPosition = getMaxPosition();
32+
return cars.stream()
33+
.filter(car -> car.getPosition() == maxPosition)
34+
.map(Car::getCarName)
35+
.collect(Collectors.toList());
36+
}
37+
38+
private int getMaxPosition() {
39+
return cars.stream()
40+
.mapToInt(Car::getPosition)
41+
.max()
42+
.orElse(0);
43+
}
44+
45+
public List<Car> getCars() {
46+
return Collections.unmodifiableList(cars);
47+
}
48+
49+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package model.domain;
2+
3+
import model.strategy.MoveCarStrategy;
4+
5+
import java.util.List;
6+
7+
public class Race {
8+
9+
private Cars cars;
10+
private MoveCarStrategy moveCarStrategy;
11+
12+
public Race(Cars cars, MoveCarStrategy moveCarStrategy) {
13+
this.cars = cars;
14+
this.moveCarStrategy = moveCarStrategy;
15+
}
16+
17+
public void runRound() {
18+
cars.moveEachCar(moveCarStrategy);
19+
}
20+
21+
public List<String> getWinners() {
22+
return cars.findWinners();
23+
}
24+
25+
public List<Car> getCars() {
26+
return cars.getCars();
27+
}
28+
29+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package model.strategy;
2+
3+
import model.domain.Car;
4+
5+
public class MoveCarStrategy {
6+
7+
private static final int MOVE_THRESHOLD = 4;
8+
9+
private final NumberGenerator numberGenerator;
10+
11+
public MoveCarStrategy(NumberGenerator numberGenerator) {
12+
this.numberGenerator = numberGenerator;
13+
}
14+
15+
public void tryMove(Car car) {
16+
int randomNumber = numberGenerator.generate();
17+
18+
if (shouldMove(randomNumber)) {
19+
car.moveForward();
20+
}
21+
}
22+
23+
private boolean shouldMove(int randomNumber) {
24+
return randomNumber >= MOVE_THRESHOLD;
25+
}
26+
27+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package model.strategy;
2+
3+
public interface NumberGenerator {
4+
int generate();
5+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package model.strategy;
2+
3+
import java.util.Random;
4+
5+
public class RandomNumberGenerator implements NumberGenerator {
6+
7+
private static final Random random = new Random();
8+
private static final int RANDOM_NUMBER_BOUND = 10;
9+
10+
@Override
11+
public int generate() {
12+
return random.nextInt(RANDOM_NUMBER_BOUND);
13+
}
14+
}

src/main/java/view/InputView.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package view;
2+
3+
import java.util.Scanner;
4+
5+
public class InputView {
6+
7+
private static Scanner scanner = new Scanner(System.in);
8+
9+
public static String[] readCarNames() {
10+
System.out.println("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분).");
11+
return scanner.nextLine().split(",");
12+
}
13+
14+
public static int readRounds() {
15+
System.out.println("시도할 회수는 몇회인가요?");
16+
int rounds = scanner.nextInt();
17+
scanner.nextLine();
18+
return rounds;
19+
}
20+
21+
public static void close() {
22+
scanner.close();
23+
}
24+
}

0 commit comments

Comments
 (0)