diff --git a/README.md b/README.md index 8fe711203..40e06fad6 100644 --- a/README.md +++ b/README.md @@ -24,3 +24,20 @@ git checkout main // 기본 브랜치가 main인 경우 git checkout -b 브랜치이름 ex) git checkout -b apply-feedback ``` + +4. 기능 요구 사항 +```jsx +- 3 대의 자동차의 이름을 입력받는다.(5자를 초과할 수 없다) +- 경주 레이스의 횟수를 입력받는다. +- 자동차마다 0에서 9 사이 랜덤 숫자를 저장할 변수를 갖는다. + +(경주 시작) +- 매 횟수마다 자동차의 random 값이 갱신 +- 4이상일 경우 전진 + +(경주 종료) +- 마지막에 가장 많이 전진한 자동차가 우승했음을 알려준다. +- 우승자는 한명 이상일 수 있다. + + +``` diff --git a/src/main/java/StringAddCalculator.java b/src/main/java/StringAddCalculator.java new file mode 100644 index 000000000..391f5d913 --- /dev/null +++ b/src/main/java/StringAddCalculator.java @@ -0,0 +1,54 @@ +import java.util.Arrays; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class StringAddCalculator { + public static int splitAndSum(String s) { + String[] tokens = new String[0]; + if(isNull(s)) return 0; + + Matcher m = Pattern.compile("//(.)\n(.*)").matcher(s); + // 지정된 구분자가 있을 경우 + if(m.find()) { + String customDelimiter = m.group(1); + tokens= m.group(2).split(customDelimiter); + } + + // 구분자가 , 또는 : 일 경우 + if(!m.find() && s.contains(",") || s.contains(":")) { + tokens = s.split(",|:"); + } + + // 숫자만 들어올 경우 + if(tokens.length == 0){ + return Integer.parseInt(s); + } + + List numList = arrayToList(tokens); + if(containsNegative(numList)) throw new RuntimeException(); + + return sum(numList); + } + public static List arrayToList(String[] tokens) { + return Arrays.stream(tokens).sorted().collect(Collectors.toList()); + } + public static int sum(List numList) { + return numList.stream() + .mapToInt(Integer::parseInt).sum(); + } + public static boolean isNull(String text) { + return (text == null) || (text.isEmpty()); + } + // 메인 메소드 + public static boolean containsNegative(List list) { + return list.stream().mapToInt(Integer::parseInt).anyMatch(StringAddCalculator::isNegative); + } + + // 음수인지 판별하는 메소드 + private static boolean isNegative(int number) { + return number < 0; + } + +} diff --git a/src/main/java/car_racing/Car.java b/src/main/java/car_racing/Car.java new file mode 100644 index 000000000..ac4cbec28 --- /dev/null +++ b/src/main/java/car_racing/Car.java @@ -0,0 +1,37 @@ +package car_racing; + +import java.util.Random; + +public class Car { + private final String name; + private final int randomNum; + private int raceScore; + + public Car(String name) { + this.name = name; + this.randomNum = makeRandomNum(); + this.raceScore = 0; + } + + public static String[] splitCarNames(String str) { + return str.split(","); + } + public int makeRandomNum() { + Random random = new Random(); + return random.nextInt(9)+1; // 1~9 + } + public void addScore(int randomNum, int raceScore) { + if(randomNum >= 4) raceScore++; + this.raceScore = raceScore; + } + public int getRandomNum() { + return this.randomNum; + } + public int getRaceScore() { + return this.raceScore; + } + public String getName() { + return name; + } + +} diff --git a/src/main/java/car_racing/CarRacing.java b/src/main/java/car_racing/CarRacing.java new file mode 100644 index 000000000..65f6884a3 --- /dev/null +++ b/src/main/java/car_racing/CarRacing.java @@ -0,0 +1,35 @@ +package car_racing; + +import java.util.Scanner; + +import static car_racing.Car.splitCarNames; + +public class CarRacing { + public void racing() { + Scanner sc = new Scanner(System.in); + System.out.println("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분)."); + String carNames = sc.nextLine(); + Cars cars = new Cars(splitCarNames(carNames)); + + + System.out.println("시도할 회수는 몇회인가요?"); + int racingNum = sc.nextInt(); + + System.out.println("실행결과"); + PrintResult print = null; + while (racingNum > 0) { + print = cars.printCurrent(cars.play()); + racingNum--; + } + + if(print != null) print.finalResult(cars.findHighestScore()); + + } + public CarRacing() { + racing(); + } + + public static void main(String[] args){ + new CarRacing(); + } +} diff --git a/src/main/java/car_racing/Cars.java b/src/main/java/car_racing/Cars.java new file mode 100644 index 000000000..f27705a5e --- /dev/null +++ b/src/main/java/car_racing/Cars.java @@ -0,0 +1,51 @@ +package car_racing; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.OptionalInt; +import java.util.stream.Collectors; + +public class Cars { + private final List cars; + + public Cars(String[] carsName) { + this.cars = getCars(carsName); + } + + private List getCars(String[] carsName) { + List cars = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + cars.add(new Car(carsName[i])); + } + return cars; + } + public List play() { + for (Car c: + cars) { + c.addScore(c.makeRandomNum(), c.getRaceScore()); + } + return cars; + } + // 매 회차마다 문자열 출력 + public PrintResult printCurrent(List cars) { + PrintResult result = new PrintResult(cars); + for (Car c: cars) { + result.writeCurrentResult(c); + }System.out.println(); + return result; + } + // 최대값 찾기 + public List findHighestScore() { + OptionalInt maxScore = cars.stream() + .mapToInt(Car::getRaceScore) + .max(); + + return maxScore.isPresent() ? + cars.stream() + .filter(car -> car.getRaceScore() == maxScore.getAsInt()) + .collect(Collectors.toList()) + : Collections.emptyList(); // 최대값이 없으면 빈 리스트 반환 + } + +} diff --git a/src/main/java/car_racing/PrintResult.java b/src/main/java/car_racing/PrintResult.java new file mode 100644 index 000000000..1f53efbf0 --- /dev/null +++ b/src/main/java/car_racing/PrintResult.java @@ -0,0 +1,45 @@ +package car_racing; + +import java.util.Collections; +import java.util.List; +import java.util.OptionalInt; +import java.util.stream.Collectors; + +public class PrintResult { + + private final List result; + public PrintResult(List result) { + this.result = result; + } + public void writeCurrentResult(Car car){ + StringBuilder sb = new StringBuilder(); + sb.append(car.getName()).append(" : "); + for (int i = 0; i < car.getRaceScore(); i++) { + sb.append("-"); + } + System.out.println(sb); + } + + public void finalResult(List result) { + if (result.isEmpty()) { + return; + } + String resultString = getResultString(result); + System.out.println(resultString + "가 최종 우승했습니다."); + } + + private String getResultString(List result) { + StringBuilder sb = new StringBuilder(); + + for (Car car : result) { + sb.append(car.getName()).append(", "); + } + + // 마지막 ", " 제거 + int length = sb.length(); + if (length > 0) sb.delete(length - 2, length); + + return sb.toString(); + } + +} diff --git a/src/test/java/StringAddCalculatorTest.java b/src/test/java/StringAddCalculatorTest.java new file mode 100644 index 000000000..a0fb53116 --- /dev/null +++ b/src/test/java/StringAddCalculatorTest.java @@ -0,0 +1,45 @@ +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class StringAddCalculatorTest { + @Test + public void splitAndSum_null_또는_빈문자() { + int result = StringAddCalculator.splitAndSum(null); + assertThat(result).isEqualTo(0); + + result = StringAddCalculator.splitAndSum(""); + assertThat(result).isEqualTo(0); + } + + @Test + public void splitAndSum_숫자하나() throws Exception { + int result = StringAddCalculator.splitAndSum("1"); + assertThat(result).isEqualTo(1); + } + + @Test + public void splitAndSum_쉼표구분자() throws Exception { + int result = StringAddCalculator.splitAndSum("1,2"); + assertThat(result).isEqualTo(3); + } + + @Test + public void splitAndSum_쉼표_또는_콜론_구분자() throws Exception { + int result = StringAddCalculator.splitAndSum("1,2:3"); + assertThat(result).isEqualTo(6); + } + + @Test + public void splitAndSum_custom_구분자() throws Exception { + int result = StringAddCalculator.splitAndSum("//;\n1;2;3"); + assertThat(result).isEqualTo(6); + } + + @Test + public void splitAndSum_negative() throws Exception { + assertThatThrownBy(() -> StringAddCalculator.splitAndSum("-1,2,3")) + .isInstanceOf(RuntimeException.class); + } +} \ No newline at end of file diff --git a/src/test/java/car_racing/CarTest.java b/src/test/java/car_racing/CarTest.java new file mode 100644 index 000000000..9a44b2779 --- /dev/null +++ b/src/test/java/car_racing/CarTest.java @@ -0,0 +1,32 @@ +package car_racing; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class CarTest { + Car car1, car2; + @BeforeEach + void setUp() { + car1 = new Car("pobi"); + car2 = new Car("crong"); + } + @Test + @DisplayName("자동차마다 갖게될 랜덤숫자 생성") + void car_randomNum() { + assertThat(car1.getRandomNum()).isNotZero(); + assertThat(car2.getRandomNum()).isNotZero(); + } + @Test + @DisplayName("자동차의 랜덤숫자가 4 이상일 때 점수에 축적") + void car_addScore() { + car1.addScore(2, 0); + car2.addScore(4,2); + assertThat(car1.getRaceScore()).isEqualTo(0); + assertThat(car2.getRaceScore()).isEqualTo(3); + } + + +} \ No newline at end of file diff --git a/src/test/java/car_racing/CarsTest.java b/src/test/java/car_racing/CarsTest.java new file mode 100644 index 000000000..fcc61653d --- /dev/null +++ b/src/test/java/car_racing/CarsTest.java @@ -0,0 +1,45 @@ +package car_racing; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class CarsTest { + Car car1, car2, car3; + @BeforeEach + void setup(){ + car1 = new Car("pobi"); + car2 = new Car("crong"); + car3 = new Car("honux"); + } + + @Test + @DisplayName("3번를 진행할 때 가질 수 있는 max값은 회차 수와 같다") + void car_racing() { + String[] names = {"pobi", "crong", "honux"}; + Cars cars = new Cars(names); + for (int i = 1; i <= 3; i++) { + List carResult = cars.play(); // 1~3회 진행 + assertThat(carResult.get(0).getRaceScore()).isLessThanOrEqualTo(i); // i이하 + assertThat(carResult.get(1).getRaceScore()).isLessThanOrEqualTo(i); // i이하 + assertThat(carResult.get(2).getRaceScore()).isLessThanOrEqualTo(i); // i이하 + } + + } + + @Test + @DisplayName(("종료 후 가장 높은 raceScore 을 보유한 List 출력 - 무조건 1개 이상")) + void find_highestScore() { + String[] names = {"pobi", "crong", "honux"}; + Cars cars = new Cars(names); + for (int i = 1; i <= 3; i++) { + cars.play(); // 3회 진행 + } + assertThat(cars.findHighestScore()).isNotNull(); + } + +} \ No newline at end of file