diff --git a/README.md b/README.md index d0286c859f..afdd47c3a6 100644 --- a/README.md +++ b/README.md @@ -1 +1,23 @@ # java-racingcar-precourse + +## 구현할 기능 목록 + +1. RacingManager라는 클래스를 만들어 구체적인 함수들 포함. + 1. RacingManager의 생성자에서 자동차 이름들과 횟수 입력받기 + 2. 자동차이름 ‘,’기준으로 나눠 자동차이름, 전진한 횟수(position)를 멤버 변수로 가진 Car클래스의 객체 리스트에 저장 + 3. 객체 리스트를 하나씩 확인하며 랜덤숫자가 4이상이면 전진한 횟수를 +1시킨다. + 4. 한번의 횟수(스텝)마다 전진한 횟수대로 ‘-’를 생성하여 출력 + 5. 입력한 횟수가 끝나면 전진한 횟수를 비교해 우승자 출력 +2. 예외처리 해주기 + 1. `자동차이름입력값_빈값일때_예외_테스트` + 2. `반복횟수_빈값일때_예외_테스트` + 3. `반복횟수_0일때_예외_테스트` + 4. `반복횟수_음수일때_예외_테스트` + 5. `유효하지않은_구분자_예외_테스트` : ‘,’이외의 구분자가 입력으로 들어왔을 때 + 6. `자동차이름에_숫자_포함돼있을시_예외_테스트` + 7. `자동차이름에_다른구분자_포함돼있을시_예외_테스트` + 8. `구분자가_맨앞에있을때_예외_테스트` + 9. `구분자가_겹쳐있을때_예외_테스트` + 10. `구분자가_맨뒤에있을때_예외_테스트` +3. 예외처리 테스트 +4. 우승자 여러명일 때 테스트 diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java index a17a52e724..61d2d62e79 100644 --- a/src/main/java/racingcar/Application.java +++ b/src/main/java/racingcar/Application.java @@ -1,7 +1,17 @@ package racingcar; +import camp.nextstep.edu.missionutils.Console; +import camp.nextstep.edu.missionutils.Randoms; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + public class Application { public static void main(String[] args) { // TODO: 프로그램 구현 + RacingManager racingManager = new RacingManager(); + racingManager.runRacing(); } } diff --git a/src/main/java/racingcar/Car.java b/src/main/java/racingcar/Car.java new file mode 100644 index 0000000000..0974bcec70 --- /dev/null +++ b/src/main/java/racingcar/Car.java @@ -0,0 +1,23 @@ +package racingcar; + +public class Car { + private String name; + private int POSITION; + + public Car (String name, int position){ + this.name = name; + this.POSITION = position; + } + + public void moveForword(){ + this.POSITION += 1; + } + + public String getName() { + return name; + } + + public int getPosition() { + return POSITION; + } +} diff --git a/src/main/java/racingcar/ExceptionManager.java b/src/main/java/racingcar/ExceptionManager.java new file mode 100644 index 0000000000..14ab316a39 --- /dev/null +++ b/src/main/java/racingcar/ExceptionManager.java @@ -0,0 +1,70 @@ +package racingcar; + +public class ExceptionManager { + + private String input = ""; + private String[] inputCars; + private int NUMBER; + + ExceptionManager(String input, String[] inputCars, int NUMBER){ + this.input = input; + this.inputCars = inputCars; + this.NUMBER = NUMBER; + } + + // 빈값 확인 + private void checkInputCarsIsNull(){ + if(input.equals("")){ + throw new IllegalArgumentException("입력된 값이 없습니다."); + } + } + + // NUMBER 0또는 음수인지 확인 + private void checkWrongInputNumber(){ + if(NUMBER <= 0){ + throw new IllegalArgumentException("양수를 입력해야합니다."); + } + } + + private void checkWrongWord(){ + // 다른 구분자나 숫자가 포함되어 있는지 확인하기 + if(!input.matches("^[a-zA-Z,]*$")) { + throw new IllegalArgumentException("문자와 구분자','외에 다른문자가 포함되어 있습니다."); + } + } + + private void checkWrongDelimiter(){ + // input의 delimiter 위치 확인(','가 맨앞에 오거나 겹치는 경우) + for(String inputCar : inputCars) { + if(inputCar.isEmpty()){ + throw new IllegalArgumentException("구분자가 겹쳐있거나 문자열 맨앞에 위치해 있습니다."); + } + } + // input의 delimiter 위치 확인(','가 맨앞 맨뒤에 있는 경우) + if(input.charAt(input.length() - 1) == ','){ + throw new IllegalArgumentException("구분자가 문자열 맨뒤에 위치해 있습니다."); + } + } + + private void checkWrongLength(){ + // input의 차 이름이 5글자 이하인지 확인 + for(String inputCar : inputCars) { + checkNumOfCarName(inputCar); + } + } + + private void checkNumOfCarName(String inputCar) { + int MAX_NUM_OF_CAR_NAME = 5; + if(inputCar.length() > MAX_NUM_OF_CAR_NAME){ + throw new IllegalArgumentException("자동차 이름이 5글자 이하여야합니다."); + } + } + + public void checkException(){ + checkInputCarsIsNull(); + checkWrongInputNumber(); + checkWrongWord(); + checkWrongDelimiter(); + checkWrongLength(); + } +} diff --git a/src/main/java/racingcar/RacingManager.java b/src/main/java/racingcar/RacingManager.java new file mode 100644 index 0000000000..12c5107a98 --- /dev/null +++ b/src/main/java/racingcar/RacingManager.java @@ -0,0 +1,110 @@ +package racingcar; + +import camp.nextstep.edu.missionutils.Console; +import camp.nextstep.edu.missionutils.Randoms; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +public class RacingManager { + + private String input = ""; + private int NUMBER; + private String[] inputCars; + private ExceptionManager exceptionManager; + private List carList = new ArrayList<>(); + private int MAX_POSITION; + private List names = new ArrayList<>(); + + + RacingManager(){ + System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"); + this.input = Console.readLine(); // 사용자 입력을 받는 메소드 + System.out.println("시도할 횟수는 몇 회인가요?"); + try { + this.NUMBER = Integer.parseInt(Console.readLine()); + } catch (NumberFormatException e){ + throw new IllegalArgumentException("숫자를 입력하지 않았습니다."); + } + splitInputCars(); + exceptionManager = new ExceptionManager(input, inputCars, NUMBER); + } + + private void splitInputCars() { + this.inputCars = input.split(","); + } + + private void createCar() { + for(int i = 0; i < inputCars.length; i++){ + Car car = new Car(inputCars[i], 0); + carList.add(car); + } + } + + private void startRacing() { + System.out.println(); + System.out.println("실행 결과"); + while(NUMBER > 0){ + startMove(carList); + System.out.println(); + NUMBER -= 1; + } + } + + private void startMove(List carList) { + int RANDOM_NUM; + for(int i = 0; i < carList.size(); i++) { + String position = ""; + Car car = carList.get(i); + checkMove(car); + printPosition(car, position); + } + } + + private void checkMove(Car car) { + int RANDOM_NUM = Randoms.pickNumberInRange(0, 9); + int MOVE_FORWARD_NUM = 4; + if(RANDOM_NUM >= MOVE_FORWARD_NUM) { + car.moveForword(); + } + } + + private void printPosition(Car car, String position) { + for(int j = 0; j < car.getPosition(); j++) { + position += '-'; + } + System.out.println(car.getName() + " : " + position); + } + + public void getMaxPosition() { + MAX_POSITION = carList.stream() + .max(Comparator.comparingInt(Car::getPosition)) + .map(Car::getPosition) + .orElse(-1); + } + + public void getMaxPostionCars() { + // 최대 position을 가진 모든 객체의 name을 리스트로 추출 + names = carList.stream() + .filter(o -> o.getPosition() == MAX_POSITION) + .map(Car::getName) + .collect(Collectors.toList()); + } + + public void printMaxPositionCars() { + String result = names.stream() + .collect(Collectors.joining(", ")); + System.out.println("최종 우승자 : " + result); + } + + public void runRacing() { + exceptionManager.checkException(); + createCar(); + startRacing(); + getMaxPosition(); + getMaxPostionCars(); + printMaxPositionCars(); + } +} diff --git a/src/test/java/racingcar/ApplicationTest.java b/src/test/java/racingcar/ApplicationTest.java index 1d35fc33fe..ea4a2b5574 100644 --- a/src/test/java/racingcar/ApplicationTest.java +++ b/src/test/java/racingcar/ApplicationTest.java @@ -23,6 +23,16 @@ class ApplicationTest extends NsTest { ); } + @Test + void 우승자_여러명일때_기능_테스트() { + assertSimpleTest( + () -> { + run("pobi,woni", "1"); + assertThat(output()).contains("pobi : -", "woni : -", "최종 우승자 : pobi, woni"); + } + ); + } + @Test void 예외_테스트() { assertSimpleTest(() -> @@ -31,6 +41,86 @@ class ApplicationTest extends NsTest { ); } + @Test + void 자동차이름입력값_빈값일때_예외_테스트() { + assertSimpleTest(() -> + assertThatThrownBy(() -> runException("", "1")) + .isInstanceOf(IllegalArgumentException.class) + ); + } + + @Test + void 반복횟수_빈값일때_예외_테스트() { + assertSimpleTest(() -> + assertThatThrownBy(() -> runException("pobi,java", null)) + .isInstanceOf(IllegalArgumentException.class) + ); + } + + @Test + void 반복횟수_0일때_예외_테스트() { + assertSimpleTest(() -> + assertThatThrownBy(() -> runException("pobi,java", "0")) + .isInstanceOf(IllegalArgumentException.class) + ); + } + + @Test + void 반복횟수_음수일때_예외_테스트() { + assertSimpleTest(() -> + assertThatThrownBy(() -> runException("pobi,java", "-1")) + .isInstanceOf(IllegalArgumentException.class) + ); + } + + @Test + void 유효하지않은_구분자_예외_테스트() { + assertSimpleTest(() -> + assertThatThrownBy(() -> runException("pobi@java", "1")) + .isInstanceOf(IllegalArgumentException.class) + ); + } + + @Test + void 자동차이름에_숫자_포함돼있을시_예외_테스트() { + assertSimpleTest(() -> + assertThatThrownBy(() -> runException("pobi,java2", "1")) + .isInstanceOf(IllegalArgumentException.class) + ); + } + + @Test + void 자동차이름에_다른구분자_포함돼있을시_예외_테스트() { + assertSimpleTest(() -> + assertThatThrownBy(() -> runException("pobi:java", "1")) + .isInstanceOf(IllegalArgumentException.class) + ); + } + + @Test + void 구분자가_맨앞에있을때_예외_테스트() { + assertSimpleTest(() -> + assertThatThrownBy(() -> runException(",pobi,java", "1")) + .isInstanceOf(IllegalArgumentException.class) + ); + } + + @Test + void 구분자가_겹쳐있을때_예외_테스트() { + assertSimpleTest(() -> + assertThatThrownBy(() -> runException("pobi,,java", "1")) + .isInstanceOf(IllegalArgumentException.class) + ); + } + + @Test + void 구분자가_맨뒤에있을때_예외_테스트() { + assertSimpleTest(() -> + assertThatThrownBy(() -> runException("pobi,java,", "1")) + .isInstanceOf(IllegalArgumentException.class) + ); + } + @Override public void runMain() { Application.main(new String[]{});