Skip to content
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
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,18 @@ out/

### Mac OS ###
.DS_Store
.AppleDouble
.LSOverride

### Eclipse ###
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,31 @@
# java-racingcar-precourse

## ︎⚙️ .gitignore 설정
### "[7기] 프리코스 1주 차 웹 백엔드 피드백"
* "Git으로 관리할 자원을 고려한다" 내용 중, "IntelliJ IDEA의 .idea 폴더와 Eclipse의 .metadata 폴더" 제외

## 🚀 초간단 자동차 경주 게임을 구현한다.
* 주어진 횟수 동안 n대의 자동차는 전진 또는 멈출 수 있다.
* 각 자동차에 이름을 부여할 수 있다. 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다.
* 자동차 이름은 쉼표(,)를 기준으로 구분하며 이름은 5자 이하만 가능하다.
* 사용자는 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다.
* 전진하는 조건은 0에서 9 사이에서 무작위 값을 구한 후 무작위 값이 4 이상일 경우이다.
* 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한 명 이상일 수 있다.
* 우승자가 여러 명일 경우 쉼표(,)를 이용하여 구분한다.
* 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시킨 후 애플리케이션은 종료되어야 한다.

## ︎📝 구현할 기능 목록
### - 경주에 참여하는 자동차 이름을 입력 받기
* 자동차 경주게임에 참여하는 차량의 이름을 입력받는다. 이 때, MVC 구조를 고려한다.
* 사용자에게 전달되는 메시지는 상수를 이용한다.
* 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시킨 후 애플리케이션을 종료한다.
* 자동차 이름의 입력은 쉼표(,)를 기준으로 구분하며 이름은 5자 이하만 가능하다.
* 차량의 대수를 저장소에 저장하고, 저장소에 저장된 개수를 체크하는 테스트코드 작성한다.
### - 자동차 레이싱 시도 회수 입력 받기
* 사용자는 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다.
* 자동차 레이싱 시도 회수 입력값 검증
### - Repository에 여러 자동차 저장
* 저장소를 만들어 경기에 참여하는 차량들을 보관
### - 저장소에 있는 자동차들을 이용해서 레이싱 게임 처리
* 전진하는 조건은 0에서 9 사이에서 무작위 값을 구한 후 무작위 값이 4 이상일 경우이다.
* 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한 명 이상일 수 있다.
5 changes: 4 additions & 1 deletion src/main/java/racingcar/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package racingcar;

import racingcar.controller.RacingcarController;

public class Application {
private static RacingcarController racingcarController = RacingcarController.getInstance();
public static void main(String[] args) {
// TODO: 프로그램 구현
racingcarController.playGame();
}
}
111 changes: 111 additions & 0 deletions src/main/java/racingcar/controller/RacingcarController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package racingcar.controller;

import static camp.nextstep.edu.missionutils.Console.readLine;

import java.util.ArrayList;
import java.util.List;
import racingcar.domain.enums.InterfaceMsg;
import racingcar.domain.enums.ValidationMsg;
import racingcar.dto.RacingCarInitDto;
import racingcar.service.RacingCarService;
import racingcar.service.StringUtilService;
import racingcar.service.ValidatorService;
import racingcar.view.InputView;
import racingcar.view.OutputView;

