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

[자동차 경주 미션] 김정우 미션 제출합니다. #2372

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 21 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
## 구현할 기능 목록
### 입력
- [x] 경주에 참여할 자동차들의 목록을 입력 받기
- 자동차 이름은 쉼표(,)를 기준으로 구분한다.
- 각각의 자동차 이름은 5자 이하로 제한한다.
- 한 대 이상의 자동차 이름을 입력하도록 한다.
- 중복되는 자동차 이름은 허용하지 않는다.
- [x] 시도할 횟수를 입력 받기
- 1 이상의 정수를 입력 받도록 한다.
- 입력 받은 수가 정수인지 확인한다.
- 양수인지 확인한다.
### 경주 게임 처리
- [x] 시도 횟수만큼 게임 진행 반복하기
- 매 게임 진행마다 각각의 자동차 별로 0 ~ 9의 무작위 정수값을 생성한다.
- 무작위 정수값이 4 이상인 경우 앞으로 전진하고, 3 이하라면 정지한다.
### 출력
- [x] 매게임 진행 마다 각 자동차의 실행 결과를 출력하기
- 진행 상황은 (-)로 출력한다.
- 진행 상황과 함께 각 자동차의 이름을 출력한다.
- [x] 게임 종료 후, 최종 우승자 출력하기
- 우승자는 2명 이상일 수 있고, 여러 명인 경우 콤마(,)로 구분한다.
12 changes: 11 additions & 1 deletion src/main/java/racingcar/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
package racingcar;

import racingcar.Controller.RacingGame;

import static racingcar.view.OutputView.printErrorMessage;

public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
RacingGame racingGame = new RacingGame();

try {
racingGame.start();
} catch (IllegalArgumentException e) {
printErrorMessage(e.getMessage());
}
}
}
61 changes: 61 additions & 0 deletions src/main/java/racingcar/Controller/RacingGame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package racingcar.Controller;

import racingcar.domain.Car;
import racingcar.domain.Cars;
import racingcar.dto.CarDto;
import racingcar.util.AttemptCount;
import racingcar.util.RandomMoving;
import racingcar.view.OutputView;

import java.util.List;

import static racingcar.view.InputView.setAttempt;
import static racingcar.view.InputView.setCarNames;
import static racingcar.view.OutputView.printLine;
import static racingcar.view.OutputView.printWinners;

public class RacingGame {
private Cars cars;
private AttemptCount gameAttemptCount;
private RandomMoving movingStrategy = new RandomMoving();

public void start() throws IllegalArgumentException {
initRacingCarGame();

while (gameAttemptCount.isContinue()) {
gameAttemptCount.reduceAttemptCount();
run();
}

List<String> winnerNameList = getWinners();
printWinners(winnerNameList);
}

private void initRacingCarGame() throws IllegalArgumentException {
List<String> carNames = setCarNames();
cars = new Cars(carNames);

String attempt = setAttempt();
gameAttemptCount = new AttemptCount(attempt);
}

private void run() {
cars.progressWithAllCar(movingStrategy);
printProgress();
printLine();
}

private void printProgress() {
for (int i = 0; i < cars.getSize(); i++) {
Car car = cars.getCar(i);

OutputView.printProgress(CarDto.of(car));
}
}

private List<String> getWinners() {
int maxPosition = cars.getMaxPosition();

return cars.getWinner(maxPosition);
}
}
32 changes: 32 additions & 0 deletions src/main/java/racingcar/domain/Car.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package racingcar.domain;

import racingcar.util.RandomMoving;

