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

[자동차 경주 게임] 박준수 미션 제출합니다. #3

Open
wants to merge 41 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
ee97879
docs: 기능 구현 정의
GaBaljaintheroom Sep 8, 2023
d6736be
feat: InputView readCarNames 작성
GaBaljaintheroom Sep 8, 2023
e40863f
feat: OutputView 생성
GaBaljaintheroom Sep 8, 2023
6be50c5
feat: ProgressMessage INPUT_CAR_NAMES 작성
GaBaljaintheroom Sep 8, 2023
579574f
feat: ErrorMessage 생성
GaBaljaintheroom Sep 8, 2023
1f32e20
feat: InputValidator 생성
GaBaljaintheroom Sep 8, 2023
fcffeb0
test: 쉼표를 포함하여 입력값을 2명이상 입력하지 않았을 때 에러가 발생
GaBaljaintheroom Sep 8, 2023
13501c9
test: 자동차 이름이 5자를 초과하면 에러가 발생
GaBaljaintheroom Sep 8, 2023
862c683
feat: Car validateCarNameLength 추가
GaBaljaintheroom Sep 8, 2023
da9476f
feat: Cars addCars 작성
GaBaljaintheroom Sep 8, 2023
bed5643
feat: InputView readTryCount 작성
GaBaljaintheroom Sep 8, 2023
6e1db51
feat: InputValidator validateTryCount 작성
GaBaljaintheroom Sep 8, 2023
9d52a2d
feat: ErrorMessage TRY_COUNT_ERROR 작성
GaBaljaintheroom Sep 8, 2023
3577d1d
feat: ProgressMessage INPUT_TRY_COUNT 작성
GaBaljaintheroom Sep 8, 2023
1f941ea
feat: OutputView printInputTryCount 작성
GaBaljaintheroom Sep 8, 2023
1ee97d4
test: 시도할 횟수가 1회 이상이 아니라면 에러가 발생
GaBaljaintheroom Sep 8, 2023
b1ef153
feat: CreateRandomValue 생성
GaBaljaintheroom Sep 8, 2023
298f03f
feat: RacingCarService moveCars 작성
GaBaljaintheroom Sep 8, 2023
aa28507
feat: Car movePosition 작성
GaBaljaintheroom Sep 8, 2023
70da97e
feat: Cars moveCars 작성
GaBaljaintheroom Sep 8, 2023
ca64fe3
feat: Car makeScreen 작성
GaBaljaintheroom Sep 8, 2023
7620eaf
feat: Cars executionResult 작성
GaBaljaintheroom Sep 8, 2023
a27c098
feat: OutputView printExecuteResult 작성
GaBaljaintheroom Sep 8, 2023
185a1b1
feat: OutputView printCarsStatus 작성
GaBaljaintheroom Sep 8, 2023
d8d28fc
feat: ProgressMessage EXECUTE_RESULT 작성
GaBaljaintheroom Sep 8, 2023
e613eff
feat: RacingCarService moveCars 작성
GaBaljaintheroom Sep 8, 2023
bf3ba33
feat: RacingCarController run 작성
GaBaljaintheroom Sep 8, 2023
a9e6db7
test: 자동차를 추가했을 때 차를 움직이면 실행결과에 이름이 나타난다.
GaBaljaintheroom Sep 8, 2023
527c152
feat: Car getter 추가
GaBaljaintheroom Sep 8, 2023
ac8c13e
feat: Cars finalWinner 추가
GaBaljaintheroom Sep 8, 2023
a0402b0
feat: OutputView printFinalWinner 추가
GaBaljaintheroom Sep 8, 2023
13cdefd
feat: ProgressMessage FINAL_WINNER 추가
GaBaljaintheroom Sep 8, 2023
2c47b76
feat: controller run 수정
GaBaljaintheroom Sep 8, 2023
e181959
test: 게임에서 이긴 최종 우승자의 이름을 나타난다.
GaBaljaintheroom Sep 8, 2023
064c898
feat: main 함수 작성
GaBaljaintheroom Sep 8, 2023
3f22d55
refactor: import 변경
GaBaljaintheroom Sep 8, 2023
82442ce
refactor: InputValidator validateNumeric 추가
GaBaljaintheroom Sep 8, 2023
b8c7566
refactor: 상수 처리 추가
GaBaljaintheroom Sep 8, 2023
97da3e9
refactor: 패키지 구조 변경
GaBaljaintheroom Sep 8, 2023
8cb4433
refactor: 패키지 구조 변경
GaBaljaintheroom Sep 8, 2023
8621d8b
docs: 리드미 수정
GaBaljaintheroom Sep 8, 2023
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
29 changes: 29 additions & 0 deletions docs/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
## 기능 구현
- Car
- [x] 각 자동차에 이름을 부여할 수 있다. 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다.
- [x] 자동차 이름은 쉼표(,)를 기준으로 구분하며 이름은 5자 이하만 가능하다.
- [x] 자동차의 개수는 2대 이상

