diff --git a/README.md b/README.md index 8fe711203..0adb608f4 100644 --- a/README.md +++ b/README.md @@ -24,3 +24,29 @@ git checkout main // 기본 브랜치가 main인 경우 git checkout -b 브랜치이름 ex) git checkout -b apply-feedback ``` +4. 구현할 기능 목록 + +### InputView +```jsx +- 3자리의 난수 생성 (조건 : 각 숫자가 겹치지 않는다) +- 사용자의 입력값 받고 저장 + - 입력값 검증 : + - 3자리의 각 자리가 중복이 안되는지, + - 1~9 사이의 수 인지 +``` +### NumbersBaseball +```jsx +- 난수와 입력값 비교 + - 같은 위치에 같은 숫자라면 strike + - 다른 위치에 같은 숫자가 있으면 ball + - 아무것도 겹치지 않으면 낫싱 +- 3 strike가 아니라면 다시 입력값 받기 +- 3 strike라면 게임이 끝 +- 게임을 다시 시작하거나 완전히 종료할 수 있다 +``` +### ResultView +```jsx +- strike, ball, nothing 점수 혹은 결과 출력 +- 3 strike일 때 종료 메세지 출력 +``` + diff --git a/build.gradle b/build.gradle index 8172fb73f..0606c3114 100644 --- a/build.gradle +++ b/build.gradle @@ -12,6 +12,7 @@ repositories { dependencies { testImplementation "org.junit.jupiter:junit-jupiter:5.7.2" testImplementation "org.assertj:assertj-core:3.19.0" + testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1' } test { diff --git a/src/main/java/numbersBaseball/InputView.java b/src/main/java/numbersBaseball/InputView.java new file mode 100644 index 000000000..c89bee5c0 --- /dev/null +++ b/src/main/java/numbersBaseball/InputView.java @@ -0,0 +1,64 @@ +package numbersBaseball; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Scanner; + +public class InputView { + public static int[] check = new int[10]; // 1 ~ 9 + + // 3자리 수 입력 받기 + public static int inputNumber() { + Scanner sc = new Scanner(System.in); + return sc.nextInt(); + } + + // 랜덤 수 3자리 생성 + public static int duplicateCheck(int[] randomNum, int idx, int num) { + if(check[num] == 0) { + randomNum[idx] = num; + check[num] = idx + 1; // random number 각 인덱스값 저장 + idx++; + } + return idx; //현재 idx 반환 + } + public static void makeRandomNumber(int[] randomNum) { + int idx = 0; + + while (idx != 3) { + int cur = ((int)(Math.random()*8)+1); // random number 생성 + idx = duplicateCheck(randomNum, idx, cur); + } + } + + + // validation + public static boolean validateNumber(ArrayList numList) { + boolean verification = false; + + if(!(numList.size()==3)) return verification; + for (Integer number: numList) { + if(!(Collections.frequency(numList, number) == 1)) { + System.out.println(ValidationError.duplication); + return verification; + } + if(!((0 < number) && (number < 10))) { + System.out.println(ValidationError.intermediateValue); + return verification; + } + } + + return true; + } + + // 정수 쪼개기 + public static ArrayList splitNumber(int inputNum) { +// int[] numList = new int[4]; + ArrayList arr = new ArrayList<>(); + arr.add(inputNum / 100); + arr.add((inputNum % 100) / 10); + arr.add((inputNum % 10)); + + return arr; + } +} diff --git a/src/main/java/numbersBaseball/NumbersBaseball.java b/src/main/java/numbersBaseball/NumbersBaseball.java new file mode 100644 index 000000000..080f27314 --- /dev/null +++ b/src/main/java/numbersBaseball/NumbersBaseball.java @@ -0,0 +1,54 @@ +package numbersBaseball; + +import java.util.ArrayList; + +public class NumbersBaseball { + + public static int compareTo(ArrayList compareNum){ + // 초기화 + int strike = 0, ball = 0; + + for (int i = 1; i <= 3; i++) { + int cur = compareNum.get(i-1); + + if(InputView.check[cur] != 0 && InputView.check[cur] == i) { + strike++; + continue; + } + if(InputView.check[cur] != 0) { + ball++; + } + } + System.out.println(ResultView.scoreResult(strike, ball)); + return strike; + } + + public void game(int[] randomNum) { + int strike = 0, ball = 0; + InputView.makeRandomNumber(randomNum); + + while(strike != 3) { + System.out.print("숫자를 입력해 주세요 : "); + + int inputNum = InputView.inputNumber(); + ArrayList inputList = InputView.splitNumber(inputNum); + + if(!InputView.validateNumber(inputList)) continue; + + strike = compareTo(inputList); + } + } + + public NumbersBaseball() { + int[] randomNum = new int[3]; + while (true) { + game(randomNum); + ResultView.ending(); + if(InputView.inputNumber() == 2) return; + } + } + + public static void main(String[] args) { + new NumbersBaseball(); + } +} diff --git a/src/main/java/numbersBaseball/ResultView.java b/src/main/java/numbersBaseball/ResultView.java new file mode 100644 index 000000000..beeba8de2 --- /dev/null +++ b/src/main/java/numbersBaseball/ResultView.java @@ -0,0 +1,18 @@ +package numbersBaseball; + +public class ResultView { + public static String scoreResult(int strike, int ball) { + StringBuilder sb = new StringBuilder(); + + if(ball != 0) sb.append(ball).append("볼 "); + if(strike != 0) sb.append(strike).append("스트라이크"); + if(ball == 0 && strike == 0) return "낫싱"; + + return sb.toString(); + } + + public static void ending() { + System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료"); + System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."); + } +} diff --git a/src/main/java/numbersBaseball/ValidationError.java b/src/main/java/numbersBaseball/ValidationError.java new file mode 100644 index 000000000..97916ed53 --- /dev/null +++ b/src/main/java/numbersBaseball/ValidationError.java @@ -0,0 +1,7 @@ +package numbersBaseball; + +public class ValidationError { + public static String intermediateValue = "1 ~ 9 사이의 숫자를 입력해주세요."; + public static String duplication = "중복된 값 없이 입력해주세요."; + +} diff --git a/src/main/java/study/StringCalculator.java b/src/main/java/study/StringCalculator.java new file mode 100644 index 000000000..6307044ff --- /dev/null +++ b/src/main/java/study/StringCalculator.java @@ -0,0 +1,55 @@ +package study; + +import java.util.Scanner; + +public class StringCalculator { + // 사칙연산 + public int add(int a, int b){ return a + b;} + public int subtract(int a, int b){ return a - b;} + public int multiply(int a, int b){ return a * b;} + public int divide(int a, int b){ + try { + return a / b; + } catch (Exception e) { + System.out.println("0으로 나눌 수 없습니다."); + }return 0; + } + // 분할 메소드 + public String[] split(String str) { + return str.split(" "); + } + public int toInt(String input) { + return Integer.parseInt(input); + } + public int transform(String[] values) { + int result = toInt(values[0]); + for (int i = 1; i < values.length; i += 2) { + result = operator(result, values[i],toInt(values[i+1])); + } + return result; + } + // 더하기, 곱하기, 나누기, 빼기 함수 + public int operator(int firstValue, String operator, int secondValue) { + switch (operator) { + case "+": + return add(firstValue, secondValue); + case "-": + return subtract(firstValue, secondValue); + case "*": + return multiply(firstValue, secondValue); + case "/": + return divide(firstValue, secondValue); + default: + System.out.println("사칙 연산자가 아닙니다."); + + } + return 0; + } + + public static void main(String[] args) { + Scanner sc = new Scanner(System.in); + String value = sc.nextLine(); + StringCalculator T = new StringCalculator(); + T.transform(T.split(value)); + } +} diff --git a/src/test/java/numbersBaseball/InputViewTest.java b/src/test/java/numbersBaseball/InputViewTest.java new file mode 100644 index 000000000..e2635c7c9 --- /dev/null +++ b/src/test/java/numbersBaseball/InputViewTest.java @@ -0,0 +1,50 @@ +package numbersBaseball; + +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; + +import static org.assertj.core.api.Assertions.assertThat; + +class InputViewTest { + // 난수 생성 테스트 + @Test + void makeRandomNumTest() { + int[] randomNum = new int[3]; + + InputView.makeRandomNumber(randomNum); + for (int i = 0; i < randomNum.length; i++) { + assertThat(0 < randomNum[i] && randomNum[i] <10).isEqualTo(true); + assertThat(InputView.check[randomNum[i]]).isNotZero(); + } + } + // 각 자리수를 정수 배열로 생성하는 테스트 + @Test + void splitNumTest() { + int num = 235; + ArrayList numList = InputView.splitNumber(num); + assertThat(numList.toString()).isEqualTo("[0, 2, 3, 5]"); // idx 1~3 사용 + } + + /** + * 입력값 유효성 검증 테스트 + */ + @Test + void validateNumTest_success() { + ArrayList numList = InputView.splitNumber(146); + assertThat(InputView.validateNumber(numList)).isEqualTo(true); + } + + // 사용자가 중복값 입력 시 false + @Test + void validateNumTest_fail1() { + ArrayList numList = InputView.splitNumber(444); + assertThat(InputView.validateNumber(numList)).isEqualTo(false); + } + // 사용자가 1~9 이외의 값 입력 시 + @Test + void validateNumTest_fail2() { + ArrayList numList = InputView.splitNumber(405); + assertThat(InputView.validateNumber(numList)).isEqualTo(false); + } +} \ No newline at end of file diff --git a/src/test/java/numbersBaseball/NumbersBaseballTest.java b/src/test/java/numbersBaseball/NumbersBaseballTest.java new file mode 100644 index 000000000..fff2c3a42 --- /dev/null +++ b/src/test/java/numbersBaseball/NumbersBaseballTest.java @@ -0,0 +1,35 @@ +package numbersBaseball; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Arrays; + +import static numbersBaseball.NumbersBaseball.compareTo; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; + + +class NumbersBaseballTest { + // 각 자리수 비교 테스트 + @Test + void compareToTest() { + // given + int[] randomNum = new int[3]; + InputView.makeRandomNumber(randomNum); + + + ArrayList sameList = new ArrayList<>(); + for (int x: + randomNum) { + sameList.add(x); + } + + // expected + // strike의 개수가 0 이상? + assertEquals(compareTo(sameList), 3); + + } + +} \ No newline at end of file diff --git a/src/test/java/study/SetTest.java b/src/test/java/study/SetTest.java new file mode 100644 index 000000000..8ffc28884 --- /dev/null +++ b/src/test/java/study/SetTest.java @@ -0,0 +1,47 @@ +package study; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +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; +import static org.junit.jupiter.api.Assertions.assertEquals; + +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 case 구현 + @Test + @DisplayName("set 중복을 허용하지 않는 자료구조") + void size() { + assertThat(numbers.size()).isEqualTo(3); + } + + + @ParameterizedTest + @DisplayName("ParameterizedTest - 중복소거") + @ValueSource(ints = {1, 2, 3}) + void contains1(Integer integer) { + assertThat(numbers).contains(integer); //contains 메소드 결과 값이 true인 경우만 테스트 가능 + } + + @ParameterizedTest + @DisplayName("ParameterizedTest - 입력 값에 따라 결과 값이 다른 경우") + @CsvSource(value = {"1:true", "2:true", "3:true", "4:false", "5:false"}, delimiter = ':') + void contains2(String input, String output) { + boolean actualNum = numbers.contains(Integer.parseInt(input)); + assertEquals(Boolean.parseBoolean(output),actualNum); + } +} diff --git a/src/test/java/study/StringCalculatorTest.java b/src/test/java/study/StringCalculatorTest.java new file mode 100644 index 000000000..f97a5c785 --- /dev/null +++ b/src/test/java/study/StringCalculatorTest.java @@ -0,0 +1,47 @@ +package study; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class StringCalculatorTest { + StringCalculator cal; + + @BeforeEach + public void setUp() { + cal = new StringCalculator(); + } + + @Test + public void add() { + assertEquals(7, cal.add(3, 4)); + } + + @Test + public void subtract() { + assertEquals(1, cal.subtract(5, 4)); + } + + @Test + public void multiply() { + assertEquals(6, cal.multiply(2, 3)); + } + + @Test + public void divide() { + assertEquals(2, cal.divide(8, 4)); + } + + @Test void calc() { + int result = cal.transform(cal.split("2 + 3 * 4 / 2")); + assertEquals(10, result); + } + + @AfterEach + public void tearDown() { + cal = null; + } +} \ No newline at end of file diff --git a/src/test/java/study/StringTest.java b/src/test/java/study/StringTest.java index 43e47d90b..e2e97abd1 100644 --- a/src/test/java/study/StringTest.java +++ b/src/test/java/study/StringTest.java @@ -1,8 +1,10 @@ package study; +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.assertThatExceptionOfType; public class StringTest { @Test @@ -10,4 +12,40 @@ void replace() { String actual = "abc".replace("b", "d"); assertThat(actual).isEqualTo("adc"); } + + @Test + void split() { + String[] test1 = "1,2".split(","); + assertThat(test1).contains("1","2"); + + String[] test2 = "1".split(","); + assertThat(test2).containsExactly("1"); + } + + @Test + void substring() { + String test3 = "(1,2)".substring(1,4); + assertThat(test3).isEqualTo("1,2"); + } + + @Test + @DisplayName("charAt() - 특정 index의 문자 구하기 메소드") + void charAt() { + String test4 = "abc"; + char temp = test4.charAt(0); + assertThat(temp).isEqualTo('a'); + + } + @Test + @DisplayName("charAt() - 위치값을 벗어나 발생하는 예외") + void chatAtException() { + //when + String test4 = "abc"; + //then + assertThatExceptionOfType(IndexOutOfBoundsException.class) + .isThrownBy(()->{ + test4.charAt(4); + }).withMessageMatching("String index out of range: 4"); + } + }