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

[자동차 경주 게임] 김규철 미션 제출합니다. #370

Closed
wants to merge 33 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
16b77bf
docs(readme): 기능 구현 목록 정리
Gyuchool Dec 4, 2021
424077d
feat(car): 자동차 이름과 위치를 반환하는 기능 구현
Gyuchool Dec 4, 2021
1810059
feat(car): 0~9까지 랜덤 값중 4이상이면 전진하는 기능 구현
Gyuchool Dec 4, 2021
9f4c582
feat(raceStadium): 경기장 클래스 생성
Gyuchool Dec 4, 2021
2cd1356
feat: inputView생성 및 패키지 정리
Gyuchool Dec 4, 2021
a4013b6
feat(inputView): 자동차 이름을 입력 받는 기능 구현
Gyuchool Dec 4, 2021
d10c34f
feat(inputView): 시도할 횟수를 입력 받는 기능 구현
Gyuchool Dec 4, 2021
1497530
feat(cars): 자동차를 관리하는 클래스 생성
Gyuchool Dec 4, 2021
1205b35
feat(exception): 유저 인풋이 ','로 끝나면 예외 처리
Gyuchool Dec 4, 2021
3e0f082
feat(exception): 중복되는 이름 예외 처리
Gyuchool Dec 4, 2021
c021dbf
feat(exception): 6자 이상인 자동차 이름 예외 처리
Gyuchool Dec 4, 2021
7d5cadf
docs(readme): 자동차 이름에 빈칸 입력되었을때 예외 처리 추가 및 자동차 개수에 따른 예외 처리 수정
Gyuchool Dec 4, 2021
89bd488
feat(exception): 자동차 이름에 빈칸이 입력되었을때 예외 처리
Gyuchool Dec 4, 2021
115b3a4
refactor(exception): 변수명 가독성 좋게 변화 및 예외 반환하도록 처리
Gyuchool Dec 4, 2021
aa9955b
feat: 에러 출력후 다시 입력받을수 있도록 기능 구현
Gyuchool Dec 4, 2021
587dba6
feat(exception): 자동차가 1개 이하일때, 예외 처리
Gyuchool Dec 4, 2021
d6d108b
test(cars): 입력값에 따라 join로직 정상 작동 테스트
Gyuchool Dec 4, 2021
2aecc01
feat(exception): 정수가 아닌 시도횟수 입력이면 예외 처리
Gyuchool Dec 4, 2021
6608bc5
feat(exception): 0이하 입력은 예외 처리
Gyuchool Dec 4, 2021
80d11a9
feat:(outputView): 매 횟수마다 자동차들의 이름과 위치를 출력하는 기능 구현
Gyuchool Dec 4, 2021
78fd246
feat(winner): 우승자를 결정하는 기능 구현
Gyuchool Dec 4, 2021
6e7d56c
feat: 우승자가 2명 이상일 경우에는 쉼표로 구분해서 출력하는 기능 구현
Gyuchool Dec 4, 2021
45f2170
style: convention 적용
Gyuchool Dec 4, 2021
e26026c
style: convnetion에 맞게 수정
Gyuchool Dec 4, 2021
1c53858
feat: 우승자 반환할때 dto를 통해서 반환하도록 구현
Gyuchool Dec 4, 2021
3eddfd8
refactor(winnerDto): 맴버 변수 초기화
Gyuchool Dec 4, 2021
05be3de
refactor(cars): lamda함수 간결화
Gyuchool Dec 4, 2021
ee19aee
refactor: 가독성 좋은 이름으로 변수이름 변경 및 convetion에 맞게 줄 조정
Gyuchool Dec 4, 2021
621d939
docs(readme): 프로그래밍 요구 사항 check
Gyuchool Dec 5, 2021
0f1d94f
refactor(exception): 가독성 좋게 상수 이름 변경 및 validNumber함수 간결화
Gyuchool Dec 5, 2021
daf5aef
refactor(cars): 비즈니스에 종속적인 자료구조로 구현 및 그에 따른 테스트코드 수정
Gyuchool Dec 5, 2021
09c9b8f
fix: 에러 발생하면 다시 입력받도록 수정
Gyuchool Dec 5, 2021
8738b1e
docs(readme): README.md 파일 디렉토리 위치 변경
Gyuchool Dec 6, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
41 changes: 22 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@
## ✉️ 미션 제출 방법

