From bb020a67e17711ecf490e9488e3915e66eba9a15 Mon Sep 17 00:00:00 2001 From: yun <90806941+yunji1201@users.noreply.github.com> Date: Thu, 26 Sep 2024 09:23:22 +0900 Subject: [PATCH 01/14] Step1 (#5615) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test : "1,2"을 ,로 split 했을 때 1과 2로 잘 분리되는지 테스트 * refactor : 메소드명 변경 split() -> splitTwoNum() * test : "1"을 ,로 split 했을 때 1만을 포함하는 배열이 반환되는지 테스트 * test : "(1,2)" 값에서 substring() 메소드를 활용해 ()을 제거하고 "1,2"를 반환하는 테스트 * test : charAt() 메소드로 특정 위치의 문자 가져오는 테스트 * test : 위치 값 벗어났을 떄의 StringIndexOutOfBoundsException 발생 테스트 * test : @DisplayName 사용하여 가독성 향상 * test : @BeforeEach로 테스트 메서드가 실행되기 전에 매번 실행되는 메서드 정의 * test : size() 메소드를 통해 Set의 크기를 확인하는 테스트 * test : Set의 contains() 메소드를 활용해 1, 2, 3의 값이 존재하는지를 확인 테스트 * test : @ParameterizedTest @ValueSource 활용해 중복 코드 제거 * test : @CsvSource 활용하여 true/false 검증을 위한 파라미터화 테스트 --- src/test/java/study/SetTest.java | 46 ++++++++++++++++++++++++++ src/test/java/study/StringTest.java | 50 +++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/test/java/study/SetTest.java create mode 100644 src/test/java/study/StringTest.java diff --git a/src/test/java/study/SetTest.java b/src/test/java/study/SetTest.java new file mode 100644 index 00000000000..c93f761a7f2 --- /dev/null +++ b/src/test/java/study/SetTest.java @@ -0,0 +1,46 @@ +package study; + +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.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +import java.util.HashSet; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SetTest { + private Set numbers; + + @BeforeEach + void setUp() { + numbers = new HashSet<>(); + numbers.add(1); + numbers.add(1); + numbers.add(2); + numbers.add(3); + } + + @Test + @DisplayName("Set의 size() 메소드로 Set의 크기를 확인") + void setSize() { + assertThat(numbers).hasSize(3); + } + + @ParameterizedTest + @ValueSource(ints = {1, 2, 3}) + @DisplayName("Set의 contains() 메소드로 1,2,3의 값이 존재하는지 확인") + void setContains(int values) { + assertThat(numbers.contains(values)).isTrue(); + } + + @ParameterizedTest + @CsvSource(value = {"1,true", "2,true", "3,true", "4,false", "5,false"}) + @DisplayName("Set의 contains() 메소드로 1,2,3 값이 존재하는지 아닌지 확인") + void setContainsWithBoolean(int values, boolean expected) { + assertThat(numbers.contains(values)).isEqualTo(expected); + } +} diff --git a/src/test/java/study/StringTest.java b/src/test/java/study/StringTest.java new file mode 100644 index 00000000000..07ecd16fac4 --- /dev/null +++ b/src/test/java/study/StringTest.java @@ -0,0 +1,50 @@ +package study; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.*; + +public class StringTest { + + @Test + @DisplayName("문자열 '1,2'를 ','로 분리하여 두 개의 숫자로 나누어 결과 확인") + void splitTwoNum() { + String[] result = "1,2".split(","); + assertThat(result).containsExactly("1", "2"); + } + + @Test + @DisplayName("문자열 '1'을 ','로 분리하여 하나의 숫자를 포함하는 배열 확인") + void splitOneNum() { + String[] result = "1".split(","); + assertThat(result).containsExactly("1"); + } + + @Test + @DisplayName("substring() 메서드로 문자열 '(1,2)'에서 괄호를 제거하고 내용 추출") + void substringParentheses() { + String result = "(1,2)".substring(1, 4); + assertThat(result).isEqualTo("1,2"); + } + + @Test + @DisplayName("charAt() 메서드를 사용하여 특정 위치의 문자 추출") + void getCharacterUsingCharAt() { + String str = "abc"; + char result = str.charAt(0); + assertThat(result).isEqualTo('a'); + } + + @Test + @DisplayName("인덱스가 범위를 벗어날 경우 예외 발생 확인") + void StringIndexOutOfBoundsExceptionTest() { + String str = "abc"; + + assertThatThrownBy(() -> { + str.charAt(3); + }).isInstanceOf(IndexOutOfBoundsException.class) + .hasMessageContaining("String index out of range: 3"); // String index out of range: 3 + } + +} From cdfb759489cd3ba9892a30aaed1990b54355981e Mon Sep 17 00:00:00 2001 From: yun <90806941+yunji1201@users.noreply.github.com> Date: Thu, 3 Oct 2024 07:52:57 +0900 Subject: [PATCH 02/14] =?UTF-8?q?2=EB=8B=A8=EA=B3=84=20-=20=EB=AC=B8?= =?UTF-8?q?=EC=9E=90=EC=97=B4=20=EB=8D=A7=EC=85=88=20=EA=B3=84=EC=82=B0?= =?UTF-8?q?=EA=B8=B0=20(#5715)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor : 코드리뷰 코멘트 받은 부분 수정 * test : 숫자 하나를 문자열로 입력할 시 해당 숫자를 반환하는지 테스트 * test : 쉼표 또는 콜론을 구분자로 가지는 문자열을 전달할 경우 구분자를 기준으로 분리한 각 숫자의 합을 반환하는지 테스트 * test : 빈 문자열 또는 null 값을 입력할 경우 0을 반환하는 테스트 * refactor : 같은 함수 안에서 추상화 레벨 맞추는 리팩토링 * test : //”와 “\\n” 문자 사이에 놓인 문자를 커스텀 구분자로 지정하여 사용할 수 있는지 확인하는 테스트 * test : 숫자 이외의 값 또는 음수를 전달할 경우 RuntimeException 예외를 던지는지 확인하는 테스트 * refactor : 이름으로 어떤 역할을 하는지 알 수 있도록 명확한 이름으로 메소드명 수정 * remove : 불필요한 클래스 삭제 * refactor : 클래스 레벨 상수로 만들어 Pattern 인스턴스를 한 번만 생성하고 재활용할 수 있도록 변경 * test : 숫자 이외의 값을 전달할 경우 RuntimeException 예외를 던지는지 확인하는 테스트 * test : null 값을 전달할 경우 0을 반환하는지 @NullAndEmptySource을 사용하여 확인 테스트 * add : 일부 시스템에서 마지막 줄이 정상적으로 읽히지 않을 경우를 방지하기 위해 개행 추가 --- .../java/calculator/StringAddCalculator.java | 64 +++++++++++++++++++ .../calculator/StringAddCalculatorTest.java | 64 +++++++++++++++++++ src/test/java/study/SetTest.java | 4 +- src/test/java/study/StringTest.java | 4 +- 4 files changed, 132 insertions(+), 4 deletions(-) create mode 100644 src/main/java/calculator/StringAddCalculator.java create mode 100644 src/test/java/calculator/StringAddCalculatorTest.java diff --git a/src/main/java/calculator/StringAddCalculator.java b/src/main/java/calculator/StringAddCalculator.java new file mode 100644 index 00000000000..24936934698 --- /dev/null +++ b/src/main/java/calculator/StringAddCalculator.java @@ -0,0 +1,64 @@ +package calculator; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class StringAddCalculator { + + public static final String DEFAULT_DELIMITER = ",|:"; + public static final String CUSTOM_DELIMITER = "//(.)\n(.*)"; + public static final Pattern CUSTOM_DELIMITER_PATTERN = Pattern.compile(CUSTOM_DELIMITER); + + public static int calculateSum(String text) { + if (isBlank(text)) { + return 0; + } + return sumValues(toInts(splitValues(text))); + } + + private static String[] splitValues(String text) { + Matcher matcher = CUSTOM_DELIMITER_PATTERN.matcher(text); + if (matcher.find()) { + String customDelimiter = matcher.group(1); + return matcher.group(2).split(customDelimiter); + } + return text.split(DEFAULT_DELIMITER); + } + + private static boolean isBlank(String text) { + return text == null || text.isBlank(); + } + + private static int[] toInts(String[] values) { + int[] numbers = new int[values.length]; + + for (int i = 0; i < values.length; i++) { + validateNumber(values[i]); + numbers[i] = Integer.parseInt(values[i]); + } + return numbers; + } + + private static void validateNumber(String value) { + int number = parseNumber(value); + if (number < 0) { + throw new IllegalArgumentException("음수는 계산되지 않습니다."); + } + } + + private static int parseNumber(String value) { + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("숫자 이외의 값이 입력되었습니다."); + } + } + + private static int sumValues(int[] values) { + int result = 0; + for (int value : values) { + result += value; + } + return result; + } +} diff --git a/src/test/java/calculator/StringAddCalculatorTest.java b/src/test/java/calculator/StringAddCalculatorTest.java new file mode 100644 index 00000000000..5984db95615 --- /dev/null +++ b/src/test/java/calculator/StringAddCalculatorTest.java @@ -0,0 +1,64 @@ +package calculator; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullAndEmptySource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class StringAddCalculatorTest { + + @Test + @DisplayName("숫자 하나를 문자열로 입력할 시 해당 숫자를 반환하는지 확인") + void oneStringNumTest() { + int result = StringAddCalculator.calculateSum("1"); + assertThat(result).isEqualTo(1); + } + + @Test + @DisplayName("콤마를 구분자로 나뉘어 각 숫자의 합을 반환하는지 확인") + void sumWithCommaDelimiter() { + int result = StringAddCalculator.calculateSum("1,2"); + assertThat(result).isEqualTo(3); + } + + @Test + @DisplayName("콜론을 구분자로 나뉘어 각 숫자의 합을 반환하는지 확인") + void sumWithColonDelimiter() { + int result = StringAddCalculator.calculateSum("1:2"); + assertThat(result).isEqualTo(3); + } + + @ParameterizedTest + @DisplayName("빈 문자열 또는 null 값을 입력할 경우 0을 반환하는지 확인") + @NullAndEmptySource + void returnZeroForEmpty(String input) { + int result = StringAddCalculator.calculateSum(input); + assertThat(result).isEqualTo(0); + } + + @Test + @DisplayName("//”와 “\\n” 문자 사이에 커스텀 구분자 지정하여 사용할 수 있는지 확인") + void sumWithCustomDelimiter() { + int result = StringAddCalculator.calculateSum("//;\n1;2;3"); + assertThat(result).isEqualTo(6); + } + + @Test + @DisplayName("음수를 전달할 경우 RuntimeException 예외 throw하는지 확인") + void returnErrorForNegativeNum() { + assertThatThrownBy(() -> { + StringAddCalculator.calculateSum("-3"); + }).isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("숫자 이외의 값을 전달할 경우 RuntimeException 예외 throw하는지 확인") + void returnErrorForInvalidText() { + assertThatThrownBy(() -> { + StringAddCalculator.calculateSum("&"); + }).isInstanceOf(IllegalArgumentException.class); + } +} diff --git a/src/test/java/study/SetTest.java b/src/test/java/study/SetTest.java index c93f761a7f2..ef64be4f2c1 100644 --- a/src/test/java/study/SetTest.java +++ b/src/test/java/study/SetTest.java @@ -33,8 +33,8 @@ void setSize() { @ParameterizedTest @ValueSource(ints = {1, 2, 3}) @DisplayName("Set의 contains() 메소드로 1,2,3의 값이 존재하는지 확인") - void setContains(int values) { - assertThat(numbers.contains(values)).isTrue(); + void setContains(int value) { + assertThat(numbers.contains(value)).isTrue(); } @ParameterizedTest diff --git a/src/test/java/study/StringTest.java b/src/test/java/study/StringTest.java index 07ecd16fac4..2986ecfd946 100644 --- a/src/test/java/study/StringTest.java +++ b/src/test/java/study/StringTest.java @@ -37,8 +37,8 @@ void getCharacterUsingCharAt() { } @Test - @DisplayName("인덱스가 범위를 벗어날 경우 예외 발생 확인") - void StringIndexOutOfBoundsExceptionTest() { + @DisplayName("특정 위치의 문자를 가져올 때 위치 값을 벗어날 경우 StringIndexOutOfBoundsException 예외 발생 확인") + void checkIndexOutOfBounds() { String str = "abc"; assertThatThrownBy(() -> { From e06edf283def1db553d84b024a88dc79dbb5ed84 Mon Sep 17 00:00:00 2001 From: yun <90806941+yunji1201@users.noreply.github.com> Date: Sat, 5 Oct 2024 09:20:59 +0900 Subject: [PATCH 03/14] =?UTF-8?q?3=EB=8B=A8=EA=B3=84=20-=20=EC=9E=90?= =?UTF-8?q?=EB=8F=99=EC=B0=A8=20=EA=B2=BD=EC=A3=BC=20(#5736)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs : 기능 분석 후 todo.md 업데이트 * test : 0에서 9 사이에서 값이 4 이상일 경우에만 전진하고 4 이하일 경우 멈춰있는지 확인하는 테스트 * feat : 사용자가 자동자 수, 이동 수를 입력 할 수 있어야 함 * test : 0에서 9 사이에서 random 값을 구한 후 random 값이 4이상일 경우에만 전진하는 테스트 * feat : 자동차가 사용자가 입력한 값에 따라 경기를 진행하고 움직이도록 기능 추가 * feat : 자동차의 상태를 화면에 출력 * refactor : 중복된 내용의 테스트 메소드 제거 * refactor : 축약된 메소드명, 변수명 명확한 의미를 갖도록 수정 * refactor : private 생성자로 불필요한 인스턴스화 막기 * refactor : for문 -> repeat 함수 사용 * refactor : 첫번째 라운드에서 자동차가 반드시 전진하지 않아도 되도록 코드 수정 * refactor : 레이싱 라운드 시작 표시 콘솔을 VIEW에서 하도록 수정 * refactor : 비즈니스 로직과 UI 로직을 분리하기 위하여 의존성 주입을 사용한다 --- TODO.md | 23 +++++++++++++++ src/main/java/racingcar/Car.java | 19 ++++++++++++ src/main/java/racingcar/InputView.java | 22 ++++++++++++++ src/main/java/racingcar/Racing.java | 34 ++++++++++++++++++++++ src/main/java/racingcar/RacingCarMain.java | 22 ++++++++++++++ src/main/java/racingcar/ResultView.java | 19 ++++++++++++ src/test/java/racingcar/RacingCarTest.java | 34 ++++++++++++++++++++++ 7 files changed, 173 insertions(+) create mode 100644 TODO.md create mode 100644 src/main/java/racingcar/Car.java create mode 100644 src/main/java/racingcar/InputView.java create mode 100644 src/main/java/racingcar/Racing.java create mode 100644 src/main/java/racingcar/RacingCarMain.java create mode 100644 src/main/java/racingcar/ResultView.java create mode 100644 src/test/java/racingcar/RacingCarTest.java diff --git a/TODO.md b/TODO.md new file mode 100644 index 00000000000..216882403a0 --- /dev/null +++ b/TODO.md @@ -0,0 +1,23 @@ +### TODO + +1. [x] 구현할 기능 목록을 정리해 추가 +2. [x] 자동자 수, 이동 수 입력 할 수 있어야 함 +3. [x] 전진하는 조건은 0에서 9 사이에서 random 값을 구한 후 random 값이 4이상일 경우 +4. [x] 모든 자동차가 이동을 완료하면 종료 +5. [x] 자동차의 상태를 화면에 출력 + +- 값을 입력 받는 API는 Scanner를 이용 +- 랜덤 값은 자바 java.util.Random 클래스의 nextInt(10) 메소드를 활용 +- else 예약어를 쓰지 않는다 +- 기능을 구현하기 전에 README.md 파일에 구현할 기능 목록을 정리해 추가 +- git의 commit 단위는 앞 단계에서 README.md 파일에 정리한 기능 목록 단위로 추가 + +### AngularJS Commit Message Conventions + +* feat (feature) +* fix (bug fix) +* docs (documentation) +* style (formatting, missing semi colons, …) +* refactor +* test (when adding missing tests) +* chore (maintain) diff --git a/src/main/java/racingcar/Car.java b/src/main/java/racingcar/Car.java new file mode 100644 index 00000000000..82af9296074 --- /dev/null +++ b/src/main/java/racingcar/Car.java @@ -0,0 +1,19 @@ +package racingcar; + +public class Car { + + public static final int MOVE_CONDITION = 4; + private int currentPosition; + + public int moveCar(int randomNumber) { + if (randomNumber >= MOVE_CONDITION) { + currentPosition++; + } + return currentPosition; + } + + public int getCurrentPosition() { + return currentPosition; + } + +} diff --git a/src/main/java/racingcar/InputView.java b/src/main/java/racingcar/InputView.java new file mode 100644 index 00000000000..f9b3a6064b0 --- /dev/null +++ b/src/main/java/racingcar/InputView.java @@ -0,0 +1,22 @@ +package racingcar; + +import java.util.Scanner; + +public class InputView { + + private static final Scanner SCANNER = new Scanner(System.in); + + private InputView() { + + } + + public static int getCarNumber() { + System.out.println("자동차 개수는 몇 개 인가요?"); + return SCANNER.nextInt(); + } + + public static int getRoundNumber() { + System.out.println("시도 할 횟수는 몇 번 인가요?"); + return SCANNER.nextInt(); + } +} diff --git a/src/main/java/racingcar/Racing.java b/src/main/java/racingcar/Racing.java new file mode 100644 index 00000000000..65eec9d6608 --- /dev/null +++ b/src/main/java/racingcar/Racing.java @@ -0,0 +1,34 @@ +package racingcar; + +import java.util.List; +import java.util.Random; + +public class Racing { + + private static final Random RANDOM = new Random(); + + private final List cars; + private final int roundNum; + private final ResultView resultView; + + public Racing(List cars, int roundNum, ResultView resultView) { + this.cars = cars; + this.roundNum = roundNum; + this.resultView = resultView; + } + + public void start() { + for (int i = 0; i < roundNum; i++) { + resultView.roundStart(i + 1); + play(); + } + } + + private void play() { + for (Car car : cars) { + int position = car.moveCar(RANDOM.nextInt(10)); + resultView.drawCarPosition(position); + } + } + +} diff --git a/src/main/java/racingcar/RacingCarMain.java b/src/main/java/racingcar/RacingCarMain.java new file mode 100644 index 00000000000..54ebb0835ce --- /dev/null +++ b/src/main/java/racingcar/RacingCarMain.java @@ -0,0 +1,22 @@ +package racingcar; + +import java.util.ArrayList; +import java.util.List; + +public class RacingCarMain { + + public static void main(String[] args) { + int carNum = InputView.getCarNumber(); + int roundNum = InputView.getRoundNumber(); + + List cars = new ArrayList<>(); + for (int i = 0; i < carNum; i++) { + cars.add(new Car()); + } + + ResultView resultView = new ResultView(); + Racing racing = new Racing(cars, roundNum, resultView); + racing.start(); + } + +} diff --git a/src/main/java/racingcar/ResultView.java b/src/main/java/racingcar/ResultView.java new file mode 100644 index 00000000000..30fa748e4ff --- /dev/null +++ b/src/main/java/racingcar/ResultView.java @@ -0,0 +1,19 @@ +package racingcar; + +import java.util.Scanner; + +public class ResultView { + + private static final Scanner scanner = new Scanner(System.in); + public static final String LINE = "-".repeat(5); + + public static void roundStart(int roundNumber) { + System.out.println(LINE + roundNumber + " 라운드 시작!" + LINE); + } + + public static void drawCarPosition(int position) { + StringBuilder sb = new StringBuilder(); + sb.append("-".repeat(position)); + System.out.println(sb.toString()); + } +} diff --git a/src/test/java/racingcar/RacingCarTest.java b/src/test/java/racingcar/RacingCarTest.java new file mode 100644 index 00000000000..6c00de0e01d --- /dev/null +++ b/src/test/java/racingcar/RacingCarTest.java @@ -0,0 +1,34 @@ +package racingcar; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Random; +import java.util.stream.IntStream; + +import static org.assertj.core.api.Assertions.assertThat; + +public class RacingCarTest { + + @ParameterizedTest + @MethodSource("randomNum") + @DisplayName("자동차가 이동하는 값이 4 이상일 경우에만 전진하고 그렇지않으면 멈춰있는지 확인") + void carMovesOrStopsByRandomNum(int num) { + Car car = new Car(); + car.moveCar(num); + + System.out.println("num :: " + num); + if (num >= 4) { + assertThat(car.getCurrentPosition()).isEqualTo(1); + return; + } + assertThat(car.getCurrentPosition()).isEqualTo(0); + } + + static IntStream randomNum() { + Random random = new Random(); + return IntStream.generate(() -> random.nextInt(10)).limit(1); + } +} From 3945b000e8593609b03304ed6fdd0ca8f8b1fe04 Mon Sep 17 00:00:00 2001 From: yun <90806941+yunji1201@users.noreply.github.com> Date: Tue, 8 Oct 2024 03:04:06 +0900 Subject: [PATCH 04/14] =?UTF-8?q?refactor=20:=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=A6=AC=EB=B7=B0=EB=A5=BC=20=EB=B0=94=ED=83=95=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81=20=EC=9E=91?= =?UTF-8?q?=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/racingcar/Car.java | 3 ++- src/main/java/racingcar/Racing.java | 2 +- src/main/java/racingcar/ResultView.java | 11 ++++----- src/test/java/racingcar/RacingCarTest.java | 26 +++++++++------------- 4 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/main/java/racingcar/Car.java b/src/main/java/racingcar/Car.java index 82af9296074..865fda22334 100644 --- a/src/main/java/racingcar/Car.java +++ b/src/main/java/racingcar/Car.java @@ -3,9 +3,10 @@ public class Car { public static final int MOVE_CONDITION = 4; + private int currentPosition; - public int moveCar(int randomNumber) { + public int move(int randomNumber) { if (randomNumber >= MOVE_CONDITION) { currentPosition++; } diff --git a/src/main/java/racingcar/Racing.java b/src/main/java/racingcar/Racing.java index 65eec9d6608..6dfd880939f 100644 --- a/src/main/java/racingcar/Racing.java +++ b/src/main/java/racingcar/Racing.java @@ -26,7 +26,7 @@ public void start() { private void play() { for (Car car : cars) { - int position = car.moveCar(RANDOM.nextInt(10)); + int position = car.move(RANDOM.nextInt(10)); resultView.drawCarPosition(position); } } diff --git a/src/main/java/racingcar/ResultView.java b/src/main/java/racingcar/ResultView.java index 30fa748e4ff..0ba80876a52 100644 --- a/src/main/java/racingcar/ResultView.java +++ b/src/main/java/racingcar/ResultView.java @@ -1,19 +1,16 @@ package racingcar; -import java.util.Scanner; - public class ResultView { - private static final Scanner scanner = new Scanner(System.in); - public static final String LINE = "-".repeat(5); + private static final String LINE = "-".repeat(5); public static void roundStart(int roundNumber) { System.out.println(LINE + roundNumber + " 라운드 시작!" + LINE); } public static void drawCarPosition(int position) { - StringBuilder sb = new StringBuilder(); - sb.append("-".repeat(position)); - System.out.println(sb.toString()); + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("-".repeat(position)); + System.out.println(stringBuilder.toString()); } } diff --git a/src/test/java/racingcar/RacingCarTest.java b/src/test/java/racingcar/RacingCarTest.java index 6c00de0e01d..e4d2d6ee956 100644 --- a/src/test/java/racingcar/RacingCarTest.java +++ b/src/test/java/racingcar/RacingCarTest.java @@ -12,23 +12,19 @@ public class RacingCarTest { - @ParameterizedTest - @MethodSource("randomNum") - @DisplayName("자동차가 이동하는 값이 4 이상일 경우에만 전진하고 그렇지않으면 멈춰있는지 확인") - void carMovesOrStopsByRandomNum(int num) { + @Test + @DisplayName("자동차가 이동하는 값이 4 이상일 경우 전진하는지 확인") + void carMovesWhenFourOrMore() { Car car = new Car(); - car.moveCar(num); - - System.out.println("num :: " + num); - if (num >= 4) { - assertThat(car.getCurrentPosition()).isEqualTo(1); - return; - } - assertThat(car.getCurrentPosition()).isEqualTo(0); + car.move(4); + assertThat(car.getCurrentPosition()).isEqualTo(1); } - static IntStream randomNum() { - Random random = new Random(); - return IntStream.generate(() -> random.nextInt(10)).limit(1); + @Test + @DisplayName("자동차가 이동하는 값이 4 이하일 경우 멈춰있는지 확인") + void carStopWhenLessThanFour() { + Car car = new Car(); + car.move(3); + assertThat(car.getCurrentPosition()).isEqualTo(0); } } From 0dc8a6b0563354e421ecf82ca3d5e967dcf93967 Mon Sep 17 00:00:00 2001 From: yun <90806941+yunji1201@users.noreply.github.com> Date: Tue, 8 Oct 2024 03:39:24 +0900 Subject: [PATCH 05/14] =?UTF-8?q?refactor=20:=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8(Racing)=EC=9D=B4=20view(ResultView)=EC=97=90=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/racingcar/Racing.java | 22 +++++++--------------- src/main/java/racingcar/RacingCarMain.java | 9 +++++++-- src/main/java/racingcar/ResultView.java | 12 ++++++++---- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/main/java/racingcar/Racing.java b/src/main/java/racingcar/Racing.java index 6dfd880939f..fdb37737373 100644 --- a/src/main/java/racingcar/Racing.java +++ b/src/main/java/racingcar/Racing.java @@ -1,5 +1,6 @@ package racingcar; +import java.util.ArrayList; import java.util.List; import java.util.Random; @@ -8,27 +9,18 @@ public class Racing { private static final Random RANDOM = new Random(); private final List cars; - private final int roundNum; - private final ResultView resultView; - public Racing(List cars, int roundNum, ResultView resultView) { + public Racing(List cars) { this.cars = cars; - this.roundNum = roundNum; - this.resultView = resultView; } - public void start() { - for (int i = 0; i < roundNum; i++) { - resultView.roundStart(i + 1); - play(); - } - } - - private void play() { + public List play() { + List positions = new ArrayList(); for (Car car : cars) { - int position = car.move(RANDOM.nextInt(10)); - resultView.drawCarPosition(position); + car.move(RANDOM.nextInt(10)); + positions.add(car.getCurrentPosition()); } + return positions; } } diff --git a/src/main/java/racingcar/RacingCarMain.java b/src/main/java/racingcar/RacingCarMain.java index 54ebb0835ce..575e1f86ab0 100644 --- a/src/main/java/racingcar/RacingCarMain.java +++ b/src/main/java/racingcar/RacingCarMain.java @@ -15,8 +15,13 @@ public static void main(String[] args) { } ResultView resultView = new ResultView(); - Racing racing = new Racing(cars, roundNum, resultView); - racing.start(); + Racing racing = new Racing(cars); + + for (int i = 0; i < roundNum; i++) { + resultView.roundStart(i + 1); + List carPositions = racing.play(); + resultView.drawCarPositions(carPositions); + } } } diff --git a/src/main/java/racingcar/ResultView.java b/src/main/java/racingcar/ResultView.java index 0ba80876a52..9acbf3e59ca 100644 --- a/src/main/java/racingcar/ResultView.java +++ b/src/main/java/racingcar/ResultView.java @@ -1,5 +1,7 @@ package racingcar; +import java.util.List; + public class ResultView { private static final String LINE = "-".repeat(5); @@ -8,9 +10,11 @@ public static void roundStart(int roundNumber) { System.out.println(LINE + roundNumber + " 라운드 시작!" + LINE); } - public static void drawCarPosition(int position) { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("-".repeat(position)); - System.out.println(stringBuilder.toString()); + public static void drawCarPositions(List positions) { + for (int position : positions) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("-".repeat(position)); + System.out.println(stringBuilder.toString()); + } } } From d80b43b068b05249216029c2d48de2f1f8b14651 Mon Sep 17 00:00:00 2001 From: yun <90806941+yunji1201@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:18:07 +0900 Subject: [PATCH 06/14] =?UTF-8?q?docs=20:=204=EB=8B=A8=EA=B3=84=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/TODO.md b/TODO.md index 216882403a0..bbad38a7312 100644 --- a/TODO.md +++ b/TODO.md @@ -5,6 +5,11 @@ 3. [x] 전진하는 조건은 0에서 9 사이에서 random 값을 구한 후 random 값이 4이상일 경우 4. [x] 모든 자동차가 이동을 완료하면 종료 5. [x] 자동차의 상태를 화면에 출력 +6. [ ] 각 자동차에 이름 입력 가능. +7. [ ] 자동차 이름은 5글자를 초과할 수 없음 +8. [ ] 전진하는 자동차를 출력할 때 이름 같이 출력 +9. [ ] 자동차 이름은 쉼표(,)를 기준으로 구분 +10. [ ] 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려줌. 우승자는 한명 이상도 가능. - 값을 입력 받는 API는 Scanner를 이용 - 랜덤 값은 자바 java.util.Random 클래스의 nextInt(10) 메소드를 활용 From ea596ee7232fa1b40f95123df22c59ad92976c32 Mon Sep 17 00:00:00 2001 From: yun <90806941+yunji1201@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:11:08 +0900 Subject: [PATCH 07/14] =?UTF-8?q?test=20:=20=EC=9E=90=EB=8F=99=EC=B0=A8=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=EC=9D=B4=205=EA=B8=80=EC=9E=90=20=EC=9D=B4?= =?UTF-8?q?=EC=83=81=EC=9D=B8=20=EA=B2=BD=EC=9A=B0=20=EC=97=90=EB=9F=AC?= =?UTF-8?q?=EB=A5=BC=20=EB=B0=98=ED=99=98=ED=95=98=EB=8A=94=EC=A7=80=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8=ED=95=98=EB=8A=94=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/racingcar/Car.java | 21 +++++++++++++++ src/test/java/racingcar/RacingCarTest.java | 30 ++++++++++++++-------- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/main/java/racingcar/Car.java b/src/main/java/racingcar/Car.java index 865fda22334..d81d2e4a445 100644 --- a/src/main/java/racingcar/Car.java +++ b/src/main/java/racingcar/Car.java @@ -3,9 +3,30 @@ public class Car { public static final int MOVE_CONDITION = 4; + private static final int MAX_NAME_LENGTH = 5; + private final String name; private int currentPosition; + public Car(final String name) { + this(name, 0); + } + + public Car(String name, int position) { + validationCarName(name); + this.name = name.trim(); + this.currentPosition = position; + } + + private static void validationCarName(String name) { + if (name == null) { + throw new IllegalArgumentException("자동차 이름은 값이 존재해야 합니다."); + } + if (name.trim().length() >= MAX_NAME_LENGTH) { + throw new IllegalArgumentException("자동차 이름은 5 미만의 글자여야 합니다."); + } + } + public int move(int randomNumber) { if (randomNumber >= MOVE_CONDITION) { currentPosition++; diff --git a/src/test/java/racingcar/RacingCarTest.java b/src/test/java/racingcar/RacingCarTest.java index e4d2d6ee956..b39ea22f420 100644 --- a/src/test/java/racingcar/RacingCarTest.java +++ b/src/test/java/racingcar/RacingCarTest.java @@ -3,28 +3,38 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.Random; -import java.util.stream.IntStream; +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 RacingCarTest { - @Test + @ParameterizedTest @DisplayName("자동차가 이동하는 값이 4 이상일 경우 전진하는지 확인") - void carMovesWhenFourOrMore() { - Car car = new Car(); + @ValueSource(strings = {"yun"}) + void carMovesWhenFourOrMore(String name) { + Car car = new Car(name); car.move(4); assertThat(car.getCurrentPosition()).isEqualTo(1); } - @Test + @ParameterizedTest @DisplayName("자동차가 이동하는 값이 4 이하일 경우 멈춰있는지 확인") - void carStopWhenLessThanFour() { - Car car = new Car(); + @ValueSource(strings = {"yun"}) + void carStopWhenLessThanFour(String name) { + Car car = new Car(name); car.move(3); assertThat(car.getCurrentPosition()).isEqualTo(0); } + + @ParameterizedTest + @ValueSource(strings = {"longName"}) + @DisplayName("자동차 이름이 5글자 이상인 경우 에러를 반환하는지 확인") + void carNameThrowsExceptionWhenTooLong(String name) { + assertThatThrownBy(() -> new Car(name)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("자동차 이름은 5 미만의 글자여야 합니다."); + } + } From 29fff60bebf5c0e762456182c389ba659dadd8bf Mon Sep 17 00:00:00 2001 From: yun <90806941+yunji1201@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:13:24 +0900 Subject: [PATCH 08/14] =?UTF-8?q?feat=20:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EA=B0=80=20=EC=9E=90=EB=8F=99=EC=B0=A8=EC=9D=98=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=EC=9D=84=20=EC=9E=85=EB=A0=A5=20=ED=95=A0=20=EC=88=98?= =?UTF-8?q?=20=EC=9E=88=EC=96=B4=EC=95=BC=20=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO.md | 4 ++-- src/main/java/racingcar/InputView.java | 8 ++++---- src/main/java/racingcar/RacingCarMain.java | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/TODO.md b/TODO.md index bbad38a7312..c970f633e32 100644 --- a/TODO.md +++ b/TODO.md @@ -5,8 +5,8 @@ 3. [x] 전진하는 조건은 0에서 9 사이에서 random 값을 구한 후 random 값이 4이상일 경우 4. [x] 모든 자동차가 이동을 완료하면 종료 5. [x] 자동차의 상태를 화면에 출력 -6. [ ] 각 자동차에 이름 입력 가능. -7. [ ] 자동차 이름은 5글자를 초과할 수 없음 +6. [x] 각 자동차에 이름 입력 가능 +7. [x] 자동차 이름은 5글자를 초과할 수 없음 8. [ ] 전진하는 자동차를 출력할 때 이름 같이 출력 9. [ ] 자동차 이름은 쉼표(,)를 기준으로 구분 10. [ ] 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려줌. 우승자는 한명 이상도 가능. diff --git a/src/main/java/racingcar/InputView.java b/src/main/java/racingcar/InputView.java index f9b3a6064b0..c7970dc02b5 100644 --- a/src/main/java/racingcar/InputView.java +++ b/src/main/java/racingcar/InputView.java @@ -7,12 +7,12 @@ public class InputView { private static final Scanner SCANNER = new Scanner(System.in); private InputView() { - + } - public static int getCarNumber() { - System.out.println("자동차 개수는 몇 개 인가요?"); - return SCANNER.nextInt(); + public static String[] getCarNames() { + System.out.println("경주할 자동차 이름을 입력하세요. (이름은 쉼표(,)를 기준으로 구분"); + return SCANNER.nextLine().split(","); } public static int getRoundNumber() { diff --git a/src/main/java/racingcar/RacingCarMain.java b/src/main/java/racingcar/RacingCarMain.java index 575e1f86ab0..73c65836702 100644 --- a/src/main/java/racingcar/RacingCarMain.java +++ b/src/main/java/racingcar/RacingCarMain.java @@ -6,12 +6,12 @@ public class RacingCarMain { public static void main(String[] args) { - int carNum = InputView.getCarNumber(); + String[] names = InputView.getCarNames(); int roundNum = InputView.getRoundNumber(); List cars = new ArrayList<>(); - for (int i = 0; i < carNum; i++) { - cars.add(new Car()); + for (int i = 0; i < names.length; i++) { + cars.add(new Car(names[i])); } ResultView resultView = new ResultView(); From badbbeccaaed503ae6623d47c2df0c4aa291c08d Mon Sep 17 00:00:00 2001 From: yun <90806941+yunji1201@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:34:08 +0900 Subject: [PATCH 09/14] =?UTF-8?q?feat=20:=20=EC=A0=84=EC=A7=84=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EC=9E=90=EB=8F=99=EC=B0=A8=EB=A5=BC=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5=ED=95=A0=20=EB=95=8C=20=EC=9D=B4=EB=A6=84=EC=9D=84=20?= =?UTF-8?q?=EA=B0=99=EC=9D=B4=20=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO.md | 4 ++-- src/main/java/racingcar/Car.java | 4 ++++ src/main/java/racingcar/Racing.java | 10 ++++++---- src/main/java/racingcar/RacingCarMain.java | 2 +- src/main/java/racingcar/RacingResult.java | 20 ++++++++++++++++++++ src/main/java/racingcar/ResultView.java | 8 +++++--- 6 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 src/main/java/racingcar/RacingResult.java diff --git a/TODO.md b/TODO.md index c970f633e32..5c85455142d 100644 --- a/TODO.md +++ b/TODO.md @@ -7,8 +7,8 @@ 5. [x] 자동차의 상태를 화면에 출력 6. [x] 각 자동차에 이름 입력 가능 7. [x] 자동차 이름은 5글자를 초과할 수 없음 -8. [ ] 전진하는 자동차를 출력할 때 이름 같이 출력 -9. [ ] 자동차 이름은 쉼표(,)를 기준으로 구분 +9. [x] 자동차 이름은 쉼표(,)를 기준으로 구분 +8. [x] 전진하는 자동차를 출력할 때 이름 같이 출력 10. [ ] 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려줌. 우승자는 한명 이상도 가능. - 값을 입력 받는 API는 Scanner를 이용 diff --git a/src/main/java/racingcar/Car.java b/src/main/java/racingcar/Car.java index d81d2e4a445..ee9be70f7c9 100644 --- a/src/main/java/racingcar/Car.java +++ b/src/main/java/racingcar/Car.java @@ -38,4 +38,8 @@ public int getCurrentPosition() { return currentPosition; } + public String getName() { + return name; + } + } diff --git a/src/main/java/racingcar/Racing.java b/src/main/java/racingcar/Racing.java index fdb37737373..c6a3162fd07 100644 --- a/src/main/java/racingcar/Racing.java +++ b/src/main/java/racingcar/Racing.java @@ -14,13 +14,15 @@ public Racing(List cars) { this.cars = cars; } - public List play() { - List positions = new ArrayList(); + public List play() { + List racingResults = new ArrayList(); + for (Car car : cars) { car.move(RANDOM.nextInt(10)); - positions.add(car.getCurrentPosition()); + RacingResult racingResult = new RacingResult(car.getName(), car.getCurrentPosition()); + racingResults.add(racingResult); } - return positions; + return racingResults; } } diff --git a/src/main/java/racingcar/RacingCarMain.java b/src/main/java/racingcar/RacingCarMain.java index 73c65836702..dc487ab2db3 100644 --- a/src/main/java/racingcar/RacingCarMain.java +++ b/src/main/java/racingcar/RacingCarMain.java @@ -19,7 +19,7 @@ public static void main(String[] args) { for (int i = 0; i < roundNum; i++) { resultView.roundStart(i + 1); - List carPositions = racing.play(); + List carPositions = racing.play(); resultView.drawCarPositions(carPositions); } } diff --git a/src/main/java/racingcar/RacingResult.java b/src/main/java/racingcar/RacingResult.java new file mode 100644 index 00000000000..af4e39f0e0c --- /dev/null +++ b/src/main/java/racingcar/RacingResult.java @@ -0,0 +1,20 @@ +package racingcar; + +public class RacingResult { + + private final String name; + private final int position; + + public RacingResult(String name, int position) { + this.name = name; + this.position = position; + } + + public String getName() { + return name; + } + + public int getPosition() { + return position; + } +} diff --git a/src/main/java/racingcar/ResultView.java b/src/main/java/racingcar/ResultView.java index 9acbf3e59ca..7f494128146 100644 --- a/src/main/java/racingcar/ResultView.java +++ b/src/main/java/racingcar/ResultView.java @@ -10,10 +10,12 @@ public static void roundStart(int roundNumber) { System.out.println(LINE + roundNumber + " 라운드 시작!" + LINE); } - public static void drawCarPositions(List positions) { - for (int position : positions) { + public static void drawCarPositions(List results) { + for (RacingResult result : results) { StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("-".repeat(position)); + stringBuilder.append(result.getName()) + .append(" : ") + .append("-".repeat(result.getPosition())); System.out.println(stringBuilder.toString()); } } From d98673986901b0f361a68bf9863eae1118837a4e Mon Sep 17 00:00:00 2001 From: yun <90806941+yunji1201@users.noreply.github.com> Date: Wed, 9 Oct 2024 13:56:05 +0900 Subject: [PATCH 10/14] =?UTF-8?q?test=20:=20=EA=B0=80=EC=9E=A5=20=EB=A7=8E?= =?UTF-8?q?=EC=9D=80=20=EA=B1=B0=EB=A6=AC=EB=A5=BC=20=EA=B0=84=20=EC=9E=90?= =?UTF-8?q?=EB=8F=99=EC=B0=A8=EB=A5=BC=20=EC=9A=B0=EC=8A=B9=EC=9E=90?= =?UTF-8?q?=EB=A1=9C=20=EB=B0=98=ED=99=98=ED=95=98=EB=8A=94=EC=A7=80=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8=ED=95=98=EB=8A=94=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=A7=84=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/racingcar/Winners.java | 28 ++++++++++++++++++++++ src/test/java/racingcar/RacingCarTest.java | 17 +++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 src/main/java/racingcar/Winners.java diff --git a/src/main/java/racingcar/Winners.java b/src/main/java/racingcar/Winners.java new file mode 100644 index 00000000000..21918993593 --- /dev/null +++ b/src/main/java/racingcar/Winners.java @@ -0,0 +1,28 @@ +package racingcar; + +import java.util.ArrayList; +import java.util.List; + +public class Winners { + public static List findWinners(List cars) { + return findWinners(cars, getMaxPosition(cars)); + } + + private static List findWinners(List cars, int maxPosition) { + List winners = new ArrayList<>(); + for (Car car : cars) { + if (maxPosition == car.getCurrentPosition()) { + winners.add(car); + } + } + return winners; + } + + private static int getMaxPosition(List cars) { + int maxPosition = 0; + for (Car car : cars) { + maxPosition = Math.max(car.getCurrentPosition(), maxPosition); + } + return maxPosition; + } +} diff --git a/src/test/java/racingcar/RacingCarTest.java b/src/test/java/racingcar/RacingCarTest.java index b39ea22f420..aa182e0769e 100644 --- a/src/test/java/racingcar/RacingCarTest.java +++ b/src/test/java/racingcar/RacingCarTest.java @@ -5,6 +5,9 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import java.util.Arrays; +import java.util.List; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -37,4 +40,18 @@ void carNameThrowsExceptionWhenTooLong(String name) { .hasMessageContaining("자동차 이름은 5 미만의 글자여야 합니다."); } + @Test + @DisplayName("가장 많은 거리를 간 자동차를 우승자로 반환하는지 확인") + void findWinner() { + Car testCar1 = new Car("yun1", 3); + Car testCar2 = new Car("yun2", 2); + Car testCar3 = new Car("yun3", 1); + List cars = Arrays.asList(testCar1, testCar2, testCar3); + + List winners = Winners.findWinners(cars); + + assertThat(winners).hasSize(1); + assertThat(winners).contains(testCar1); + } + } From 0e5005e1534f56cee90184362bfd82fb76606d1d Mon Sep 17 00:00:00 2001 From: yun <90806941+yunji1201@users.noreply.github.com> Date: Wed, 9 Oct 2024 13:57:03 +0900 Subject: [PATCH 11/14] =?UTF-8?q?feat=20:=20=EB=A0=88=EC=9D=B4=EC=8B=B1=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C=20=ED=9B=84=20=EC=9A=B0=EC=8A=B9=EC=9E=90?= =?UTF-8?q?=EB=A5=BC=20=EC=B6=9C=EB=A0=A5=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO.md | 2 +- src/main/java/racingcar/Car.java | 2 +- src/main/java/racingcar/RacingCarMain.java | 2 ++ src/main/java/racingcar/ResultView.java | 15 ++++++++++++++- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/TODO.md b/TODO.md index 5c85455142d..cf659ddd422 100644 --- a/TODO.md +++ b/TODO.md @@ -9,7 +9,7 @@ 7. [x] 자동차 이름은 5글자를 초과할 수 없음 9. [x] 자동차 이름은 쉼표(,)를 기준으로 구분 8. [x] 전진하는 자동차를 출력할 때 이름 같이 출력 -10. [ ] 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려줌. 우승자는 한명 이상도 가능. +10. [x] 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려줌. 우승자는 한명 이상도 가능. - 값을 입력 받는 API는 Scanner를 이용 - 랜덤 값은 자바 java.util.Random 클래스의 nextInt(10) 메소드를 활용 diff --git a/src/main/java/racingcar/Car.java b/src/main/java/racingcar/Car.java index ee9be70f7c9..6950ee0dab9 100644 --- a/src/main/java/racingcar/Car.java +++ b/src/main/java/racingcar/Car.java @@ -4,8 +4,8 @@ public class Car { public static final int MOVE_CONDITION = 4; private static final int MAX_NAME_LENGTH = 5; - private final String name; + private final String name; private int currentPosition; public Car(final String name) { diff --git a/src/main/java/racingcar/RacingCarMain.java b/src/main/java/racingcar/RacingCarMain.java index dc487ab2db3..2f31a29603b 100644 --- a/src/main/java/racingcar/RacingCarMain.java +++ b/src/main/java/racingcar/RacingCarMain.java @@ -22,6 +22,8 @@ public static void main(String[] args) { List carPositions = racing.play(); resultView.drawCarPositions(carPositions); } + List winners = Winners.findWinners(cars); + resultView.printWinners(winners); } } diff --git a/src/main/java/racingcar/ResultView.java b/src/main/java/racingcar/ResultView.java index 7f494128146..77ea886990b 100644 --- a/src/main/java/racingcar/ResultView.java +++ b/src/main/java/racingcar/ResultView.java @@ -1,6 +1,7 @@ package racingcar; import java.util.List; +import java.util.stream.Collectors; public class ResultView { @@ -13,10 +14,22 @@ public static void roundStart(int roundNumber) { public static void drawCarPositions(List results) { for (RacingResult result : results) { StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(result.getName()) + stringBuilder + .append(result.getName()) .append(" : ") .append("-".repeat(result.getPosition())); System.out.println(stringBuilder.toString()); } } + + public void printWinners(List winners) { + String winnersName = winners.stream().map(Car::getName) + .collect(Collectors.joining(",")); + + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder + .append(winnersName) + .append("이(가) 최종 우승 했습니다."); + System.out.println(stringBuilder.toString()); + } } From 13a74348da23126a69c6cfa9f4ff6880396e780e Mon Sep 17 00:00:00 2001 From: yun <90806941+yunji1201@users.noreply.github.com> Date: Wed, 9 Oct 2024 22:20:06 +0900 Subject: [PATCH 12/14] =?UTF-8?q?test=20:=20Racing=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=EC=97=90=20=EB=8C=80=ED=95=9C=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/racingcar/RacingTest.java | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/test/java/racingcar/RacingTest.java diff --git a/src/test/java/racingcar/RacingTest.java b/src/test/java/racingcar/RacingTest.java new file mode 100644 index 00000000000..f687bcac53d --- /dev/null +++ b/src/test/java/racingcar/RacingTest.java @@ -0,0 +1,30 @@ +package racingcar; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class RacingTest { + + @Test + @DisplayName("자동차의 위치와 이름을 가지고 있는 RacingResult로 잘 반환하는지 확인") + void playTest() { + Car testCar1 = new Car("yun", 0); + Car testCar2 = new Car("yun2", 0); + List cars = Arrays.asList(testCar1, testCar2); + + Racing racing = new Racing(cars); + List results = racing.play(); + + assertThat(results).hasSize(2); + assertThat(results.get(0).getName()).isEqualTo("yun"); + assertThat(results.get(1).getName()).isEqualTo("yun2"); + assertThat(results.get(0).getPosition()).isGreaterThanOrEqualTo(0); + assertThat(results.get(1).getPosition()).isGreaterThanOrEqualTo(0); + } + +} From f1813302ff465c418fa117672f656a354fbb03c3 Mon Sep 17 00:00:00 2001 From: yun <90806941+yunji1201@users.noreply.github.com> Date: Wed, 9 Oct 2024 22:21:04 +0900 Subject: [PATCH 13/14] =?UTF-8?q?refactor=20:=20=EA=B0=81=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{RacingCarTest.java => CarTest.java} | 20 +------------- src/test/java/racingcar/WinnersTest.java | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 19 deletions(-) rename src/test/java/racingcar/{RacingCarTest.java => CarTest.java} (69%) create mode 100644 src/test/java/racingcar/WinnersTest.java diff --git a/src/test/java/racingcar/RacingCarTest.java b/src/test/java/racingcar/CarTest.java similarity index 69% rename from src/test/java/racingcar/RacingCarTest.java rename to src/test/java/racingcar/CarTest.java index aa182e0769e..f1adff231bf 100644 --- a/src/test/java/racingcar/RacingCarTest.java +++ b/src/test/java/racingcar/CarTest.java @@ -1,17 +1,13 @@ package racingcar; 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 java.util.Arrays; -import java.util.List; - import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -public class RacingCarTest { +public class CarTest { @ParameterizedTest @DisplayName("자동차가 이동하는 값이 4 이상일 경우 전진하는지 확인") @@ -40,18 +36,4 @@ void carNameThrowsExceptionWhenTooLong(String name) { .hasMessageContaining("자동차 이름은 5 미만의 글자여야 합니다."); } - @Test - @DisplayName("가장 많은 거리를 간 자동차를 우승자로 반환하는지 확인") - void findWinner() { - Car testCar1 = new Car("yun1", 3); - Car testCar2 = new Car("yun2", 2); - Car testCar3 = new Car("yun3", 1); - List cars = Arrays.asList(testCar1, testCar2, testCar3); - - List winners = Winners.findWinners(cars); - - assertThat(winners).hasSize(1); - assertThat(winners).contains(testCar1); - } - } diff --git a/src/test/java/racingcar/WinnersTest.java b/src/test/java/racingcar/WinnersTest.java new file mode 100644 index 00000000000..1f24f2392c3 --- /dev/null +++ b/src/test/java/racingcar/WinnersTest.java @@ -0,0 +1,27 @@ +package racingcar; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class WinnersTest { + + @Test + @DisplayName("가장 많은 거리를 간 자동차를 우승자로 반환하는지 확인") + void findWinner() { + Car testCar1 = new Car("yun1", 3); + Car testCar2 = new Car("yun2", 2); + Car testCar3 = new Car("yun3", 1); + List cars = Arrays.asList(testCar1, testCar2, testCar3); + + List winners = Winners.findWinners(cars); + + assertThat(winners).hasSize(1); + assertThat(winners).contains(testCar1); + } + +} From 68499a7b0a394196660df187c33f5a8e44b374ed Mon Sep 17 00:00:00 2001 From: yun <90806941+yunji1201@users.noreply.github.com> Date: Wed, 9 Oct 2024 22:21:38 +0900 Subject: [PATCH 14/14] =?UTF-8?q?refactor=20:=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20=EB=B0=9B=EC=9D=80=EA=B1=B8=20=EB=B0=94?= =?UTF-8?q?=ED=83=95=EC=9C=BC=EB=A1=9C=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81=20=EC=A7=84=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/racingcar/Car.java | 6 +++--- src/main/java/racingcar/RacingCarMain.java | 7 +++---- src/main/java/racingcar/ResultView.java | 6 +++++- src/main/java/racingcar/Winners.java | 10 +++++++--- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/main/java/racingcar/Car.java b/src/main/java/racingcar/Car.java index 6950ee0dab9..14c2f431353 100644 --- a/src/main/java/racingcar/Car.java +++ b/src/main/java/racingcar/Car.java @@ -2,7 +2,7 @@ public class Car { - public static final int MOVE_CONDITION = 4; + private static final int MOVE_CONDITION = 4; private static final int MAX_NAME_LENGTH = 5; private final String name; @@ -18,8 +18,8 @@ public Car(String name, int position) { this.currentPosition = position; } - private static void validationCarName(String name) { - if (name == null) { + private void validationCarName(String name) { + if (name == null || name.trim().isBlank()) { throw new IllegalArgumentException("자동차 이름은 값이 존재해야 합니다."); } if (name.trim().length() >= MAX_NAME_LENGTH) { diff --git a/src/main/java/racingcar/RacingCarMain.java b/src/main/java/racingcar/RacingCarMain.java index 2f31a29603b..882fad84d92 100644 --- a/src/main/java/racingcar/RacingCarMain.java +++ b/src/main/java/racingcar/RacingCarMain.java @@ -14,16 +14,15 @@ public static void main(String[] args) { cars.add(new Car(names[i])); } - ResultView resultView = new ResultView(); Racing racing = new Racing(cars); for (int i = 0; i < roundNum; i++) { - resultView.roundStart(i + 1); + ResultView.roundStart(i + 1); List carPositions = racing.play(); - resultView.drawCarPositions(carPositions); + ResultView.drawCarPositions(carPositions); } List winners = Winners.findWinners(cars); - resultView.printWinners(winners); + ResultView.printWinners(winners); } } diff --git a/src/main/java/racingcar/ResultView.java b/src/main/java/racingcar/ResultView.java index 77ea886990b..61eb1f75e3c 100644 --- a/src/main/java/racingcar/ResultView.java +++ b/src/main/java/racingcar/ResultView.java @@ -7,6 +7,10 @@ public class ResultView { private static final String LINE = "-".repeat(5); + private ResultView() { + + } + public static void roundStart(int roundNumber) { System.out.println(LINE + roundNumber + " 라운드 시작!" + LINE); } @@ -22,7 +26,7 @@ public static void drawCarPositions(List results) { } } - public void printWinners(List winners) { + public static void printWinners(List winners) { String winnersName = winners.stream().map(Car::getName) .collect(Collectors.joining(",")); diff --git a/src/main/java/racingcar/Winners.java b/src/main/java/racingcar/Winners.java index 21918993593..b7d8442f530 100644 --- a/src/main/java/racingcar/Winners.java +++ b/src/main/java/racingcar/Winners.java @@ -11,13 +11,17 @@ public static List findWinners(List cars) { private static List findWinners(List cars, int maxPosition) { List winners = new ArrayList<>(); for (Car car : cars) { - if (maxPosition == car.getCurrentPosition()) { - winners.add(car); - } + addIfMaxPosition(maxPosition, car, winners); } return winners; } + private static void addIfMaxPosition(int maxPosition, Car car, List winners) { + if (maxPosition == car.getCurrentPosition()) { + winners.add(car); + } + } + private static int getMaxPosition(List cars) { int maxPosition = 0; for (Car car : cars) {