public class Car {
private final CarName carName;
private int position = 0;
public Car(String name) {
this.carName = new CarName(name);
}

public String getName() {
return carName.getName();
}

public int getPosition() {
return position;
}

public void progress(RandomMoving movingStrategy) {
if (movingStrategy.isMovable()) {
position++;
}
}

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

public class CarName {

private final String name;
public CarName(String name) {
checkCarName(name);
this.name = name;
}

public String getName() {
return name;
}

private void checkCarName(String carName) {
if (carName == null) {
throw new IllegalArgumentException("err: 자동차 이름은 null이 될 수 없습니다.");
}

checkCarNameLength(carName);
}

private void checkCarNameLength(String carName) {
if (carName.length() < 1) {
throw new IllegalArgumentException("err: 자동차 이름은 한 글자 이상이어야 합니다.");
}
if (carName.length() > 5) {
throw new IllegalArgumentException("err: 자동차 이름은 다섯 글자 이하만 가능합니다.");
}
}
}
61 changes: 61 additions & 0 deletions src/main/java/racingcar/domain/Cars.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package racingcar.domain;

import racingcar.util.RandomMoving;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;

public class Cars {
private List<Car> cars;

public Cars(List<String> carNames) {
initCar(carNames);
}

public int getMaxPosition() {
cars.sort((o1, o2) -> o2.getPosition() - o1.getPosition());

return cars.get(0).getPosition();
}

public List<String> getWinner(int position) {
return cars.stream()
.filter(car -> car.isSamePosition(position))
.map(car -> car.getName())
.collect(Collectors.toList());
}

public void progressWithAllCar(RandomMoving movingStrategy) {
for (Car car : cars) {
car.progress(movingStrategy);
}
}

public int getSize() {
return cars.size();
}

public Car getCar(int index) {
return cars.get(index);
}

private void initCar(List<String> carNames) throws IllegalArgumentException {
checkDuplication(carNames);

cars = new ArrayList<>();

for (String name : carNames) {
cars.add(new Car(name));
}
}

private void checkDuplication(List<String> carNames) {
HashSet<String> hashSet = new HashSet<>(carNames);

if (hashSet.size() < carNames.size()) {
throw new IllegalArgumentException("err: 자동차 이름이 중복되면 안됩니다.");
}
}
}
26 changes: 26 additions & 0 deletions src/main/java/racingcar/dto/CarDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package racingcar.dto;

import racingcar.domain.Car;

public class CarDto {

private final String carName;
private final int position;

public CarDto(String carName, int position) {
this.carName = carName;
this.position = position;
}

public String getCarName() {
return carName;
}

public int getPosition() {
return position;
}

public static CarDto of(Car car) {
return new CarDto(car.getName(), car.getPosition());
}
}
38 changes: 38 additions & 0 deletions src/main/java/racingcar/util/AttemptCount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package racingcar.util;

public class AttemptCount {
private int totalAttemptCount;
public AttemptCount(String totalAttemptCount) {
this.totalAttemptCount = checkTranslateInteger(totalAttemptCount);
checkPositiveNumber(this.totalAttemptCount);
}

public int getTotalAttemptCount() {
return totalAttemptCount;
}

public boolean isContinue() {
if (totalAttemptCount == 0) {
return false;
}

return true;
}

public void reduceAttemptCount() {
totalAttemptCount = totalAttemptCount - 1;
}

private int checkTranslateInteger(String attempt) {
try {
return Integer.parseInt(attempt);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("err: 시도 횟수는 숫자여야 합니다.");
}
}
private void checkPositiveNumber(int number) {
if (number <= 0) {
throw new IllegalArgumentException("err: 양수를 입력해주세요.");
}
}
}
15 changes: 15 additions & 0 deletions src/main/java/racingcar/util/RandomMoving.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package racingcar.util;

import camp.nextstep.edu.missionutils.Randoms;

public class RandomMoving {
public boolean isMovable() {
int randomNumber = getRandomNumber();

return randomNumber >= 4;
}

private static int getRandomNumber() {
return Randoms.pickNumberInRange(0,9);
}
}
26 changes: 26 additions & 0 deletions src/main/java/racingcar/view/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package racingcar.view;

import camp.nextstep.edu.missionutils.Console;

import java.util.Arrays;
import java.util.List;

public class InputView {

private static final String SEPARATOR = ",";
private InputView() {}

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

String input = Console.readLine();
List<String> carNames = Arrays.asList(input.split(SEPARATOR));

return carNames;
}

public static String setAttempt() {
System.out.println("시도할 회수는 몇회인가요?");
return Console.readLine();
}
}
40 changes: 40 additions & 0 deletions src/main/java/racingcar/view/OutputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package racingcar.view;

import racingcar.dto.CarDto;

import java.util.List;

public class OutputView {

private static final String DELIMITER = ", ";
private static final String PROGRESS_SYMBOL = "-";

private OutputView() {}

public static void startMessage() {
printLine();
System.out.println("실행 결과");
}

public static void printLine() {
System.out.println();
}

public static void printProgress(CarDto car) {
String carName = car.getCarName();
int position = car.getPosition();

String positionSign = PROGRESS_SYMBOL.repeat(position);

System.out.println(carName + " : " + positionSign);
}

public static void printWinners(List<String> winners) {
System.out.print(String.join(DELIMITER, winners));
System.out.println("가 최종 우승했습니다.");
}

public static void printErrorMessage(String errorMessage) {
System.out.println(errorMessage);
}
}