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

[자동차 경주 게임] 김연진 미션 제출합니다. #2

Open
wants to merge 34 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
b37e050
docs: 기능 목록 작성
homebdy Sep 8, 2023
809116f
refactor(Car): 패키지 이동
homebdy Sep 8, 2023
88a3fde
feat(OutputView): 이름 입력 안내 출력 기능 구현
homebdy Sep 8, 2023
0820e66
feat(RacingCarController): 게임 시작 기능 구현
homebdy Sep 8, 2023
4c258e7
feat(InputView): 이름 입력 기능 구현
homebdy Sep 8, 2023
23ecd46
feat(Name): 이름이 5글자가 넘을 경우 예외 발생
homebdy Sep 8, 2023
3398f73
feat(OutputView): 횟수 입력 안내 출력 기능 구현
homebdy Sep 8, 2023
94c4d6e
feat(InputView): 횟수 입력 기능 구현
homebdy Sep 8, 2023
b680d76
feat(RacingCarController): 횟수 입출력 기능 구현
homebdy Sep 8, 2023
caa95e8
feat(Cars): 입력받은 이름의 레이싱카 생성
homebdy Sep 8, 2023
ebc8aaf
feat(Position): 랜덤으로 숫자 뽑기 기능 구현
homebdy Sep 8, 2023
68917bc
feat(Position): 뽑은 숫자가 4이상일 경우 이동
homebdy Sep 8, 2023
be6ce0e
feat(CarService): 입력받은 시도 횟수만큼 차 이동
homebdy Sep 8, 2023
7bbee81
docs: 구현 완료 기능 체크
homebdy Sep 8, 2023
bededc2
feat(Position): 달린 만큼 `-`를 출력
homebdy Sep 8, 2023
1bdf9c3
feat(Car): `이름: --` 형식으로 출력
homebdy Sep 8, 2023
ab75b3f
feat(OutputView): 차수별 실행 결과 출력
homebdy Sep 8, 2023
afc00cf
feat(Cars): 우승자 계산
homebdy Sep 8, 2023
5722ce8
feat: 우승자 출력 기능 구현
homebdy Sep 8, 2023
61a169a
fix(Position): 이동 가능 확인 식 수정
homebdy Sep 8, 2023
068ebe5
feat(InputValidator): `,`로 이름을 나누어 입력하지 않은 경우 예외 발생
homebdy Sep 8, 2023
c9a0cd1
feat(InputValidator): 숫자로 입력하지 않은 경우 예외 발생
homebdy Sep 8, 2023
762d671
feat(InputView): 오류 발생 지점부터 다시 입력
homebdy Sep 8, 2023
d9c2724
feat: Names 일급컬렉션 생성
homebdy Sep 8, 2023
6993dfb
test(Name): 이름 생성 테스트
homebdy Sep 8, 2023
8e2f5ac
test(InputValidator): 입력값 검증 테스트
homebdy Sep 8, 2023
2800d0c
refactor(Name): 미사용 메서드 삭제
homebdy Sep 8, 2023
0c8df1d
refactor: 하드코딩 제거
homebdy Sep 8, 2023
ca59429
refactor: 줄 바꿈 출력
homebdy Sep 8, 2023
80eef93
refactor(RacingCarController): 메서드 분리
homebdy Sep 8, 2023
dc9ee2e
feat(TryCount): 0이하의 숫자를 입력할 경우 예외 발생
homebdy Sep 8, 2023
0de42f1
test(TryCount): 시도 횟수 입력 시 예외 발생 테스트
homebdy Sep 8, 2023
1197ac8
refactor(Cars): 접근 제어자 변경
homebdy Sep 8, 2023
1f070de
refactor(CarService): 서비스 생성
homebdy Sep 19, 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
21 changes: 21 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
## 기능 목록