- Cars
- [x] 자동차들을 추가할 수 있다.
- [x] 주어진 횟수 동안 n대의 자동차는 전진 또는 멈출 수 있다.
- [x] 자동차 상태를 문자열로 확인할 수 있다.
- [x] 우승 자동차를 확인할 수 찾을 수 있다.

- InputView
- [x] 경주 할 자동차 이름을 입력한다(이름은 쉼표(,) 기준으로 구분)
- [x] 사용자는 몇 번의 이동을 할 것인지를 입력한다.

- CreateRandomValue
- [x] 전진하는 조건은 0에서 9 사이에서 무작위 값을 구한 후 무작위 값이 4 이상일 경우이다.

- OutputView
- [x] 실행 결과 출력
- [x] 최종 결과 출력 -> 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한 명 이상일 수 있다.
- [x] 우승자가 여러 명일 경우 쉼표(,)를 이용하여 구분한다.

- InputValidator
- [x] 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException를 발생시키고,
- [x] "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다.
- [x] 쉼표로 구분
- [x] 시도 횟수 숫자 확인
5 changes: 4 additions & 1 deletion src/main/java/racingcar/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package racingcar;

import racingcar.controller.RacingCarController;

public class Application {
public static void main(String[] args) {
// TODO 구현 진행
RacingCarController racingCarController = new RacingCarController();
racingCarController.run();
}
}
12 changes: 0 additions & 12 deletions src/main/java/racingcar/Car.java

This file was deleted.

20 changes: 20 additions & 0 deletions src/main/java/racingcar/constants/ErrorMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package racingcar.constants;

public enum ErrorMessage {
NAME_DIVISION_ERROR("이름은 쉼표(,) 기준으로 구분합니다."),
NAME_LENGTH_ERROR("자동차 이름이름은 5자 이하만 가능합니다."),
TRY_COUNT_ERROR("시도할 회수는 1회 이상입니다."),
INPUT_NUMERIC_ERROR("숫자가 아닙니다.");

private static final String ERROR = "[ERROR]";
private final String message;

ErrorMessage(String message) {
this.message = message;
}

public String getMessage() {
return ERROR + message;
}

}
20 changes: 20 additions & 0 deletions src/main/java/racingcar/constants/ProgressMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package racingcar.constants;

public enum ProgressMessage {

INPUT_CAR_NAMES("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"),
INPUT_TRY_COUNT("시도할 회수는 몇회인가요?"),
EXECUTE_RESULT("실행 결과"),
FINAL_WINNER("최종 우승자 : ");

private final String message;

ProgressMessage(String message) {
this.message = message;
}

@Override
public String toString() {
return message;
}
}
35 changes: 35 additions & 0 deletions src/main/java/racingcar/controller/RacingCarController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package racingcar.controller;

import racingcar.domain.Cars;
import racingcar.view.InputView;
import racingcar.view.OutputView;
import racingcar.service.RacingCarService;

public class RacingCarController {

private final InputView inputView;
private final OutputView outputView;
private final RacingCarService racingCarService;

public RacingCarController() {
this.inputView = new InputView();
this.outputView = new OutputView();
this.racingCarService = new RacingCarService();
}

public void run(){
Cars cars = inputView.readCarNames();
int tryCount = inputView.readTryCount();

outputView.printExecuteResult();
changeCarsStatus(cars, tryCount);
outputView.printFinalWinner(cars);
}

private void changeCarsStatus(Cars cars, int tryCount) {
for (int i = 0; i < tryCount; i++){
racingCarService.moveCars(cars);
outputView.printCarsStatus(cars);
}
}
}
42 changes: 42 additions & 0 deletions src/main/java/racingcar/domain/Car.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package racingcar.domain;

import racingcar.constants.ErrorMessage;

