-
Notifications
You must be signed in to change notification settings - Fork 85
[중앙대 동네] 한성재 레이싱카 미션 #66
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
base: bingle625
Are you sure you want to change the base?
Changes from all commits
817a2e5
91ee068
950db53
46df3ff
bda9c1c
d98d93a
04759fe
91488de
4d88902
c3647b1
fe72b38
43c5f4c
c74a2cd
ccf524e
4d5d8f4
44f8134
0d474fd
95e3a35
e7257ab
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
|
||
# 자동차 경주 | ||
|
||
## 1. 움직이는 자동차 구하기 | ||
- [x] 자동차 구현 | ||
- [x] 이름 property 를 가짐 | ||
- [x] 좌표 property 를 가짐 | ||
- [x] 움직이는 기능 | ||
- [x] 0~9 무작위 숫자 4 이상 => 전진, 3 이하 => 전진 | ||
- [x] 코드 컨벤션 | ||
- [x] 인덴트 2를 넘지 않도록 구현 | ||
- [x] 3항 연산자 사용 X | ||
- [x] `else` 사용 X | ||
- [x] `switch/case` 사용 X | ||
- [x] 메서드의 길이 15라인을 넘지 않도록 | ||
- [x] 메서드는 하나의 일만 수행하도록 | ||
- [x] 메인 메서드는 생성 X | ||
- [x] 테스트 코드 | ||
- [x] 자동차 이름 확인 | ||
- [x] 자동차 움직임 기능 확인 | ||
|
||
## 2. 우승 자동차 구하기 | ||
- [x] 경주 게임 구현 | ||
- [x] n대의 자동차가 참여 가능 | ||
- [x] 횟수 x 번 동안 각 자동차 전진 혹은 정지 | ||
- [x] 경주 게임 완료 후 우승 자동차(중복 가능) 확인 가능 | ||
- [x] 코드 컨벤션 | ||
- [ ] 인덴트 2를 넘지 않도록 구현 | ||
- [x] 3항 연산자 사용 X | ||
- [x] `else` 사용 X | ||
- [x] `switch/case` 사용 X | ||
- [x] 메서드의 길이 15라인을 넘지 않도록 | ||
- [x] 메서드는 하나의 일만 수행하도록 | ||
- [x] 메인 메서드는 생성 X | ||
- [x] 테스트 코드 | ||
- [x] 자동차 움직임 기능 확인 | ||
|
||
## 3. 게임 실행 | ||
- [X] 주어진 횟수 동안 n대의 자동차는 전진 또는 멈출 수 있다. | ||
- [X] 각 자동차에 이름을 부여할 수 있다. 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다. | ||
- [X] 자동차 이름은 쉼표(,)를 기준으로 구분하며 이름은 5자 이하만 가능하다. | ||
- [X] 사용자는 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다. | ||
- [X] 전진하는 조건은 0에서 9 사이에서 random 값을 구한 후 random 값이 4 이상일 경우 전진하고, 3 이하의 값이면 멈춘다. | ||
- [X] 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한 명 이상일 수 있다. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import Exceptions.InvalidCarNameLengthException; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.Scanner; | ||
|
||
public class Application { | ||
|
||
public static void main(String[] args) { | ||
Scanner sc = new Scanner(System.in); | ||
|
||
List<String> names = RacingGameHost.getCarNames(sc); | ||
int round = RacingGameHost.getCount(sc); | ||
|
||
RacingGame game = new RacingGame(names, round); | ||
|
||
RacingGameHost.playGame(game); | ||
|
||
RacingGameHost.projectWinners(game); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
public class Car { | ||
|
||
private int coordinateX; | ||
private final String name; | ||
private final NumberGenerator numberGenerator; | ||
|
||
public static Car makeCar(String name) { | ||
return new Car(new RandomNumberGenerator(), 0, name); | ||
} | ||
|
||
public Car(NumberGenerator numberGenerator, int coordinateX, String name) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. production에선 NumberGenerator나 coordinateX의 경우에는 현재 요구사항에선 고정되어있어요. numberGenerator -> RandomNumberGenerator name만 받는 생성자를 만들어보면 어떨까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. name 만 인자로 받는 static 메서드를 Car 클래스 내부에 추가했습니다. |
||
this.numberGenerator = numberGenerator; | ||
this.coordinateX = coordinateX; | ||
this.name = name; | ||
} | ||
|
||
public void move() { | ||
int randomNumber = this.numberGenerator.getNumber(); | ||
|
||
if (randomNumber >= 4) { | ||
this.coordinateX += 1; | ||
} | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public int getCoordinateX() { | ||
return coordinateX; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package Exceptions; | ||
|
||
public class InvalidCarNameLengthException extends IllegalArgumentException implements | ||
RacingException { | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package Exceptions; | ||
|
||
public interface RacingException { | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
public interface NumberGenerator { | ||
|
||
public int getNumber(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
public class RacingGame { | ||
|
||
private final List<Car> cars; | ||
private final int round; | ||
|
||
/** | ||
* Constructor `self` | ||
*/ | ||
public RacingGame() { | ||
this.cars = new ArrayList<>(); | ||
this.round = 0; | ||
} | ||
|
||
/** | ||
* Constructor `self` | ||
* | ||
* @param names 입력받은 차량 이름들 | ||
* @param round 입력받은 게임 라운드 수 | ||
*/ | ||
public RacingGame(List<String> names, int round) { | ||
this.round = round; | ||
this.cars = new ArrayList<>(); | ||
|
||
for (String name : names) { | ||
this.addCar(Car.makeCar(name)); | ||
} | ||
} | ||
|
||
public List<Car> getCars() { | ||
return this.cars; | ||
} | ||
|
||
|
||
public int getRound() { | ||
return this.round; | ||
} | ||
|
||
/** | ||
* @param car 게임 참여 차량 | ||
*/ | ||
public void addCar(Car car) { | ||
this.cars.add(car); | ||
} | ||
|
||
/** | ||
* 게임 진행 | ||
*/ | ||
public void proceedGame() { | ||
this.cars.forEach(Car::move); | ||
} | ||
|
||
/** | ||
* @return winners 현재 우승자 이름 배열 | ||
*/ | ||
public List<String> getWinnerNames() { | ||
int maxLocation = 0; | ||
List<String> winners = new ArrayList<>(); | ||
|
||
for (Car car : this.cars) { | ||
int carLocation = car.getCoordinateX(); | ||
if (maxLocation < carLocation) { | ||
maxLocation = carLocation; | ||
winners.clear(); | ||
winners.add(car.getName()); | ||
} else if (maxLocation == carLocation) { | ||
winners.add(car.getName()); | ||
} | ||
} | ||
|
||
return winners; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import Exceptions.InvalidCarNameLengthException; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.Scanner; | ||
|
||
public class RacingGameHost { | ||
|
||
public static List<String> getCarNames(final Scanner sc) { | ||
List<String> result = null; | ||
while (result == null) { | ||
System.out.println("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분)."); | ||
String namesText = sc.nextLine(); | ||
|
||
try { | ||
result = Arrays.stream(namesText.split(",")) | ||
.map(String::strip) | ||
.peek(RacingGameHost::checkNameLength) | ||
.toList(); | ||
} catch (InvalidCarNameLengthException exception) { | ||
System.out.println("이름은 5자 이하만 입력 가능합니다."); | ||
} | ||
|
||
} | ||
|
||
return result; | ||
} | ||
|
||
private static void checkNameLength(final String name) { | ||
if (name.length() > 5) { | ||
throw new InvalidCarNameLengthException(); | ||
} | ||
} | ||
|
||
public static int getCount(final Scanner sc) { | ||
System.out.println("시도할 회수는 몇회인가요?"); | ||
return sc.nextInt(); | ||
} | ||
|
||
public static void projectWinners(final RacingGame game) { | ||
List<String> winnerNames = game.getWinnerNames(); | ||
System.out.println(String.join(",", winnerNames) + "가 최종우승했습니다."); | ||
} | ||
|
||
public static void projectCars(List<Car> cars) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 어떤건 final을 붙였고, 어떤건 안붙였군요 성재님만의 기준이 있으신가요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. final에 대한 기준이 아직 모호해서 발생하는 것 같습니다. 따라서 기준이 있다기보다는 익숙치 않은 사용으로 봐주시면 될거 같습니다.ㅎㅎ |
||
cars.forEach((car) -> { | ||
String progressBar = "-".repeat(car.getCoordinateX()); | ||
System.out.println(car.getName() + " : " + progressBar); | ||
}); | ||
} | ||
|
||
|
||
public static void playGame(final RacingGame game) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. RacingGameHost에서 입출력 뿐 아니라 게임도 진행시키는군요. 이렇게 설정하신 이유가 있을까요?? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 해당 부분에 대해서 좀 고민을 했는데, progressBar가 시스템 상에서 출력이 되는 부분이 |
||
List<Car> cars = game.getCars(); | ||
|
||
for (int i = 0; i < game.getRound(); i++) { | ||
game.proceedGame(); | ||
RacingGameHost.projectCars(cars); | ||
System.out.println(); | ||
} | ||
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import java.security.SecureRandom; | ||
import java.util.Random; | ||
|
||
public class RandomNumberGenerator implements NumberGenerator{ | ||
|
||
private final SecureRandom secureRandom; | ||
|
||
public RandomNumberGenerator() { | ||
this.secureRandom = new SecureRandom(); | ||
} | ||
|
||
@Override | ||
public int getNumber() { | ||
return this.secureRandom.nextInt(9); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||
|
||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
|
||
@DisplayName("자동차 테스트") | ||
public class CarTest { | ||
|
||
@Test | ||
@DisplayName("이름 속성 확인") | ||
void testName() { | ||
Car car = new Car(new TestNumberGenerator(3), 0, "자동차1"); | ||
|
||
String name = car.getName(); | ||
|
||
assertThat(name).isEqualTo("자동차1"); | ||
} | ||
|
||
@Test | ||
@DisplayName("숫자가 4이상일 때 자동차가 움직이는 지 테스트") | ||
void testMove() { | ||
Car car = new Car(new TestNumberGenerator(4),0, "자동차1"); | ||
|
||
car.move(); | ||
|
||
assertThat(car.getCoordinateX()).isEqualTo(1); | ||
} | ||
|
||
@Test | ||
@DisplayName("숫자가 3 이하일 때 자동차가 움직이지 않는 지 테스트") | ||
void testNotMove() { | ||
Car car = new Car(new TestNumberGenerator(3), 0, "자동차1"); | ||
|
||
car.move(); | ||
|
||
assertThat(car.getCoordinateX()).isEqualTo(0); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
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.Test; | ||
|
||
@DisplayName("레이싱 게임 테스트") | ||
public class RacingGameTest { | ||
|
||
@Test | ||
@DisplayName("자동차 참여 테스트") | ||
void testCarJoin() { | ||
Car car1 = new Car(new TestNumberGenerator(3), 0, "자동차1"); | ||
Car car2 = new Car(new TestNumberGenerator(4), 0, "자동차2"); | ||
|
||
RacingGame game1 = new RacingGame(); | ||
|
||
game1.addCar(car1); | ||
game1.addCar(car2); | ||
|
||
assertThat(game1.getCars().size()).isEqualTo(2); | ||
} | ||
|
||
@Test | ||
@DisplayName("우승자 확인 테스트") | ||
void testRacingWinner() { | ||
Car car1 = new Car(new TestNumberGenerator(3), 0, "자동차1"); | ||
Car car2 = new Car(new TestNumberGenerator(4), 0, "자동차2"); | ||
|
||
RacingGame game1 = new RacingGame(); | ||
game1.addCar(car1); | ||
game1.addCar(car2); | ||
|
||
game1.proceedGame(); | ||
|
||
List<String> winnerNames = game1.getWinnerNames(); | ||
|
||
assertThat(winnerNames).containsExactlyInAnyOrderElementsOf(List.of("자동차2")); | ||
} | ||
|
||
@Test | ||
@DisplayName("복수 우승자 확인 테스트") | ||
void testMultipleWinner() { | ||
Car car0 = new Car(new TestNumberGenerator(3), 0, "자동차0"); | ||
Car car1 = new Car(new TestNumberGenerator(3), 0, "자동차1"); | ||
Car car2 = new Car(new TestNumberGenerator(4), 0, "자동차2"); | ||
Car car3 = new Car(new TestNumberGenerator(4), 0, "자동차3"); | ||
|
||
RacingGame game1 = new RacingGame(); | ||
game1.addCar(car0); | ||
game1.addCar(car1); | ||
game1.addCar(car2); | ||
game1.addCar(car3); | ||
|
||
game1.proceedGame(); | ||
|
||
List<String> winnerNames = game1.getWinnerNames(); | ||
|
||
assertThat(winnerNames).containsExactlyInAnyOrderElementsOf(List.of("자동차3", "자동차2")); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
public class TestNumberGenerator implements NumberGenerator{ | ||
|
||
private final int setNumber; | ||
|
||
public TestNumberGenerator(int number) { | ||
this.setNumber = number; | ||
} | ||
|
||
@Override | ||
public int getNumber() { | ||
return this.setNumber; | ||
} | ||
} |
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.
깔끔하게 분리가 되었네요. 잘하셨습니다!