-
Notifications
You must be signed in to change notification settings - Fork 9
김나현 - 자동차 경주 게임 #7
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
Open
nahyun0121
wants to merge
15
commits into
Dcom-KHU:nahyun0121
Choose a base branch
from
nahyun0121:nahyun0121
base: nahyun0121
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
6731ff4
docs: 기능 목록 작성
nahyun0121 693c37f
feat: 모든 자동차 이름을 형식에 맞게 입력 받는 기능 구현
nahyun0121 5731074
feat: 모든 자동차 이름을 저장하는 기능 구현
nahyun0121 654a576
feat: 랜덤 전진값 생성 기능 구현
nahyun0121 7fe522b
feat: 자동차가 전달받은 숫자에 따라 이동하는 기능 구현
nahyun0121 b572eca
feat: 시도할 횟수를 입력받는 기능 구현
nahyun0121 033477c
feat: 전달받은 횟수만큼 자동차를 이동시키는 기능 구현
nahyun0121 8b55998
feat: 횟수별 실행 결과 출력 기능 구현
nahyun0121 cd883bf
feat: 자동차 간 위치 비교 후 우승자를 구하는 기능 구현
nahyun0121 a65ea3d
feat: 우승자(들) 안내 출력 기능 구현
nahyun0121 8a0376d
feat: 에러 메시지 출력 기능 구현
nahyun0121 3cc2b3d
feat: 잘못된 값 입력 시 그부분부터 재입력하는 기능 구현
nahyun0121 747c46f
fix: 변수 이름 및 함수 일부 변경 및 예외 처리 추가
nahyun0121 5e04967
fix: java version으로 인해 돌아가지 않던 repeat 부분 수정
nahyun0121 4f7d694
fix: charAt()의 argument 수정
nahyun0121 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,11 @@ | ||
package racingcar; | ||
|
||
import racingcar.controller.RacingController; | ||
|
||
public class Application { | ||
public static void main(String[] args) { | ||
// TODO 구현 진행 | ||
RacingController racingController = new RacingController(); | ||
racingController.run(); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package racingcar.controller; | ||
|
||
import racingcar.controller.util.ExceptionHandler; | ||
import racingcar.dto.CarStatusDTO; | ||
import racingcar.model.RacingGame; | ||
import racingcar.model.RandomNumberGenerator; | ||
import racingcar.view.InputView; | ||
import racingcar.view.OutputView; | ||
|
||
import java.util.List; | ||
|
||
public class RacingController { | ||
private final InputView inputView = new InputView(); | ||
private final OutputView outputView = new OutputView(); | ||
private final RacingGame racingGame = new RacingGame(new RandomNumberGenerator()); | ||
|
||
public void run() { | ||
try { | ||
repeatUntilGetLegalAnswer(this::enrollCarToRace); | ||
repeatUntilGetLegalAnswer(this::moveCarsByCount); | ||
showWinners(); | ||
} catch (Exception e) { | ||
e.printStackTrace(); | ||
outputView.printErrorMessage(e.getMessage()); | ||
} | ||
} | ||
|
||
private void repeatUntilGetLegalAnswer(Runnable runnable) { | ||
ExceptionHandler.retryForIllegalArgument(runnable, outputView::printErrorMessage); | ||
} | ||
|
||
private void enrollCarToRace() { | ||
List<String> carNames = inputView.inputCarNames(); | ||
racingGame.enrollCars(carNames); | ||
} | ||
|
||
private void moveCarsByCount() { | ||
int moveCount = inputView.inputMoveCount(); | ||
List<CarStatusDTO> carStatuses = racingGame.repeatMovingCars(moveCount); // moveCount만큼 반복 이동 | ||
outputView.printGameResult(carStatuses); | ||
} | ||
|
||
private void showWinners() { | ||
List<String> winnerNames = racingGame.findWinners(); | ||
outputView.printWinners(winnerNames); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
src/main/java/racingcar/controller/util/ExceptionHandler.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package racingcar.controller.util; | ||
|
||
import java.util.function.Consumer; | ||
|
||
public class ExceptionHandler { | ||
private ExceptionHandler() { | ||
} | ||
|
||
public static void retryForIllegalArgument(Runnable runnable, Consumer<String> exceptionMessageHandling) { | ||
while (true) { | ||
try { | ||
runnable.run(); | ||
return; | ||
} catch (IllegalArgumentException e) { | ||
exceptionMessageHandling.accept(e.getMessage()); | ||
} | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package racingcar.dto; | ||
|
||
public class CarDTO { | ||
private final String name; | ||
private final int position; | ||
|
||
public CarDTO(String name, int position) { | ||
this.name = name; | ||
this.position = position; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public int getPosition() { | ||
return position; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "CarDTO{" + | ||
"name='" + name + '\'' + | ||
", position=" + position + | ||
'}'; | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package racingcar.dto; | ||
|
||
import java.util.List; | ||
|
||
public class CarStatusDTO { | ||
private final List<CarDTO> cars; | ||
|
||
public CarStatusDTO(List<CarDTO> cars) { | ||
this.cars = cars; | ||
} | ||
|
||
public List<CarDTO> getCars() { | ||
return cars; | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package racingcar.model; | ||
|
||
@FunctionalInterface // 1개의 추상 메소드를 갖는 인터페이스 | ||
public interface NumberGenerator { | ||
int make(); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package racingcar.model; | ||
|
||
import racingcar.dto.CarDTO; | ||
import racingcar.dto.CarStatusDTO; | ||
import racingcar.model.domain.Car; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
public class RacingGame { | ||
private final List<Car> racingCars = new ArrayList<>(); | ||
private final NumberGenerator numberGenerator; | ||
|
||
public RacingGame(NumberGenerator numberGenerator) { | ||
this.numberGenerator = numberGenerator; | ||
} | ||
|
||
public void enrollCars(List<String> carNames) { | ||
carNames.forEach(name -> racingCars.add(new Car(name))); | ||
} | ||
|
||
public List<CarStatusDTO> repeatMovingCars(int moveCount) { | ||
List<CarStatusDTO> carStatuses = new ArrayList<>(); | ||
for (int count = 0; count < moveCount; count++) | ||
carStatuses.add(new CarStatusDTO(moveCars())); | ||
return carStatuses; | ||
} | ||
|
||
public List<CarDTO> moveCars() { | ||
racingCars.forEach(car -> car.move(numberGenerator.make())); | ||
return racingCars.stream() | ||
.map(Car::to) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
public List<String> findWinners() { | ||
List<String> winners = new ArrayList<>(); | ||
for (Car car : racingCars) { | ||
if (findAnyHeadCar().compareTo(car) == 0) | ||
winners.add(car.getName()); | ||
} | ||
return winners; | ||
} | ||
|
||
private Car findAnyHeadCar() { | ||
List<Car> sortedCars = new ArrayList<>(racingCars); | ||
Collections.sort(sortedCars); // Car 클래스의 compareTo()로 인해 position에 따라 많이 전진한 순대로 정렬 | ||
return sortedCars.get(0); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package racingcar.model; | ||
|
||
import camp.nextstep.edu.missionutils.Randoms; | ||
|
||
public class RandomNumberGenerator implements NumberGenerator { | ||
|
||
@Override | ||
public int make() { | ||
return Randoms.pickNumberInRange(0, 9); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package racingcar.model.domain; | ||
|
||
import racingcar.dto.CarDTO; | ||
|
||
public class Car implements Comparable<Car> { | ||
private final String name; | ||
private int position = 0; | ||
|
||
public Car(String name) { | ||
validateName(name); | ||
this.name = name; | ||
} | ||
|
||
private void validateName(String name) { | ||
if (name.length() > 5) | ||
throw new IllegalArgumentException("자동차 이름이 다섯 글자를 초과합니다."); | ||
} | ||
|
||
public void move(int number) { | ||
validateNumber(number); | ||
if (number >= 4) | ||
position++; | ||
} | ||
|
||
public void validateNumber(int number) { | ||
if (number < 0 || number > 9) | ||
throw new IllegalArgumentException("전진하는 조건은 0에서 9 사이의 숫자일 때입니다."); | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public CarDTO to() { | ||
return new CarDTO(name, position); | ||
} | ||
|
||
@Override | ||
public int compareTo(Car anotherCar) { | ||
return anotherCar.position - this.position; | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package racingcar.view; | ||
|
||
import camp.nextstep.edu.missionutils.Console; | ||
import racingcar.view.utils.FormatParser; | ||
import racingcar.view.utils.NumberParser; | ||
|
||
import java.util.List; | ||
|
||
public class InputView { | ||
public List<String> inputCarNames() { | ||
System.out.println("경주할 자동차 이름들을 입력하세요. (이름은 쉼표(,)로 구분함)"); | ||
String line = Console.readLine(); // 콘솔로부터 값 읽기 | ||
return FormatParser.split(line, ","); // ',' 단위로 자른 공백 제거한 입력한 자동차 이름들의 목록 | ||
} | ||
|
||
public int inputMoveCount() { | ||
System.out.println("몇 번 시도할지 입력하세요. (숫자)"); | ||
String line = Console.readLine(); | ||
return NumberParser.parseDigit(line); // 입력값을 정수로 변환 | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package racingcar.view; | ||
|
||
import racingcar.dto.CarDTO; | ||
import racingcar.dto.CarStatusDTO; | ||
import racingcar.view.utils.FormatParser; | ||
|
||
import java.util.List; | ||
|
||
public class OutputView { | ||
public void printGameResult(List<CarStatusDTO> carStatuses) { // 경주 결과 자동차들 각각 상태 출력 | ||
System.out.println("실행 결과"); | ||
carStatuses.forEach(this::printCarStatuses); | ||
} | ||
|
||
private void printCarStatuses(CarStatusDTO carStatus) { | ||
List<CarDTO> cars = carStatus.getCars(); | ||
cars.forEach(this::printCar); | ||
System.out.println(); | ||
} | ||
|
||
private void printCar(CarDTO carDTO) { | ||
System.out.printf("%s : %s" + System.lineSeparator(), carDTO.getName(), | ||
FormatParser.make(carDTO.getPosition(), "-")); // lineSeparator: 개행문자 | ||
} | ||
|
||
public void printWinners(List<String> winnerNames) { | ||
System.out.printf("최종 우승자 : %s" + System.lineSeparator(), | ||
FormatParser.join(winnerNames, ", ")); | ||
} | ||
|
||
public void printErrorMessage(String message) { | ||
System.out.printf("[ERROR] %s" + System.lineSeparator(), message); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package racingcar.view.utils; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
public class FormatParser { | ||
private FormatParser() { | ||
} | ||
|
||
public static List<String> split(String line, String delimiter) { | ||
validateWrongFormat(line); | ||
String[] values = line.split(delimiter); // 문자열 배열 | ||
List<String> parsedValue = Arrays.stream(values) | ||
.map(String::trim) // trim: 문자열 공백 제거 | ||
.collect(Collectors.toList()); | ||
validateEmpty(parsedValue); | ||
return parsedValue; | ||
} | ||
private static void validateWrongFormat(String line) { | ||
if (hasWrongFormat(line)) { | ||
throw new IllegalArgumentException("입력값의 형식이 잘못되었습니다."); | ||
} | ||
} | ||
|
||
private static boolean hasWrongFormat(String line) { | ||
if (line.isEmpty()) { | ||
return true; | ||
} | ||
return line.startsWith(",") || line.endsWith(","); | ||
} | ||
|
||
private static void validateEmpty(List<String> values) { | ||
if (hasEmptyValue(values)) | ||
throw new IllegalArgumentException("입력값에 빈 문자열이 있습니다."); | ||
} | ||
|
||
private static boolean hasEmptyValue(List<String> values) { | ||
return values.stream() | ||
.anyMatch(String::isEmpty); // anyMatch(): 최소한 한 개의 요소가 주어진 조건에 만족하는지 조사하는 함수 & '::': 메소드 레퍼런스. 람다식을 더욱 간결하게 해준다. | ||
} | ||
|
||
public static String join(List<String> values, String delimiter) { | ||
return String.join(delimiter, values); | ||
} | ||
|
||
public static String make(int count, String unit) { | ||
String units = ""; | ||
for (int i = 0; i < count; i++) | ||
units = units + unit.charAt(0); | ||
return units; | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package racingcar.view.utils; | ||
|
||
public class NumberParser { | ||
private NumberParser() {} | ||
|
||
public static int parseDigit(String value) { | ||
int number = parseInteger(value); // 입력값을 정수로 변환 | ||
if (number <= 0) | ||
throw new IllegalArgumentException("입력값이 자연수가 아닙니다."); | ||
|
||
return number; | ||
} | ||
|
||
public static int parseInteger(String value) { | ||
try { | ||
return Integer.parseInt(value); // 숫자형의 문자열을 인자 값으로 받으면 십진수의 Integer 형으로 변환해줌 | ||
} catch (NumberFormatException e) { | ||
throw new IllegalArgumentException("입력값이 숫자가 아닙니다."); | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NumberGenerator 인터페이스에서 make()를 선언하고
RandomNumberGenerator에서 이를 받아 정의하는 형태로 되어있는데
이러한 형태가 가지는 장점이 있을까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
지금 시점에서는 큰 장점이 없는 것 같지만, 다른 숫자생성기가 만들어져야 하는 상황과 같이 앞으로 다른 기능이 추가되어야 할 상황이 온다면, NumberGenerator 인터페이스를 통해 다중 상속이라든지 여러 숫자생성기 클래스에서 기본이 되는 틀이 된다든지 하는 점에서 이 인터페이스를 잘 활용할 수 있을 것 같습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
그리고 더 찾아보니 대규모 프로젝트 개발 시 일관되고 정형화된 개발을 위한 표준화가 가능하다는 장점도 있다고 합니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SOLID의 5가지 원칙중에서 OCP에 해당하는 것 같네요.
하나 배워갑니다!