Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,45 @@
# java-racingcar-precourse
## 📍구현할 기능 목록
**1. 입력**
- 자동차 이름과 시도 횟수를 입력 받는다
- 빈 값, 시도 횟수 검증
- `,`을 기준으로 자동차 이름을 분리한다
- 자동차 이름 길이 검증

**2. 자동차**
- 입력받은 이름을 저장한다
- 총 움직임을 저장한다

**3. 난수 생성**
- 0에서 9사이의 난수를 생성한다

**4. 경주**
- 입력받은 횟수만큼 라운드를 진행한다

**5. 출력**
- 최종 우승자를 출력한다

<!--
1. 차
- 이름을 가짐
- 움직임을 가짐 (전진/멈춤, 뒤로가는건 없음)
2. 움직임
- 제공되는 랜덤함수 사용(Randoms.pickNumberInRange(start, end))
- 0~3: 멈춤
- 4~9: 전진
3. 기타
- 1번 실행될 때마다 결과 출력
- 최종 우승자 출력(n명)
4. 발생할 수 있는 예외
- 자동차 이름 빈값
- 시도할 횟수 0 이하
- 이름 길이 6 이상
- 동명이차가 있을 가능성이 있는가?
- 이름에 특수문자가 들어갈 수 있는가?

<기억할 사항>
1. 들여쓰기 depth가 3을 넘지 않도록(넘을거 같으면 함수나 메서드 분리)
2. 3항 연산자 쓰지 않기(ㅠㅠ)
3. 함수/메서드가 한 가지 일만 하도록 최대한 작게 쪼개기
4. 테스트 코드 작성하기
-->
10 changes: 9 additions & 1 deletion src/main/java/racingcar/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
package racingcar;

import racingcar.controller.RaceController;
import racingcar.view.InputView;
import racingcar.view.OutputView;

public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
InputView inputView = new InputView();
OutputView outputView = new OutputView();
RaceController raceController = new RaceController(inputView, outputView);

raceController.run();
}
}
14 changes: 14 additions & 0 deletions src/main/java/racingcar/Race.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package racingcar;

import racingcar.model.Cars;
import racingcar.utils.RandomNumberGenerator;

public class Race {
public void run(Cars cars) {
cars.getCarList().forEach((car -> {
if (RandomNumberGenerator.IsMoveable()) {
car.moveForward();
}
}));
}
}
40 changes: 40 additions & 0 deletions src/main/java/racingcar/RacingGame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package racingcar;

import racingcar.model.Car;
import racingcar.model.Cars;
import racingcar.view.OutputView;

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

public class RacingGame {
private OutputView outputView;
public RacingGame(OutputView outputView) {
this.outputView = outputView;
}
public void run(Cars cars, Integer round) {
Race race = new Race();
for(int i = 0; i < round ; i++) {
race.run(cars);
outputView.printRaceResult(cars);
}

outputView.printWinner(getWinner(cars));
}

public String getWinner(Cars cars) {
Integer maxMovement = getMaxMovement(cars);
return cars.getCarList().stream()
.filter((car) -> car.getMovement().equals(maxMovement))
.map(Car::getName)
.collect(Collectors.joining(","));
}

private Integer getMaxMovement(Cars cars) {
return cars.getCarList().stream()
.map(Car::getMovement)
.max(Comparator.naturalOrder())
.orElse(0);
}
}
26 changes: 26 additions & 0 deletions src/main/java/racingcar/controller/RaceController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package racingcar.controller;

import racingcar.RacingGame;
import racingcar.model.Cars;
import racingcar.view.InputView;
import racingcar.view.OutputView;

import java.util.List;

public class RaceController {
private final InputView inputView;
private final OutputView outputView;
public RaceController (InputView inputView, OutputView outputView) {
this.inputView = inputView;
this.outputView = outputView;
}

public void run() {
List<String> inputCarNameList = inputView.readCarNames();
Cars cars = new Cars(inputCarNameList);
Integer round = inputView.readRounds();

RacingGame racingGame = new RacingGame(outputView);
racingGame.run(cars, round);
}
}
23 changes: 23 additions & 0 deletions src/main/java/racingcar/model/Car.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package racingcar.model;

