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

[자동차경주] 박정현 미션 제출합니다. #1475

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
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,18 @@
# java-racingcar-precourse
# 🐣자동차 경주 게임
## 기능 요구 사항
- 주어진 횟수 동안 n대의 자동차는 전진 또는 멈출 수 있다.
- 각 자동차에 이름을 부여할 수 있다. 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다.
- 자동차 이름은 쉼표(,)를 기준으로 구분하며 이름은 5자 이하만 가능하다.
- 사용자는 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다.
- 전진하는 조건은 0에서 9 사이에서 무작위 값을 구한 후 무작위 값이 4 이상일 경우이다.
- 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한 명 이상일 수 있다.
- 우승자가 여러 명일 경우 쉼표(,)를 이용하여 구분한다.
- 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시킨 후 애플리케이션은 종료되어야 한다.

## ✅ 기능 목록
- [X] 쉼표(,)로 구분할 수 있는 {\$자동차 이름 목록}과 {\$게임횟수}를 입력받는다.
- [X] 각 {\$자동차 이름}의 길이가 5 초과일 경우 예외(IllegalArgumentException)로 처리한다.
- [X] 0~9의 범위에서 랜덤으로 불러와 4이상일 경우에만 자동차가 전진한다.
- [X] 게임 라운드별 실행결과를 출력한다.
- [X] 실행결과가 끝나면 우승자를 출력한다. "최종 우승자 : {\$자동차 이름}" 형식으로 출력한다.
- [X] 만약 최종 우승자가 여러 명일 경우 "최종 우승자 : {\$자동차 이름}, {\$자동차 이름}" 과 같이 쉼표로 구분하여 출력한다.
5 changes: 5 additions & 0 deletions src/main/java/racingcar/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package racingcar;


import racingcar.controller.RacingCarController;

public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
RacingCarController racingCarController = new RacingCarController();
racingCarController.race();
}
}
52 changes: 52 additions & 0 deletions src/main/java/racingcar/RacingCar.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package racingcar;

import java.util.*;
import java.util.stream.Collectors;

import camp.nextstep.edu.missionutils.Randoms;

public class RacingCar {
public static final HashMap<String, Integer> carList = new HashMap<>();
public static final String moveString = "-";
public static List<String> Winner = new ArrayList<>();
//public static StringBuilder resultString = new StringBuilder("최종 우승자 : ");

public static void run(final String carNameString, final String roundString){
if (carNameString==null || carNameString.isBlank()){
throw new IllegalArgumentException();
}

if (roundString==null || roundString.isBlank()){
throw new IllegalArgumentException();
}
int round = Integer.parseInt(roundString);

for(final String carNameSplit: carNameString.split(",")){
if (carNameSplit.length()>5){
throw new IllegalArgumentException();
}
carList.put(carNameSplit, 0);
}

System.out.println("실행결과");
for(int i=0; i<round; i++) {
for (String carName : carList.keySet()) {
int randomMove = Randoms.pickNumberInRange(0, 9);
if (randomMove >= 4) {
carList.put(carName, carList.get(carName) + 1);
}
System.out.println(carName + " : " + moveString.repeat(carList.get(carName)));
}
System.out.println();
}

int winValue = Collections.max(carList.values());
List<String> findWinner = carList.entrySet().stream()
.filter(e -> e.getValue() == winValue)
.map(Map.Entry::getKey)
.collect(Collectors.toList());

System.out.println("최종 우승자 : " + String.join(",", findWinner));
}
}

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

import racingcar.service.RacingCarService;
import racingcar.util.InputParser;
import racingcar.view.InputView;
import racingcar.view.OutputView;
import java.util.List;
import java.util.Map;
import static racingcar.service.RacingCarService.*;

public class RacingCarController {

private final InputView inputView;
private final OutputView outputView;
private final RacingCarService service;

public RacingCarController() {
this.inputView = new InputView();
this.outputView = new OutputView();
this.service = new RacingCarService();
}

public void race() {
final String carNameString = getInputCarNameString();
final List<String> carNameList = InputParser.splitCarNameString(carNameString);
final String roundCountString = getInputRoundCount();
final int roundCount = InputParser.getIntRoundCount(roundCountString);

run(carNameList, roundCount);
}

private String getInputCarNameString() {
return inputView.getCarString();
}

private String getInputRoundCount() {
return inputView.getRoundCount();
}

public void run(List<String> carNameList, int roundCount) {
final Map<String, Integer> raceResultList = service.raceAllRound(carNameList, roundCount);
printRaceResult(raceResultList);
}

public void printRaceResult(Map<String, Integer> raceResultList) {
outputView.printResultMessage();
final List<String> winnerList = getWinnerList(raceResultList);
outputView.printWinner(winnerList);
}
}
18 changes: 18 additions & 0 deletions src/main/java/racingcar/exception/ErrorMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package racingcar.exception;

