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
40 changes: 40 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
## view
#### 입력

- 자동차 이름을 입력받는다.
- 5자 이하만 가능하다.
- 시도할 횟수를 입력받는다.

#### 출력

- 회차 별로 실행 결과를 출력한다.
- 하나 이상의 우승자를 출력한다.

## domain
#### Car

- 자동차 이름
- 자동차 위치
- 자동차 움직임

#### Cars

- 모든 자동차의 정보를 가진다.

#### Name
- 사용할 수 있는 이름인지 검증한다.

#### AttemptNumber

- 시도 가능한 횟수가 몇 번 남았는지 나타낸다.

#### MoveCar

- 0에서 9 사이에서 random 값을 구한 후,
random 값이 4 이상일 경우 전진하고, 3 이하의 값이면 멈춘다.




## controller
- 전체적인 진행을 관리한다.
11 changes: 7 additions & 4 deletions src/main/java/RacingMain.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
public class RacingMain {
import controller.RacingCarController;

import java.io.IOException;

public static void main(String[] args) {
// TODO: MVC 패턴을 기반으로 자동차 경주 미션 구현해보기
System.out.println("Hello, World!");
public class RacingMain {
public static void main(String[] args) throws IOException {
RacingCarController racingCarController = new RacingCarController();
racingCarController.run();
}
}
67 changes: 67 additions & 0 deletions src/main/java/controller/RacingCarController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package controller;

import domain.AttemptNumber;
import domain.Cars;
import domain.RandomNumberGenerator;
import dto.CarDto;
import view.InputView;
import view.OutputView;

import java.io.IOException;
import java.util.List;

public class RacingCarController {

private final RandomNumberGenerator randomNumberGenerator;

public RacingCarController() {
this.randomNumberGenerator = new RandomNumberGenerator();
}

public void run() throws IOException {
Cars cars = getCars();
AttemptNumber attemptNumber = getAttemptNumber();
race(cars, attemptNumber);
printWinners(cars);
}

private Cars getCars() throws IOException {
List<String> carNames = InputView.readCarNames();
try {
return Cars.from(carNames);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
return getCars();
}
}

private AttemptNumber getAttemptNumber() throws IOException {
try {
int number = InputView.readAttemptNumber();
return new AttemptNumber(number);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
return getAttemptNumber();
}
}

private void race(final Cars cars, final AttemptNumber attemptNumber) throws IOException {
OutputView.printResult();
while (attemptNumber.isRemain()) {
attemptNumber.decrease();
cars.moveAll(randomNumberGenerator);
printStatus(cars);
}
}

private void printStatus(final Cars cars) {
List<CarDto> carDtos = CarDto.getInstances(cars);
OutputView.printStatus(carDtos);
}

private void printWinners(final Cars cars) {
Cars winnerCars = cars.findWinners();
List<CarDto> winnerCarDtos = CarDto.getInstances(winnerCars);
OutputView.printWinners(winnerCarDtos);
}
}
30 changes: 30 additions & 0 deletions src/main/java/domain/AttemptNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package domain;

public class AttemptNumber {
private static final String NOT_POSITIVE_INTEGER_MESSAGE = "[ERROR] 시도 회수는 양의 정수여야 합니다.";

private int attemptNumber;

public AttemptNumber(int attemptNumber) {
validate(attemptNumber);
this.attemptNumber = attemptNumber;
}

private void validate(int attemptNumber) {
if (attemptNumber <= 0) {
throw new IllegalArgumentException(NOT_POSITIVE_INTEGER_MESSAGE);
}
}

public void decrease() {
attemptNumber--;
}

public boolean isRemain() {
return attemptNumber != 0;
}

public int getAttemptNumber() {
return attemptNumber;
}
}
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;

public class Car {
public static final int MOVED_LOWER_BOUND = 4;

private final Name name;
private final Position position;

private Car(final String name, final int position) {
this.name = new Name(name);
this.position = new Position(position);
}

public static Car from(final String name) {
return new Car(name, 0);
}

public static Car of(final String name, final int position) {
return new Car(name, position);
}


public void move(final int number) {
if (number >= MOVED_LOWER_BOUND) {
position.increase();
}
}

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

public int getPosition() {
return position.getPosition();
}
}
48 changes: 48 additions & 0 deletions src/main/java/domain/Cars.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package domain;

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

public class Cars {
private final int DEFAULT_POSITION = 0;

private final List<Car> cars;

public Cars(final List<Car> cars) {
this.cars = Collections.unmodifiableList(cars);
}

public static Cars from(final List<String> carNames) {
List<Car> cars = carNames.stream()
.map(Car::from)
.collect(Collectors.toList());
return new Cars(cars);
}

public void moveAll(final RandomNumberGenerator randomNumberGenerator) {
for (Car car : cars) {
int number = randomNumberGenerator.generate();
car.move(number);
}
}

public Cars findWinners() {
int maxPosition = getMaxPosition();
List<Car> winningCars = cars.stream()
.filter(car -> car.getPosition() == maxPosition)
.collect(Collectors.toList());
return new Cars(winningCars);
}

private int getMaxPosition() {
return cars.stream()
.mapToInt(Car::getPosition)
.max()
.orElse(DEFAULT_POSITION);
}

public List<Car> getCars() {
return cars;
}
}
26 changes: 26 additions & 0 deletions src/main/java/domain/Name.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package domain;

public class Name {
private static final String NO_NAME_EXISTS_MESSSGE = "[ERROR] 이름은 반드시 있어야 합니다.";
private static final String INVALID_LENGTH_MESSAGE = "[ERROR] 이름은 5글자까지 가능합니다.";

private final String name;

public Name(final String name) {
validate(name);
this.name = name;
}

private void validate(final String name) {
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException(NO_NAME_EXISTS_MESSSGE);
}
if (name.length() > 5) {
throw new IllegalArgumentException(INVALID_LENGTH_MESSAGE);
}
}

public String getName(){
return name;
}
}
17 changes: 17 additions & 0 deletions src/main/java/domain/Position.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package domain;

public class Position {
private int position;

public Position(final int position) {
this.position = position;
}

public void increase() {
position++;
}

public int getPosition() {
return position;
}
}
7 changes: 7 additions & 0 deletions src/main/java/domain/RandomNumberGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package domain;

public class RandomNumberGenerator {
public int generate() {
return (int)(Math.random() * 10);
}
}
35 changes: 35 additions & 0 deletions src/main/java/dto/CarDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package dto;

import domain.Car;
import domain.Cars;

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

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

private CarDto(final String name, final int position) {
this.name = name;
this.position = position;
}

public static CarDto getInstance(final Car car) {
return new CarDto(car.getName(), car.getPosition());
}

public static List<CarDto> getInstances(final Cars cars) {
return cars.getCars().stream()
.map(CarDto::getInstance)
.collect(Collectors.toList());
}

public String getName() {
return name;
}

public int getPosition() {
return position;
}
}
48 changes: 48 additions & 0 deletions src/main/java/view/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package view;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;

public class InputView {

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

private static final String NOT_INTEGER_MESSAGE = "[ERROR] 입력 값은 정수여야 합니다.";

private static final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));

public static List<String> readCarNames() throws IOException {
System.out.println(READ_CAR_NAME_MESSAGE);
String input = bufferedReader.readLine();
return splitByComma(input);
}

public static List<String> splitByComma(final String input) {
String[] split = input.split(",", -1);
return Arrays.asList(split);
}

public static int readAttemptNumber() throws IOException {
try {
System.out.println(READ_ATTEMPT_NUMBER_MESSAGE);
String input = bufferedReader.readLine();
return parse(input);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
return readAttemptNumber();
}
}

public static int parse(final String input) {
try {
return Integer.parseInt(input);
} catch (NumberFormatException e) {
throw new IllegalArgumentException(NOT_INTEGER_MESSAGE, e);
}
}

}
Loading