Skip to content

Commit 9ddba9f

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

File tree

14 files changed

+600
-0
lines changed

14 files changed

+600
-0
lines changed

README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# 자동차 경주 - 초간단 애플리케이션
2+
3+
## [1] 움직이는 자동차
4+
5+
- 자동차에 관한 요구사항
6+
- [x] 자동차는 이름을 가지고 있다.
7+
- [x] 자동차는 움직일 수 있다.
8+
- [x] 0에서 9 사이의 random 값을 구해 그 값이 **4 이상이면 전진**하고, **3 이하 값이면 멈춘다**.
9+
10+
---
11+
12+
## [2] 우승 자동차 구하기
13+
14+
- 기능 요구사항
15+
- [x] n대의 자동차 참여 가능
16+
- [x] 주어진 횟수동안 n대의 자동차는 전진 또는 멈출 수 있다.
17+
- [x] 이동 조건은 앞의 [움직이는 자동차]와 동일
18+
- [x] 경주 게임 완료 후 우승자를 구할 수 있다.
19+
- [x] 우승자는 한 명 이상일 수 있다.
20+
21+
---
22+
23+
## [3] 게임 실행
24+
25+
- 기능 요구사항
26+
- [x] 자동차 및 게임 방법은 앞의 [움직이는 자동차], [우승 자동차 구하기]와 동일
27+
- [x] 사용자로부터 `이름`, `게임횟수` 를 입력받는다.
28+
- [x] 자동차 이름은 쉼표(,) 기준으로 구분하며, 이름은 5자 이하만 가능하다.
29+
- [x] 메인 메서드를 추가하여 실행 가능하게 만든다.
30+
31+
---
32+
33+
## [4] 리팩터링
34+
35+
- 요구사항
36+
- [x] 단위 테스트를 구현한다.
37+
38+
---
39+
40+
- 코드 작성 요구사항
41+
- [x] 자동차가 움직이는 기능이 의도대로 되는지 테스트한다.
42+
- [x] 자바 코드 컨벤션 `Java Style Guide` 원칙으로 프로그래밍한다.
43+
- [x] 3항 연산자를 쓰지 않는다.
44+
- [x] else 예약어를 쓰지 않는다.
45+
- [x] switch/case도 사용하지 않는다.
46+
- [x] 함수(또는 메서드) 길이가 15라인을 넘어가지 않도록 구현한다.
47+
- [x] 함수(또는 메서드)가 한 가지 일만 하도록 한다.

