Skip to content

Commit d3ba012

Browse files
committed
step3) 자동차 경주 게임 구현
1 parent c824141 commit d3ba012

9 files changed

+306
-0
lines changed

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
# 자동차 경주 게임
2+
3+
## 기능 목록
4+
* 게임 참가자의 이름을 입력받는다. 이름의 구분자는 쉼표(,)이고, 이름이 5자가 넘어가면 NameLengthExceededException을 발생시키고 이름을 다시 입력받도록 한다.
5+
* 자동차별로 random값을 만들고, 그 숫자가 4 이상이면 전진한다.
6+
* 전진칸수가 최대값인 자동차가 우승자이다. 공동우승이 가능하다.
7+
28
## 진행 방법
39
* 자동차 경주 게임 요구사항을 파악한다.
410
* 요구사항에 대한 구현을 완료한 후 자신의 github 아이디에 해당하는 브랜치에 Pull Request(이하 PR)를 통해 코드 리뷰 요청을 한다.

build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ repositories {
1111
dependencies {
1212
testImplementation 'org.assertj:assertj-core:3.22.0'
1313
testImplementation 'org.junit.jupiter:junit-jupiter:5.8.2'
14+
testImplementation 'org.mockito:mockito-core:4.8.1'
1415
}
1516

1617
java {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package exception;
2+
3+
public class NameLengthExceededException extends RuntimeException {
4+
public NameLengthExceededException(String message) {
5+
super(message);
6+
}
7+
}
+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package racingCar;
2+
3+
import exception.NameLengthExceededException;
4+
5+
import java.util.ArrayList;
6+
import java.util.Arrays;
7+
import java.util.List;
8+
9+
public class CarRacingGame {
10+
private final InputView inputView;
11+
private final ResultView resultView;
12+
13+
public CarRacingGame(InputView inputView, ResultView resultView) {
14+
this.inputView = inputView;
15+
this.resultView = resultView;
16+
}
17+
18+
public static void main(String[] args) {
19+
InputView inputView = new InputView();
20+
ResultView resultView = new ResultView();
21+
CarRacingGame game = new CarRacingGame(inputView, resultView);
22+
game.startGame();
23+
}
24+
25+
void startGame() {
26+
RacingCar[] cars = getParticipant();
27+
28+
play(cars, inputView.requestPlayCount());
29+
30+
findWinners(cars);
31+
}
32+
33+
RacingCar[] getParticipant() {
34+
while (true) {
35+
String names = inputView.requestParticipant();
36+
try {
37+
validateNames(names);
38+
return createRacingCars(names);
39+
} catch (NameLengthExceededException e) {
40+
System.out.println(e.getMessage());
41+
}
42+
}
43+
}
44+
45+
void validateNames(String names) {
46+
boolean isValid = Arrays.stream(names.split(","))
47+
.allMatch(name -> name.length() <= 5);
48+
49+
if (!isValid) {
50+
throw new NameLengthExceededException("이름이 5글자를 초과할 수 없습니다. 다시 입력해주세요.");
51+
}
52+
}
53+
54+
RacingCar[] createRacingCars(String names) {
55+
return Arrays.stream(names.split(","))
56+
.map(name -> new RacingCar(name, 0))
57+
.toArray(RacingCar[]::new);
58+
}
59+
60+
void play(RacingCar[] cars, int count) {
61+
resultView.printResultTitle();
62+
for (int i=0 ; i<count ; i++) {
63+
moveCar(cars);
64+
resultView.printPlay(cars);
65+
}
66+
}
67+
68+
void moveCar(RacingCar[] cars) {
69+
for (RacingCar car : cars) {
70+
car.progress();
71+
}
72+
}
73+
74+
List<String> findWinners(RacingCar[] cars) {
75+
List<String> winnerList = new ArrayList<>();
76+
int maxPos = 0;
77+
78+
for (RacingCar car : cars) {
79+
int currentPos = car.getPos();
80+
81+
if (currentPos > maxPos) {
82+
maxPos = currentPos;
83+
winnerList.clear();
84+
winnerList.add(car.getName());
85+
} else if (currentPos == maxPos) {
86+
winnerList.add(car.getName());
87+
}
88+
}
89+
90+
resultView.printWinner(winnerList);
91+
return winnerList;
92+
}
93+
}
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package racingCar;
2+
3+
import java.util.Scanner;
4+
5+
public class InputView {
6+
private static Scanner scanner = new Scanner(System.in);
7+
String requestParticipant() {
8+
System.out.println("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분).");
9+
return scanner.nextLine();
10+
}
11+
12+
int requestPlayCount() {
13+
System.out.println("시도할 회수는 몇회인가요?");
14+
return Integer.parseInt(scanner.nextLine());
15+
}
16+
}
+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package racingCar;
2+
3+
import java.util.Random;
4+
5+
public class RacingCar {
6+
private String name;
7+
private int pos;
8+
9+
public RacingCar(String name, int pos) {
10+
this.name = name;
11+
this.pos = pos;
12+
}
13+
14+
public String getName() {
15+
return name;
16+
}
17+
18+
public void setName(String name) {
19+
this.name = name;
20+
}
21+
22+
public int getPos() {
23+
return pos;
24+
}
25+
26+
public void setPos(int pos) {
27+
this.pos = pos;
28+
}
29+
30+
@Override
31+
public String toString() {
32+
return "RacingCar{" + "name='" + name + '\'' + ", pos=" + pos + '}';
33+
}
34+
35+
protected int makeRandomNum() {
36+
return new Random().nextInt(10);
37+
}
38+
39+
void progress() {
40+
if (makeRandomNum() >= 4){
41+
incPos();
42+
}
43+
}
44+
45+
protected void incPos() {
46+
++this.pos;
47+
}
48+
}
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package racingCar;
2+
3+
import java.util.List;
4+
5+
public class ResultView {
6+
void printResultTitle() {
7+
System.out.println("실행 결과");
8+
}
9+
10+
void printPlay(RacingCar[] cars) {
11+
for (RacingCar car : cars) {
12+
System.out.println(car.getName() + " : " + "-".repeat(car.getPos()));
13+
}
14+
System.out.println();
15+
}
16+
17+
void printWinner(List<String> winner) {
18+
String winnerMessage = String.join(", ", winner) + "가 최종 우승했습니다.";
19+
System.out.println(winnerMessage);
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package racingCar;
2+
3+
import exception.NameLengthExceededException;
4+
import org.junit.jupiter.api.BeforeEach;
5+
import org.junit.jupiter.api.Test;
6+
7+
import java.util.Arrays;
8+
import java.util.List;
9+
10+
import static org.junit.jupiter.api.Assertions.*;
11+
import static org.mockito.Mockito.mock;
12+
13+
class CarRacingGameTest {
14+
private CarRacingGame carRacingGame;
15+
private RacingCar[] cars;
16+
17+
@BeforeEach
18+
void setUp() {
19+
InputView mockInputView = mock(InputView.class);
20+
ResultView mockResultView = mock(ResultView.class);
21+
carRacingGame = new CarRacingGame(mockInputView, mockResultView);
22+
cars = new RacingCar[]{
23+
new RacingCar("apple", 0),
24+
new RacingCar("cloud", 0),
25+
new RacingCar("bori", 0)
26+
};
27+
}
28+
29+
@Test
30+
void testValidateNames_validNames() {
31+
String names = "apple,cloud,bori";
32+
assertDoesNotThrow(() -> carRacingGame.validateNames(names));
33+
}
34+
35+
@Test
36+
void testValidateNames_invalidNames() {
37+
String names = "apple,cloud,longname";
38+
assertThrows(NameLengthExceededException.class, () -> carRacingGame.validateNames(names));
39+
}
40+
41+
@Test
42+
void testCreateRacingCars() {
43+
String names = "apple,cloud,bori";
44+
RacingCar[] createdCars = carRacingGame.createRacingCars(names);
45+
assertEquals(3, createdCars.length);
46+
assertArrayEquals(new String[]{"apple", "cloud", "bori"},
47+
Arrays.stream(createdCars).map(RacingCar::getName).toArray());
48+
}
49+
50+
@Test
51+
void testFindWinners_singleWinner() {
52+
cars = new RacingCar[]{
53+
new RacingCar("apple", 1),
54+
new RacingCar("cloud", 3),
55+
new RacingCar("bori", 2)
56+
};
57+
58+
List<String> winners = carRacingGame.findWinners(cars);
59+
60+
assertEquals(1, winners.size());
61+
assertTrue(winners.contains(cars[1].getName()));
62+
}
63+
64+
@Test
65+
void testFindWinners_multipleWinners() {
66+
cars = new RacingCar[]{
67+
new RacingCar("apple", 1),
68+
new RacingCar("cloud", 2),
69+
new RacingCar("bori", 2)
70+
};
71+
72+
List<String> winners = carRacingGame.findWinners(cars);
73+
74+
assertEquals(2, winners.size());
75+
assertTrue(winners.contains(cars[1].getName()) && winners.contains(cars[2].getName()));
76+
}
77+
}
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package racingCar;
2+
3+
import org.junit.jupiter.api.BeforeEach;
4+
import org.junit.jupiter.api.Test;
5+
6+
import static org.junit.jupiter.api.Assertions.assertEquals;
7+
import static org.junit.jupiter.api.Assertions.assertTrue;
8+
import static org.mockito.Mockito.when;
9+
10+
class RacingCarTest {
11+
12+
private RacingCar car;
13+
14+
@BeforeEach
15+
void setUp() {
16+
car = new RacingCar("apple", 0);
17+
}
18+
19+
@Test
20+
void makeRandomNum() {
21+
int random = car.makeRandomNum();
22+
assertTrue(random >= 0 && random <= 9);
23+
}
24+
25+
@Test
26+
void progress() {
27+
// given
28+
when(car.makeRandomNum()).thenReturn(4);
29+
int expected = car.getPos()+1;
30+
31+
// when
32+
car.progress();
33+
34+
// then
35+
assertEquals(expected, car.getPos());
36+
}
37+
}

0 commit comments

Comments
 (0)