-
Notifications
You must be signed in to change notification settings - Fork 93
[최보현] 자동차 경주 미션 제출 #133
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
Merged
Merged
[최보현] 자동차 경주 미션 제출 #133
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
04e2c45
docs: 1단계 요구사항 작성
boya-go 884845c
feat: car 객체 정보 클래스 생성
boya-go 72129c3
feat: 랜덤값 생성기 구현 및 car 객체 정보에 움직임 메서드 추가
boya-go 34fcac4
refactor: 테스트를 위해 랜덤숫자 생성기능과 움직이는 기능 분리
boya-go fcaa1d5
test: 움직이는 자동차 테스트 작성
boya-go 0c97bd5
docs: 1단계 요구사항 결과 및 2단계 요구사항 작성
boya-go 933f644
refactor: 불필요하게 Random 객체 생성되는 것을 방지하기 위해 static final로 변경해서 선언
boya-go 3a8ff9b
feat: 게임 실행해 우승자 반환하는 기능 작성, 기존 Car 클래스에 있던 랜덤숫자생성기를 인터페이스로 만듦
boya-go bbb7480
test: 우승 자동차 구하기 테스트 작성
boya-go 8ebd4ee
docs: 2단계 요구사항 결과 및 3단계 요구사항 작성
boya-go 27b8519
refactor: mvc패턴으로 수정 및 게임 실행 구현
boya-go 1dd8c56
refactor: 전반적인 코드 리팩토링 및 테스트 케이스 추가
boya-go f21a690
docs: 3단계 요구사항 결과 및 4단계 요구사항, 결과 작성
boya-go 51cd513
refactor: RacingGameController 구조 변경
boya-go 960b262
test: 테스트에만 사용하는 FixedNumberGeneraotor 구현체 테스트 패키지로 이동, @Nested 사용해 논…
boya-go f5fe592
refactor: 변수에 값 할당 이전에 검증하도록 수정
boya-go 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 |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# 자동차 경주 - 초간단 애플리케이션 | ||
|
||
## [1] 움직이는 자동차 | ||
|
||
- 자동차에 관한 요구사항 | ||
- [x] 자동차는 이름을 가지고 있다. | ||
- [x] 자동차는 움직일 수 있다. | ||
- [x] 0에서 9 사이의 random 값을 구해 그 값이 **4 이상이면 전진**하고, **3 이하 값이면 멈춘다**. | ||
|
||
--- | ||
|
||
## [2] 우승 자동차 구하기 | ||
|
||
- 기능 요구사항 | ||
- [x] n대의 자동차 참여 가능 | ||
- [x] 주어진 횟수동안 n대의 자동차는 전진 또는 멈출 수 있다. | ||
- [x] 이동 조건은 앞의 [움직이는 자동차]와 동일 | ||
- [x] 경주 게임 완료 후 우승자를 구할 수 있다. | ||
- [x] 우승자는 한 명 이상일 수 있다. | ||
|
||
--- | ||
|
||
## [3] 게임 실행 | ||
|
||
- 기능 요구사항 | ||
- [x] 자동차 및 게임 방법은 앞의 [움직이는 자동차], [우승 자동차 구하기]와 동일 | ||
- [x] 사용자로부터 `이름`, `게임횟수` 를 입력받는다. | ||
- [x] 자동차 이름은 쉼표(,) 기준으로 구분하며, 이름은 5자 이하만 가능하다. | ||
- [x] 메인 메서드를 추가하여 실행 가능하게 만든다. | ||
|
||
--- | ||
|
||
## [4] 리팩터링 | ||
|
||
- 요구사항 | ||
- [x] 단위 테스트를 구현한다. | ||
|
||
--- | ||
|
||
- 코드 작성 요구사항 | ||
- [x] 자동차가 움직이는 기능이 의도대로 되는지 테스트한다. | ||
- [x] 자바 코드 컨벤션 `Java Style Guide` 원칙으로 프로그래밍한다. | ||
- [x] 3항 연산자를 쓰지 않는다. | ||
- [x] else 예약어를 쓰지 않는다. | ||
- [x] switch/case도 사용하지 않는다. | ||
- [x] 함수(또는 메서드) 길이가 15라인을 넘어가지 않도록 구현한다. | ||
- [x] 함수(또는 메서드)가 한 가지 일만 하도록 한다. |
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,10 @@ | ||
import controller.RacingGameController; | ||
|
||
public class App { | ||
public static void main(String[] args) { | ||
RacingGameController racingGameController = new RacingGameController(); | ||
|
||
racingGameController.startRacingGame(); | ||
|
||
} | ||
} |
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,45 @@ | ||
package controller; | ||
|
||
import domain.Car; | ||
import domain.CarNameParser; | ||
import domain.CarRaceGame; | ||
import java.util.List; | ||
import view.inputView; | ||
import view.outputView; | ||
|
||
public class RacingGameController { | ||
|
||
public void startRacingGame() { | ||
String carNames = inputView.enterCarNames(); | ||
List<Car> cars = CarNameParser.parseCarName(carNames); | ||
final CarRaceGame carRaceGame = new CarRaceGame(cars); | ||
|
||
int round = inputView.enterRoundNumber(); | ||
|
||
outputView.printGameResultTitle(); | ||
|
||
printGameRounds(carRaceGame, round, cars); | ||
|
||
printWinners(carRaceGame); | ||
} | ||
|
||
private void printGameRounds(CarRaceGame carRaceGame, int round, List<Car> cars) { | ||
carRaceGame.validateRoundNumber(round); | ||
|
||
for (int i = 0; i < round; i++) { | ||
|
||
carRaceGame.playOneRound(); | ||
System.out.println(); | ||
outputView.printRoundResult(cars); | ||
} | ||
} | ||
|
||
|
||
private void printWinners(CarRaceGame carRaceGame) { | ||
|
||
List<String> winnersName = carRaceGame.getWinnerNames(); | ||
|
||
outputView.printGameWinners(winnersName); | ||
|
||
} | ||
} |
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 domain; | ||
|
||
import domain.generator.NumberGenerator; | ||
|
||
public class Car { | ||
|
||
private final String name; | ||
private int position; | ||
private final NumberGenerator generator; | ||
private static final int MOVE_THRESHOLD = 4; | ||
|
||
public Car(String name, NumberGenerator generator) { | ||
validateName(name); | ||
this.name = name.trim(); | ||
this.position = 0; | ||
this.generator = generator; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public int getPosition() { | ||
return position; | ||
} | ||
|
||
private void validateName(String name) { | ||
|
||
if (name == null || name.isBlank()) { | ||
throw new IllegalArgumentException("이름은 빈 값이 될 수 없습니다."); | ||
} | ||
if (name.length() > 5) { | ||
throw new IllegalArgumentException("이름은 5자 이하만 가능합니다."); | ||
} | ||
} | ||
|
||
public void movePosition() { | ||
if (generator.generate() >= MOVE_THRESHOLD ) { | ||
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,35 @@ | ||
package domain; | ||
|
||
import domain.generator.RandomNumberGenerator; | ||
import java.util.Arrays; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Set; | ||
import java.util.stream.Collectors; | ||
|
||
public class CarNameParser { | ||
|
||
public static final String CAR_NAME_DELIMITER = ","; | ||
|
||
public static List<Car> parseCarName(String carNames) { | ||
|
||
List<String> carNameList = Arrays.stream(carNames.split(CAR_NAME_DELIMITER)) | ||
.map(String::trim) | ||
.collect(Collectors.toList()); | ||
|
||
validateDuplicateCarName(carNameList); | ||
|
||
return carNameList.stream() | ||
.map(name -> new Car(name.trim(), new RandomNumberGenerator())) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
private static void validateDuplicateCarName(List<String> carNameList) { | ||
|
||
Set<String> uniqueCarNames = new HashSet<>(carNameList); | ||
|
||
if (uniqueCarNames.size() != carNameList.size()) { | ||
throw new IllegalArgumentException("중복된 자동차 이름은 입력할 수 없습니다."); | ||
} | ||
} | ||
} |
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,57 @@ | ||
package domain; | ||
|
||
import java.util.List; | ||
|
||
public class CarRaceGame { | ||
|
||
private final List<Car> cars; | ||
|
||
public CarRaceGame(List<Car> cars) { | ||
this.cars = cars; | ||
} | ||
|
||
public void validateRoundNumber(int gameRound) { | ||
if (gameRound < 1 ) { | ||
throw new IllegalArgumentException("라운드는 한 번 이상 진행되어야 합니다."); | ||
} | ||
} | ||
|
||
public void playOneRound() { | ||
for (Car car : cars) { | ||
car.movePosition(); | ||
} | ||
} | ||
|
||
private int getMaxDistance() { | ||
int maxDistance = cars.stream() | ||
.mapToInt(Car::getPosition) | ||
.max() | ||
.orElseThrow(); | ||
|
||
return maxDistance; | ||
} | ||
|
||
private List<String> getWinners(int maxDistance) { | ||
return cars.stream() | ||
.filter(car -> car.getPosition() == maxDistance) | ||
.map(Car::getName) | ||
.toList(); | ||
} | ||
|
||
public void playRacingGame(int gameRound) { | ||
validateRoundNumber(gameRound); | ||
|
||
for (int i=0; i < gameRound;i++) { | ||
playOneRound(); | ||
} | ||
} | ||
|
||
public List<String> getWinnerNames() { | ||
List<String> winners = getWinners(getMaxDistance()); | ||
|
||
if (winners == null) { | ||
throw new IllegalStateException("게임이 실행되지 않았습니다."); | ||
} | ||
return winners; | ||
} | ||
} |
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,5 @@ | ||
package domain.generator; | ||
|
||
public interface NumberGenerator { | ||
int generate(); | ||
} |
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,13 @@ | ||
package domain.generator; | ||
|
||
import java.util.Random; | ||
|
||
public class RandomNumberGenerator implements NumberGenerator { | ||
|
||
private static final Random RANDOM = new Random(); | ||
|
||
@Override | ||
public int generate( ) { | ||
return RANDOM.nextInt( 10 ); | ||
} | ||
} |
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,18 @@ | ||
package view; | ||
|
||
import java.util.Scanner; | ||
|
||
public class inputView { | ||
|
||
private static final Scanner scanner = new Scanner(System.in); | ||
|
||
public static String enterCarNames() { | ||
System.out.println("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분)."); | ||
return scanner.nextLine(); | ||
} | ||
|
||
public static int enterRoundNumber() { | ||
System.out.println("시도할 회수는 몇회인가요?"); | ||
return scanner.nextInt(); | ||
} | ||
} |
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,26 @@ | ||
package view; | ||
|
||
import domain.Car; | ||
|
||
import java.util.List; | ||
|
||
public class outputView { | ||
|
||
private static final String CAR_POSITION_EXPRESSION = "-"; | ||
private static final String WINNER_NAMES_DELIMITER = ","; | ||
|
||
public static void printGameResultTitle() { | ||
System.out.print("\n실행 결과"); | ||
} | ||
|
||
public static void printRoundResult(List<Car> cars) { | ||
for (Car car : cars) { | ||
System.out.println(car.getName() + ": " + CAR_POSITION_EXPRESSION.repeat(car.getPosition())); | ||
} | ||
System.out.println(); | ||
} | ||
|
||
public static void printGameWinners(List<String> winners) { | ||
System.out.println(String.join(WINNER_NAMES_DELIMITER, winners) + "가 최종 우승했습니다."); | ||
} | ||
} |
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,59 @@ | ||
package domain; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||
|
||
import java.util.List; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Nested; | ||
import org.junit.jupiter.api.Test; | ||
|
||
public class CarNameParserTest { | ||
|
||
@Nested | ||
@DisplayName("입력된 문자열은 구분자로 나누어 차의 이름이 된다.") | ||
class ParseCarNameTest { | ||
|
||
@Test | ||
@DisplayName("공백없이 들어왔을 경우") | ||
public void parseCarName_문자열을입력하면_차이름리스트가생성된다() { | ||
|
||
// given | ||
String carNames = "차1,차2,차3"; | ||
|
||
// when | ||
List<Car> cars = CarNameParser.parseCarName(carNames); | ||
|
||
// then | ||
assertThat(cars).extracting(Car::getName).containsExactly("차1", "차2", "차3"); | ||
|
||
} | ||
|
||
@Test | ||
@DisplayName("공백 포함해 들어왔을 경우") | ||
public void parseCarName_구분자기준으로공백이포함된경우_공백제거후차이름리스트가생성된다() { | ||
|
||
// given | ||
String carNames = "차1 , 차2,차3 "; | ||
|
||
// when | ||
List<Car> cars = CarNameParser.parseCarName(carNames); | ||
|
||
// then | ||
assertThat(cars).extracting(Car::getName).containsExactly("차1", "차2", "차3"); | ||
|
||
} | ||
} | ||
|
||
@Test | ||
@DisplayName("입력된 차들의 이름은 중복이 없어야 한다.") | ||
public void parseCarName_중복된차이름_예외처리() { | ||
// given | ||
CarNameParser carNameParser = new CarNameParser(); | ||
String carNames = "차1,차1,차3"; | ||
|
||
assertThatThrownBy(() -> carNameParser.parseCarName(carNames)) | ||
.isInstanceOf(IllegalArgumentException.class) | ||
.hasMessageContaining("중복된 자동차 이름은 입력할 수 없습니다."); | ||
} | ||
} |
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.
Uh oh!
There was an error while loading. Please reload this page.