Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 19 additions & 0 deletions README.md
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

기능을 4개 정도로 분리하신 것 같은데, 기능에 따라 여러번 커밋해주시면 더 좋을 것 같습니다~~

Original file line number Diff line number Diff line change
@@ -1 +1,20 @@
# java-racingcar-precourse

### 1. 입력 받기

- 경주 할 자동차 이름
- 시도할 회수

### 2. 전진 조건 생성

- 랜덤 값 생성 후 자동차에 적용

### 3. 출력

- 진행 상황 표시
- 최종 결과 표시

### 0. 예외 케이스 처리

- 자동차 이름이 5자 초과된 경우
- 자동차 이름이 같은 경우
19 changes: 18 additions & 1 deletion src/main/java/racingcar/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
package racingcar;

import camp.nextstep.edu.missionutils.Console;
import racingcar.Game;
import racingcar.InputValidator;
import java.util.List;
import java.lang.String;

public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현

// 경주 할 자동차 입력받기
System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)");
List<String> carNames = InputValidator.validateCarNames(Console.readLine());

// 시도 할 횟수 입력받기
System.out.println("시도할 회수는 몇회인가요?");
int attempts = InputValidator.validateAttempts(Console.readLine());

// 게임 진행
Game game = new Game(carNames, attempts);
game.start();
}
}
36 changes: 36 additions & 0 deletions src/main/java/racingcar/Car.java
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

MVC패턴을 도입해볼 의향이 있으시면 이걸 model 디렉토리 하에 넣어 모델 취급해주셔도 좋을 것 같아요~~

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package racingcar;

import camp.nextstep.edu.missionutils.Randoms;

public class Car {
private final String carName;
private int position = 0;

// Car 클래스 생성자
public Car(String name) {
if(name.length() > 5) { // 자동차 이름의 길이가 5 초과일 경우 예외 발생
throw new IllegalArgumentException("Car name cannot be longer than 5 characters");
}
this.carName = name;
}

// 객체 움직임 정의 :
public void move() {
int value = Randoms.pickNumberInRange(0,9);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

여기에서 랜덤값추출하는건 상수화와 함께 따로 util로 분리하는 것은 어떨까용?

if(value >= 4) {
this.position++;
}
}

public int getPosition() {
return position;
}

public String getName() {
return carName;
}

public String getStatus() {
return carName + " : " + "-".repeat(position);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

MVC패턴을 도입하신다면 입출력은 이 객체에서 분리하는게 좋을듯해용

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

import racingcar.Car;
import java.util.List;
import java.util.stream.Collectors;

public class Game {
private final List<Car> cars;
private final int attempts;

// Game 클래스의 생성자
public Game(List<String> carNames, int counts) {
this.cars = carNames.stream().map(name -> new Car(name)).collect(Collectors.toList());
this.attempts = counts;
}

// 게임 시작 메소드
public void start() {
System.out.println("실행 결과");
run();
}

// 게임 진행 메소드
private void run() {
for(int i = 0; i < attempts; i++) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

여기서 stream대신 이중 for문을 사용하신 이유가 있을까용??

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.

stream 사용이 어색해 아직 stream을 사용해야겠다 생각 못한 정도..

for(Car car : cars) {
car.move();
}
printStatus();
}
printWinner();
}

// 게임 과정 출력 메소드
private void printStatus() {
for(Car car : cars) {
System.out.println(car.getStatus());
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

위쪽에서 car를 순회하는 for문이 이미 있으니 이걸 따로 메소드로 뽑기보단 저 for문에 넣는게 더 좋을 것 같아요!! 메소드 유지하시려면 메소드 내 for문은 없애고 마찬가지로 기존 for문 내에 넣으시면 더 좋을 것 같습니다

System.out.println();
}

// 최종 우승자 출력 메소드
private void printWinner() {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested change
private void printWinner() {
private void printWinner() {
String winners = cars.stream()
.filter(car -> car.getPosition() == winnerDistance)
.map(Car::getName)
.collect(Collectors.joining(", "));
System.out.println("최종 우승자 : " + winners);

이런식으로 코드를 한줄로 최적화할 수 있을 것 같아요!

// 1. 최고 거리 찾기
int winnerDistance = cars.stream().mapToInt(Car::getPosition).max().orElse(0);

// 2. 최고 거리를 간 자동차 찾기
List<String> winnerNames = cars.stream().filter(car -> car.getPosition() == winnerDistance).map(Car::getName).collect(Collectors.toList());

// 3. 최종 우승자 출력
System.out.println("최종 우승자 : " + String.join(", ", winnerNames));
}
}
40 changes: 40 additions & 0 deletions src/main/java/racingcar/InputValidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package racingcar;

import java.util.List;
import java.util.Arrays;

// 올바르지 않은 입력의 경우
// 1. 자동차 이름이 1~5 글자를 벗어날 경우
// 2. 시도 횟수가 숫자가 아닌 경우
// 3. 시도 횟수가 0인 경우

public class InputValidator {

// 경주할 자동차 입력과 관련한 예외
public static List<String> validateCarNames(String input) {
List<String> carNames = Arrays.asList(input.split(","));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Arrays.asList(input.split(","));에서 불변리스트를 생성해서 요소 자체는 변경할 수 있지만, 리스트크기는 변경할 수 없을 것 같아요! 나중에 혹시 모를 확장성을 고려하여 new ArrayList<>(Arrays.asList(input.split(",")));로 변경하는것은 어떨까요?? 만약, carNames가 변결되지않는다면, 차라리 진짜 불변리스트로 List.of()를 활용하는것이 좋아보여요!

Copy link
Copy Markdown

Choose a reason for hiding this comment

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


// 1. 자동차 이름이 1~5 글자를 벗어날 경우
if(carNames.stream().anyMatch(name -> name.length() > 5 || name.length() < 1)) {
throw new IllegalArgumentException("Car name cannot be longer than 5 and shorter than 1 characters");
}
return carNames;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

위쪽 car 생성자에서 이미 예외처리를 해두셨던데 validator를 중심으로 사용하실거면 생성자 내의 예외처리는 없애셔도 될 것 같아요~

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

동의합니다!validator로 분리했다면 예외처리는 이쪽에서 다루는게 좋아보여용!

// 시도 횟수 입력과 관련한 예외
public static int validateAttempts(String input) {
if (input == null || input.trim().isEmpty()) {
throw new IllegalArgumentException("Attempt number cannot be empty.");
}

try { // 3. 시도 횟수가 0인 경우
int attempts = Integer.parseInt(input);
if (attempts < 1) {
throw new IllegalArgumentException("Attempt number cannot be less than 1");
}
return attempts;
} catch (NumberFormatException e) { // 2. 시도 횟수가 숫자가 아닌 경우
throw new IllegalArgumentException("Attempt number must be a number");
}
}
}