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

[자동차 경주 게임] 정종현 미션 제출합니다. #2383

Open
wants to merge 44 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
c05e861
docs: 구현 기능 목록 생성
viaunixue Oct 31, 2023
597094f
feat: 경주할 자동차 이름 입력
viaunixue Oct 31, 2023
539481d
feat: 자동차 이동 횟수 입력
viaunixue Oct 31, 2023
4f617ff
feat: 0부터 9 사이에 무작위 값 생성
viaunixue Oct 31, 2023
2834cc8
feat: 무작위 값이 4 이상일 경우 전진
viaunixue Oct 31, 2023
fe19f08
feat: 각 차수별 실행 결과 출력
viaunixue Oct 31, 2023
ef7d56b
feat: 최종 우승자 출력
viaunixue Oct 31, 2023
fb596c5
refactor: 쉼표 공백 제거
viaunixue Oct 31, 2023
57d28ba
feat: 경주할 자동차 이름이 1 이상 5 이하가 아닌 경우 예외 발생
viaunixue Nov 2, 2023
3b32b47
feat: 경주할 자동차 없는 경우
viaunixue Nov 2, 2023
08a94c8
refactor: Car, Racer 1급 Collection 적용
viaunixue Nov 2, 2023
f6448cf
refactor: 시도할 횟수 (Round) 1급 컬렉션 적용
viaunixue Nov 3, 2023
cd16a9a
refactor: 상수 사용
viaunixue Nov 7, 2023
7ee1cad
refactor: Interface 통한 Car 검증
viaunixue Nov 7, 2023
1a0429b
refactor: Interface 통한 Racer 검증
viaunixue Nov 28, 2023
15e0389
refactor: Interface 통한 Round 검증
viaunixue Nov 28, 2023
f752a6e
refactor: View 에서 Interface 도입
viaunixue Nov 28, 2023
148a058
refactor: RacingCar Application 생성
viaunixue Nov 28, 2023
de5d24c
refactor: hasRound() 메서드 명 변경 및 메서드 분리
viaunixue Nov 28, 2023
0503e6c
doc: 리팩토링 목록 추가
viaunixue Nov 28, 2023
3605cb8
feat: 여러 방법으로 정렬 수행할 수 있도록 구조 변경
viaunixue Nov 28, 2023
f66dfca
docs: 고민 주제 추가
viaunixue Nov 28, 2023
d41f3be
fix: 0번 시도도 가능하도록 변경
viaunixue Nov 28, 2023
e72c821
remove: 이전 승자 확인 클래스 삭제
viaunixue Nov 28, 2023
f2367ff
refactor: 출력 값 포장 시 stream API 사용하기
viaunixue Nov 28, 2023
84ed92b
refactor: 검증기 Factory 구현 후 해당 팩토리에서 get 검증기 형태로 구현
viaunixue Nov 28, 2023
1cd2151
docs: 예외 사항 추가
viaunixue Nov 28, 2023
ceff32e
style: 출력시 공백 및 개행 추가
viaunixue Nov 28, 2023
5e75e49
feat: 경주할 자동차 이름 공백일 경우 예외
viaunixue Nov 28, 2023
483f5fa
feat: 횟수 타입 Integer 대신 Long 사용
viaunixue Nov 28, 2023
481a1f0
refactor: 상수 사용
viaunixue Nov 28, 2023
a29b932
refactor: 예외 메시지 매직 리터럴 치환
viaunixue Nov 28, 2023
be86df0
refactor: 출력 메시지 매직 리터럴 치환
viaunixue Nov 28, 2023
d50e51d
feat: 경주할 자동차 중 중복된 이름이 있는 경우 예외 처리
viaunixue Nov 28, 2023
5222ff4
test: 올바른 범위 랜덤 숫자 생성 테스트
viaunixue Nov 28, 2023
d2b13de
refactor: 정규식을 Pattern 정적 객체로 변경
viaunixue Nov 28, 2023
9b77dce
refactor: 정렬 조건 파라미터 주입으로 변경
viaunixue Nov 28, 2023
d2d01d3
refactor: stream() API 활용 (collect)
viaunixue Nov 30, 2023
ef783db
refactor: Round 정적 팩토리 메서드 적용
viaunixue Nov 30, 2023
9d9b5b0
refactor: 메서드가 한가지 일만 하도록 수정
viaunixue Nov 30, 2023
340982f
refactor: controller 클래스 메서드 분리
viaunixue Nov 30, 2023
527ae0b
refactor: Car 정적 팩토리 메서드 사용
viaunixue Nov 30, 2023
eb259c7
test: Round 플레이 테스트 추가
viaunixue Nov 30, 2023
c0715df
doc: 고민해볼 주제 수정
viaunixue Nov 30, 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
47 changes: 47 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# 구현 기능 목록

