Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
62e0cd4
docs: update implementation function docs
Untaini Mar 14, 2023
5e38f7e
feat: getCarListFromInput function
Untaini Mar 14, 2023
ecddec2
refactor: change getCarListFromInput function return type
Untaini Mar 15, 2023
c4b9717
refactor: Add InputUtils class
Untaini Mar 15, 2023
1b780d9
feat: getTotalRoundFromInput
Untaini Mar 15, 2023
32e13eb
feat: move and print function in Car class
Untaini Mar 15, 2023
5e45720
feat: get function in Car class
Untaini Mar 15, 2023
cd48ee3
feat: playAllRounds function
Untaini Mar 15, 2023
04615d7
refactor: change incorrect function name
Untaini Mar 15, 2023
06b3c8b
feat: printWinners function
Untaini Mar 15, 2023
65b263b
refactor: change error tag
Untaini Mar 15, 2023
f788aef
refactor: change pickNumberInRange import
Untaini Mar 15, 2023
681039c
style: change newline format and function order
Untaini Mar 15, 2023
be24ffb
feat: add StringValidator class
Untaini Mar 18, 2023
b118782
refactor: add PrintManager class
Untaini Mar 18, 2023
56122be
feat: add StringConvertor class
Untaini Mar 18, 2023
e7f1526
feat: add Round class
Untaini Mar 18, 2023
0324770
feat: add Game class
Untaini Mar 18, 2023
1dabec0
feat: createCar func
Untaini Mar 18, 2023
4b6fc87
refactor: remove unused function
Untaini Mar 18, 2023
8dc465d
refactor: use Game instance and remove unused function
Untaini Mar 18, 2023
1fee1e4
feat: getWinnersString function
Untaini Mar 18, 2023
1d07b2b
refactor: add tool, game package
Untaini Mar 18, 2023
66ed54a
refactor: change canCarName to cannotUseCarName
Untaini Mar 18, 2023
e76735a
refactor: move func from PrintManger to ListConvertor
Untaini Mar 25, 2023
dc2657f
refactor: change var name and func name for deleting type in name
Untaini Mar 25, 2023
63b1b06
refactor: declare that the constructor cannot be called
Untaini Mar 25, 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
9 changes: 9 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<h1>구현할 기능 목록</h1>

- ### 사용자로부터 자동차 이름 입력받고 유효성 검사하기
- ### 사용자로부터 시도할 횟수 입력받고 유효성 검사하기
- ### 시도할 횟수만큼 라운드 반복하기
- ### 모든 자동차 전진 또는 정지하기
- ### 자동차의 상태 출력하기
- ### 최종 우승자 찾기
- ### 최종 우승자 출력하기
59 changes: 58 additions & 1 deletion src/main/java/racingcar/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,64 @@
package racingcar;

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

