Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
102238e
docs: 기능 구현 예정 목록 추가
sanghee0820 Jun 8, 2024
c5bae08
feat: Car클래스 추가
sanghee0820 Jun 9, 2024
83f8853
feat: Track클래스 추가
sanghee0820 Jun 9, 2024
3d510c3
fix: Car클래스 Position 기본값 0으로 변경
sanghee0820 Jun 9, 2024
4893d64
feat: 차량 추가 기능 추가
sanghee0820 Jun 9, 2024
934d248
feat: count(개수)만큼 특정범위(start - end)의 랜덤 값 생성 기능 추가
sanghee0820 Jun 9, 2024
703871a
test: 랜덤값 생성 테스트 추가
sanghee0820 Jun 9, 2024
a228930
feat: 차량 이동 로직 추가
sanghee0820 Jun 9, 2024
76f2c06
feat: CarState 추가
sanghee0820 Jun 9, 2024
2db7082
refactor: 차량 이동 매서드 리턴값 수정
sanghee0820 Jun 9, 2024
dfa2341
feat: winner 목록을 반환하는 로직 추가
sanghee0820 Jun 9, 2024
66031a0
feat: Track생성 기능 추가
sanghee0820 Jun 9, 2024
1a32a54
feat: 단계 진행 기능 추가
sanghee0820 Jun 9, 2024
da7636c
feat: 최종 winner 반환 로직 추가
sanghee0820 Jun 9, 2024
09219ac
test: Car 관련 테스트 추가
sanghee0820 Jun 9, 2024
b3af122
docs: 구현 목록 업데이트
sanghee0820 Jun 9, 2024
7da4ecc
test: Track 클래스 테스트 추가
sanghee0820 Jun 9, 2024
88135a2
refactor: step -> runStep 매서드 이름 변경
sanghee0820 Jun 9, 2024
3165a34
refactor: step -> runStep 매서드 이름 변경
sanghee0820 Jun 9, 2024
01c418d
feat: 차량 리스트 반환 로직 추가
sanghee0820 Jun 9, 2024
876c5dd
feat: Controller 추가
sanghee0820 Jun 9, 2024
ce572c1
feat: 입력값 받기로직 추가
sanghee0820 Jun 10, 2024
82d23d5
feat: CarDTO 추가
sanghee0820 Jun 10, 2024
3757234
feat: 결과값 출력 및 에러 출력 추가
sanghee0820 Jun 10, 2024
abbff33
feat: Controller 입력 및 출력 로직 추가
sanghee0820 Jun 10, 2024
f153323
refactor: 출력값 수정
sanghee0820 Jun 10, 2024
4eb77e5
feat: Application.main() 추가
sanghee0820 Jun 10, 2024
9b559fb
feat: Parser의 패키지 변경
sanghee0820 Jun 10, 2024
3a6be48
feat: Parser의 테스트코드 추가
sanghee0820 Jun 10, 2024
6ae01b8
docs: 구현 목록 업데이트
sanghee0820 Jun 10, 2024
cad6d8e
fix: 테스트 함수 변경
sanghee0820 Jun 10, 2024
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
27 changes: 26 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,26 @@
# java-racingcar-precourse
# java-racingcar-precourse

- [x] 차량 클래스
- [x] 차량 이동
- [x] 유닛 테스팅
- [x] 차량 이름이 5자 이상 일때
- [x] 유닛 테스팅
- [x] 레이싱 트랙
- [x] 경기 참여 차량 저장
- [x] 유닛 테스팅
- [x] 경기 단계 진행 및 단계 결과 반환
- [x] 유닛 테스팅
- [x] 랜덤값 생성 Util
- [x] 특정 범위의 특정 개수의 Random값 생성
- [x] 유닛 테스팅


- [x] 예외 처리
- [x] 게임 시행 횟수 타입
- [x] 유닛 테스팅
- [ ] 게임 시행 횟수가 0 이하일 때
- [x] 유닛 테스팅
- [ ] 게임 이름 입력이 공백일 때
- [x] 유닛 테스팅
- [ ] 게임 입력 시 이름에 공백이 있을 때
- [x] 유닛 테스팅
Empty file removed src/main/java/.gitkeep
Empty file.
11 changes: 11 additions & 0 deletions src/main/java/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import controller.RacingGameController;
import view.InputView;