## 기능

* [x] 0부터 9 사이에 무작위 값 생성
* [x] 무작위 값이 4 이상일 경우 전진

## 입력

* [x] 각 자동차 이름 입력
* 이름은 5자 이하
* 쉽표(,)를 기준 으로 자동차 이름 구분
* [x] 자동자 이동 횟수 입력

## 출력

* [x] 각 차수별 실행 결과 출력
* 자동차 이름과 함께 전진 하는 자동차 출력
* [x] 최종 우승자 안내 문구
* 공동 우승일 경우 쉼표를 이용 하여 구분

## 예외 사항
* [x] 경주할 자동차 없는 경우
* [x] 경주할 자동차 이름이 1 이상 5 이하가 아닌 경우
* [x] 경주할 자동차 이름이 공백인 경우
* [x] 경주할 자동차 중 중복된 이름이 있는 경우
* [ ] 경주할 자동차 구분자 "," 가 아닌 경우
* [x] 시도할 횟수가 자연수 아닌 경우

### 사용자 숫자

* [ ] 이름이 5자리 이하가 아닐시 예외
* [ ] 0부터 9까지의 수가 아닐시 예외

## 🔨 리팩토링 목록
* [x] 1급 Collection 적용
* [ ] 상수 사용
* [ ] interface 활용 (메세지 던지기)
* [x] Integer 대신 Long 사용 고려

## 고민해 볼 주제
* [X] 마지막 ,로 끝나는 경우
* 해당 경우 예외 처리 하지 않음
* new String[]{"1", "3", }; 같은 경우도 가능 하기 때문
* [ ] 각 차수별 실행 결과 출력의 순서
* 사용자 입력 순
* 사전 정렬 순
12 changes: 11 additions & 1 deletion src/main/java/racingcar/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
package racingcar;

import racingcar.application.RacingCarApplication;
import racingcar.controller.RacingCarController;
import racingcar.view.InputViewImpl;
import racingcar.view.OutputViewImpl;

public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
// RacingCarController racingCarController = new RacingCarController(new InputViewImpl(), new OutputViewImpl());
// racingCarController.run();

RacingCarApplication racingCarApplication = new RacingCarApplication();

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

import racingcar.controller.RacingCarController;
import racingcar.view.InputView;
import racingcar.view.OutputView;
import racingcar.view.InputViewImpl;
import racingcar.view.OutputViewImpl;

public class RacingCarApplication {
public void run() {
InputView inputView = new InputViewImpl();
OutputView outputView = new OutputViewImpl();

RacingCarController racingCarController = new RacingCarController(inputView, outputView);
racingCarController.run();
}
}

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

import racingcar.model.Racer;
import racingcar.model.Round;
import racingcar.view.InputView;
import racingcar.view.OutputView;

public class RacingCarController {
private final InputView inputView;
private final OutputView outputView;

public RacingCarController(InputView inputView, OutputView outputView){
this.inputView = inputView;
this.outputView = outputView;
}

public void run(){
// String cars = inputView.readRaceCarNames();
// String resultCars = cars.replaceAll(" ", "");
// List<String> names = List.of(resultCars.split(","));
Racer racer = new Racer(inputView.readCars());
// int round = Integer.parseInt(inputView.readRaceRound());
// Round round = new Round(inputView.readRound());
Round round = Round.of(inputView.readRound());
// 각각의 racer 초기화
// Map<String, Integer> position = new LinkedHashMap<>();
// for(String name: names){
// position.put(name, 0);
// }

outputView.printExecutionResult();
// 라운드 별 각각의 레이서 결과 출력
while(round.hasRound()){
play(racer);
// racer.play();
// outputView.printResult(racer.toString());
round.turn();
}
// for (int i=0 ; i < round ; i++){
// racer.play();
// outputView.printResult(racer);
// play(position);
// outputView.printResult(position);
// System.out.println();
// }

outputView.printFinalWinner(racer.winnerToString());
}

private void play(Racer racer){
racer.play();
outputView.printResult(racer.toString());
}

// private void play(Map<String, Integer> position) {
// for (String name : position.keySet()){
// if (ShiftGear.moveForward()) {
// playMoveForward(position, name);
// }
// }
// }

// private void playMoveForward(Map<String, Integer> position, String name){
// position.put(name, position.get(name) + 1);
// }
}
117 changes: 117 additions & 0 deletions src/main/java/racingcar/model/Racer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package racingcar.model;

