Skip to content
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

[자동차 경주] 남인우 미션 제출합니다. #2374

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
31fb897
docs: 기능 명세서 (구현 목록) 추가
korean5078 Oct 27, 2023
5c0eda7
docs: 기능 명세서 수정
korean5078 Oct 28, 2023
9596525
feat(RacingCar): 0부터 9까지 랜덤 값을 구하는 기능 구현
korean5078 Oct 28, 2023
df262df
feat(RacingCar): 무작위 숫자가 4부터 9가 나오면 전진하는 기능 구현
korean5078 Oct 28, 2023
e6e1381
docs: 기능 명세서 수정
korean5078 Oct 28, 2023
409fe60
feat(Player): 각 자동차에 부여할 이름 입력 기능 구현
korean5078 Oct 30, 2023
0ac9398
fix(Player): inputNames 함수에서 질문 출력 순서 변경
korean5078 Oct 30, 2023
6a91747
feat(Player): 자동차들의 이동 횟수를 입력하는 기능 구현
korean5078 Oct 30, 2023
4d66eb4
docs: 기능 명세서 수정
korean5078 Oct 31, 2023
3483923
feat(RacingCarGame): 플레이어에게 이름을 입력받으면 자동차 객체들을 생성하는 기능 구현
korean5078 Oct 31, 2023
4adfae2
feat(RacingCarGame,RacingCar): 플레이어에게 입력받은 라운드 횟수만큼 게임을 실행하는 기능 구현
korean5078 Oct 31, 2023
86401e6
feat(RacingCarGame): 라운드가 모두 끝나면 최종 우승자를 가리고 출력하는 기능 구현
korean5078 Nov 1, 2023
e8499da
refactor(RacingCarGame): 최종 우승자를 가리는 기능 함수 수정
korean5078 Nov 1, 2023
822d457
refactor(RacingCar): 자동차가 전진하거나 멈추는 기능 함수 수정
korean5078 Nov 1, 2023
8dcea68
Merge branch 'feature/go-or-stop' into develop
korean5078 Nov 1, 2023
fd41d09
refactor(RacingCarGame): 불필요한 코드 삭제 및 Player 클래스의 의존성 주입 방식 적용
korean5078 Nov 1, 2023
7f98b80
test(ApplicationTest): 이름 입력 받을 시 끝에 ',' 있을 때 예외 테스트 함수 작성
korean5078 Nov 1, 2023
cc3a4b1
fix(Player): Player 클래스 함수 수정
korean5078 Nov 1, 2023
a9913ff
refactor(RacingCarGame): init 함수 기능 분리
korean5078 Nov 1, 2023
8b65bae
test(ApplicationTest): 라운드 횟수가 많은 테스트 코드 작성
korean5078 Nov 1, 2023
f0b8ec6
test(ApplicationTest): 기능 명세서 기능 별 테스트 코드 작성
korean5078 Nov 1, 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
23 changes: 23 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# 기능 명세서

## 자동차

- [x] 게임 라운드마다 0-9까지 랜덤 값을 구한다
- [x] 0부터 3이 나오면 멈추고 4부터 9가 나오면 전진한다
- [x] 이름을 부여할 수 있다
- [x] 이름과 거리를 `-`로 출력할 수 있다

## 플레이어

- [x] 각 자동차에 부여할 이름을 최대 5자까지 입력할 수 있다
- [x] 이름이 5자 이상 입력된 경우 `IllegalArgumentException`을 발생한다
- [x] 자동차들이 몇 번의 이동을 할 것 인지 입력할 수 있다

## 자동차 경주 게임

