Skip to content
Open
5 changes: 3 additions & 2 deletions src/main/java/racingcar/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
GameController gameController = new GameController();
gameController.run();
}
}
}
21 changes: 21 additions & 0 deletions src/main/java/racingcar/Car.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package racingcar;

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

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

public void move(int number) {
if (number >= 4) position++;
}

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

import camp.nextstep.edu.missionutils.Randoms;
import java.util.ArrayList;
import java.util.List;

public class GameController {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

정한님이 생각하시는 Controller 네이밍은 무엇이라고 생각하시나욥
제가 생각하는 Controller은 중제자 역할을 해서 여러 객체와 상호작용을 통해 값을 주고 받고, 이를 통해 하나의 로직을 수행하는 클래스에 네이밍을 지어 준다고 생각합니다 !

현재 GameController에는 레이싱 게임 운영 과정에서 필요한 로직들이 메소드로 분리되어 있는 거 같아요 ! 레이싱 관련 클래스로 분리를 한다면 단일 원칙을 준수할 수 단일 원칙을 준수할 수 있을 거 같아요. 고민해보시면 좋을 거 같습니다

private InputView inputView = new InputView();
private OutputView outputView = new OutputView();
private List<Car> cars = new ArrayList<>();

//게임 실행 메인 로직
public void run() {
String[] carNames = inputView.getCarNames();
for (String name : carNames) {
cars.add(new Car(name.trim()));
}

int attemptCount = inputView.getCount();
outputView.printExecutionResultMessage();

for (int i = 0; i < attemptCount; i++) {
playRound();
outputView.printRaceStatus(cars);
}

List<String> winners = findWinners();
outputView.printFinalWinners(winners);
}

private void playRound() {
for (Car car : cars) {
int randomNumber = Randoms.pickNumberInRange(0, 9);
car.move(randomNumber);
}
}

private List<String> findWinners() {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

함수(또는 메서드)가 한 가지 일만 하도록 최대한 작게 만들어라.

해당 메소드는 지금 주석에 작성해주신 것 처럼 두 가지 일을 하고 있네요 👀
요구사항을 만족 시킬려면 어떻게 해야할지 고민해보면 좋을 거 같습니다

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

요구사항을 만족하려면 가장 멀리 간 자동차의 위치를 찾는 메소드와 우승자를 찾는 메소드로 나누는 것이 좋을 것 같습니다. 피드백 감사합니다!

int maxPosition = getMaxPosition();
return getWinnersNames(maxPosition);
}

private int getMaxPosition() {
int maxPosition = 0;
for (Car car : cars) {
if (car.getPosition() > maxPosition) {
maxPosition = car.getPosition();
}
}
return maxPosition;
}

private List<String> getWinnersNames(int maxPosition) {
List<String> winners = new ArrayList<>();
for (Car car : cars) {
if (car.getPosition() == maxPosition) {
winners.add(car.getName());
}
}
return winners;
}
}
56 changes: 56 additions & 0 deletions src/main/java/racingcar/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package racingcar;

import camp.nextstep.edu.missionutils.Console;
import java.util.ArrayList;
import java.util.List;

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

public int getCount() {
System.out.println("시도할 회수는 몇회인가요?");
String input = Console.readLine(); //처음부터 int로 받는 것보다 String으로 받고 int로 바꾸는게 더 정확함
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

처음부터 int로 받는 것보다 String으로 받고 int로 바꾸는게 더 정확함

혹시 이렇게 생각하신 이유를 여쭤봐도 될까요 👀

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

문자열에 대해서 찾아보다가 int로 입력을 받을 때 사용자가 문자열을 입력할 경우 에러가 발생하기 때문에 String으로 일단 받고 나중에 int로 변환하는 것이 더 좋다고 하여 저렇게 주석을 적게 되었습니다.

try {
int count = Integer.parseInt(input);
if (count <= 0) {
throw new IllegalArgumentException("시도 횟수는 0보다 커야 합니다.");
}
return count;
} catch (NumberFormatException e) {
throw new IllegalArgumentException("시도 횟수는 숫자여야 합니다.");
}
}


private void validateCarNames(String[] names) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

InputView에서는 최소한의 유효성 검사(null, 자료형 등)사용자로부터 입력을 받는 클래스라고 생각합니다. View에서 CarName에 대한 유효성 검사는 레이싱 게임에서의 규칙도 포함되어 있다고 생각해서 InputView가 2개 이상의 책임을 가지고 있는 거 같아요 !

일급 컬렉션이라는 개념을 활용해도 좋고, Controller에서 List를 생성하는 과정에서 유효성 검증을 한다면 InputView의 책임이 줄어들 거 같습니다 !

List<String> nameList = new ArrayList<>();

for (String name : names) {
// 공백이 들어있는지 확인
if(name.contains(" ")) {
throw new IllegalArgumentException("자동차 이름에는 공백이 포함될 수 없습니다.");
}
// 이름이 비어있는지 확인
String trimmedName = name.trim();
if (trimmedName.isEmpty()) {
throw new IllegalArgumentException("자동차 이름은 빈 값일 수 없습니다.");
}
// 5자가 넘는지 확인
if (trimmedName.length() > 5) {
throw new IllegalArgumentException("자동차 이름은 5자 이하만 가능합니다.");
}
// 이미 나온 이름인지 확인 (중복 체크)
if (nameList.contains(name)) {
throw new IllegalArgumentException("중복된 이름이 있습니다.");
}

nameList.add(name); // 검사를 통과한 이름은 리스트에 보관
}
}
}
28 changes: 28 additions & 0 deletions src/main/java/racingcar/OutputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package racingcar;

import java.util.List;

public class OutputView {

public void printExecutionResultMessage() {
System.out.println("\n실행 결과");
}

public void printRaceStatus(List<Car> cars) {
for (Car car : cars) {
System.out.print(car.getName() + " : ");

for (int i = 0; i < car.getPosition(); i++) {
System.out.print("-");
}

System.out.println();
}
System.out.println();
}

public void printFinalWinners(List<String> winners) {
String result = String.join(", ", winners);
System.out.println("최종 우승자 : " + result);
}
}