public class Application {

public static void main(String[] args) {
RacingGameController racingGameController = new RacingGameController();
racingGameController.carInit();
racingGameController.runGame();
}
}
51 changes: 51 additions & 0 deletions src/main/java/controller/RacingGameController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package controller;

import controller.res.CarInfoDto;
import domain.state.CarState;
import java.util.List;
import java.util.stream.Collectors;
import service.RacingGameService;
import view.InputView;
import view.OutputView;

public class RacingGameController {
private final RacingGameService racingGameService;

public RacingGameController() {
this.racingGameService = new RacingGameService();
}
public void carInit(){
while(true){
try{
var carName = InputView.readCarName();
racingGameService.trackInit(carName);
break;
}catch (IllegalArgumentException e){
OutputView.printError(e.getMessage());
}
}

}

public int gameCountInit(){
while(true){
try{
return InputView.readGameCount();
}catch (IllegalArgumentException e){
OutputView.printError(e.getMessage());
}
}
}
public void runGame(){
var gameCount = gameCountInit();

OutputView.printResultOutput();
for(int i = 0; i < gameCount; i++){
racingGameService.runStep();
var cars = racingGameService.getCars();
OutputView.printStep(cars.stream().map(CarInfoDto::toDTO).toList());
}

OutputView.printResult(racingGameService.getWinners().stream().map(CarInfoDto::toDTO).toList());
}
}
25 changes: 25 additions & 0 deletions src/main/java/controller/res/CarInfoDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package controller.res;

import domain.state.CarState;

public class CarInfoDto {
private final String name;
private final int position;

public CarInfoDto(String name, int position) {
this.name = name;
this.position = position;
}

public String getName() {
return name;
}

public int getPosition() {
return position;
}

public static CarInfoDto toDTO(CarState carState){
return new CarInfoDto(carState.getName(), carState.getPosition());
}
}
36 changes: 36 additions & 0 deletions src/main/java/domain/Car.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package domain;

import domain.state.CarState;

public class Car implements CarState {
private String name;
private int position;

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

private void setName(String name){
// ToDo: 다른 이름형식 제한 예정
if(name.length() > 5){
// TODO: ExcessiveParticipantsNameException
throw new IllegalArgumentException("[Error]: 자동차의 이름이 6자 이상입니다.");
}
this.name = name;
}

public String getName() {
return name;
}

public int getPosition() {
return position;
}

public void move(Integer seed){
if(seed > 3){
this.position ++;
}
}
}
49 changes: 49 additions & 0 deletions src/main/java/domain/Track.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package domain;

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

public class Track {
private final List<Car> cars;

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

public void addCar(String carName){
cars.add(new Car(carName));
}
public void runStep(List<Integer> seeds){
validateSeedSize(seeds);
for(int i = 0; i < seeds.size(); i++){
cars.get(i).move(seeds.get(i));
}
}

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

public List<Car> getWinners(){
int maxPosition = 0;

List<Car> winner = new ArrayList<>();
for(Car car : cars){
if(car.getPosition() == maxPosition){
winner.add(car);
continue;
}
if(car.getPosition() > maxPosition){
winner.clear();
maxPosition = car.getPosition();
winner.add(car);
}
}
return winner;
}
private void validateSeedSize(List<Integer> seeds){
if(seeds.size() != cars.size()){
throw new IllegalArgumentException("[ERROR]: Seed 개수가 차량 개수와 일치하지 않습니다");
}
}
}
6 changes: 6 additions & 0 deletions src/main/java/domain/state/CarState.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package domain.state;

public interface CarState {
String getName();
int getPosition();
}
33 changes: 33 additions & 0 deletions src/main/java/service/RacingGameService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package service;

import domain.Track;
import domain.state.CarState;
import java.util.ArrayList;
import java.util.List;
import utils.Randoms;

public class RacingGameService {
private Track track;

public void trackInit(List<String> carNames){
track = new Track();
for(String name : carNames){
track.addCar(name);
}
}

public void runStep(){
track.runStep(
Randoms.pickNumbersInRange(track.getCars().size(), 0, 9)
);
}

public List<CarState> getCars(){
var cars = track.getCars();
return new ArrayList<>(cars);
}
public List<CarState> getWinners(){
var winners = track.getWinners();
return new ArrayList<>(winners);
}
}
11 changes: 11 additions & 0 deletions src/main/java/utils/Console.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package utils;

