Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
c6c10c9
docs(기능목록): 구현 전 기능 목록 작성
sschan99 Mar 18, 2023
ac4c112
feat(Car): 랜덤하게 생성한 숫자가 4 이상일 경우 전진
sschan99 Mar 18, 2023
46f4043
feat(InputView): 자동차의 이름들을 입력받는 기능 추가
sschan99 Mar 18, 2023
928b6a1
feat(InputView): 자동차 이름의 입력이 잘못된 경우 에러 메시지를 출력 후 다시 입력받음
sschan99 Mar 18, 2023
7d34efb
feat(InputView): 시도할 횟수를 입력받는 기능, 입력값이 숫자가 아닐 경우 예외 처리
sschan99 Mar 18, 2023
da2a2d9
feat(Car): Car 객체를 출력할 때 사용하기 위한 toString 메서드 구현
sschan99 Mar 18, 2023
17cf22c
feat(OutputView): 각 차수마다 사용할 실행 결과 출력 함수 구현
sschan99 Mar 18, 2023
82a426b
feat(OutputView): 머리말 및 가독성을 위한 빈 줄 출력
sschan99 Mar 18, 2023
7b491be
feat(Application): 구현한 기능들을 사용하여 자동차 경주 게임 구현 (최종 우승자 안내 제외)
sschan99 Mar 18, 2023
975675b
feat(Car): name의 getter 생성
sschan99 Mar 18, 2023
b379fe3
feat(OutputView): 최종 우승자 목록을 구하고 출력하는 기능 구현
sschan99 Mar 18, 2023
e0233fd
feat(Application): 자동차 경주 게임에 최종 우승자 안내 추가
sschan99 Mar 18, 2023
ab07e6b
refactor(Application): 최종 우승자 결정 알고리즘을 OutputView에서 Application으로 이동
sschan99 Mar 25, 2023
2926732
refactor(InputView): validate 메서드들의 이름을 서로 다르게 변경, 변수명 수정
sschan99 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
31 changes: 30 additions & 1 deletion src/main/java/racingcar/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,36 @@
package racingcar;

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

public class Application {
public static void main(String[] args) {
// TODO 구현 진행
InputView inputView = new InputView();
OutputView outputView = new OutputView();

List<Car> cars = initializeCars(inputView.receiveCarNames());
int attemptNumber = inputView.receiveAttemptNumber();

outputView.printPreface();
for (int i = 0; i < attemptNumber; i++) {
moveCars(cars);
outputView.printExecutionResults(cars);
}

outputView.printFinalWinner(cars);
}

private static List<Car> initializeCars(List<String> carNames) {
List<Car> cars = new ArrayList<>();
for (String name : carNames) {
cars.add(new Car(name));
}
return cars;
}

private static void moveCars(List<Car> cars) {
for (Car car : cars) {
car.forward();
}
}
}
24 changes: 23 additions & 1 deletion src/main/java/racingcar/Car.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package racingcar;

import static camp.nextstep.edu.missionutils.Randoms.pickNumberInRange;

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

// 추가 기능 구현
public String getName() {
return name;
}

public int getPosition() {
return position;
}

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

public String toString() {
StringBuilder bar = new StringBuilder();
for (int i = 0; i < this.position; i++) {
bar.append("-");
}
return this.name + " : " + bar;
}
Comment on lines +27 to +33
Copy link

Choose a reason for hiding this comment

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

StringBuilder를 사용하는 이유가 + 연산보다 속도가 빠르기 때문으로 알고 있습니다. 혹시 bar만 StringBuilder를 쓰고 return 에서는 + 연산을 사용한 이유가 있을까요?

Copy link
Author

Choose a reason for hiding this comment

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

java 컴파일러에서 + 연산을 StringBuilder의 append로 바꿔준다고 합니다!
따라서 둘 중 무엇을 사용하든 성능상으로는 비슷하다고 하는데, 개인적으로는 간결하게 + 연산을 사용하는 것을 좋아합니다. :)
그러나 반복문 내에서는 컴파일시에 변환이 안된다고 하여 StringBuilder를 사용했습니다!

참고
https://stackoverflow.com/questions/7817951/string-concatenation-in-java-when-to-use-stringbuilder-and-concat
https://choichumji.tistory.com/135

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

import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

import static camp.nextstep.edu.missionutils.Console.readLine;
Copy link
Collaborator

Choose a reason for hiding this comment

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

