diff --git a/README.md b/README.md index 491aece1..3e276164 100644 --- a/README.md +++ b/README.md @@ -1 +1,79 @@ -# java-racingcar-precourse \ No newline at end of file +# java-racingcar-precourse + +# 객체별 기능 목록 + +## 자동차 객체 Car class +- [x] String name 자동차 이름 저장하는 변수 +- [x] int state 현재까지 얼만큼 움직였는지 저장하는 변수 +- [x] move() 움직일지 말지 결정하고 반영하는 메서드 + * 0~9사이 무작위 값 구한후, 무작위 값이 4 이상일 경우 1칸 움직임 + * 실행 결과를 자동차 객체 상태 state 변수에 반영 +- [x] 자동차 객체의 이동 현황 출력 + +## 게임 진행 프로그램 Game class +- [x] getCarName() 자동차 이름 입력받기 기능 + - [x] 경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분) + [x] 이상치 체크 후 이상한 값인 경우 입력을 다시 받도록함 + +[x] getTryNum() 시도 회수 입력받기 기능 + [x] 시도할 회수는 몇회인가요? + [x] 이상치 체크 후 이상한 값인 경우 입력을 다시 받도록함 + +[x] 자동차 객체를 생성 하는 기능 + +[x] findWinner() 경주 종료 후, 최종 우승자를 판별하는 기능 (여러명 일 수 있음) +[x] printWinner() 최종 우승자를 출력하는 기능 + [x] 최종 우승자 : + + +## 이상치 판별 클래스 CheckInput class +[x] checkCarName(List carNames)자동차 이름 이상 판별 + 자동차 이름은 쉼표(,)를 기준으로 구분하며 이름은 5자 이하만 가능하다. + +[x] isWrongValue() 잘못된 값 입력시 에러발생 및 출력 + [x] IllegalArgumentException 를 발생시키고, + [x] "[ERROR]"로 시작하는 에러 메시지를 출력 + +## 게임 진행 클래스 Application class +[x] 사용자로부터 자동차 이름 입력받기 +[x] 자동차 객체 생성하기 +[x] 사용자로부터 게임 회수 입력받기 + +[x] 회수만큼 게임 진행 + [x] 자동차 객체별로 이동거리 관리 + [x] 실행결과 출력 +[x] 최종 우승자 계산 +[x] 최종 우승자 출력 + +## 참고 +[ ] 메서드 명은 동사로 시작 +[ ] 메서드명 , 클래스 명이 모호하지 않도록 하기 + + +## 실행결과 예시 +경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분) +pobi,woni,jun +시도할 회수는 몇회인가요? +5 +실행 결과 +pobi : +woni : +jun : + +pobi : - +woni : +jun : - + +pobi : -- +woni : - +jun : -- + +pobi : --- +woni : -- +jun : --- + +pobi : ---- +woni : --- +jun : ---- + +최종 우승자 : pobi, jun \ 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..82e7aa04 --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,23 @@ +import java.util.List; + +public class Application { + public static void main(String[] args) { + Game g = new Game(); + List carNames = g.getCarNames(); + List cars = g.makeCars(carNames); + + int tryNum= g.getTryNum(); + System.out.println("실행 결과"); + for (int i=0; i winners= g.findWinners(cars); + g.printWinners(winners); + + } +} diff --git a/src/main/java/Car.java b/src/main/java/Car.java new file mode 100644 index 00000000..84f25053 --- /dev/null +++ b/src/main/java/Car.java @@ -0,0 +1,42 @@ +import java.util.Random; + +public class Car { + private String name; + private int state; + + public Car(String carName) { + this.name= carName; + this.state = 0; + } + + public void move() { + + Random r = new Random(); + int randNum= r.nextInt(0,9); + + if (randNum >= 4) { + setState(getState() + 1); + } + } + + public void printState() { + System.out.printf("%s : ",this.getName()); + for (int i=0; i carNames) { + if (carNames.size() < 2) { + throw new IllegalArgumentException("[ERROR] 자동차를 2대 이상 적어야 경주가 시작됩니다."); + } + } + + public static void checkCarNames(List carNames) { + checkCarNameDiffer(carNames); + for (String carName : carNames) { + int carLength = carName.length(); + checkCarNameLength(carName); + } + } + + public static void checkCarNameDiffer(List carNames) { + HashSet setNames = new HashSet<>(carNames); + if (setNames.size() != carNames.size()) { + throw new IllegalStateException("[ERROR] 자동차의 이름은 모두 다르게 입력해주세요."); + } + } + + public static void checkCarNameLength(String name) { + if ((name.isEmpty()) || (name.length() > 5)) { + throw new IllegalArgumentException("[ERROR] 차 이름의 길이는 1글자~5글자 사이로 입력해주세요."); + } + } + + public static void isWrongIntValue(int tryNum) { + if (tryNum < 1) { + throw new IllegalArgumentException("[ERROR] 잘못된 값을 입력했습니다. 1이상의 정수를 다시 입력하세요."); + } + } +} diff --git a/src/main/java/Game.java b/src/main/java/Game.java new file mode 100644 index 00000000..4bb8b14f --- /dev/null +++ b/src/main/java/Game.java @@ -0,0 +1,81 @@ +import java.util.*; + +public class Game { + Scanner sc; + + public Game(){ + sc = new Scanner(System.in); + } + public List getCarNames() { + List carNames; + + + while (true) { + try { + System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"); + carNames = List.of(sc.next().split(",")); + CheckInput.checkCarCount(carNames); + CheckInput.checkCarNames(carNames); + return carNames; + } catch (IllegalArgumentException | IllegalStateException e) { + System.out.println(e.getMessage()); + } + } + } + + public int getTryNum() { + int tryNum; + System.out.println("시도할 회수는 몇회인가요?"); + while (true) { + try { + tryNum = sc.nextInt(); + CheckInput.isWrongIntValue(tryNum); + break; + } catch (InputMismatchException e){ + System.out.println("[ERROR] 잘못된 값을 입력했습니다. 1 이상의 정수를 다시 입력하세요."); + sc.next(); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + return tryNum; + } + + public List makeCars(List carNames) { + List Cars = new ArrayList<>(); + for (String carName : carNames) { + Cars.add(new Car(carName)); + } + return Cars; + } + + public List findWinners(List cars) { + + int winnerState= cars.get(0).getState(); + + for (Car car : cars) { + int carState = car.getState(); + if (carState > winnerState) { + winnerState = carState; + } + } + + List winnerList= new ArrayList<>(); + + for (Car car : cars) { + int carState = car.getState(); + if (carState == winnerState) { + winnerList.add(car); + } + } + return winnerList; + } + + public void printWinners(List cars) { + System.out.print("최종 우승자 : "); + for (int i = 0; i < (cars.size() - 1); i++) { + System.out.print(cars.get(i).getName() + ", "); + } + System.out.println(cars.get(cars.size() - 1).getName()); + } +} diff --git a/src/test/java/CarTest.java b/src/test/java/CarTest.java new file mode 100644 index 00000000..fc656250 --- /dev/null +++ b/src/test/java/CarTest.java @@ -0,0 +1,20 @@ + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + + +public class CarTest { + @Test + public void carNameShouldNotExceedFiveCharacters() { + assertThatThrownBy(() -> new Car("sixletters")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("[ERROR] 자동차 이름은 5자를 초과할 수 없습니다."); + } + + @Test + + } +} diff --git a/src/test/java/CarTest2.java b/src/test/java/CarTest2.java new file mode 100644 index 00000000..83474a94 --- /dev/null +++ b/src/test/java/CarTest2.java @@ -0,0 +1,54 @@ + +/*참고용 파일*/ + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.junit.jupiter.api.Test; + +public class CarTest2 { + + @Test + void 자동차_이름이_유효한_경우() { + Car car = new Car("민성"); + assertThat(car.getName()).isEqualTo("민성"); + } + + @Test + void 자동차_이름이_null인_경우_예외처리() { + assertThatThrownBy(() -> new Car(null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("[ERROR]"); + } + + @Test + void 자동차_이름이_5자를_초과하는_경우_예외처리() { + assertThatThrownBy(() -> new Car("pobi123")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("[ERROR]"); + } + + @Test + void 자동차_이름이_1자_미만인_경우_예외처리() { + assertThatThrownBy(() -> new Car("")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("[ERROR]"); + } + + /*@Test + void 자동차가_전진하는_경우() { + Car car = new Car("민성"); + car.run(4); + assertThat(car.getDistance()).isEqualTo(1); + } + + @Test + void 자동차가_멈추는_경우() { + Car car = new Car("민성"); + car.run(3); + assertThat(car.getDistance()).isEqualTo(0); + } + */ + +} + diff --git a/src/test/java/CarsTest.java b/src/test/java/CarsTest.java new file mode 100644 index 00000000..a7e03e09 --- /dev/null +++ b/src/test/java/CarsTest.java @@ -0,0 +1,30 @@ +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class CarsTest { + Car car; + CheckInput checkInput; + Game game; + + @BeforeEach + void setUp() { + checkInput=new CheckInput(); + game= new Game(); + } + + @ParameterizedTest + @ValueSource(strings = "aaa,bbb,abdcdddd") + @DisplayName("입력받은 자동차 이름 길이 유효성 검사,길이가 5이상 일 경우(예외 발생)") + void checkInputCarNameLengthValidException(final String name) { + assertThatThrownBy(() -> game.getCarNames()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("[ERROR] 차 이름의 길이는 1글자~5글자 사이로 입력해주세요."); + } +} diff --git a/src/test/java/CheckInputTest.java b/src/test/java/CheckInputTest.java new file mode 100644 index 00000000..3403f281 --- /dev/null +++ b/src/test/java/CheckInputTest.java @@ -0,0 +1,28 @@ +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class CheckInputTest { + + @Test + @DisplayName("자동차 이름 중복 되는 경우 예외처리 테스트") + public void carNameShouldNotExceedFiveCharacters() { + assertThatThrownBy(() -> new Car("sixletters")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("[ERROR] 자동차 이름은 5자를 초과할 수 없습니다."); + } + /*public void checkCarNames_InvalidInput() { + List carNames = new ArrayList<>(Arrays.asList("abc", "abc", "ghi")); + + // IllegalStateException 예외 발생 확인 + assertThatThrownBy(() -> CheckInput.checkCarNames(carNames)) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("[ERROR] 자동차의 이름은 모두 다르게 입력해주세요."); + }*/ + +}