import racingcar.model.car.Car;
import racingcar.model.car.OrderByPosition;
import racingcar.model.car.OrderStrategy;
import racingcar.validation.Validator;
import racingcar.validation.ValidatorFactory;
import static racingcar.type.message.MessageType.NAME_SEPARATOR;

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

public class Racer {
// public static final String SEPERATOR = ",";
private final List<Car> racer;
public Racer(String name) {
validate(name);
this.racer = Arrays.stream(name.split(NAME_SEPARATOR.getMessageValue()))
.map(Car::ofStartPoint)
.toList();
}

public void play(){
racer.forEach(Car::move);
}

private void validate(String value){
ValidatorFactory validatorFactory = ValidatorFactory.buildDefaultValidatorFactory();
Validator validator = validatorFactory.getValidator(this.getClass());
validator.validate(value);
// Validator validator = new RacerValidator();
// validator.validate(value);
}

// public String getWinner() {
// Car winner = racer.stream().max(Car::compareTo).orElseThrow();
//
// return racer.stream()
// .filter(winner::equals)
// .map(Car::getName)
// .collect(Collectors.joining(SEPERATOR));
// }

// public List<Car> getWinner() {
// Car first = racer.stream()
// .max(Car::compareTo)
// .orElseThrow(IllegalAccessError::new);
//
// return racer.stream()
// .filter(car -> car.equals(first))
// .toList();
// }

public List<Car> getWinner(OrderStrategy orderStrategy){
Car first = racer.stream()
.max(orderStrategy)
.orElseThrow();
return racer.stream()
.filter(car -> car.equals(first))
.toList();
}

public String winnerToString() {
return getWinner(new OrderByPosition())
.stream()
.map(Car::getName)
.collect(Collectors.joining(NAME_SEPARATOR + " "));

// List<String> winner = getWinner(new OrderByPosition())
// .stream()
// .map(Car::getName)
// .toList();
//
// return String.join(NAME_SEPARATOR + " ", winner);

// List<Car> winner = getWinner();
// StringBuilder stringBuilder = new StringBuilder();
// for (Car car : winner){
// stringBuilder.append(car.getName()).append(",");
// }
// stringBuilder.deleteCharAt(stringBuilder.length() - 1);
// return stringBuilder.toString();
}

@Override
public String toString(){
StringBuilder stringBuilder = new StringBuilder();
for (Car car : racer){
stringBuilder.append(car.toString()).append("\n");
}
return stringBuilder.toString();
}

@Override
public boolean equals(Object obj){
if (this == obj){
return true;
}

if (!(obj instanceof Racer target)){
return false;
}

return racer.equals(target.racer);
}

// private void validate(String name){
// validateSize(name);
// }
//
// private void validateSize(String value){
// if (value == null || value.split(SEPERATOR).length == 0){
// throw new IllegalArgumentException("참가자 없음");
// }
// }
}
61 changes: 61 additions & 0 deletions src/main/java/racingcar/model/Round.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package racingcar.model;

import racingcar.validation.RoundValidator;
import racingcar.validation.Validator;
import racingcar.validation.ValidatorFactory;

import static racingcar.type.PlayType.MAX_NUM;
import static racingcar.type.PlayType.MIN_NUM;

public class Round {
private Long round;
// private Integer round;

private Round(String round){
validate(round);
this.round = Long.valueOf(round);
}

public static Round of(String round){
return new Round(round);
}

// TODO: 진행 중인지 확인 하는 것 뿐 아니라 감소도 함
// public Boolean isContinue(){
// if (round > 0){
// round --;
// return true;
// }
// return false;
// }
public Boolean hasRound(){
// turn();
return round >= 0;
}

public void turn() {
round--;
}

private void validate(String value){
ValidatorFactory validatorFactory = ValidatorFactory.buildDefaultValidatorFactory();
Validator validator = validatorFactory.getValidator(this.getClass());
validator.validate(value);
// Validator validator = new RoundValidator();
// validator.validate(value);
// validateType(value);
// validateRange(value);
}

// private void validateType(String value){
// if (value != null && !value.matches(ONLY_NUMBER)){
// throw new IllegalArgumentException();
// }
// }
//
// private void validateRange(String value){
// if (0 >= Integer.parseInt(value)) {
// throw new IllegalArgumentException();
// }
// }
}
Loading