public class Application {
public static void main(String[] args) {
// TODO 구현 진행
List<Car> carList = InputUtils.getInstance().getCarListFromInput();
int totalRound = InputUtils.getInstance().getTotalRoundFromInput();

playAllRounds(totalRound, carList);

printWinners(carList);
}

private static void playAllRounds(int totalRound, List<Car> carList) {
System.out.println("\n실행 결과");
while (--totalRound >= 0) {
playRound(carList);
}
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

대부분의 Application method들이 carList를 파라미터로 받는 static 함수들입니다. 게임을 나타내는 클래스를 하나 작성하시고, 파라미터가 아니라 fiel로 carList를 작성해 보시는건 어떠신가요?

private static void playRound(List<Car> carList) {
moveAllCars(carList);
printAllCarsStatus(carList);
}

private static void moveAllCars(List<Car> carList) {
carList.forEach(Car::move);
}

private static void printAllCarsStatus(List<Car> carList) {
carList.forEach(System.out::println);
System.out.println();
}

private static void printWinners(List<Car> carList) {
System.out.printf("최종 우승자 : %s", getWinnersString(carList));
}

private static String getWinnersString(List<Car> carList) {
List<String> winnerNameList = findWinners(carList).stream()
.map(Car::getName)
.collect(Collectors.toList());

return String.join(", ", winnerNameList);
}

private static List<Car> findWinners(List<Car> carList) {
if (carList.size() == 0) {
return Collections.emptyList();
}

int maxPosition = carList.stream()
.map(Car::getPosition)
.max(Integer::compareTo)
.get();

return carList.stream()
.filter(car -> car.getPosition() == maxPosition)
.collect(Collectors.toList());
}
}
33 changes: 32 additions & 1 deletion src/main/java/racingcar/Car.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
package racingcar;

import camp.nextstep.edu.missionutils.Randoms;

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


public class Car {
private final String name;
private int position = 0;
Expand All @@ -8,5 +15,29 @@ public Car(String name) {
this.name = name;
}

// 추가 기능 구현
public int getPosition() {
return this.position;
}

public String getName() {
return this.name;
}

public String toString() {
return String.format("%s : %s",this.name, getMoveString());
}

public void move() {
if (Randoms.pickNumberInRange(0, 9) >= 4) {
this.position += 1;
}
}

private String getMoveString() {
List<String> movePositionList = Arrays.stream(new String[this.position])
.map(s -> "-")
.collect(Collectors.toList());

return String.join("", movePositionList);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

stream을 잘쓰시네요! join method를 활용한 "-"만들기 좋은것 같습니다!

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

import camp.nextstep.edu.missionutils.Console;

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

public class InputUtils {
private static InputUtils inputUtils;

private InputUtils() {}

public static InputUtils getInstance() {
if (inputUtils == null) {
inputUtils = new InputUtils();
}
return inputUtils;
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

유틸리티 클래스는 싱글턴 패턴으로 구현하신것 같습니다. 싱글턴 패턴을 쓰신 이유를 혹시 알 수 있을까요? Static 클래스로 구현하지 않은 이유가 궁금합니다!

public List<Car> getCarListFromInput() {
while (true) {
printCarNameInputDescription();

String carNames = Console.readLine();
try {
checkCarNameInputAvailable(carNames);

return convertCarNamesIntoCarList(carNames);
} catch (IllegalArgumentException exception) {
System.out.println("[ERROR] " + exception.getMessage());
}
}
}

private void printCarNameInputDescription() {
System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)");
}

private void checkCarNameInputAvailable(String carNameInput) throws IllegalArgumentException {
if (carNameInput.endsWith(",")) {
throw new IllegalArgumentException("쉼표(,)로 끝난 올바르지 않은 입력입니다.");
}
}

private List<Car> convertCarNamesIntoCarList(String carNames) throws IllegalArgumentException {
return Arrays.stream(carNames.split(","))
.map(this::createCar)
.collect(Collectors.toList());
}

private Car createCar(String carName) throws IllegalArgumentException {
checkCarNameAvailable(carName);

return new Car(carName);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Car 객체를 생성하는 코드가 Utility Class에 있는데, Factory Method는 주로 해당 클래스 안에서 작성하거나, Factory Class를 만드는 경우가 많은것 같습니다. utility class 안에서 작성하신 이유를 혹시 알 수 있을까요?


private void checkCarNameAvailable(String carName) throws IllegalArgumentException {
if (carName.length() == 0) {
throw new IllegalArgumentException("자동차 이름은 공백일 수 없습니다.");
} else if (carName.length() > 5) {
throw new IllegalArgumentException("자동차 이름은 최대 5자리입니다. 불가능한 이름: " + carName);
}
}

public int getTotalRoundFromInput() {
while (true) {
printTotalRoundInputDescription();

String roundInput = Console.readLine();
try {
int totalRound = convertRoundInputIntoRoundInteger(roundInput);

checkTotalRoundAvailable(totalRound);

return totalRound;
} catch (IllegalArgumentException exception) {
System.out.println("[ERROR] " + exception.getMessage());
}
}
}

private void printTotalRoundInputDescription() {
System.out.println("시도할 회수는 몇회인가요?");
}

private Integer convertRoundInputIntoRoundInteger(String roundInput) throws IllegalArgumentException {
try {
return Integer.parseInt(roundInput);
} catch (NumberFormatException exception) {
throw new IllegalArgumentException("자연수가 아닌 값은 입력할 수 없습니다.");
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

public
class NumberFormatException extends IllegalArgumentException {
    static final long serialVersionUID = -2848938806368998894L;

    /**
     * Constructs a <code>NumberFormatException</code> with no detail message.
     */
    public NumberFormatException () {
        super();
    }

사실 NumberFormatException은 IllegalArgumentException의 Child Class입니다. 해당 메소드는 불필요하다고 보여집니다.

Copy link
Author

Choose a reason for hiding this comment

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

parseInt에서 발생하는 exception message를 변경하고 싶은데 다른 방법이 있을까요?

Copy link
Collaborator

Choose a reason for hiding this comment

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

아항 parseInt에서 나오는 메세지를 바로 변경...이 안되니 원하는 메세지를 넣어서 에러 핸들링을 하시려면, 지금 방식이 맞는것 같네요!


private void checkTotalRoundAvailable(int totalRound) throws IllegalArgumentException {
if (totalRound < 1) {
throw new IllegalArgumentException("자연수가 아닌 값은 입력할 수 없습니다.");
}
}
}