- 미션 구현을 완료한 후 GitHub을 통해 제출해야 한다.
- GitHub을 활용한 제출 방법은 [프리코스 과제 제출 문서](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse) 를 참고해 제출한다.
- GitHub을 활용한 제출 방법은 [프리코스 과제 제출 문서](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse) 를 참고해
제출한다.
- GitHub에 미션을 제출한 후 [우아한테크코스 지원 플랫폼](https://apply.techcourse.co.kr) 에 접속하여 프리코스 과제를 제출한다.
- 자세한 방법은 [링크](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse#제출-가이드) 를 참고한다.
- **Pull Request만 보내고, 지원 플랫폼에서 과제를 제출하지 않으면 최종 제출하지 않은 것으로 처리되니 주의한다.**
- 자세한 방법은 [링크](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse#제출-가이드) 를 참고한다.
- **Pull Request만 보내고, 지원 플랫폼에서 과제를 제출하지 않으면 최종 제출하지 않은 것으로 처리되니 주의한다.**

## ✔️ 과제 제출 전 체크리스트 - 0점 방지

- 터미널에서 `java -version`을 실행해 자바 8인지 확인한다. 또는 Eclipse, IntelliJ IDEA와 같은 IDE의 자바 8로 실행하는지 확인한다.
- 터미널에서 맥 또는 리눅스 사용자의 경우 `./gradlew clean test`, 윈도우 사용자의 경우 `gradlew.bat clean test` 명령을 실행했을 때 모든 테스트가 아래와 같이 통과하는지 확인한다.
- 터미널에서 맥 또는 리눅스 사용자의 경우 `./gradlew clean test`, 윈도우 사용자의 경우 `gradlew.bat clean test` 명령을 실행했을 때 모든 테스트가 아래와 같이 통과하는지
확인한다.

```
BUILD SUCCESSFUL in 0s
Expand Down Expand Up @@ -123,21 +125,21 @@ jun : -----
- 프로그램을 실행하는 시작점은 `Application`의 `main()`이다.
- JDK 8 버전에서 실행 가능해야 한다. **JDK 8에서 정상 동작하지 않을 경우 0점 처리**한다.
- 자바 코드 컨벤션을 지키면서 프로그래밍한다.
- https://naver.github.io/hackday-conventions-java
- https://naver.github.io/hackday-conventions-java
- indent(인덴트, 들여쓰기) depth를 3이 넘지 않도록 구현한다. 2까지만 허용한다.
- 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다.
- 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메소드)를 분리하면 된다.
- 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다.
- 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메소드)를 분리하면 된다.
- 3항 연산자를 쓰지 않는다.
- 함수(또는 메소드)가 한 가지 일만 하도록 최대한 작게 만들어라.
- 프로그래밍 요구사항에서 별도로 변경 불가 안내가 없는 경우 파일 수정과 패키지 이동을 자유롭게 할 수 있다.

### 추가된 요구사항

- 함수(또는 메소드)의 길이가 15라인을 넘어가지 않도록 구현한다.
- 함수(또는 메소드)가 한 가지 일만 잘 하도록 구현한다.
- 함수(또는 메소드)가 한 가지 일만 잘 하도록 구현한다.
- else 예약어를 쓰지 않는다.
- 힌트: if 조건절에서 값을 return하는 방식으로 구현하면 else를 사용하지 않아도 된다.
- else를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다.
- 힌트: if 조건절에서 값을 return하는 방식으로 구현하면 else를 사용하지 않아도 된다.
- else를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다.

### 프로그래밍 요구사항 - Car 객체

Expand All @@ -148,22 +150,22 @@ jun : -----

```java
public class Car {
private final String name;
private int position = 0;
private final String name;
private int position = 0;

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

// 추가 기능 구현
// 추가 기능 구현
}
```

### 프로그래밍 요구사항 - Randoms, Console

- JDK에서 기본 제공하는 Random, Scanner API 대신 `camp.nextstep.edu.missionutils`에서 제공하는 `Randoms`, `Console` API를 활용해 구현해야 한다.
- Random 값 추출은 `camp.nextstep.edu.missionutils.Randoms`의 `pickNumberInRange()`를 활용한다.
- 사용자가 입력하는 값은 `camp.nextstep.edu.missionutils.Console`의 `readLine()`을 활용한다.
- Random 값 추출은 `camp.nextstep.edu.missionutils.Randoms`의 `pickNumberInRange()`를 활용한다.
- 사용자가 입력하는 값은 `camp.nextstep.edu.missionutils.Console`의 `readLine()`을 활용한다.
- 프로그램 구현을 완료했을 때 `src/test/java` 디렉터리의 `ApplicationTest`에 있는 모든 테스트 케이스가 성공해야 한다. **테스트가 실패할 경우 0점 처리한다.**

<br>
Expand All @@ -175,7 +177,8 @@ public class Car {
- 미션은 [java-racingcar-precourse](https://github.com/woowacourse/java-racingcar-precourse) 저장소를 Fork/Clone해 시작한다.
- **기능을 구현하기 전에 java-racingcar-precourse/docs/README.md 파일에 구현할 기능 목록을 정리**해 추가한다.
- **Git의 커밋 단위는 앞 단계에서 README.md 파일에 정리한 기능 목록 단위**로 추가한다.
- [AngularJS Commit Message Conventions](https://gist.github.com/stephenparish/9941e89d80e2bc58a153) 참고해 commit log를 남긴다.
- [AngularJS Commit Message Conventions](https://gist.github.com/stephenparish/9941e89d80e2bc58a153) 참고해 commit log를
남긴다.
- 과제 진행 및 제출 방법은 [프리코스 과제 제출 문서](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse) 를 참고한다.

<br>
Expand Down
66 changes: 66 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# 2주차 미션 : 자동차 경주 게임 🏎

```
1. 참가자의 이름을 입력받는다.
2. 경기 횟수를 입력받는다.
3. 경주를 진행한다.
4. 우승자를 결정한다.
5. 우승자를 발표한다.
```

## 💡 의식하기

- [x] 함수의 길이가 15라인을 넘지 않도록 구현한다.
- [x] else 예약어 사용하지 않는다.
- [x] 함수, 클래스를 분리하자 --> 일급 컬렉션을 한번 사용해보자
- [x] indent는 2까지

### 일급 컬렉션을 사용하는 이유는?

- 컬렉션의 불변을 보장한다.
- 상태와 행위를 한 곳에서 관리한다.
- 이름이 있는 컬렉션
- 비지니스에 종속적인 자료구조

적용해보면서 느껴보겠다.

## 🎮 기능 구현 목록

### Car

- [x] 이름을 반환하는 기능 구현
- [x] 현재 위치를 반환하는 기능 구현
- [x] 0~9까지 랜덤 값중 4이상이면 전진하는 기능 구현
- 예외 처리
- [x] 자동차가 1개 이하 일때, 예외 처리(경쟁자가 없으면 경주가 아니기 때문에)
- [x] 자동차 이름에 빈칸이 입력되었을때 예외 처리
- [x] 6자 이상인 자동차 이름 예외 처리
- [x] 중복되는 이름 예외 처리
- [x] 유저 인풋이 ',' 로 끝나면 예외 처리

### Cars

- 컬렉션을 포함한 클래스는 반드시 다른 멤버 변수가 없어야 한다. (일급 컬렉션 조건)
- 자동차를 관리하는 클래스이다.

### RaceStadium

- 전체적인 진행이 일어나는 클래스이다.

### Winner

- [x] 우승자를 결정하는 기능 구현
- [x] 우승자가 여러명일 경우 ','를 이용하여 구분하는 기능 구현

### InputView

- [x] 자동차의 이름을 입력 받는 기능 구현
- [x] 시도할 횟수를 입력 받는 기능 구현
- 예외처리
- [x] 정수가 아니면 예외 처리
- [x] 0 이하 입력은 예외 처리

### OutputView

- [x] 매 횟수마다 자동차들의 이름과 위치를 출력하는 기능 구현
- [x] 우승자가 2명 이상일 경우에는 쉼표로 구분해서 출력하는 기능 구현
10 changes: 7 additions & 3 deletions src/main/java/racingcar/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package racingcar;

import racingcar.controller.RaceStadium;

public class Application {
public static void main(String[] args) {
// TODO 구현 진행
}
public static void main(String[] args) {
// TODO 구현 진행
RaceStadium race = new RaceStadium();
race.start();
}
}
12 changes: 0 additions & 12 deletions src/main/java/racingcar/Car.java

This file was deleted.

36 changes: 36 additions & 0 deletions src/main/java/racingcar/controller/RaceStadium.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package racingcar.controller;

import racingcar.domain.Car;
import racingcar.domain.Cars;
import racingcar.domain.Winner;
import racingcar.dto.WinnerDto;
import racingcar.view.InputView;
import racingcar.view.OutputView;

public class RaceStadium {
private final Cars cars = new Cars();

private int trial;

public void start() {
cars.join(InputView.getInputRaceCar());
trial = InputView.getInputTrial();
racing();
WinnerDto winners = Winner.decision(cars);
OutputView.printWinner(winners);
}

private void racing() {
OutputView.printGameStartMessage();
for (int round = 0; round < trial; round++) {
moveTry();
OutputView.printRacingCurrentSituation(cars);
}
}

private void moveTry() {
for (Car participant : cars.getCars()) {
participant.moveOrStop();
}
}
}
44 changes: 44 additions & 0 deletions src/main/java/racingcar/domain/Car.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package racingcar.domain;

import camp.nextstep.edu.missionutils.Randoms;

public class Car {
private static final int RANDOM_MIN_NUMBER = 0;
private static final int RANDOM_MAX_NUMBER = 9;
private static final int STANDARD = 4;
private final String name;
private int position = 0;

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

// 추가 기능 구현
public String getName() {
return this.name;
}

public int getPosition() {
return this.position;
}

public void moveOrStop() {
if (canGo()) {
position++;
}
}

private boolean canGo() {
if (Randoms.pickNumberInRange(RANDOM_MIN_NUMBER, RANDOM_MAX_NUMBER) >= STANDARD) {
return true;
}
return false;
}

public boolean isSamePosition(int position) {
if (this.position == position) {
return true;
}
return false;
}
}
37 changes: 37 additions & 0 deletions src/main/java/racingcar/domain/Cars.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package racingcar.domain;

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

import racingcar.exception.InputException;
import racingcar.view.InputView;

public class Cars {
List<Car> cars;

public Cars() {
this.cars = new ArrayList<>();
}

public void join(String carNames) {
try {
String[] validCarNames = InputException.isValidCarNames(carNames);
for (String carName : validCarNames) {
cars.add(new Car(carName));
}
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
join(InputView.getInputRaceCar());
}
}

public List<Car> getCars() {
return cars;
}

public Car getCarWithMaxPosition() {
return cars.stream().max(Comparator.comparingInt(Car::getPosition)).get();
}

}
23 changes: 23 additions & 0 deletions src/main/java/racingcar/domain/Winner.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package racingcar.domain;

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

import racingcar.dto.WinnerDto;

public class Winner {
public static WinnerDto decision(Cars cars) {

List<String> winnerList = new ArrayList<>();
Car winner = cars.getCarWithMaxPosition();

List<Car> carList = cars.getCars();
for (Car candidateCar : carList) {
if (candidateCar.isSamePosition(winner.getPosition())) {
winnerList.add(candidateCar.getName());
}
}
return new WinnerDto(winnerList);
}

}
17 changes: 17 additions & 0 deletions src/main/java/racingcar/dto/WinnerDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package racingcar.dto;

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

public class WinnerDto {

private List<String> winnerNames;

public WinnerDto(List<String> names) {
this.winnerNames = new ArrayList<>(names);
}

public List<String> getNames() {
return this.winnerNames;
}
}