- [x] 이름 입력 안내 출력
- [x] 이름 입력
- [x] `,`로 이름을 나누어 입력하지 않은 경우 예외 발생
- [x] 이름이 5글자가 넘을 경우 예외 발생
- [x] 횟수 입력 안내 출력
- [x] 횟수 입력
- [x] 숫자로 입력하지 않은 경우 예외 발생
- [x] 0이하의 숫자를 입력할 경우 예외 발생
- [x] 입력받은 횟수만큼 자동차 이동
- [x] 랜덤으로 숫자를 뽑는다.
- [x] 뽑은 숫자가 4이상일 경우 이동한다.
- [x] 진행 내용 출력
- [x] 달린 만큼 `-`를 출력한다
- [x] `이름: --` 형식으로 출력한다.
- [x] 최종 결과
- [x] 가장 멀리 나간 자동차가 무엇인지 구한다.
- [x] 최종 우승자 출력
- [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.

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

public enum ExceptionMessage {

INVALID_LENGTH("이름은 5글자 이하로 입력해야합니다."),
INCORRECT_DELIMITER("','로 구분하여 입력해야합니다."),
NOT_INTEGER("숫자로 입력해야 합니다."),
INVALID_TRY_COUNT_RANGE("0이상의 숫자를 입력해야 합니다.");

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

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

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

public enum OutputMessage {
READ_NAME("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"),
READ_TRY_COUNT("시도할 회수는 몇회인가요?"),
RACING_RESULT("%s : %s"),
RESULT_MESSAGE("실행 결과"),
WINNER("최종 우승자 : ");

private final String message;

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

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

public enum PrintElement {

NEW_LINE("\n"),
SEPARATOR(", ");

private final String element;

PrintElement(String element) {
this.element = element;
}

public String getElement() {
return element;
}
}
18 changes: 18 additions & 0 deletions src/main/java/racingcar/constant/RandomNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package racingcar.constant;

public enum RandomNumber {

START_RANGE(0),
END_RANGE(9),
CAN_MOVE_NUMBER(4);

private final int value;

RandomNumber(int value) {
this.value = value;
}

public int getValue() {
return value;
}
}
42 changes: 42 additions & 0 deletions src/main/java/racingcar/controller/RacingCarController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package racingcar.controller;

import racingcar.domain.Names;
import racingcar.domain.TryCount;
import racingcar.service.CarService;
import racingcar.view.InputView;
import racingcar.view.OutputView;

public class RacingCarController {

private final OutputView outputView = new OutputView();
private final InputView inputView = new InputView();
private CarService carService;

public void run() {
carService = new CarService(readNames());
TryCount tryCount = readTryCount();
startRacing(tryCount);
}

private Names readNames() {
outputView.printCarNames();
Names names = inputView.readNames();
outputView.printNewLine();
return names;
}

private TryCount readTryCount() {
outputView.printTryCount();
TryCount tryCount = inputView.readTryCount();
outputView.printNewLine();
return tryCount;
}

private void startRacing(TryCount tryCount) {
outputView.printResultMessage();
for (int i = 0; i < tryCount.getValue(); i++) {
outputView.printRacingResult(carService.race());
}
outputView.printWinner(carService.getWinner());
}
}
33 changes: 33 additions & 0 deletions src/main/java/racingcar/domain/Car.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package racingcar.domain;

import racingcar.constant.OutputMessage;

public class Car {
private final Name name;
private final Position position;

public Car(Name name) {
this.name = name;
this.position = new Position();
}

public void race() {
position.move();
}

public boolean isWinner(int maxPosition) {
return position.isSame(maxPosition);
}

public String getRacingResult() {
return String.format(OutputMessage.RACING_RESULT.toString(), name.getValue(), position.getValue());
}

public Position getPosition() {
return position;
}

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

import racingcar.constant.PrintElement;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class Cars {

private final List<Car> cars = new ArrayList<>();

public Cars(Names names) {
names.getNames()
.forEach(name -> cars.add(new Car(name)));
}

public void race() {
cars.forEach(Car::race);
}

public String getRacingResult() {
StringBuilder stringBuilder = new StringBuilder();
cars.forEach(car ->
stringBuilder.append(car.getRacingResult())
.append(PrintElement.NEW_LINE.getElement())
);
return stringBuilder.toString();
}

public Names getWinner() {
int maxPosition = calculateMaxPosition();
List<Name> winner = cars.stream()
.filter(car -> car.isWinner(maxPosition))
.map(Car::getName)
.collect(Collectors.toList());
return new Names(winner);
}

private int calculateMaxPosition() {
List<Integer> positions = cars.stream()
.map(Car::getPosition)
.mapToInt(Position::getPosition)
.boxed()
.collect(Collectors.toList());
return Collections.max(positions);
}
}
24 changes: 24 additions & 0 deletions src/main/java/racingcar/domain/Name.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package racingcar.domain;

import racingcar.constant.ExceptionMessage;

public class Name {

private static final int MAX_LENGTH = 5;
private final String value;

public Name(String value) {
validateName(value);
this.value = value;
}

private void validateName(String value) {
if (value.length() > MAX_LENGTH) {
throw new IllegalArgumentException(ExceptionMessage.INVALID_LENGTH.toString());
}
}

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

import racingcar.constant.PrintElement;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringJoiner;

public class Names {

private final List<Name> element;

public Names(List<Name> names) {
this.element = new ArrayList<>(names);
}

public String getElements() {
StringJoiner stringJoiner = new StringJoiner(PrintElement.SEPARATOR.getElement());
element.forEach(name -> stringJoiner.add(name.getValue()));
return stringJoiner.toString();
}

public List<Name> getNames() {
return Collections.unmodifiableList(element);
}
}
42 changes: 42 additions & 0 deletions src/main/java/racingcar/domain/Position.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package racingcar.domain;

import camp.nextstep.edu.missionutils.Randoms;
import racingcar.constant.RandomNumber;

public class Position {

private static final String RACING_LINE = "-";
private int value = 0;

public void move() {
if (canMove()) {
value += 1;
}
}

private boolean canMove() {
return pickRandomNumber() >= RandomNumber.CAN_MOVE_NUMBER.getValue();
}

private int pickRandomNumber() {
int start = RandomNumber.START_RANGE.getValue();
int end = RandomNumber.END_RANGE.getValue();
return Randoms.pickNumberInRange(start, end);
}

public boolean isSame(int maxPosition) {
return value == maxPosition;
}

public int getPosition() {
return value;
}

public String getValue() {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < value; i++) {
stringBuilder.append(RACING_LINE);
}
return stringBuilder.toString();
}
}
25 changes: 25 additions & 0 deletions src/main/java/racingcar/domain/TryCount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package racingcar.domain;

import racingcar.constant.ExceptionMessage;

public class TryCount {

private static final int MIN_VALUE= 1;

private final int value;

public TryCount(int value) {
validateRange(value);
this.value = value;
}

public void validateRange(int value) {
if (value < MIN_VALUE) {
throw new IllegalArgumentException(ExceptionMessage.INVALID_TRY_COUNT_RANGE.toString());
}
}

public int getValue() {
return value;
}
}
22 changes: 22 additions & 0 deletions src/main/java/racingcar/service/CarService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package racingcar.service;

import racingcar.domain.Cars;
import racingcar.domain.Names;

public class CarService {

private final Cars cars;

public CarService(Names names) {
this.cars = new Cars(names);
}

public String race() {
cars.race();
return cars.getRacingResult();
}

public Names getWinner() {
return cars.getWinner();
}
}
Loading