src/main/java/App.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import controller.RacingGameController;
2+
3+
public class App {
4+
public static void main(String[] args) {
5+
RacingGameController racingGameController = new RacingGameController();
6+
7+
racingGameController.startRacingGame();
8+
9+
}
10+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package controller;
2+
3+
import domain.Car;
4+
import domain.CarNameParser;
5+
import domain.CarRaceGame;
6+
import java.util.List;
7+
import view.inputView;
8+
import view.outputView;
9+
10+
public class RacingGameController {
11+
12+
public void startRacingGame() {
13+
String carNames = inputView.enterCarNames();
14+
List<Car> cars = CarNameParser.parseCarName(carNames);
15+
final CarRaceGame carRaceGame = new CarRaceGame(cars);
16+
17+
int round = inputView.enterRoundNumber();
18+
19+
outputView.printGameResultTitle();
20+
21+
printGameRounds(carRaceGame, round, cars);
22+
23+
printWinners(carRaceGame);
24+
}
25+
26+
private void printGameRounds(CarRaceGame carRaceGame, int round, List<Car> cars) {
27+
carRaceGame.validateRoundNumber(round);
28+
29+
for (int i = 0; i < round; i++) {
30+
31+
carRaceGame.playOneRound();
32+
System.out.println();
33+
outputView.printRoundResult(cars);
34+
}
35+
}
36+
37+
38+
private void printWinners(CarRaceGame carRaceGame) {
39+
40+
List<String> winnersName = carRaceGame.getWinnerNames();
41+
42+
outputView.printGameWinners(winnersName);
43+
44+
}
45+
}

src/main/java/domain/Car.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package domain;
2+
3+
import domain.generator.NumberGenerator;
4+
5+
public class Car {
6+
7+
private final String name;
8+
private int position;
9+
private final NumberGenerator generator;
10+
private static final int MOVE_THRESHOLD = 4;
11+
12+
public Car(String name, NumberGenerator generator) {
13+
validateName(name);
14+
this.name = name.trim();
15+
this.position = 0;
16+
this.generator = generator;
17+
}
18+
19+
public String getName() {
20+
return name;
21+
}
22+
23+
public int getPosition() {
24+
return position;
25+
}
26+
27+
private void validateName(String name) {
28+
29+
if (name == null || name.isBlank()) {
30+
throw new IllegalArgumentException("이름은 빈 값이 될 수 없습니다.");
31+
}
32+
if (name.length() > 5) {
33+
throw new IllegalArgumentException("이름은 5자 이하만 가능합니다.");
34+
}
35+
}
36+
37+
public void movePosition() {
38+
if (generator.generate() >= MOVE_THRESHOLD ) {
39+
position++;
40+
}
41+
}
42+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package domain;
2+
3+
import domain.generator.RandomNumberGenerator;
4+
import java.util.Arrays;
5+
import java.util.HashSet;
6+
import java.util.List;
7+
import java.util.Set;
8+
import java.util.stream.Collectors;
9+
10+
public class CarNameParser {
11+
12+
public static final String CAR_NAME_DELIMITER = ",";
13+
14+
public static List<Car> parseCarName(String carNames) {
15+
16+
List<String> carNameList = Arrays.stream(carNames.split(CAR_NAME_DELIMITER))
17+
.map(String::trim)
18+
.collect(Collectors.toList());
19+
20+
validateDuplicateCarName(carNameList);
21+
22+
return carNameList.stream()
23+
.map(name -> new Car(name.trim(), new RandomNumberGenerator()))
24+
.collect(Collectors.toList());
25+
}
26+
27+
private static void validateDuplicateCarName(List<String> carNameList) {
28+
29+
Set<String> uniqueCarNames = new HashSet<>(carNameList);
30+
31+
if (uniqueCarNames.size() != carNameList.size()) {
32+
throw new IllegalArgumentException("중복된 자동차 이름은 입력할 수 없습니다.");
33+
}
34+
}
35+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package domain;
2+
3+
import java.util.List;
4+
5+
public class CarRaceGame {
6+
7+
private final List<Car> cars;
8+
9+
public CarRaceGame(List<Car> cars) {
10+
this.cars = cars;
11+
}
12+
13+
public void validateRoundNumber(int gameRound) {
14+
if (gameRound < 1 ) {
15+
throw new IllegalArgumentException("라운드는 한 번 이상 진행되어야 합니다.");
16+
}
17+
}
18+
19+
public void playOneRound() {
20+
for (Car car : cars) {
21+
car.movePosition();
22+
}
23+
}
24+
25+
private int getMaxDistance() {
26+
int maxDistance = cars.stream()
27+
.mapToInt(Car::getPosition)
28+
.max()
29+
.orElseThrow();
30+
31+
return maxDistance;
32+
}
33+
34+
private List<String> getWinners(int maxDistance) {
35+
return cars.stream()
36+
.filter(car -> car.getPosition() == maxDistance)
37+
.map(Car::getName)
38+
.toList();
39+
}
40+
41+
public void playRacingGame(int gameRound) {
42+
validateRoundNumber(gameRound);
43+
44+
for (int i=0; i < gameRound;i++) {
45+
playOneRound();
46+
}
47+
}
48+
49+
public List<String> getWinnerNames() {
50+
List<String> winners = getWinners(getMaxDistance());
51+
52+
if (winners == null) {
53+
throw new IllegalStateException("게임이 실행되지 않았습니다.");
54+
}
55+
return winners;
56+
}
57+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package domain.generator;
2+
3+
public interface NumberGenerator {
4+
int generate();
5+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package domain.generator;
2+
3+
import java.util.Random;
4+
5+
public class RandomNumberGenerator implements NumberGenerator {
6+
7+
private static final Random RANDOM = new Random();
8+
9+
@Override
10+
public int generate( ) {
11+
return RANDOM.nextInt( 10 );
12+
}
13+
}

src/main/java/view/inputView.java

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

src/main/java/view/outputView.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package view;
2+
3+
import domain.Car;
4+
5+
import java.util.List;
6+
7+
public class outputView {
8+
9+
private static final String CAR_POSITION_EXPRESSION = "-";
10+
private static final String WINNER_NAMES_DELIMITER = ",";
11+
12+
public static void printGameResultTitle() {
13+
System.out.print("\n실행 결과");
14+
}
15+
16+
public static void printRoundResult(List<Car> cars) {
17+
for (Car car : cars) {
18+
System.out.println(car.getName() + ": " + CAR_POSITION_EXPRESSION.repeat(car.getPosition()));
19+
}
20+
System.out.println();
21+
}
22+
23+
public static void printGameWinners(List<String> winners) {
24+
System.out.println(String.join(WINNER_NAMES_DELIMITER, winners) + "가 최종 우승했습니다.");
25+
}
26+
}

0 commit comments

Comments
 (0)