diff --git a/src/main/java/Main.java b/src/main/java/Main.java new file mode 100644 index 000000000..385e1ab79 --- /dev/null +++ b/src/main/java/Main.java @@ -0,0 +1,39 @@ +import study.numberBaseball.NumberBaserball; + +import java.util.Scanner; + +public class Main { + public static void main(String[] args) { + + Scanner sc = new Scanner(System.in); + + int gameStart = 1; + int number = 0; + int input = 0; + NumberBaserball baseball = new NumberBaserball(); + number = baseball.initNumber(); + while (gameStart == 1){ + + input = baseball.scanNumber(sc); + + int ballCount = baseball.countBall(number, input); + int strikeCount = baseball.countStrike(number, input); + + String result = baseball.printResult(ballCount, strikeCount); + System.out.println(result); + + if(strikeCount != 3){ + continue; + } + + if(baseball.contiueGame(sc) == 1){ + baseball.initNumber(); + continue; + } + + gameStart = 2; + baseball.printGameOver(); + } + + } +} diff --git a/src/main/java/study/StringCalculator.java b/src/main/java/study/StringCalculator.java new file mode 100644 index 000000000..a1b2dd06a --- /dev/null +++ b/src/main/java/study/StringCalculator.java @@ -0,0 +1,48 @@ +package study; + +public class StringCalculator { + + public StringCalculator(){ + } + + public String[] split(String s){ + return s.split(" "); + } + + public int calculate(String[] strings){ + + int[] nums = new int[strings.length/2 + 1]; + String[] oper = new String[strings.length/2]; + + int numsI = 0; + int operI = 0; + for(String s : strings){ + + if(s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")){ + oper[operI++] = s; + }else{ + nums[numsI++] = Integer.parseInt(s); + } + } + + int sum = nums[0]; + for(int i = 1 ; i < nums.length ; i++){ + if(oper[i-1].equals("+")){ + sum += nums[i]; + }else if(oper[i-1].equals("-")){ + sum -= nums[i]; + }else if(oper[i-1].equals("*")){ + sum *= nums[i]; + }else if(oper[i-1].equals("/")){ + sum /= nums[i]; + } + } + + return sum; + } + + + + + +} diff --git a/src/main/java/study/numberBaseball/NumberBaserball.java b/src/main/java/study/numberBaseball/NumberBaserball.java new file mode 100644 index 000000000..ec91a298a --- /dev/null +++ b/src/main/java/study/numberBaseball/NumberBaserball.java @@ -0,0 +1,117 @@ +package study.numberBaseball; + +import java.util.Scanner; + +public class NumberBaserball { + + + public int initNumber() { + + int num = makeNumber(); + + while(hasSameNumber(num)){ + num = makeNumber(); + } + + return num; + + } + + public boolean hasSameNumber(int num) { + int[] nums = new int[3]; + int index = 0; + while(num > 0){ + nums[index++] = num % 10; + num /= 10; + } + + return nums[0] == nums[1] + || nums[1] == nums[2] + || nums[2] == nums[0]; + } + + public int makeNumber() { + return (int)(Math.random() * 1000); + } + + public int scanNumber(Scanner sc) { + + System.out.print("숫자를 입력해 주세요 : "); + return sc.nextInt(); + } + + public int countBall(int number, int input) { + + int[] numbers = numberToArray(number); + int[] inputs = numberToArray(input); + + int count = 0; + if(numbers[0] == inputs[1] || numbers[0] == inputs[2]){ + count += 1; + } + if(numbers[1] == inputs[2] || numbers[1] == inputs[0]){ + count += 1; + } + if(numbers[2] == inputs[0] || numbers[2] == inputs[1]){ + count += 1; + } + + return count; + } + + public int[] numberToArray(int number) { + int[] result = new int[3]; + for(int i = 2 ; i >= 0 ; i--){ + result[i] = number % 10; + number /= 10; + } + return result; + } + + public int countStrike(int number, int input) { + int[] numbers = numberToArray(number); + int[] inputs = numberToArray(input); + int count = 0; + for(int i = 0 ; i < inputs.length ; i++){ + count += numbers[i] == inputs[i] ? 1 : 0; + } + return count; + } + + public String printResult(int ballCount, int strikeCount) { + + StringBuilder sb = new StringBuilder(); + if(strikeCount == 3){ + sb.append("3스트라이크\n"); + sb.append("3개의 숫자를 모두 맞히셧습니다! 게임종료"); + + return sb.toString(); + } + + + if(ballCount > 0){ + sb.append(ballCount).append("볼"); + } + if(ballCount > 0 && strikeCount > 0){ + sb.append(" "); + } + if(strikeCount > 0){ + sb.append(strikeCount).append("스트라이크"); + } + if(ballCount == 0 && strikeCount == 0){ + sb.append("아무것도 없습니다."); + } + + return sb.toString(); + + } + + public int contiueGame(Scanner sc) { + System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."); + return sc.nextInt(); + } + + public void printGameOver() { + System.out.println("게임종료!"); + } +} diff --git a/src/main/java/study/numberBaseball/README.md b/src/main/java/study/numberBaseball/README.md new file mode 100644 index 000000000..c330fa492 --- /dev/null +++ b/src/main/java/study/numberBaseball/README.md @@ -0,0 +1,34 @@ +숫자야구게임 구현 +============== + +숫자야구게임을 구현합니다. +컴퓨터가 겹치지 않는 랜덤한 숫자 3개를 뽑고 +플레이어가 입력한 숫자가 같은자리면 스트라이크, +다른자리면 볼, 전혀 없으면 포볼 또는 낫싱 이란 +힌트를 얻고 숫자를 맞추면 된다. + + +### 주요기능 +1. 겹치지 않는 서로 다른 숫자 3자리 수 만들기 +2. 사용자의 입력 받기 +3. 입력에 따른 숫자의 결과 출력 +4. 2~3의 과정을 맞출 때 까지 반복하기 +5. 다 맞추면(3스트라이크)면 반복 종료 +6. 게임을 새로 시작(1) 하거나 종료(2) 하기 + +### 프로그래밍 요구사항 + -자바 코드 컨벤션을 지키면서 프로그래밍한다. + -기본적으로 Google Java Style Guide을 원칙으로 한다. + -단, 들여쓰기는 '2 spaces'가 아닌 '4 spaces'로 한다. + -indent(인덴트, 들여쓰기) depth를 2가 넘지 않도록 구현한다. 1까지만 허용한다. + -예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다. + -힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메소드)를 분리하면 된다. + -else 예약어를 쓰지 않는다. + -힌트: if 조건절에서 값을 return하는 방식으로 구현하면 else를 사용하지 않아도 된다. + -else를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다. + -모든 로직에 단위 테스트를 구현한다. 단, UI(System.out, System.in) 로직은 제외 + -핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다. + -UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다. + -3항 연산자를 쓰지 않는다. + -함수(또는 메소드)가 한 가지 일만 하도록 최대한 작게 만들어라. + diff --git a/src/test/java/study/SetTest.java b/src/test/java/study/SetTest.java new file mode 100644 index 000000000..1160245ef --- /dev/null +++ b/src/test/java/study/SetTest.java @@ -0,0 +1,43 @@ +package study; + +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.BeforeEach; +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; + +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 + void sizeTest(){ + int actual = numbers.size(); + assertThat(actual).isEqualTo(3); + } + + @ParameterizedTest + @ValueSource(ints = {1, 2, 3}) + void contains(int i){ + assertThat(numbers.contains(i)).isTrue(); + } + + @ParameterizedTest + @CsvSource(value={"1:true", "2:true", "3:true", "4: false", "5:false"}, delimiter = ':') + void containsFailureTest(int i, boolean result){ + assertThat(numbers.contains(i)).isEqualTo(result); + } +} diff --git a/src/test/java/study/StringCalculatorTest.java b/src/test/java/study/StringCalculatorTest.java new file mode 100644 index 000000000..d4d7ddd4b --- /dev/null +++ b/src/test/java/study/StringCalculatorTest.java @@ -0,0 +1,16 @@ +package study; + +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + +public class StringCalculatorTest { + + @Test + void calculator(){ + StringCalculator s = new StringCalculator(); + String[] strings = s.split("2 + 3 * 4 / 2"); + int actual = s.calculate(strings); + assertThat(actual).isEqualTo(10); + } + +} diff --git a/src/test/java/study/StringTest.java b/src/test/java/study/StringTest.java index 43e47d90b..d3b2982a6 100644 --- a/src/test/java/study/StringTest.java +++ b/src/test/java/study/StringTest.java @@ -1,8 +1,11 @@ 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.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertTrue; public class StringTest { @Test @@ -10,4 +13,40 @@ void replace() { String actual = "abc".replace("b", "d"); assertThat(actual).isEqualTo("adc"); } + + @Test + void split(){ + String[] actual = "1,2".split(","); + assertThat(actual).contains("1","2"); + } + + @Test + void spilt2(){ + String[] actual = "1".split(","); + assertThat(actual).containsExactly("1"); + } + + @Test + void subString(){ + String actual = "(1,2)".substring(1,4); + assertThat(actual).isEqualTo("1,2"); + } + + @Test + void charAt(){ + char actual = "abc".charAt(1); + assertThat(actual).isEqualTo('b'); + } + + @Test + @DisplayName("charAtExceptionText") + void chatAtException(){ + assertThatThrownBy(() -> { + char c = "abc".charAt(4); + }).isInstanceOf(StringIndexOutOfBoundsException.class) + .hasMessageContaining("String index out of range: 4"); + } + + + } diff --git a/src/test/java/study/numberBaseball/NumberBaseballTest.java b/src/test/java/study/numberBaseball/NumberBaseballTest.java new file mode 100644 index 000000000..0790bef4d --- /dev/null +++ b/src/test/java/study/numberBaseball/NumberBaseballTest.java @@ -0,0 +1,58 @@ +package study.numberBaseball; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import study.numberBaseball.NumberBaserball; + +public class NumberBaseballTest { + + NumberBaserball baserball; + + @BeforeEach + void init(){ + baserball = new NumberBaserball(); + } + + @Test + void makeNumber(){ + int actual = baserball.makeNumber(); + Assertions.assertThat(actual).isNotEqualTo(0); + } + + @ParameterizedTest + @CsvSource(value={"121:true", "944:true","631:false", "225:true", "547:false"}, delimiter = ':') + void hasSameNumber(int num, boolean result){ + boolean actual = baserball.hasSameNumber(num); + Assertions.assertThat(actual).isEqualTo(result); + + + } + + @ParameterizedTest + @CsvSource(value = {"123:123:0","123:321:2","583:358:3","794:421:1"}, delimiter = ':') + void countBall(int number, int input, int expected){ + int actual = baserball.countBall(number, input); + Assertions.assertThat(actual).isEqualTo(expected); + } + + @ParameterizedTest + @CsvSource(value = {"123:123:3","567:561:2","953:243:1","521:251:1"},delimiter = ':') + void countStrike(int number, int input, int expected){ + int actual = baserball.countStrike(number, input); + Assertions.assertThat(actual).isEqualTo(expected); + } + + @ParameterizedTest + @CsvSource(value = {"1:2:1볼 2스트라이크","2:1:2볼 1스트라이크" + ,"3:0:3볼", "0:0:아무것도 없습니다."}, delimiter = ':') + void printResult(int ball, int strike, String expeced){ + String actual = baserball.printResult(ball, strike); + Assertions.assertThat(actual).matches(expeced); + } + + + +}