import java.util.Scanner;

public class Console {
private static final Scanner sc = new Scanner(System.in);

public static String readLine(){
return sc.nextLine();
}
}
53 changes: 53 additions & 0 deletions src/main/java/utils/Parser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package utils;

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

public class Parser {
private static final String INVALID_INPUT_ERROR = "[ERROR]: 이름을 확인할 수 없습니다. 다시 입력해주세요.";
private static final String INVALID_COUNT_ERROR = "[ERROR]: 유효한 숫자를 입력해주세요.";
public static List<String> validateCarNameInput(String input){
try {
validateNameContainsBlank(input);

return Arrays.stream(input.split(", "))
.map(String::trim)
.toList();
} catch (Exception e) {
throw new IllegalArgumentException(e.getMessage());
}
}

private static void validateNameContainsBlank(String input){
if (input == null ||
input.trim().isEmpty() ||
Arrays.stream(input.split(",")).anyMatch(String::isBlank)) {

throw new IllegalArgumentException(INVALID_INPUT_ERROR);
}
}

public static int validateGameCountInput(String input) {
try {
validateGameCountIsPositive(input);
int count = Integer.parseInt(input.trim());
validateGameCountIsPositive(count);

return count;
} catch (NumberFormatException e) {
throw new IllegalArgumentException(INVALID_COUNT_ERROR);
}
}

private static void validateGameCountIsPositive(String input){
if (input == null || input.trim().isEmpty()) {
throw new IllegalArgumentException(INVALID_COUNT_ERROR);
}
}
private static void validateGameCountIsPositive(int count){
if (count <= 0) {
throw new IllegalArgumentException(INVALID_COUNT_ERROR);
}
}

}
28 changes: 28 additions & 0 deletions src/main/java/utils/Randoms.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

public class Randoms {
private static final Random random = ThreadLocalRandom.current();
private Randoms() {
}

public static List<Integer> pickNumbersInRange(final int count, final int start, final int end){
validateRange(start, end);
List<Integer> randomNumbers = new ArrayList<>();
for(int i = 0; i < count; i++){
randomNumbers.add(start + random.nextInt(end - start + 1));
}

return randomNumbers;
}

private static void validateRange(final int start, final int end){
if (start > end) {
throw new IllegalArgumentException(String.format("[Error]: 시작 번호[%d]가 끝 번호[%s] 보다 큽니다.", start, end));
}
}
}
22 changes: 22 additions & 0 deletions src/main/java/view/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package view;

import java.util.List;
import utils.Console;
import utils.Parser;

public class InputView {
private static final String GET_CAR_NAME_REQUEST = "경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)";
private static final String GET_GAME_COUNT_REQUEST = "시도할 회수는 몇회인가요?";

public static List<String> readCarName(){
System.out.println(GET_CAR_NAME_REQUEST);
return Parser.validateCarNameInput(Console.readLine());
}


public static int readGameCount(){
System.out.println(GET_GAME_COUNT_REQUEST);
return Parser.validateGameCountInput(Console.readLine());
}

}
32 changes: 32 additions & 0 deletions src/main/java/view/OutputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package view;

import controller.res.CarInfoDto;
import domain.state.CarState;
import java.util.List;
import java.util.stream.Collectors;

public class OutputView {
private static final String RESULT_OUTPUT = "\n실행결과";
private static final String WINNER_OUTPUT = "최종우승자 : %s\n";
public static void printError(String error){
System.out.println(error + "\n");
}

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

public static void printStep(List<CarInfoDto> cars){
for(CarInfoDto car : cars){
System.out.printf("%s : %s\n", car.getName(), "-".repeat(car.getPosition()));
}
System.out.println();
}

public static void printResult(List<CarInfoDto> cars){
System.out.printf(WINNER_OUTPUT,
cars.stream().map(CarInfoDto::getName)
.collect(Collectors.joining(", ")
));
}
}
Empty file removed src/test/java/.gitkeep
Empty file.
Loading