public class Car {
private String name;
private Integer movement;

public Car (String name) {
this.name = name;
this.movement = 0;
}

public void moveForward() {
this.movement++;
}

public String getName() {
return name;
}

public Integer getMovement() {
return movement;
}
}
21 changes: 21 additions & 0 deletions src/main/java/racingcar/model/Cars.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package racingcar.model;

import java.util.List;

public class Cars {
private List<Car> cars;

public Cars (List<String> carNameList) {
this.cars = parseCarList(carNameList);
}

private List<Car> parseCarList(List<String> carNameList) {
return carNameList.stream()
.map(Car::new)
.toList();
}

public List<Car> getCarList() {
return cars;
}
}
8 changes: 8 additions & 0 deletions src/main/java/racingcar/utils/ErrorCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package racingcar.utils;

public class ErrorCode {
public static final String INPUT_CANT_BLANK = "입력은 비어있을 수 없습니다.";
public static final String NAME_TOO_LONG = "자동차 이름은 5자 이내여야 합니다.";
public static final String DUPLICATE_NOT_ALLOWED = "자동차 이름은 중복일 수 없습니다.";
public static final String INVALID_ROUND = "라운드는 양수만 허용됩니다.";
}
12 changes: 12 additions & 0 deletions src/main/java/racingcar/utils/RandomNumberGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package racingcar.utils;

import camp.nextstep.edu.missionutils.Randoms;

public class RandomNumberGenerator {
public static Boolean IsMoveable() {
return randomNumberGenerator() >= 4;
}
private static Integer randomNumberGenerator() {
return Randoms.pickNumberInRange(0, 9);
}
}
50 changes: 50 additions & 0 deletions src/main/java/racingcar/utils/Validator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package racingcar.utils;

import java.util.List;

public class Validator {
public static void isCarNameBlank(String input) {
if (input.isBlank()) { throw new IllegalArgumentException(ErrorCode.INPUT_CANT_BLANK); }
}

public static void isNameLengthValid(List<String> names) {
names.forEach(name -> {
if (name.length() >= 6) {
throw new IllegalArgumentException(ErrorCode.NAME_TOO_LONG);
}
});
}

public static void hasDuplicateName(List<String> inputNames) {
long distinctCount = inputNames.stream().distinct().count();
if (inputNames.size() != distinctCount) { throw new IllegalArgumentException(ErrorCode.DUPLICATE_NOT_ALLOWED); }
}

public static Integer isValidRound(String round) {
if (round == null || round.isEmpty()) {
throw new IllegalArgumentException(ErrorCode.INPUT_CANT_BLANK);
}

int roundInt;
if (isNumber(round)) {
roundInt = Integer.parseInt(round);
} else {
throw new IllegalArgumentException(ErrorCode.INVALID_ROUND);
}

if (roundInt <= 0) {
throw new IllegalArgumentException(ErrorCode.INVALID_ROUND);
}

return roundInt;
}

private static Boolean isNumber(String round) {
try {
Integer.parseInt(round);
return true;
} catch (NumberFormatException e) {
return false;
}
}
}
29 changes: 29 additions & 0 deletions src/main/java/racingcar/view/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package racingcar.view;

import java.util.Arrays;
import java.util.List;
import camp.nextstep.edu.missionutils.Console;
import racingcar.utils.Validator;

public class InputView {

public List<String> readCarNames() {
System.out.println("경주를 진행할 자동차 목록을 적어주세요.(`,`로 구분)");
String input = Console.readLine();
Validator.isCarNameBlank(input);
return parseCarNames(input);
}

private List<String> parseCarNames(String inputString) {
List<String> parseList = Arrays.asList(inputString.split(","));
Validator.isNameLengthValid(parseList);
Validator.hasDuplicateName(parseList);
return parseList;
}

public Integer readRounds() {
System.out.println("총 몇 라운드를 진행할까요?");
String input = Console.readLine();
return Validator.isValidRound(input);
}
}
14 changes: 14 additions & 0 deletions src/main/java/racingcar/view/OutputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package racingcar.view;

import racingcar.model.Cars;

public class OutputView {
public void printRaceResult(Cars cars) {
cars.getCarList()
.forEach(car -> System.out.println(car.getName() + " : " + "-".repeat(car.getMovement())));
}

public void printWinner(String result) {
System.out.println("최종 우승자 : " + result);
}
}