diff --git a/README.md b/README.md index 491aece1..941aa82c 100644 --- a/README.md +++ b/README.md @@ -1 +1,17 @@ -# java-racingcar-precourse \ No newline at end of file +# java-racingcar-precourse + +### 기능 요구사항 목록 +- [x] 자동차 이름 입력받기 + - [x] 쉼표(,)로 입력 받은 이름 구분하기 + - [x] 각 이름 5자 이하의 이름인지 검사하기 +- [x] 이동 횟수 입력 받기 + - [x] 입력 값이 숫자인지 검사하기 + - [x] 입력 값이 자연수 인지 검사하기 +- [x] 자동차 전진하기 + - [x] 입력 횟수 만큼 자동차 전진하기 + - [x] 0 ~ 9 사이의 무작위 값 구하기 + - [x] 무작위 값이 4 이상 인 경우 전진하기 +- [x] 각 횟수별로 전진 한 결과 출력하기 +- [x] 우승자 출력하기 + - [x] 우승자가 여러명일 경우 쉼표(,)로 구분해서 출력하기 + - [x] 우승자 찾기 \ No newline at end of file diff --git a/src/main/java/Application.java b/src/main/java/Application.java new file mode 100644 index 00000000..c829182b --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,11 @@ +import controller.RacingCarGame; +import java.io.IOException; + +public class Application { + + private static final RacingCarGame racingCarGame = new RacingCarGame(); + + public static void main(String[] args) throws IOException { + racingCarGame.racingGame(); + } +} \ No newline at end of file diff --git a/src/main/java/controller/RacingCarGame.java b/src/main/java/controller/RacingCarGame.java new file mode 100644 index 00000000..68395a26 --- /dev/null +++ b/src/main/java/controller/RacingCarGame.java @@ -0,0 +1,87 @@ +package controller; + +import java.util.ArrayList; +import model.Car; +import view.InputView; +import view.OutputView; + +public class RacingCarGame { + + private final InputView inputView = new InputView(); + private final OutputView outputView = new OutputView(); + private final int MAX_NAME_LENGTH = 5; + + public void racingGame() { + ArrayList cars = new ArrayList<>(); + input(cars); + System.out.println(); + output(cars); + } + + private ArrayList input(ArrayList cars) throws IllegalArgumentException { + inputView.inputName(); + + for (String name : inputView.getCarNames()) { + if (!checkNameLength(name)) { + return input(cars); + } + cars.add(new Car(name)); + } + + System.out.println("시도할 회수는 몇회인가요?"); + while (!inputView.inputIteration()) { + } + return cars; + } + + public boolean checkNameLength(String name) { + try { + if (name.length() > MAX_NAME_LENGTH) { + throw new IllegalArgumentException(); + } + } catch (IllegalArgumentException e) { + System.out.println( + "[ERROR] : 이름은 " + MAX_NAME_LENGTH + "자 이하만 가능합니다." + name + " 부분부터 다시 입력해 주세요."); + return false; + } + + return true; + } + + public void output(ArrayList cars) { + outputView.showExecutionResult(); + + for (int i = 0; i < inputView.getIteration(); i++) { + for (Car car : cars) { + car.moveForward(); + outputView.showCarMove(car); + } + System.out.println(); + } + + findWinner(cars); + outputView.showWinner(cars); + } + + public void findWinner(ArrayList cars) { + int furthestDistance = findFurthestDistance(cars); + + for (Car car : cars) { + if (car.getDistance() == furthestDistance) { + car.setWinner(true); + } + } + } + + public int findFurthestDistance(ArrayList cars) { + int furthestDistance = 0; + for (Car car : cars) { + if (car.getDistance() > furthestDistance) { + furthestDistance = car.getDistance(); + } + } + + return furthestDistance; + } + +} diff --git a/src/main/java/model/Car.java b/src/main/java/model/Car.java new file mode 100644 index 00000000..3b223d3e --- /dev/null +++ b/src/main/java/model/Car.java @@ -0,0 +1,49 @@ +package model; + +import java.util.Random; + +public class Car { + + private String name; + private int distance = 0; + private boolean winner = false; + + public Car(String name) { + setName(name); + } + + public void setName(String name) { + this.name = name; + } + + public void setDistance(int distance) { + this.distance = distance; + } + + public void setWinner(boolean isWin) { + this.winner = isWin; + } + + public String getName() { + return this.name; + } + + public int getDistance() { + return this.distance; + } + + public boolean isWinner() { + return this.winner; + } + + public void moveForward() { + Random random = new Random(); + + int distance = random.nextInt(0, 10); + + if (distance > 3) { + setDistance(this.distance + 1); + } + } + +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 00000000..048a33c3 --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,41 @@ +package view; + +import java.util.InputMismatchException; +import java.util.Scanner; + +public class InputView { + + private String[] carNames; + private int iteration; + + public void inputName() { + Scanner scanner = new Scanner(System.in); + System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"); + this.carNames = scanner.nextLine().split("\\s*,\\s*"); + } + + public boolean inputIteration() { + Scanner scanner = new Scanner(System.in); + try { + int iteration = scanner.nextInt(); + if (iteration < 1) { + throw new IllegalArgumentException("[ERROR] : 시도할 회수는 자연수만 입력 가능합니다. 다시 입력 해주세요."); + } + this.iteration = iteration; + return true; + } catch (InputMismatchException | IllegalArgumentException e) { // 올바르지 않은 값을 입력 받은 경우 + System.out.println("[ERROR] : 시도할 회수는 자연수만 입력 가능합니다. 다시 입력 해주세요."); + return false; + } + } + + + public String[] getCarNames() { + return this.carNames; + } + + public int getIteration() { + return this.iteration; + } + +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 00000000..0126b70b --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,32 @@ +package view; + +import java.util.ArrayList; +import model.Car; + +public class OutputView { + + public void showExecutionResult() { + System.out.println("실행 결과"); + } + + public void showCarMove(Car car) { + int distance = car.getDistance(); + String name = car.getName(); + + System.out.println(name + " : " + ("-".repeat(distance))); + } + + public void showWinner(ArrayList cars) { + ArrayList winners = new ArrayList<>(); + + for (Car car : cars) { + if (car.isWinner()) { + winners.add(car.getName()); + } + } + + String winnersName = String.join(",", winners); + + System.out.println("최종 우승자 : " + winnersName); + } +} diff --git a/src/test/java/controller/RacingCarGameTest.java b/src/test/java/controller/RacingCarGameTest.java new file mode 100644 index 00000000..536fa476 --- /dev/null +++ b/src/test/java/controller/RacingCarGameTest.java @@ -0,0 +1,55 @@ +package controller; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import model.Car; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class RacingCarGameTest { + + private RacingCarGame racingCarGame = new RacingCarGame(); + + @Test + @DisplayName("이름이 5자 넘는 경우 테스트") + void checkNameLength_이름이_5자_초과() { + // given + String name = "abcdef"; + // when + boolean actual = racingCarGame.checkNameLength(name); + // then + assertEquals(false, actual); + } + + @Test + @DisplayName("이름이 5자 이하로 알맞게 들어온 경우 테스트") + void checkNameLength_이름이_5자_이하() { + // given + String name = "abcd"; + // when + boolean actual = racingCarGame.checkNameLength(name); + // then + assertEquals(true, actual); + } + + @Test + @DisplayName("우승자 찾기 테스트") + void findWinner() { + // given + ArrayList cars = new ArrayList<>(); + Car winner = new Car("winner"); + winner.setDistance(2); + cars.add(winner); + Car loser = new Car("loser"); + loser.setDistance(1); + cars.add(loser); + //when + racingCarGame.findWinner(cars); + //then + assertEquals(true, winner.isWinner()); + assertEquals(false, loser.isWinner()); + } +} \ No newline at end of file diff --git a/src/test/java/model/CarTest.java b/src/test/java/model/CarTest.java new file mode 100644 index 00000000..6e523b5d --- /dev/null +++ b/src/test/java/model/CarTest.java @@ -0,0 +1,62 @@ +package model; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; + +class CarTest { + + private Car car; + + @BeforeEach + void setCar(){ + car = new Car("test"); + } + + @Test + @DisplayName("이름이 제대로 입력 되는지 테스트") + void getName(){ + assertEquals("test", car.getName()); + } + + @RepeatedTest(100) + @DisplayName("자동차가 한칸씩 전진하는지 테스트") + void moveForward_한칸_전진() { + // given + int beforeDistance = car.getDistance(); + // when + car.moveForward(); + // then + assertTrue(car.getDistance() - beforeDistance == 1 || car.getDistance() == beforeDistance); + } + + @Test + @DisplayName("자동차가 한번에 두칸 이상 전진 테스트") + void moveForward_한번에_두칸_이상_전진(){ + // given + int beforeDistance = car.getDistance(); + // when + car.moveForward(); + // then + assertFalse(car.getDistance() - beforeDistance > 1); + + } + + @Test + @DisplayName("자동차 여러번 전진 테스트") + void moveForward_여러번_전진() { + // given + int beforeDistance = car.getDistance(); + int repeat = 100; + // when + for (int i = 0; i < repeat; i++) { + car.moveForward(); + } + // then + assertTrue(car.getDistance() - beforeDistance >= 0 && car.getDistance() - beforeDistance <= repeat); + } + +} \ No newline at end of file