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

[자동차 경주] 김주언 제출합니다 #1482

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7e9897e
doc: 기능 명세 작성
wndjs803 Oct 27, 2024
9ebedca
자동차 이름 부여 및 제약사항 체크
wndjs803 Oct 27, 2024
1f791c7
feat: 시도 횟수 입력 기능
wndjs803 Oct 27, 2024
8a9c4ac
feat: 자동차 전진 및 출력 기능
wndjs803 Oct 27, 2024
5ee1427
feat: 웃승자 추출 및 출력 기능
wndjs803 Oct 27, 2024
209a676
refactor: 사용자 입력 기능 InputView 분리
wndjs803 Oct 28, 2024
1ca084a
fix: Car forward 기본값 지정
wndjs803 Oct 28, 2024
5f2cb91
feat: carName 유효성 클래스 분리
wndjs803 Oct 28, 2024
c42196f
feat: init 메서드 작성
wndjs803 Oct 28, 2024
773841f
feat: printPlayMessage 메서드 작성
wndjs803 Oct 28, 2024
10cd9fe
fix: 랜덤 상수 발생 기능 분리
wndjs803 Oct 28, 2024
635dc21
feat: playRound 메서드 작성
wndjs803 Oct 28, 2024
75e43a7
feat: Car getResult 메서드 작성
wndjs803 Oct 28, 2024
14f22f5
feat: Cars getResults 메서드 작성
wndjs803 Oct 28, 2024
de83a11
feat: OutputView printPlayResults 메서드 작성
wndjs803 Oct 28, 2024
ceb6130
feat: play 메서드 작성
wndjs803 Oct 28, 2024
c477278
fix: getter public으로 수정
wndjs803 Oct 28, 2024
fdf9520
feat: Cars getWinners 메서드 작성
wndjs803 Oct 28, 2024
e154259
fix: 오타 수정
wndjs803 Oct 28, 2024
b27d1bd
feat: printWinners 메서드 작성
wndjs803 Oct 28, 2024
4e0275a
feat: showWinners 메서드 작성
wndjs803 Oct 28, 2024
5048b01
fix: getForward 수정
wndjs803 Oct 28, 2024
9d09673
fix: playRound 수정
wndjs803 Oct 28, 2024
9619cf6
fix: GameController 생성자 파라미터 순서 변경
wndjs803 Oct 28, 2024
d093894
feat: main 메서드 작성
wndjs803 Oct 28, 2024
56b07cf
fix: printWinners 오타 수정
wndjs803 Oct 28, 2024
8fe5b4d
fix: getForward 리턴 타입 변경
wndjs803 Oct 28, 2024
83cfd96
fix: 코드 포맷 및 불필요한 import 제거
wndjs803 Oct 28, 2024
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
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,12 @@
# java-racingcar-precourse

- [x] 각 자동차에 이름을 부여할 수 있다.
- [x] 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다.
- [x] 자동차 이름은 쉼표(,)를 기준으로 구분한다.
- [x] 이름은 5자 이하만 가능하다.
- [x] 사용자는 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다.
- [x] 전진하는 조건은 0에서 9 사이에서 무작위 값을 구한 후 무작위 값이 4 이상일 경우이다.
- [x] 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한 명 이상일 수 있다.
- [x] 우승자가 여러 명일 경우 쉼표(,)를 이용하여 구분한다.
- [ ] 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시킨 후 애플리케이션은 종료되어야 한다.

Choose a reason for hiding this comment

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

앗 마지막 체크는 실수로 빼먹으신걸까요?

- 추후에 클래스를 나누자. 일단은 동작하도록 구현하자.
13 changes: 12 additions & 1 deletion src/main/java/racingcar/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
package racingcar;

import racingcar.controller.GameController;
import racingcar.model.CarNameValidator;
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();
CarNameValidator carNameValidator = new CarNameValidator();

GameController gameController = new GameController(inputView, outputView, carNameValidator);
gameController.run();
}

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

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

import java.util.List;

public class GameController {
private final InputView inputView;
private final OutputView outputView;
private final CarNameValidator carNameValidator;
private Cars cars;
private int tryCount;

public GameController(InputView inputView, OutputView outputView, CarNameValidator carNameValidator) {
this.inputView = inputView;
this.outputView = outputView;
this.carNameValidator = carNameValidator;
}

public void run() {
init();
play();
showWinners();
}

public void init() {
String input = inputView.inputCarNames();
String[] carNames = input.split(",");

Choose a reason for hiding this comment

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

Car 모델을 묶는 일급컬렉션 Cars를 만들어주신 것 처럼 String[]을 사용하기보다는 List을 멤버로 가지는 일급 컬렉션 CarNames를 만들어서 사용해주시는 게 좋을 것 같습니다!

Copy link

Choose a reason for hiding this comment

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

"배열 대신 컬렉션을 사용한다"는 우테코의 1주차 피드백을 보시면 좋을 것 같아요!

carNameValidator.validate(carNames);
cars = new Cars(carNames);
tryCount = inputView.inputTryCount();

Choose a reason for hiding this comment

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

다른 View와 Validator는 생성자 주입으로 받아서 사용하는데 Cars만 컨트롤러에서 직접 생성해주는 이유가 있을까요?

}

public void play() {
outputView.printPlayMessage();
cars.playRound(tryCount);
outputView.printPlayResults(cars.getResults());
}

public void showWinners() {
List<String> winners = cars.getWinners();
outputView.printWinners(winners);
}
}
33 changes: 33 additions & 0 deletions src/main/java/racingcar/model/Car.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package racingcar.model;