- [x] 플레이어에게 이름을 입력받으면 받은 수만큼 자동차 객체를 생성한다
- [x] 플레이어에게 입력받은 라운드 횟수만큼 게임을 실행한다.
- [x] 자동차가 전진 또는 멈춘다.
- [x] 해당 라운드마다 자동차들의 이름과 이동 횟수를 `-`로 출력한다
- [x] 라운드가 모두 끝나면 최종 우승자를 출력한다 (여러 명일 경우 `,`를 사용해서 모두 출력)
- [x] 모든 라운드 합계 가장 이동한 수가 많은 자동차를 최종 우승자로 선정한다
6 changes: 6 additions & 0 deletions src/main/java/racingcar/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package racingcar;

import racingcar.domain.Player;
import racingcar.domain.RacingCarGame;

public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
Player player = new Player();
RacingCarGame racingCarGame = new RacingCarGame(player);
racingCarGame.init();
}
}
44 changes: 44 additions & 0 deletions src/main/java/racingcar/domain/Player.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package racingcar.domain;

import camp.nextstep.edu.missionutils.Console;
import java.util.ArrayList;
import java.util.List;

public class Player {
public List<String> inputNames() throws IllegalArgumentException {
System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)");

List<String> names = new ArrayList<>();
String input = Console.readLine();

validateLine(input);
for (String name : input.split(",")) {
validateName(name);
names.add(name);
}

return names;
}

private void validateLine(String line) throws IllegalArgumentException {
if (line.substring(line.length() - 1).equals(",")) {
throw new IllegalArgumentException();
}
}

private void validateName(String name) throws IllegalArgumentException {
if (name.length() > 5) {
throw new IllegalArgumentException();
}
}

public int inputNumberOfRounds() throws IllegalArgumentException {
System.out.println("시도할 회수는 몇회인가요?");
String input = Console.readLine();
try {
return Integer.parseInt(input);
} catch (NumberFormatException e) {
throw new IllegalArgumentException();
}
}
}
36 changes: 36 additions & 0 deletions src/main/java/racingcar/domain/RacingCar.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package racingcar.domain;

import camp.nextstep.edu.missionutils.Randoms;

public class RacingCar {
private final String name;
public int randomNumber;
public int distance;

public RacingCar(String name) {
this.name = name;
}

private void makeRandomNumber() {
this.randomNumber = Randoms.pickNumberInRange(0, 9);
}

public void goOrStop() {
makeRandomNumber();
if (this.randomNumber >= 4) {
this.distance++;
}
}

public void printDistance() {
System.out.print(this.name + " : ");
for (int i = 0; i < distance; i++) {
System.out.print("-");
}
System.out.println();
}

public String getName() {
return this.name;
}
}
87 changes: 87 additions & 0 deletions src/main/java/racingcar/domain/RacingCarGame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package racingcar.domain;

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

public class RacingCarGame {
private final Player player;

public RacingCarGame(Player player) {
this.player = player;
}

public List<RacingCar> createRacingCars(List<String> carNames) {
List<RacingCar> racingCars = new ArrayList<>();

for (int i = 0; i < carNames.size(); i++) {
racingCars.add(new RacingCar(carNames.get(i)));
}

return racingCars;
}

public void roundStart(List<RacingCar> cars) {
for (RacingCar car : cars) {
car.goOrStop();
}
}

public void printRoundScore(List<RacingCar> cars) {
for (RacingCar car : cars) {
car.printDistance();
}
}

public List<RacingCar> chooseWinner(List<RacingCar> cars) {
List<RacingCar> winners = new ArrayList<>();
int max = getHighestDistance(cars);

for (RacingCar car : cars) {
if (car.distance == max) {
winners.add(car);
}
}

return winners;
}

public int getHighestDistance(List<RacingCar> cars) {
cars.sort(new Comparator<RacingCar>() {
@Override
public int compare(RacingCar o1, RacingCar o2) {
return o1.distance - o2.distance;
}
});

return cars.get(cars.size() - 1).distance;
}

public void printWinnerName(List<RacingCar> winners) {
System.out.print("최종 우승자 : ");

for (int i = 0; i < winners.size(); i++) {
System.out.print(winners.get(i).getName());
if (i != winners.size() - 1) {
System.out.print(",");
}
}
}

public void startGameRounds(List<RacingCar> cars, int numberOfRounds) {
for (int i = 0; i < numberOfRounds; i++) {
roundStart(cars);
printRoundScore(cars);
System.out.println();
}
}

public void init() {
List<RacingCar> cars = createRacingCars(player.inputNames());
int numberOfRounds = player.inputNumberOfRounds();
System.out.println();
System.out.println("실행 결과");
startGameRounds(cars, numberOfRounds);
printWinnerName(chooseWinner(cars));
}
}
90 changes: 90 additions & 0 deletions src/test/java/racingcar/ApplicationTest.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package racingcar;

