diff --git a/src/main/java/baseball/Ball.java b/src/main/java/baseball/Ball.java new file mode 100644 index 000000000..6e581d338 --- /dev/null +++ b/src/main/java/baseball/Ball.java @@ -0,0 +1,47 @@ +package baseball; + +import java.util.Objects; + +public class Ball { + + private final int position, ballNo; + + public Ball(int position, int ballNo) { + this.position = position; + this.ballNo = ballNo; + } + + public BallStatus play(Ball ball) { + + // 1,4 - 2,5 / nothing + // 1,4 - 2,4 / ball + // 1,4 - 1,4 / strike + + if (this.equals(ball)) { + return BallStatus.STRIKE; + } + + if (ball.matchBallNumber(ballNo)) { + return BallStatus.BALL; + } + + return BallStatus.NOTHING; + } + + private boolean matchBallNumber(int ballNo) { + return this.ballNo == ballNo; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Ball)) return false; + Ball ball = (Ball) o; + return position == ball.position && ballNo == ball.ballNo; + } + + @Override + public int hashCode() { + return Objects.hash(position, ballNo); + } +} diff --git a/src/main/java/baseball/BallStatus.java b/src/main/java/baseball/BallStatus.java new file mode 100644 index 000000000..9a58e6829 --- /dev/null +++ b/src/main/java/baseball/BallStatus.java @@ -0,0 +1,10 @@ +package baseball; + +public enum BallStatus { + BALL, STRIKE, NOTHING; + + + public boolean isNotNothing() { + return this != NOTHING; + } +} diff --git a/src/main/java/baseball/Balls.java b/src/main/java/baseball/Balls.java new file mode 100644 index 000000000..e56a920cb --- /dev/null +++ b/src/main/java/baseball/Balls.java @@ -0,0 +1,37 @@ +package baseball; + +import java.util.ArrayList; +import java.util.List; + +public class Balls { + + private List answers; // 1,2,3 + + public Balls(List answers) { + this.answers = mapBalls(answers); + } + + public BallStatus play(Ball userBall) { + return answers.stream() + .map(answer -> answer.play(userBall)) + .filter(BallStatus::isNotNothing) + .findFirst() + .orElse(BallStatus.NOTHING); + } + + public PlayResult play(List balls) { + PlayResult result = new PlayResult(); + + Balls userBalls = new Balls(balls); + + return result; + } + + private static List mapBalls(List answers) { + List balls = new ArrayList<>(); + for (int i = 0; i < answers.size(); i++) { + balls.add(new Ball(i + 1, answers.get(i))); + } + return balls; + } +} diff --git a/src/main/java/baseball/PlayResult.java b/src/main/java/baseball/PlayResult.java new file mode 100644 index 000000000..aab5353cc --- /dev/null +++ b/src/main/java/baseball/PlayResult.java @@ -0,0 +1,11 @@ +package baseball; + +public class PlayResult { + public int getStrikes() { + return 0; + } + + public int getBalls() { + return 0; + } +} diff --git a/src/main/java/baseball/ValidationUtils.java b/src/main/java/baseball/ValidationUtils.java new file mode 100644 index 000000000..6df8e6dc8 --- /dev/null +++ b/src/main/java/baseball/ValidationUtils.java @@ -0,0 +1,33 @@ +package baseball; + +import java.util.HashSet; +import java.util.Set; + +public class ValidationUtils { + + public static final int MIN_VALUE = 0; + public static final int MAX_VALUE = 10; + + public static boolean validNo(int no) { + return no > MIN_VALUE && no < MAX_VALUE; + } + + public static boolean validNoDuplication(int balls) { + + String numbers = String.valueOf(balls); + Set set = new HashSet<>(); + char[] numbersCharArray = numbers.toCharArray(); + + for (char num : numbersCharArray) { + if (!set.add(num)) { + return false; + } + } + + return true; + } + + public static boolean validLengthThree(int balls) { + return String.valueOf(balls).length() == 3; + } +} diff --git a/src/main/java/baseballgame/InputView.java b/src/main/java/baseballgame/InputView.java new file mode 100644 index 000000000..df84a6c0d --- /dev/null +++ b/src/main/java/baseballgame/InputView.java @@ -0,0 +1,32 @@ +package baseballgame; + +import util.ScannerUtil; + +public class InputView { + + private final ScannerUtil scanner; + + public InputView(ScannerUtil scanner) { + this.scanner = scanner; + } + + public String[] input() { + System.out.print("숫자를 입력해 주세요 : "); + + final String number = scanner.nextLine(); + + validateInputLength(number); + + return number.split(""); + } + + private void validateInputLength(final String string) { + if (string.length() != 3) { + throw new RuntimeException("숫자는 반드시 3자리만 입력 해야 합니다."); + } + } + + public ScannerUtil getScanner() { + return scanner; + } +} diff --git a/src/main/java/baseballgame/NumberBaseBallGame.java b/src/main/java/baseballgame/NumberBaseBallGame.java new file mode 100644 index 000000000..e5259e9d2 --- /dev/null +++ b/src/main/java/baseballgame/NumberBaseBallGame.java @@ -0,0 +1,101 @@ +package baseballgame; + +import util.BaseballRandomNumber; +import util.BaseballScanner; +import util.RandomNumberUtil; +import util.ScannerUtil; + +public class NumberBaseBallGame { + + private final InputView inputView; + private String[] randomNumber; + + public NumberBaseBallGame() { + RandomNumberUtil randomNumberCreator = new BaseballRandomNumber(); + ScannerUtil scanner = new BaseballScanner(); + this.inputView = new InputView(scanner); + randomNumber = randomNumberCreator.createRandomNumber(); + } + + public void start() { + boolean isCorrect = false; + + while (!isCorrect) { + final String[] input = inputView.input(); + int strikes = 0, balls = 0; + + // 스트라이크 체크 + strikes = checkStrikes(input, strikes); + + // 볼 체크 + balls = checkBalls(input, balls); + + if (printBallStrikeCount(strikes, balls)) break; + } + } + + private boolean printBallStrikeCount(final int strikes, final int balls) { + if (strikes == 3) { + System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임종료"); + System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."); + final String s = inputView.getScanner().nextLine(); + + if (resetOrRestart(s)) return true; + } + + if (strikes == 0 && balls == 0) { + System.out.println("낫싱"); + } + + if (strikes > 0 && balls == 0) { + System.out.println(strikes + "스트라이크"); + } + + if(strikes == 0 && balls > 0) { + System.out.println(balls + "볼"); + } + + if (strikes > 0 && balls > 0) { + System.out.println(strikes + "스트라이크 " + balls + " 볼"); + } + return false; + } + + private boolean resetOrRestart(final String s) { + if (s.equals("1")) { + start(); + } + + if (s.equals("2")) { + return true; + } + return false; + } + + private int checkBalls(final String[] input, int balls) { + for (int i = 0; i < 3; i++) { + if (!randomNumber[i].equals(input[i]) && containsNumbers(randomNumber, input[i])) { + balls++; + } + } + return balls; + } + + private int checkStrikes(final String[] input, int strikes) { + for (int i = 0; i < 3; i++) { + if (randomNumber[i].equals(input[i])) { + strikes++; + } + } + return strikes; + } + + private boolean containsNumbers(final String[] randomNumber, final String s) { + for (String e : randomNumber) { + if (e.equals(s)) { + return true; + } + } + return false; + } +} diff --git a/src/main/java/baseballgame/TestMain.java b/src/main/java/baseballgame/TestMain.java new file mode 100644 index 000000000..840467f14 --- /dev/null +++ b/src/main/java/baseballgame/TestMain.java @@ -0,0 +1,10 @@ +package baseballgame; + +public class TestMain { + + public static void main(String[] args) { + final NumberBaseBallGame game = new NumberBaseBallGame(); + + game.start(); + } +} diff --git a/src/main/java/calculator/StringCalculator.java b/src/main/java/calculator/StringCalculator.java new file mode 100644 index 000000000..8d898f494 --- /dev/null +++ b/src/main/java/calculator/StringCalculator.java @@ -0,0 +1,48 @@ +package calculator; + +import java.util.Scanner; + +public class StringCalculator { + + private final Scanner scanner; + + public StringCalculator(final Scanner scanner) { + this.scanner = scanner; + } + + public String input() { + return scanner.nextLine(); + } + + public int calculatorResult(String input) { + final String[] split = input.split(" "); + int result = Integer.parseInt(split[0]); + String operator; + for (int i = 1; i < split.length; i = i + 2) { // 1,3,5,7,~~ + final int num = Integer.parseInt(split[i + 1]); + operator = split[i]; + result = operation(operator, num, result); + } + return result; + } + + private int operation(final String operator, final int num, int result) { + switch (operator) { + case "+": + result += num; + break; + case "-": + result -= num; + break; + case "*": + result *= num; + break; + case "/": + result /= num; + break; + default: + throw new IllegalArgumentException("잘못된 연산자입니다."); + } + return result; + } +} diff --git a/src/main/java/util/BaseballRandomNumber.java b/src/main/java/util/BaseballRandomNumber.java new file mode 100644 index 000000000..6f19b8eea --- /dev/null +++ b/src/main/java/util/BaseballRandomNumber.java @@ -0,0 +1,24 @@ +package util; + +import java.util.Random; + +public class BaseballRandomNumber implements RandomNumberUtil { + @Override + public String[] createRandomNumber() { + final Random random = new Random(); + + int first, second, third; + + first = random.nextInt(9) + 1; + + do { + second = random.nextInt(9) + 1; + } while (first == second); + + do { + third = random.nextInt(9) + 1; + } while (first == third || third == second ); + + return new String[]{String.valueOf(first), String.valueOf(second), String.valueOf(third)}; + } +} diff --git a/src/main/java/util/BaseballScanner.java b/src/main/java/util/BaseballScanner.java new file mode 100644 index 000000000..43acbfcd1 --- /dev/null +++ b/src/main/java/util/BaseballScanner.java @@ -0,0 +1,10 @@ +package util; + +import java.util.Scanner; + +public class BaseballScanner implements ScannerUtil { + @Override + public String nextLine() { + return new Scanner(System.in).nextLine(); + } +} \ No newline at end of file diff --git a/src/main/java/util/RandomNumberUtil.java b/src/main/java/util/RandomNumberUtil.java new file mode 100644 index 000000000..b8647d80b --- /dev/null +++ b/src/main/java/util/RandomNumberUtil.java @@ -0,0 +1,6 @@ +package util; + +public interface RandomNumberUtil { + + String[] createRandomNumber(); +} diff --git a/src/main/java/util/ScannerUtil.java b/src/main/java/util/ScannerUtil.java new file mode 100644 index 000000000..d288729d4 --- /dev/null +++ b/src/main/java/util/ScannerUtil.java @@ -0,0 +1,6 @@ +package util; + +public interface ScannerUtil { + + String nextLine(); +} diff --git a/src/test/java/baseball/BallTest.java b/src/test/java/baseball/BallTest.java new file mode 100644 index 000000000..2718c9961 --- /dev/null +++ b/src/test/java/baseball/BallTest.java @@ -0,0 +1,37 @@ +package baseball; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +public class BallTest { + + private Ball computer; + + @BeforeEach + void setUp() { + computer = new Ball(1,4); + } + + @Test + void nothing() { + Ball user = new Ball(2, 5); + BallStatus status = computer.play(user); + assertThat(status).isEqualTo(BallStatus.NOTHING); + } + + @Test + void ball() { + Ball user = new Ball(2, 4); + BallStatus status = computer.play(user); + assertThat(status).isEqualTo(BallStatus.BALL); + } + + @Test + void strike() { + Ball user = new Ball(1, 4); + BallStatus status = computer.play(user); + assertThat(status).isEqualTo(BallStatus.STRIKE); + } +} diff --git a/src/test/java/baseball/BallsTest.java b/src/test/java/baseball/BallsTest.java new file mode 100644 index 000000000..ac33ebde0 --- /dev/null +++ b/src/test/java/baseball/BallsTest.java @@ -0,0 +1,50 @@ +package baseball; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +public class BallsTest { + + private Balls answer; + + @BeforeEach + void setUp() { + answer = new Balls(Arrays.asList(1, 2, 3)); + } + + @Test + void play() { + PlayResult result = answer.play(Arrays.asList(4, 5, 6)); + assertThat(result.getStrikes()).isEqualTo(0); + assertThat(result.getBalls()).isEqualTo(0); + } + + @Test + void play_1strike_1ball() { + PlayResult result = answer.play(Arrays.asList(1, 4, 2)); + assertThat(result.getStrikes()).isEqualTo(1); + assertThat(result.getBalls()).isEqualTo(1); + } + + @Test + void nothing() { + BallStatus status = answer.play(new Ball(1, 4)); + assertThat(status).isEqualTo(BallStatus.NOTHING); + } + + @Test + void ball() { + BallStatus status = answer.play(new Ball(1, 3)); + assertThat(status).isEqualTo(BallStatus.BALL); + } + + @Test + void strike() { + BallStatus status = answer.play(new Ball(1, 1)); + assertThat(status).isEqualTo(BallStatus.STRIKE); + } +} diff --git a/src/test/java/baseball/ValidationUtilTest.java b/src/test/java/baseball/ValidationUtilTest.java new file mode 100644 index 000000000..e07db37ab --- /dev/null +++ b/src/test/java/baseball/ValidationUtilTest.java @@ -0,0 +1,32 @@ +package baseball; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +public class ValidationUtilTest { + + @Test + void 숫자_1_9_검증() { + assertThat(ValidationUtils.validNo(9)).isTrue(); + assertThat(ValidationUtils.validNo(1)).isTrue(); + assertThat(ValidationUtils.validNo(0)).isFalse(); + assertThat(ValidationUtils.validNo(10)).isFalse(); + } + + @Test + void 중복값_존재하는지_검증() { + assertThat(ValidationUtils.validNoDuplication(123)).isTrue(); + assertThat(ValidationUtils.validNoDuplication(234)).isTrue(); + assertThat(ValidationUtils.validNoDuplication(233)).isFalse(); + assertThat(ValidationUtils.validNoDuplication(777)).isFalse(); + } + + @Test + void 숫자가_3자리인지() { + assertThat(ValidationUtils.validLengthThree(123)).isTrue(); + assertThat(ValidationUtils.validLengthThree(456)).isTrue(); + assertThat(ValidationUtils.validLengthThree(444)).isTrue(); + assertThat(ValidationUtils.validLengthThree(1234)).isFalse(); + } +} diff --git a/src/test/java/baseballgame/NumberBaseBallGameTest.java b/src/test/java/baseballgame/NumberBaseBallGameTest.java new file mode 100644 index 000000000..1be3bdeef --- /dev/null +++ b/src/test/java/baseballgame/NumberBaseBallGameTest.java @@ -0,0 +1,21 @@ +package baseballgame; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class NumberBaseBallGameTest { + + @Test + @DisplayName("Edit") + void input() { + // TODO TEST CODE + } + + @Test + @DisplayName("Edit") + void start() { + // TODO TEST CODE + } +} \ No newline at end of file diff --git a/src/test/java/calculator/StringCalculatorTest.java b/src/test/java/calculator/StringCalculatorTest.java new file mode 100644 index 000000000..7f4329aa8 --- /dev/null +++ b/src/test/java/calculator/StringCalculatorTest.java @@ -0,0 +1,48 @@ +package calculator; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Scanner; + +import static org.junit.jupiter.api.Assertions.*; + +class StringCalculatorTest { + + private StringCalculator calculator; + + @BeforeEach + void beforeEach() { + calculator = new StringCalculator(new Scanner(System.in)); + } + + @Test + public void calculatorResult() { + String input = "2 + 3 * 4 / 2"; + final int result = calculator.calculatorResult(input); + + Assertions.assertThat(result).isEqualTo(10); + } + @Test + public void calculatorResult2() { + String input = "5 * 8 / 4 + 5 * 2"; + final int result = calculator.calculatorResult(input); + + Assertions.assertThat(result).isEqualTo(30); + } + + @Test + public void calculatorResult_fail_wrong_operator() { + String input = "2 + 3 * 4 ! 5"; + + assertThrows(IllegalArgumentException.class, () -> calculator.calculatorResult(input)); + } + + @Test + public void calculatorResult_fail_wrong_parameter() { + String input = "2 + 3 * 4 ! j"; + + assertThrows(IllegalArgumentException.class, () -> calculator.calculatorResult(input)); + } +} \ 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..8e5aae78f --- /dev/null +++ b/src/test/java/study/SetTest.java @@ -0,0 +1,46 @@ +package study; + +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 org.junit.jupiter.params.provider.ValueSource; + +import java.util.HashSet; +import java.util.Set; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; + +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 size() { + final int size = numbers.size(); + assertThat(size).isEqualTo(3); + } + + @ParameterizedTest + @ValueSource(ints = {1,1,2,3}) + void contains(int number) { + assertTrue(numbers.contains(number)); + } + + @ParameterizedTest + @CsvSource(value = {"1:true", "2:true", "3:true", "4:false", "5:false"}, delimiter = ':') + void contains_isContains_true_or_false(int number, boolean expected) { + assertThat(numbers.contains(number)).isEqualTo(expected); + } +} diff --git a/src/test/java/study/StringTest.java b/src/test/java/study/StringTest.java index 43e47d90b..48ff1ee4e 100644 --- a/src/test/java/study/StringTest.java +++ b/src/test/java/study/StringTest.java @@ -3,6 +3,7 @@ import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; public class StringTest { @Test @@ -10,4 +11,30 @@ void replace() { String actual = "abc".replace("b", "d"); assertThat(actual).isEqualTo("adc"); } + + @Test + void split() { + final String[] actual = "1,2".split(","); + assertThat(actual).contains("1"); + assertThat(actual).contains("2"); + } + + @Test + void split2() { + final String[] actual = "1".split(","); + assertThat(actual).contains("1"); + } + + @Test + void substring() { + final String before = "(1,2)"; + final String actual = before.substring(1,before.length()-1); + assertThat(actual).isEqualTo("1,2"); + } + + @Test + void charAt() { + final String string = "abc"; + assertThrows(IndexOutOfBoundsException.class, () -> string.charAt(4)); + } }