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

[자동차경주] 유재건 미션 제출합니다. #523

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
2582cec
docs: 기능목록 작성
JaegeonYu Dec 10, 2022
8ab640b
docs: 기능목록 작성
JaegeonYu Dec 10, 2022
3533fae
feat: create Random Numbber Generate Class
JaegeonYu Dec 10, 2022
b2cd25d
docs: 기능목록 추가
JaegeonYu Dec 10, 2022
2140df2
feat: create Car move method
JaegeonYu Dec 10, 2022
60daeed
docs: 기능목록 추가
JaegeonYu Dec 10, 2022
89f1d4e
feat: create Message Class
JaegeonYu Dec 10, 2022
341f881
feat: create Car toString method
JaegeonYu Dec 10, 2022
985255e
feat: test Car toString method
JaegeonYu Dec 10, 2022
3379a80
docs: 기능목록 추가
JaegeonYu Dec 10, 2022
96466cc
feat: create ErrorMessage class
JaegeonYu Dec 10, 2022
a46a553
feat: create Car validate method and test
JaegeonYu Dec 10, 2022
8be9572
docs: 기능목록 추가
JaegeonYu Dec 10, 2022
a625905
feat: create CarOperator class
JaegeonYu Dec 10, 2022
230b18f
docs: 기능목록 추가
JaegeonYu Dec 10, 2022
71754a9
feat: create Round Class
JaegeonYu Dec 10, 2022
5eac4e9
docs: 기능목록 추가
JaegeonYu Dec 10, 2022
4e5db3e
feat: create OutputView, inputView class
JaegeonYu Dec 10, 2022
6c8e714
feat: create printWinner method
JaegeonYu Dec 10, 2022
588c1b4
feat: create Controller Class
JaegeonYu Dec 10, 2022
11b36eb
refactor: 우승 조건 최대 라운드 -> 카트가 이동한 최대 포지션으로 변경
JaegeonYu Dec 10, 2022
3ccb9fd
docs: 기능목록 추가
JaegeonYu Dec 10, 2022
7d6eaad
feat: add Car validate condition
JaegeonYu Dec 10, 2022
4daf01b
refactor: 불필요한 import 제거
JaegeonYu Dec 10, 2022
92357f1
feat: test carpOperator tempPostion method
JaegeonYu Dec 10, 2022
597c564
feat: test CarvenueService ending method
JaegeonYu Dec 10, 2022
ac4002b
feat: test round ending method
JaegeonYu Dec 10, 2022
3f6a7ae
feat: test CarVenueService move and print method
JaegeonYu Dec 10, 2022
37e9f89
feat: create Car Collection class and refactoring
JaegeonYu Dec 10, 2022
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
75 changes: 75 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
## 🚀 기능목록

<<<<<<< HEAD
## CAR

- [x] 이름, 포지션 관리
- [x] 0 ~ 9 사이의 값을 입력받고 4 이상이면 포지션 이동
- [x] 이름과 포지션을 toString
- [x] 포지션과 우승 포지션 비교

## CARS
- [x] Car의 일급 컬렉션
- [x] 차의 이동, 턴당 출력문, 우승 출력문 관리

## CAR VENUE SERVICE

- [x] 참가하는 자동차, 시도 횟수 관리
- [ ] ..

## CAR POSITION OPERATOR

- [x] 대회에 참가하는 차들의 한 턴당 포지션 값들 관리

## ROUND

- [x] 우승 라운드와 현재 라운드 관리

## RANDOM NUMBER GENERATE(interface + class)

- [x] 0~9 사이의 값을 생성

## NUMBER

- [x] 대회의 무작위 값 범위 관리
- [x] 기준 값(4) 관리

## Message

- [x] 출력문에 필요한 문자열 관리

## ErrorMessage

- [x] 에러 출력문에 필요한 문자열 관리

## View

- [x] 자동차 이름 입력
- [x] 시도할 횟수 입력
- [x] 한턴당 결과 출력
- [x] 우승자 출력

## Controller

- [ ] 이름, 횟수, 결과출력, 우승자 출력의 흐름 제어

## Exception

- [ ] Car의 이름이 1보다 작거나 5보다 크면 예외처리
- [ ] 시도할 횟수가 숫자가 아니면 예외처리
-
=======

## CAR
- [ ] 이름, 포지션 관리
- [ ] 0 ~ 9 사이의 값을 입력받고 4 이상이면 포지션 이동
- [ ] 이름과 포지션을 toString으로 던져줌
- [ ] 포지션과 우승 포지션 비교,

## CAR VENUE
- [ ] 참가하는 자동차, 시도 횟수 관리
- [ ] 최종 우승자 관리, 다수이면 ","로 관리