public class Car {
private static final int MAX_NAME_LENGTH = 5;
private final String name;
private int position = 0;

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

// 추가 기능 구현
public void validateCarNameLength(String name){
if (name.length() > MAX_NAME_LENGTH){
throw new IllegalArgumentException(ErrorMessage.NAME_LENGTH_ERROR.getMessage());
}
}

public void movePosition(){
position++;
}

public StringBuilder makeScreen(StringBuilder stringBuilder) {
stringBuilder.append(name).append(" : ");
for (int i = 0; i < position; i++){
stringBuilder.append("-");
}
stringBuilder.append("\n");
return stringBuilder;
}

public int getPosition() {
return position;
}

public String getName() {
return name;
}
}
61 changes: 61 additions & 0 deletions src/main/java/racingcar/domain/Cars.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package racingcar.domain;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class Cars {

private static final int OVER_ONE_WINNER = 1;
private static final int ONLY_ONE_WINNER = 0;
private static final int DEFAULT_POSITION = 0;
private static final String DIVISION = ",";
private static final String WINNER_DELIMITER = ", ";
private final List<Car> cars = new ArrayList<>();

public void addCars(String name){
Set<String> carNames = Arrays.stream(name.split(DIVISION)).collect(Collectors.toSet());
carNames.stream().map(Car::new).forEach(cars::add);
}

public void moveCars(){
cars.forEach(car -> {
if (CreateRandomValue.canMoveCar()) {
car.movePosition();
}
});
}

public String executionResult(){
return cars.stream()
.map(car -> car.makeScreen(new StringBuilder()))
.reduce(new StringBuilder(), StringBuilder::append)
.toString();
}

public String finalWinner(){
List<String> winCars = getWinCarNames();

if (winCars.size() > OVER_ONE_WINNER) {
return String.join(WINNER_DELIMITER, winCars);
}
return winCars.get(ONLY_ONE_WINNER);
}

private List<String> getWinCarNames() {
return cars.stream()
.filter(car -> car.getPosition() == maxPosition())
.map(Car::getName)
.collect(Collectors.toList());
}

private int maxPosition(){
return cars.stream()
.mapToInt(Car::getPosition)
.max()
.orElse(DEFAULT_POSITION);
}

}
15 changes: 15 additions & 0 deletions src/main/java/racingcar/domain/CreateRandomValue.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package racingcar.domain;


import camp.nextstep.edu.missionutils.Randoms;

public class CreateRandomValue {

private static final int MIN_RANDOM_VALUE = 0;
private static final int MAX_RANDOM_VALUE = 9;
private static final int MIN_RANDOM_RANGE = 4;
public static boolean canMoveCar() {
int randomNumber = Randoms.pickNumberInRange(MIN_RANDOM_VALUE, MAX_RANDOM_VALUE);
return randomNumber >= MIN_RANDOM_RANGE;
}
}
10 changes: 10 additions & 0 deletions src/main/java/racingcar/service/RacingCarService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package racingcar.service;

import racingcar.domain.Cars;

public class RacingCarService {

public void moveCars(Cars cars){
cars.moveCars();
}
}
35 changes: 35 additions & 0 deletions src/main/java/racingcar/view/InputValidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package racingcar.view;

import racingcar.constants.ErrorMessage;

import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;

public class InputValidator {

private static final int MIN_TRY_COUNT = 1;
private static final int MIN_NAME_SIZE = 2;
private static final String DIVISION = ",";
private static final String NUMERIC_REGEX = "^\\d*$";

public void validateContainDivision(String name) {
Set<String> carNames = Arrays.stream(name.split(DIVISION)).collect(Collectors.toSet());
if(carNames.size() < MIN_NAME_SIZE){
throw new IllegalArgumentException(ErrorMessage.NAME_DIVISION_ERROR.getMessage());
}
}

public void validateTryCount(String count) {
validateNumeric(count);
if (Integer.parseInt(count) < MIN_TRY_COUNT){
throw new IllegalArgumentException(ErrorMessage.TRY_COUNT_ERROR.getMessage());
}
}

private void validateNumeric(String count){
if (!count.matches(NUMERIC_REGEX)){
throw new IllegalArgumentException(ErrorMessage.INPUT_NUMERIC_ERROR.getMessage());
}
}
}
42 changes: 42 additions & 0 deletions src/main/java/racingcar/view/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package racingcar.view;

import java.util.function.Supplier;
import camp.nextstep.edu.missionutils.Console;
import racingcar.domain.Cars;

public class InputView {

private final OutputView outputView = new OutputView();
public final InputValidator inputValidator = new InputValidator();

public Cars readCarNames(){
return read(() -> {
outputView.printInputCarNames();
String names = Console.readLine();
inputValidator.validateContainDivision(names);
Cars cars = new Cars();
cars.addCars(names);
return cars;
});
}

public int readTryCount(){
return read(() ->{
outputView.printInputTryCount();
String count = Console.readLine();
outputView.printEnter();
inputValidator.validateTryCount(count);
return Integer.parseInt(count);
});
}

private <T> T read(Supplier<T> supplier){
while (true){
try{
return supplier.get();
}catch (IllegalArgumentException e){
outputView.printErrorMessage(e.getMessage());
}
}
}
}
35 changes: 35 additions & 0 deletions src/main/java/racingcar/view/OutputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package racingcar.view;

import racingcar.constants.ProgressMessage;
import racingcar.domain.Cars;

public class OutputView {
public void printErrorMessage(String message) {
System.out.println(message);
}

public void printInputCarNames(){
System.out.println(ProgressMessage.INPUT_CAR_NAMES);
}

public void printInputTryCount(){
System.out.println(ProgressMessage.INPUT_TRY_COUNT);
}

public void printExecuteResult(){
System.out.println(ProgressMessage.EXECUTE_RESULT);
}

public void printCarsStatus(Cars cars){
System.out.println(cars.executionResult());
}

public void printFinalWinner(Cars cars){
System.out.print(ProgressMessage.FINAL_WINNER);
System.out.println(cars.finalWinner());
}

public void printEnter(){
System.out.println();
}
}
Loading