public enum ErrorMessage {
INPUT_MUST_BE_NOT_NULL("공백은 입력할 수 없습니다."),
CAR_NAME_LENGTH_OVER_FIVE("자동차의 이름은 5자 이하여야 합니다."),
CAR_NAME_MUST_UNIQUE("차 이름은 중복할 수 없습니다."),
INPUT_ROUND_COUNT_MUST_BE_NUMERIC("숫자가 아닌 문자가 포함되어 있습니다."),
INPUT_ROUND_COUNT_MUST_BE_POSITIVE("게임의 횟수는 1 이상이어야 합니다.");
private final String message;

ErrorMessage(String message) {
this.message = message;
}

public String getMessage() {
return this.message;
}
}
65 changes: 65 additions & 0 deletions src/main/java/racingcar/service/RacingCarService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package racingcar.service;

import camp.nextstep.edu.missionutils.Randoms;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class RacingCarService {
public static Map<String, Integer> carMap = new HashMap<>();


public static Map<String, Integer> raceAllRound(List<String> carNameList, int roundCount){
Map<String, Integer> carMap = initCarList(carNameList);

for(int i=0; i<roundCount; i++) {
carMap = raceOneRound(carMap);
System.out.println();
}
return carMap;
}

public static Map<String, Integer> initCarList(List<String> carNameList){
for(final String carName: carNameList){
carMap.put(carName, 0);
}
return carMap;
}

public static Map<String, Integer> raceOneRound(Map<String, Integer> carMap) {
for (String carName : carMap.keySet()) {
if (isMove()){
carMap.put(carName, carMap.get(carName) + 1);
printOneRaceResult(carName, carMap.get(carName));
}
}
return carMap;
}

public static boolean isMove(){
int randomMove = Randoms.pickNumberInRange(0, 9);
if (randomMove >= 4) {
return true;
}
else{
return false;
}
}

public static List<String> getWinnerList(Map<String, Integer> carList){
int winValue = Collections.max(carList.values());
List<String> findWinner = carList.entrySet().stream()
.filter(e -> e.getValue() == winValue)
.map(Map.Entry::getKey)
.collect(Collectors.toList());

return findWinner;
}

public static void printOneRaceResult(String carName, int n){
System.out.println(carName + " : " + "-".repeat(n));
}
}
31 changes: 31 additions & 0 deletions src/main/java/racingcar/util/InputParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package racingcar.util;

import racingcar.validator.Validator;

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

import static racingcar.validator.Validator.*;

public class InputParser {

public static List<String> splitCarNameString(String carNameString) {
List<String> carNames = Arrays.stream(carNameString.split(",", -1))
.map(String::trim)
.peek(Validator::carNameStringNotNull)
.peek(Validator::carNameLength)
.toList();
Validator.carNameDuplicated(carNames);

return carNames;
}

public static int getIntRoundCount(String rountCountString) {
roundCountStringNotNull(rountCountString);
isRoundCountNumeric(rountCountString);
final int roundCount = Integer.parseInt(rountCountString);
roundCountPositive(roundCount);

return roundCount;
}
}
50 changes: 50 additions & 0 deletions src/main/java/racingcar/validator/Validator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package racingcar.validator;

import racingcar.exception.ErrorMessage;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Validator {

public static void carNameStringNotNull(String carNameString) {
if (carNameString == null || carNameString.isBlank()) {
throw new IllegalArgumentException(ErrorMessage.INPUT_MUST_BE_NOT_NULL.getMessage());
}
}

public static void carNameLength(String carName) {
if (carName.length() > 5) {
throw new IllegalArgumentException(ErrorMessage.CAR_NAME_LENGTH_OVER_FIVE.getMessage());
}
}

public static void carNameDuplicated(List<String> CarNameList) {
Set<String> uniqueCarNames = new HashSet<>(CarNameList);

if (CarNameList.size() > uniqueCarNames.size()) {
throw new IllegalArgumentException(ErrorMessage.CAR_NAME_MUST_UNIQUE.getMessage());
}
}

public static void roundCountStringNotNull(String roundCountString) {
if (roundCountString == null || roundCountString.isBlank()) {
throw new IllegalArgumentException(ErrorMessage.INPUT_MUST_BE_NOT_NULL.getMessage());
}
}

public static void isRoundCountNumeric(String roundCountString) {
try {
Integer.parseInt(roundCountString);
} catch (NumberFormatException e) {
throw new IllegalArgumentException(ErrorMessage.INPUT_ROUND_COUNT_MUST_BE_NUMERIC.getMessage());
}
}

public static void roundCountPositive(int roundCount) {
if (roundCount < 1) {
throw new IllegalArgumentException(ErrorMessage.INPUT_ROUND_COUNT_MUST_BE_POSITIVE.getMessage());
}
}
}
16 changes: 16 additions & 0 deletions src/main/java/racingcar/view/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package racingcar.view;

import camp.nextstep.edu.missionutils.Console;

public class InputView {

public String getCarString() {
System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)");
return Console.readLine();
}

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

import java.util.List;

public class OutputView {

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

public void printWinner(List<String> winnerList) {
System.out.println("최종 우승자 : " + String.join(",", winnerList));
}
}
Loading