static import 보다는 그냥 해당 클래스를 import하는게 조금 더 좋은 것으로 알고 있습니다. STATIC import 는 주로 상수를 가져올때 많이 쓰는것 같던데, 혹시 해당 부분에서 함수를 static import하신 이유가 있으신가요?

Copy link
Author

Choose a reason for hiding this comment

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

코드의 가독성을 높이기 위해 static import를 사용했습니다.
하지만 자주 사용하는 메서드가 아닌 만큼 기본적인 import문을 사용해도 괜찮아 보이네요.
의견 주셔서 감사합니다!

별개로 질문드리고 싶은 것은 import문의 경우 컴파일 시에 처리하니까 성능적인 차이는 없는게 아닌가요?
조금 더 좋다고 얘기하신 근거에 대해서 궁금합니다!


public class InputView {
public List<String> receiveCarNames() {
while (true) {
System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)");
List<String> carNames = Arrays.asList(readLine().split(","));
try {
validate(carNames);
} catch (IllegalArgumentException iae) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

메번 에러 메세지 변수명을 e로만 지었는데 iae와 같이 조금 더 정보가 있는 이름도 좋은것 같습니다.

Choose a reason for hiding this comment

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

메세지 변수명도 예외 항목에 따라서 바꾸는 디테일을 배울 수 있어 흥미로웠습니다

System.out.println(iae.getMessage());
continue;
}
return carNames;
}
}

private void validate(List<String> carNames) {
Copy link

Choose a reason for hiding this comment

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

같은 이름의 함수가 서로 다른 기능을 수행하고 있는 것으로 보여요. 혹시 좀 더 구체적으로 함수의 이름을 지어보시는 건 어떨까요?

Copy link
Author

Choose a reason for hiding this comment

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

서로 다른 이름으로 변경하였습니다!
의견 감사합니다!

for (String name : carNames) {
if (name.length() > 5) {
throw new IllegalArgumentException("[ERROR] 자동차의 이름은 5자 이하만 가능합니다.");
}
}
}

public int receiveAttemptNumber() {
while (true) {
System.out.println("시도할 횟수는 몇 회인가요?");
String AttemptNumber = readLine();
try {
validate(AttemptNumber);
} catch (IllegalArgumentException iae) {
System.out.println(iae.getMessage());
continue;
}
return Integer.parseInt(AttemptNumber);
}
}

private void validate(String AttemptNumber) {
if (!Pattern.matches("^[0-9]+$", AttemptNumber)) {
throw new IllegalArgumentException("[ERROR] 숫자만 입력할 수 있습니다.");
}
}
Copy link

@Untaini Untaini Mar 21, 2023

Choose a reason for hiding this comment

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

패턴을 이용해서 자연수를 검사하는 방식은 참신해보여요. 원하는 에러메시지를 보내기 위해 NumberFormatException을 catch하고 새로 IllegalArgumentExcetion을 만드는 것보다 직관적으로 보입니다. XD

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

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

public class OutputView {
public void printExecutionResults(List<Car> cars) {
for (Car car : cars) {
System.out.println(car);
}
System.out.println();
}

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

public void printFinalWinner(List<Car> cars) {
List<String> finalWinner = new ArrayList<>();
int max = 0;
for (Car car : cars) {
if (car.getPosition() > max) {
finalWinner.clear();
max = car.getPosition();
}
if (car.getPosition() == max) {
finalWinner.add(car.getName());
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Output View에서 우승자를 가려내는 알고리즘이 실행되고 있는데, 대부분의 다른 로직들은 Application에 있는것으로 보입니다. 해당 로직만 여기서 처리된 이유가 있을까요?

Copy link
Author

Choose a reason for hiding this comment

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

미처 생각하지 못한 부분이네요.
해당 부분을 Application으로 옮겨서 역할에 맞는 기능을 수행하도록 수정하겠습니다.
감사합니다!

System.out.println("최종 우승자 : " + String.join(", ", finalWinner));
}
}
12 changes: 12 additions & 0 deletions 기능목록.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# 기능 목록

- 경주할 자동차를 입력
- 각 자동차의 이름이 5자 이하인지 확인
- 시도할 횟수를 입력
- 각 차수별로 하위 기능들을 실행
- 0~9의 무작위 값을 생성
- 4 이상의 값인지 판단
- 4 이상이라면 자동차를 전진
- 각 차수의 결과를 출력
- 우승자 목록을 생성
- 최종 우승자를 출력