## RANDOM NUMBER GENERATE
- [ ] 0~9 사이의 값을 생성
>>>>>>> 2582cec307554d1cd318e15d23e6ad11db432f44
3 changes: 3 additions & 0 deletions 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 구현 진행
new RacingCarController().play();
}
}
12 changes: 0 additions & 12 deletions src/main/java/racingcar/Car.java

This file was deleted.

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

import racingcar.domain.Car;
import racingcar.domain.Cars;
import racingcar.service.CarVenueService;
import racingcar.view.View;

import java.util.List;

import static racingcar.message.Message.ESCAPE_SEQUENCE;

public class RacingCarController {
private final View view = new View();

public void play() {
List<Car> cars = view.inputCar();
int round = view.inputRound();
CarVenueService carVenueService = new CarVenueService(cars, round);
moveAndPrint(carVenueService);
}

private void moveAndPrint(CarVenueService carVenueService) {
StringBuilder print = new StringBuilder();
while (!carVenueService.isEnd()) {
carVenueService.moveTurn();
print.append(carVenueService.printTurn() + ESCAPE_SEQUENCE.getMessage());
}
view.printResult(print.toString());
whoIsWinner(carVenueService);
Comment on lines +28 to +29

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

결과에는 항상 최종우승자 목록도 따라오니 하나로 합치는 방법도 있을거같아요.
view.printResult나 carVenueService.printWinner에서. '실행결과\n최종 우승자 : ' 로 출력했으면
조금은 더 깔끔해졌을꺼 같아요

}
private void whoIsWinner(CarVenueService carVenueService){
view.printWinner(carVenueService.printWinner());
}
}
52 changes: 52 additions & 0 deletions src/main/java/racingcar/domain/Car.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package racingcar.domain;

import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static racingcar.message.ErrorMessage.CAR_NAME_TOO_LONG;
import static racingcar.message.Message.*;
import static racingcar.util.NumberManager.NAME_MIN_LENGTH;
import static racingcar.util.NumberManager.STANDARD_NUMBER;

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


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

private void validate(String name) {
if (name.length() > maxNameSize || name.length() < NAME_MIN_LENGTH.getNumber()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MIN_LENGTH 보다는 null check 혹은 StringUtils.isEmpty(); 를 사용하는건 어떨까요

throw new IllegalArgumentException(CAR_NAME_TOO_LONG.getMessage());
}
}

// 추가 기능 구현
public void move(int moveInput) {
if (moveInput >= STANDARD_NUMBER.getNumber()) position++;
}

public int getPosition() {
return position;
}

@Override
public String toString() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

관련해서 비슷한 내용의 리뷰가 있어 공유드립니다
참고

StringBuilder print = new StringBuilder(name);
appendPosition(print);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StringJoiner를 사용하면 더 간결하게 표현할 수 있습니다

// ex
StringJoiner joiner = new StringJoiner(INFIX.getMessage());
String positionToMessage = doSomething();
joiner.add(name, positionToMessage);

return print.toString();
}