import camp.nextstep.edu.missionutils.test.NsTest;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
import racingcar.domain.Player;
import racingcar.domain.RacingCar;
import racingcar.domain.RacingCarGame;

import static camp.nextstep.edu.missionutils.test.Assertions.assertRandomNumberInRangeTest;
import static camp.nextstep.edu.missionutils.test.Assertions.assertSimpleTest;
Expand All @@ -23,6 +28,63 @@ class ApplicationTest extends NsTest {
);
}

@Test
void 전진_정지_5라운드() {
assertRandomNumberInRangeTest(
() -> {
run("pobi,철수,pobi2", "5");
assertThat(output()).contains("pobi : --", "철수 : -", "pobi2 : --", "최종 우승자 : pobi,pobi2");
},
MOVING_FORWARD, STOP, MOVING_FORWARD,
STOP, STOP, MOVING_FORWARD,
MOVING_FORWARD, MOVING_FORWARD, STOP
);
}

@Test
void 자동차_이름_확인() {
String name = "pobi";
RacingCar car = new RacingCar(name);
assertThat(car.getName()).isEqualTo(name);
}

@Test
void 자동차_전진() {
assertRandomNumberInRangeTest(
() -> {
RacingCar racingCar = new RacingCar("test");
racingCar.goOrStop();
assertThat(racingCar.distance).isEqualTo(1);
},
MOVING_FORWARD
);
}

@Test
void 자동차_정지() {
assertRandomNumberInRangeTest(
() -> {
RacingCar racingCar = new RacingCar("test");
racingCar.goOrStop();
assertThat(racingCar.distance).isEqualTo(0);
},
STOP
);
}

@Test
void 자동차_이름_거리_출력() {
assertRandomNumberInRangeTest(
() -> {
RacingCar racingCar = new RacingCar("pobi");
racingCar.goOrStop();
racingCar.printDistance();
assertThat(output()).contains("pobi : -");
},
MOVING_FORWARD
);
}

@Test
void 이름에_대한_예외_처리() {
assertSimpleTest(() ->
Expand All @@ -31,6 +93,34 @@ class ApplicationTest extends NsTest {
);
}

@Test
void 이름에_대한_예외_처리2() {
assertSimpleTest(() ->
assertThatThrownBy(() -> runException("pobi,java,", "1"))
.isInstanceOf(IllegalArgumentException.class)
);
}

@Test
void 자동차_객체_생성() {
RacingCarGame racingCarGame = new RacingCarGame(new Player());
List<String> testNames = new ArrayList<>();
testNames.add("pobi");
testNames.add("june");
List<RacingCar> cars = racingCarGame.createRacingCars(testNames);
assertThat(cars.size()).isEqualTo(2);
}

@Test
void 자동차_게임_라운드_시작_및_결과_출력() {
RacingCarGame racingCarGame = new RacingCarGame(new Player());
List<RacingCar> cars = new ArrayList<>();
cars.add(new RacingCar("abc"));
cars.add(new RacingCar("def"));
racingCarGame.startGameRounds(cars, 3);
assertThat(output()).contains("abc : ", "def : ");
}

@Override
public void runMain() {
Application.main(new String[]{});
Expand Down