public class RacingcarController {
private final InputView inputView;
private final ValidatorService validatorService = ValidatorService.getInstance();
private StringUtilService stringUtilService = StringUtilService.getInstance();
private RacingCarService racingCarService = RacingCarService.getInstance();

private List<String> carNameList = new ArrayList<>();
private Integer inputCarRaceTimes = 0;

private final OutputView outputView;

// start: singleton holer
private RacingcarController() {
inputView = new InputView();
outputView = new OutputView();
}

private static class InnerRacingcarController {
private static final RacingcarController INSTANCE = new RacingcarController();
}

public static RacingcarController getInstance() {
return InnerRacingcarController.INSTANCE;
}
// end: singleton holer

public void playGame() {
setCarNameList(validateCarNames(inputView.requestInputCarName()));
setInputCarRaceTimes(validateCarRaceTimes(inputView.requestInputCarRaceTimes()));
initSaveRacingCar();
System.out.println(InterfaceMsg.PRINT_OUT.getValue());
outputView.printCarRacing(racingCarService.playCarRacing());
outputView.printCarRacing(racingCarService.carRacingResult());
}

private List<String> validateCarNames(String inputCarName) throws IllegalArgumentException {
ValidationMsg validationMsg = validatorService.validationCarName(inputCarName);
if (validationMsg != ValidationMsg.PROPER_TYPE) {
throw new IllegalArgumentException(validationMsg.getValue());
}

return stringUtilService.splitByComma(inputCarName);
}

public void setCarNameList(List<String> carNameList) {
this.carNameList = carNameList;
}

public List<String> getCarNameList() {
return carNameList;
}

public void setInputCarRaceTimes(Integer inputCarRaceTimes) {
this.inputCarRaceTimes = inputCarRaceTimes;
}

public Integer getInputCarRaceTimes() {
return inputCarRaceTimes;
}


private Integer validateCarRaceTimes(String inputCarRaceTimes) {
Integer properCarRaceTimes = 0;
try {
properCarRaceTimes = this.properCarRaceTimes(inputCarRaceTimes);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage()); inputCarRaceTimes = requestInputCarRaceTimes();
return validateCarRaceTimes(inputCarRaceTimes);
}
return properCarRaceTimes;
}

private String requestInputCarRaceTimes() {
System.out.print(InterfaceMsg.REQUEST_INPUT_CAR_RACE_TIMES.getValue());
String inputCarRaceTimes = readLine();
System.out.println(inputCarRaceTimes); // Player로부터 자동차 경주의 회수를 입력받음

return inputCarRaceTimes;
}

private Integer properCarRaceTimes(String inputCarRaceTimes) throws IllegalArgumentException {
ValidationMsg validationMsg = validatorService.validationCarRaceTimes(inputCarRaceTimes);
if (validationMsg != ValidationMsg.PROPER_TYPE) {
throw new IllegalArgumentException(validationMsg.getValue());
}
return Integer.valueOf(inputCarRaceTimes);
}

private void initSaveRacingCar() {
RacingCarInitDto racingCarInitDto = RacingCarInitDto.builder()
.carNameList(this.getCarNameList())
.inputCarRaceTimes(this.getInputCarRaceTimes())
.build();
racingCarService.initSaveRacingCar(racingCarInitDto);
}
}
22 changes: 22 additions & 0 deletions src/main/java/racingcar/domain/enums/InterfaceMsg.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package racingcar.domain.enums;

public enum InterfaceMsg {
REQUEST_INPUT_CAR_NAME("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분) "),
REQUEST_INPUT_CAR_RACE_TIMES("시도할 횟수는 몇 회인가요? "),
PRINT_OUT("실행 결과"),
GAME_RESULT("최종 우승자 : ")
;

private String value;
InterfaceMsg(String value) {
this.value = value;
}

public String getKey() {
return name();
}

public String getValue() {
return value;
}
}
23 changes: 23 additions & 0 deletions src/main/java/racingcar/domain/enums/NumberTypeGameRule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package racingcar.domain.enums;

public enum NumberTypeGameRule {
MAX_CAR_NAME_LENGTH(5),
MOVING_FORWARD(4),
MIN_RAMDOM(0),
MAX_RAMDOM(9)
;

private final int value;

NumberTypeGameRule(int value) {
this.value = value;
}

public String getKey() {
return name();
}

public Integer getValue() {
return value;
}
}
26 changes: 26 additions & 0 deletions src/main/java/racingcar/domain/enums/ValidationMsg.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package racingcar.domain.enums;