import racingcar.util.RandomNumber;

public class Car {
private final String name;
private int forward = 0;

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

public void moveForward() {
if (RandomNumber.getRandomNumber() >= 4) {
forward = forward + 1;
}
}

public String getResult() {
StringBuilder result = new StringBuilder(name + " : ");
result.append("-".repeat(Math.max(0, forward)));

Choose a reason for hiding this comment

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

코드에서 forward를 0으로 초기화하셨는데, Math.max 메서드로 다시 0과 비교하신 이유가 궁금합니다 :)

return String.valueOf(result);
}

public String getName() {
return name;
}

public int getForward() {
return forward;
}

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

public class CarNameValidator {
public void validate(String[] carNames) {
for (String carName : carNames) {
if (carName.length() > 5) {
throw new IllegalArgumentException();
}
}
}
}
48 changes: 48 additions & 0 deletions src/main/java/racingcar/model/Cars.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package racingcar.model;

import java.util.ArrayList;
import java.util.List;

public class Cars {
private final List<Car> cars = new ArrayList<>();

public Cars(String[] carNames) {
for (String carName : carNames) {
cars.add(new Car(carName));
}
}

public void playRound(int tryCount) {
while (tryCount > 0) {
moveCarsWithRandomCondition();
tryCount = tryCount - 1;
}
}

private void moveCarsWithRandomCondition() {
for (Car car : cars) {
car.moveForward();
}
}

public List<String> getResults() {
List<String> results = new ArrayList<>();
for (Car car : cars) {
results.add(car.getResult());
}
return results;
}

public List<String> getWinners() {
int maxForward = cars.stream()
.mapToInt(Car::getForward)
.max()
.orElseThrow(() -> new IllegalArgumentException("최대값을 찾을 수 없습니다."));

return cars.stream()
.filter(car -> car.getForward() == maxForward)
.map(Car::getName)
.toList();
}

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

import camp.nextstep.edu.missionutils.Randoms;

public class RandomNumber {
public static int getRandomNumber() {
return Randoms.pickNumberInRange(0, 9);
Copy link

@Kimbobae1 Kimbobae1 Oct 30, 2024

Choose a reason for hiding this comment

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

0(최솟값), 9(최댓값) 과 같은 매직 넘버(의미있는 이름의 상수로 대체될 수 있는 숫자)는 상수로 관리하는 것도 좋을 것 같습니다.
주언님은 이부분에 대해 어떻게 생각하시나요?

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

import camp.nextstep.edu.missionutils.Console;

public class InputView {
public String inputCarNames() {
System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)");
return Console.readLine();
}

public int inputTryCount() {
System.out.println("시도할 횟수는 몇 회인가요?");
return Integer.parseInt(Console.readLine());
Comment on lines +11 to +13
Copy link

@lsh1215 lsh1215 Oct 29, 2024

Choose a reason for hiding this comment

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

Integer로 바로 형 변환을 하게되면 숫자가 아닌 문자가 입력됐을 때 에러 처리가 힘들거 같아요

}
}

Choose a reason for hiding this comment

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

다른 함수들은 모두 동사형이지만 여기 두 메소드 이름만 명사입니다!
getCarNames()와 getTryCount()로 바꾸는 게 좋을 것 같아요 😃

추가로 문자열로 시도 횟수를 여기서 바로 정수로 parse하여 반환하고 있는데 문자열을 정수로 변환하는 것이 과연 View의 역할일까..? 조심스레 의문을 남기고갑니다

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 java.util.List;

public class OutputView {
public void printPlayMessage() {
System.out.println();
System.out.println("실행결과");
}

public void printPlayResults(List<String> results) {
for (String result : results) {
System.out.println(result);
}
System.out.println();
}

public void printWinners(List<String> winners) {
String message = "최종 우승자 : ";
if (winners.size() == 1) {
printSingleWinner(message, winners);
return;
}
printMultipleWinners(message, winners);

}

private void printSingleWinner(String message, List<String> winners) {
System.out.println(message + winners.get(0));
}

private void printMultipleWinners(String message, List<String> winners) {
System.out.println(message + String.join(", ", winners));
}
}
Comment on lines +18 to +35

Choose a reason for hiding this comment

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

String.join() 메서드는List의 요소가 하나일 때 그 요소만 반환하는 것으로 알고 있습니다.
혹시 SingleWinner와 MultipleWinner를 따로 나누어 놓으신 이유가 따로 있으실까요?