private void appendPosition(StringBuilder print) {
print.append(INFIX.getMessage());
print.append(IntStream.range(0, position).mapToObj(i -> POSITION.getMessage()).collect(Collectors.joining()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 이번에 처음알았는데 Java 11에서 String.repeat()라는 함수가 있더라고요

String positionToMessage = "-".repeat(position);

이렇게 하면 해당 문자열을 position번 반복할수있습니다!

}

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

import racingcar.message.Message;
import racingcar.util.CarOperator;

import java.util.List;
import java.util.StringJoiner;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static racingcar.message.Message.*;

public class Cars {
private final List<Car> cars;

public Cars(List<Car> cars) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

클래스를 분할해서 List 만을 가지는 일급컬렉션으로 구현하신게 너무 좋은것 같습니다.

Car가 Cars에만 참조된다면 더 좋을꺼같아요
생성자에서 List가 아닌 파라미터를 다른 자료형으로 받았으면 조금 더 깔끔했을것 같네요!

this.cars = cars;
}

public void moveCars(CarOperator operator) {
List<Integer> nowMove = operator.tempPosition();
IntStream.range(0, cars.size()).forEach(index -> {
cars.get(index).move((nowMove.get(index)));
});
}

public String printCars() {
return cars.stream().map(car -> car.toString() + ESCAPE_SEQUENCE.getMessage())
.collect(Collectors.joining());
}

public int getMaxPosition() {
return cars.stream().mapToInt(Car::getPosition).max()
.orElseThrow(IllegalArgumentException::new);
}

public String getWinCar() {
int max = getMaxPosition();
StringJoiner joiner = new StringJoiner(DELIMITER.getMessage() + " ");
IntStream.range(0, cars.size())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stream을 이렇게 사용할 수도 있을것같아요

cars.stream()
        .filter(car -> car.getPosition() == max)
        .forEach(car -> joiner.add(car.getName());

.filter(i -> cars.get(i).getPosition() == max)
.mapToObj(i -> cars.get(i).getName())
.forEach(joiner::add);
return joiner.toString();
}

public int getSize(){
return cars.size();
}
}
19 changes: 19 additions & 0 deletions src/main/java/racingcar/domain/Round.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package racingcar.domain;

public class Round {
private final int finalRound;
private int tempRound = 0;

public Round(int finalRound) {
this.finalRound = finalRound;
}

public void next() {
tempRound++;
}

public boolean isFinish() {
if (tempRound == finalRound) return true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return (tempRound == finalRound) 로 축약해도될거같아요!

return false;
}
}
17 changes: 17 additions & 0 deletions src/main/java/racingcar/message/ErrorMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package racingcar.message;

public enum ErrorMessage {
CAR_NAME_TOO_LONG("차 이름은 공백이 아니고, 5글자 이내여야합니다."),
ROUND_IS_DIGIT("시도 횟수는 숫자여야 합니다."),
DUPLICATE_PARTICIPANT("중복된 참가자가 존재합니다.");
private final String prefix = "[ERROR]";
private String message;

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

public String getMessage(){
return prefix + message;
}
}
22 changes: 22 additions & 0 deletions src/main/java/racingcar/message/Message.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package racingcar.message;

public enum Message {
DELIMITER(","),
INFIX(" : "),
POSITION("-"),
ESCAPE_SEQUENCE("\n"),
WINNER("최종 우승자 : "),
LOSER(""),
PRINT_INPUT_NAMES("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"),
PRINT_INPUT_FINAL_ROUND("시도할 회수는 몇회인가요?"),
PRINT_OUTPUT("실행 결과");

private String message;

Message(String message) {
this.message = message;
}
public String getMessage(){
return message;
}
}
44 changes: 44 additions & 0 deletions src/main/java/racingcar/service/CarVenueService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package racingcar.service;

import racingcar.domain.Car;
import racingcar.domain.Cars;
import racingcar.domain.Round;
import racingcar.util.CarOperator;
import racingcar.util.RandomNumberGenerate;

import java.util.List;

import static racingcar.message.Message.WINNER;

public class CarVenueService {
private final Cars cars;
private final CarOperator carOperator;
private final Round round;


public CarVenueService(List<Car> cars, int finalRound) {
this.cars = new Cars(cars);
this.carOperator = new CarOperator(new RandomNumberGenerate(), cars.size());
this.round = new Round(finalRound);
}

public void moveTurn() {
round.next();
cars.moveCars(carOperator);
}

public String printTurn() {
return cars.printCars();
}

public boolean isEnd() {
if (round.isFinish()) return true;
return false;
}

public String printWinner() {
StringBuilder print = new StringBuilder(WINNER.getMessage());
print.append(cars.getWinCar());
return print.toString();
}
}
19 changes: 19 additions & 0 deletions src/main/java/racingcar/util/CarOperator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package racingcar.util;

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

public class CarOperator {
private final NumberGenerate numberGenerate;
private final int carAmount;

public CarOperator(NumberGenerate numberGenerate, int carAmount) {
this.numberGenerate = numberGenerate;
this.carAmount = carAmount;
}

public List<Integer> tempPosition() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

만약에 해당 행위를 묶어서 관리한다면 CarsOperator가 더 적절한 이름이 될거같네요

이건 개인적인 의견이지만 List로 움직임의 여부를 한꺼번에 반환하기보다는 하나씩 반환해주는 것도 괜찮은 방법인것 같아요.
getMoveFlag 정도의 역할을 하는 메소드로 만드는거죠

return numberGenerate.generate();

이렇게하면 위에서 선언하셨던 moveCars 메소드도 한층 읽기 수월해질것 같네요

// 변경전
    public void moveCars(CarOperator operator) {
        List<Integer> nowMove = operator.tempPosition();
        IntStream.range(0, cars.size()).forEach(index -> {
            cars.get(index).move((nowMove.get(index)));
        });
    }

// 변경후
    public void moveCars(CarOperator operator) {
        IntStream.range(0, cars.size()).forEach(index -> {
            cars.get(index).move(operator.getMoveFlag()));
        });
    }

return IntStream.range(0, carAmount).mapToObj(index -> numberGenerate.generate()).collect(Collectors.toList());
}
}
6 changes: 6 additions & 0 deletions src/main/java/racingcar/util/NumberGenerate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package racingcar.util;

@FunctionalInterface
public interface NumberGenerate {
int generate();
}
17 changes: 17 additions & 0 deletions src/main/java/racingcar/util/NumberManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package racingcar.util;

public enum NumberManager {
NAME_MIN_LENGTH(1),
START_NUMBER(0),
LAST_NUMBER(9),
STANDARD_NUMBER(4);
private int number;

NumberManager(int number) {
this.number = number;
}

public int getNumber() {
return number;
}
}
Loading