public enum ValidationMsg {
NULL_TYPE("[ERROR] 입력하신 값은 NULL이 될 수 없습니다."),
EMPTY_TYPE("[ERROR] 자동차 경주 게임에서 사용될 값이 입력되지 않았습니다."),
NEED_MORE_THEN_TWO("[ERROR] 자동차를 2대이상 입력해주세요"),
CAR_NAME_OVER_FIVE("[ERROR] 자동차의 이름은 5자 이하만 가능합니다."),
NOT_DUPLICATE_NAME("[ERROR] 자동차의 이름들은 중복될 수 없습니다."),
NOT_NUMBER("[ERROR] 숫자만 입력해주세요."),
ZERO_TYPE("[ERROR] 자동차 경주 게임에서 사용될 값은 0이 될 수 없습니다."),
PROPER_TYPE("바르게 입력되었습니다.")
;

private String value;
ValidationMsg(String value) {
this.value = value;
}

public String getKey() {
return name();
}

public String getValue() {
return value;
}
}
61 changes: 61 additions & 0 deletions src/main/java/racingcar/domain/racingcar/RacingCar.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package racingcar.domain.racingcar;

import camp.nextstep.edu.missionutils.Randoms;
import java.util.Objects;
import racingcar.domain.enums.ValidationMsg;

public class RacingCar {
private static final int MOVING_FORWARD = 4;
private static final int STOP = 3;

private static final int MIN_RAMDOM = 0;
private static final int MAX_RAMDOM = 9;

private String carName;
private Integer carPosition;

public RacingCar(String carName) {
validateCarName(carName);
this.carName = carName;
this.carPosition = 0;
}

private void validateCarName(String carName) {
if (carName == null || carName.isEmpty() || carName.length() == 0) {
throw new IllegalStateException(ValidationMsg.EMPTY_TYPE.getValue());
}
}

public String getCarName() {
return carName;
}

public Integer getCarPosition() {
return carPosition;
}

private void movingForwardRacingCar() {
this.carPosition++;
}

public void movingForward() {
if (Randoms.pickNumberInRange(MIN_RAMDOM, MAX_RAMDOM) >= MOVING_FORWARD) {
this.movingForwardRacingCar();
}
}

@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
RacingCar racingCar = (RacingCar)o;
return Objects.equals(carName, racingCar.carName);
}

@Override
public int hashCode() {
return Objects.hash(carName);
}
}
61 changes: 61 additions & 0 deletions src/main/java/racingcar/domain/racingcar/RacingCarRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package racingcar.domain.racingcar;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import racingcar.dto.RacingCarDto;

public class RacingCarRepository {
private Map<String, RacingCar> racingCarMap = new LinkedHashMap<>();

// start: Singleton Holder
private RacingCarRepository() {
}

private static class RacingCarRepositoryHoler {
private static final RacingCarRepository RACING_CAR_REPOSITORY = new RacingCarRepository();
}

public static RacingCarRepository getInstance() {
return RacingCarRepositoryHoler.RACING_CAR_REPOSITORY;
}

public void saveRacingCar(String carName) {
racingCarMap.put(carName, new RacingCar(carName));
}

public void initSaveRacingCar(RacingCarDto racingCarDto) {
racingCarMap.put(racingCarDto.getCarName(), new RacingCar(racingCarDto.getCarName()));
}

public void initSaveRacingCar(String carName) {
racingCarMap.put(carName, new RacingCar(carName));
}

public RacingCar getRacingCarByName(String carName) {
return racingCarMap.get(carName);
}

public void movingForwardByName(RacingCarDto racingCarDto) {
racingCarMap.get(racingCarDto.getCarName()).movingForward();
}

public Map<String, RacingCar> getRacingCarMap() {
return racingCarMap;
}

public LinkedHashMap<String, RacingCar> sortRacingCarMapByValueDesc(Map<String, RacingCar> map) {
List<Map.Entry<String, RacingCar>> entryList = new LinkedList<>(map.entrySet());
Collections.sort(entryList, (racingCar, comparedRacingCar) -> comparedRacingCar.getValue().getCarPosition().compareTo(racingCar.getValue().getCarPosition()));
LinkedHashMap<String, RacingCar> racingCarLinkedHashMap = new LinkedHashMap<>();
for (Map.Entry<String, RacingCar> entity : entryList) {
racingCarLinkedHashMap.put(entity.getKey(), entity.getValue());
}

return racingCarLinkedHashMap;
}
}

Loading