-
Notifications
You must be signed in to change notification settings - Fork 0
Song #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Song #1
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| # 숫자야구 객체지향 사고 연습 (Bulls and Cows) | ||
|
|
||
| 메시지 : 숫자 3개와 정답을 비교해 결과를 반환해라 | ||
| 게임 매니저? 심판? 컴퓨터? | ||
| -> 컴퓨터가 정답을 가지고 있으니 컴퓨터가 판단하는게 맞을듯 | ||
|
|
||
| 그럼 컴퓨터가 정답을 비교해 결과를 반환하기 위해서 해야하는 일은? | ||
| 일단 정답을 생성해서 가지고 있어야 한다. | ||
|
|
||
| 그럼 컴퓨터의 정답을 생성하는 객체가 필요할까? 컴퓨터는 랜덤한 값을 생성할 책임을 가지나? | ||
| Nope, 랜덤한 3개의 값을 생성하는 객체를 만들자. | ||
|
|
||
| 정답을 만들어서 컴퓨터를 생성했다고 가정해보자. | ||
| 입력으로 들어오는 숫자와 정답을 어떻게 비교하지? | ||
| 입력으로 들어오는 정보를 정답과 같은 데이터 타입으로 변환해주는 객체를 만들자 | ||
|
|
||
| 비교한 결과는 어떻게 생성하지? | ||
| 결과를 담을 객체가 필요하다. -> 결과에 따라 다시 입력을 받을지 끝낼지 결정하자 | ||
|
|
||
|
|
||
| ### 필요 객체 | ||
|
|
||
| - 컴퓨터 - Computer | ||
| - 정답 생성기 - RandomNumberGenerator | ||
| - 입력 변환기 - InputNumberGenerator | ||
| - 비교 결과 - ComparisonResult |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,11 @@ | ||
| package baseball; | ||
|
|
||
| import baseball.controller.BullsAndCowsController; | ||
| import baseball.view.InputView; | ||
| import baseball.view.OutputView; | ||
|
|
||
| public class Application { | ||
| public static void main(String[] args) { | ||
| // TODO: 프로그램 구현 | ||
| new BullsAndCowsController(new InputView(), new OutputView()).run(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| package baseball.controller; | ||
|
|
||
| import baseball.domain.ComparisonResult; | ||
| import baseball.domain.Computer; | ||
| import baseball.domain.InputNumberGenerator; | ||
| import baseball.domain.RandomNumberGenerator; | ||
| import baseball.view.InputView; | ||
| import baseball.view.OutputView; | ||
| import java.util.List; | ||
|
|
||
| public class BullsAndCowsController { | ||
|
|
||
| private final InputView inputView; | ||
| private final OutputView outputView; | ||
|
|
||
|
|
||
| public BullsAndCowsController(InputView inputView, OutputView outputView) { | ||
| this.inputView = inputView; | ||
| this.outputView = outputView; | ||
| } | ||
|
|
||
| public void run() { | ||
| outputView.printStartMessage(); | ||
| int restart; | ||
| do { | ||
| playGame(); | ||
| outputView.printRestartMessage(); | ||
| restart = inputView.scanRestartOrEnd(); | ||
| } while (restart == 1); | ||
| } | ||
|
|
||
| private void playGame() { | ||
| Computer computer = initComputer(); | ||
| ComparisonResult result; | ||
| do { | ||
| outputView.printNumberRequestMessage(); | ||
| result = computer.compare(scanInputNumber()); | ||
| outputView.printResult(result); | ||
| } while (!result.isThreeStrike()); | ||
| outputView.printEndGameMessage(); | ||
| } | ||
|
|
||
| private Computer initComputer() { | ||
| return new Computer(RandomNumberGenerator.generate()); | ||
| } | ||
|
|
||
| private List<Integer> scanInputNumber() { | ||
| return InputNumberGenerator.generate(inputView.scanThreeDigit()); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| package baseball.domain; | ||
|
|
||
| public record ComparisonResult(int strike, int ball) { | ||
|
|
||
| public Boolean isThreeStrike() { | ||
| return strike == 3; | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| StringBuilder stringBuilder = new StringBuilder(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. stringBuilder의 장점은 무엇일까요? |
||
| if (ball != 0) { | ||
| stringBuilder.append(ball + "볼 "); | ||
| } | ||
| if (strike != 0) { | ||
| stringBuilder.append(strike + "스트라이크"); | ||
| } | ||
| if (ball == 0 && strike == 0) { | ||
| stringBuilder.append("낫싱"); | ||
| } | ||
| return stringBuilder.toString(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| package baseball.domain; | ||
|
|
||
| import java.util.List; | ||
| import java.util.stream.IntStream; | ||
|
|
||
| public class Computer { | ||
|
|
||
| private final List<Integer> answer; | ||
|
|
||
| public Computer(List<Integer> answer) { | ||
| this.answer = answer; | ||
| } | ||
|
|
||
| public ComparisonResult compare(List<Integer> input) { | ||
| return new ComparisonResult(findStrike(input), findBall(input)); | ||
|
SongGwanSeok marked this conversation as resolved.
|
||
| } | ||
|
|
||
| private int findStrike(List<Integer> input) { | ||
| return (int) IntStream.range(0, 3) | ||
| .filter(i -> answer.get(i).equals(input.get(i))) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 왜 equals 에요?? |
||
| .count(); | ||
| } | ||
|
|
||
| private int findBall(List<Integer> input) { | ||
| return (int) IntStream.range(0, 3) | ||
| .filter(i -> !answer.get(i).equals(input.get(i)) && answer.contains(input.get(i))) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 조건이 읽기 힘든 것 같아요. 다른 방향은 없을까요? |
||
| .count(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package baseball.domain; | ||
|
|
||
| import java.util.List; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| public class InputNumberGenerator { | ||
|
|
||
| public static List<Integer> generate(String input) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. static은 언제 사용하나요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 주어진 코드는 정답일까요? |
||
|
|
||
| return input.chars() | ||
| .mapToObj(Character::getNumericValue) | ||
| .collect(Collectors.toList()); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| package baseball.domain; | ||
|
|
||
| import camp.nextstep.edu.missionutils.Randoms; | ||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| public class RandomNumberGenerator { | ||
|
|
||
| private static final int startRange = 1; | ||
| private static final int endRange = 9; | ||
|
|
||
| public static List<Integer> generate(){ | ||
| List<Integer> threeDigitNumber = new ArrayList<>(); | ||
| while (threeDigitNumber.size() < 3) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 3은 매직넘버가 아닐까요? |
||
| int randomNumber = Randoms.pickNumberInRange(startRange, endRange); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 랜덤 넘버를 테스트 할 수도 있나요? |
||
| if (!threeDigitNumber.contains(randomNumber)) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 뎁스가,,,2이다,, |
||
| threeDigitNumber.add(randomNumber); | ||
| } | ||
| } | ||
| return threeDigitNumber; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| package baseball.view; | ||
|
|
||
| import java.util.Scanner; | ||
| import java.util.regex.Pattern; | ||
|
|
||
| public class InputView { | ||
|
|
||
| private Scanner scanner = new Scanner(System.in); | ||
| private final String threeDigitPattern = "^\\d{3}$"; | ||
| private final String oneOrTwoPattern = "^(1|2)$"; | ||
|
|
||
| public String scanThreeDigit() { | ||
| String input = scanner.next(); | ||
| isNotThreeDigitNumber(input); | ||
| return input; | ||
| } | ||
|
|
||
| public int scanRestartOrEnd() { | ||
| String input = scanner.next(); | ||
| isNotOneOrTwo(input); | ||
| return Integer.parseInt(input); | ||
| } | ||
|
|
||
| private void isNotThreeDigitNumber(String input) { | ||
| if (!Pattern.matches(threeDigitPattern, input)) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 검증은 뷰의 책임이 맞나요? |
||
| throw new NumberFormatException("3자리 숫자만 입력되어야 합니다."); | ||
| } | ||
| } | ||
|
|
||
| private void isNotOneOrTwo(String input) { | ||
| if (!Pattern.matches(oneOrTwoPattern, input)) { | ||
| throw new NumberFormatException("1이나 2만 입력되어야 합니다."); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| package baseball.view; | ||
|
|
||
| import baseball.domain.ComparisonResult; | ||
|
|
||
| public class OutputView { | ||
|
|
||
| public void printStartMessage() { | ||
| System.out.println("숫자 야구 게임을 시작합니다."); | ||
| } | ||
|
|
||
| public void printNumberRequestMessage() { | ||
| System.out.print("숫자를 입력해주세요 : "); | ||
| } | ||
|
|
||
| public void printResult(ComparisonResult result) { | ||
| System.out.println(result); | ||
| } | ||
|
|
||
| public void printEndGameMessage() { | ||
| System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료"); | ||
| } | ||
|
|
||
| public void printRestartMessage() { | ||
| System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| package baseball.domain; | ||
|
|
||
| import org.junit.jupiter.api.Assertions; | ||
| import org.junit.jupiter.api.DisplayName; | ||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| class ComparisonResultTest { | ||
| @Test | ||
| @DisplayName("입력과 정답을 받아 스트라이크 볼의 개수를 가진다.") | ||
| void generate() { | ||
| int strike = 1; | ||
| int ball = 1; | ||
|
|
||
| Assertions.assertDoesNotThrow(() -> | ||
| new ComparisonResult(strike, ball)); | ||
|
|
||
| } | ||
|
|
||
| @Test | ||
| @DisplayName("3스트라이크일 때 true를 반환한다.") | ||
| void ThreeStrikeTrue() { | ||
| int strike = 3; | ||
| int ball = 0; | ||
| ComparisonResult result = new ComparisonResult(strike, ball); | ||
| Assertions.assertEquals(result.isThreeStrike(), true); | ||
| } | ||
|
|
||
| @Test | ||
| @DisplayName("3스트라이크가 아니면 false를 반환한다.") | ||
| void ThreeStrikeFalse() { | ||
| int strike = 2; | ||
| int ball = 1; | ||
| ComparisonResult result = new ComparisonResult(strike, ball); | ||
| Assertions.assertEquals(result.isThreeStrike(), false); | ||
| } | ||
|
Comment on lines
+8
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이런 테스트도 필요할까요? |
||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| package baseball.domain; | ||
|
|
||
| import java.util.List; | ||
| import org.junit.jupiter.api.Assertions; | ||
| import org.junit.jupiter.api.BeforeEach; | ||
| import org.junit.jupiter.api.DisplayName; | ||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| class ComputerTest { | ||
|
|
||
| private Computer computer; | ||
|
|
||
| @BeforeEach | ||
| void before() { | ||
| computer = new Computer(List.of(1, 2, 3)); | ||
| } | ||
|
|
||
| @Test | ||
| @DisplayName("입력 리스트를 받아 2볼 1스트라이크를 반환한다.") | ||
| void compare2Ball1Strike() throws Exception { | ||
| List<Integer> input = List.of(1, 3, 2); | ||
|
|
||
| ComparisonResult result = computer.compare(input); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 가장 작은 단위의 단위테스트인가요? |
||
| Assertions.assertEquals(result.toString(), "2볼 1스트라이크"); | ||
| } | ||
|
|
||
| @Test | ||
| @DisplayName("입력을 받아 낫싱을 출력한다.") | ||
| void compareNothing() throws Exception { | ||
| List<Integer> input = List.of(4, 5, 6); | ||
|
|
||
| ComparisonResult result = computer.compare(input); | ||
| Assertions.assertEquals(result.toString(), "낫싱"); | ||
| } | ||
|
|
||
|
|
||
| @Test | ||
| @DisplayName("입력을 받아 3스트라이크를 출력한다.") | ||
| void compare3Strike() throws Exception { | ||
| List<Integer> input = List.of(1, 2, 3); | ||
|
|
||
| ComparisonResult result = computer.compare(input); | ||
| Assertions.assertEquals(result.toString(), "3스트라이크"); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package baseball.domain; | ||
|
|
||
| import java.util.List; | ||
| import org.junit.jupiter.api.Assertions; | ||
| import org.junit.jupiter.api.DisplayName; | ||
| import org.junit.jupiter.params.ParameterizedTest; | ||
| import org.junit.jupiter.params.provider.ValueSource; | ||
|
|
||
| class InputNumberGeneratorTest { | ||
|
|
||
| @ParameterizedTest | ||
| @DisplayName("입력으로 들어온 문자열을 리스트 형태로 반환한다.") | ||
| @ValueSource(strings = {"123", "456", "789"}) | ||
| void inputThreeDigit(String input) throws Exception { | ||
| List<Integer> threeDigitNumber = InputNumberGenerator.generate(input); | ||
|
|
||
| Assertions.assertAll( | ||
| () -> Assertions.assertEquals( | ||
| Character.getNumericValue(input.charAt(0)), threeDigitNumber.get(0)), | ||
| () -> Assertions.assertEquals( | ||
| Character.getNumericValue(input.charAt(1)), threeDigitNumber.get(1)), | ||
| () -> Assertions.assertEquals( | ||
| Character.getNumericValue(input.charAt(2)), threeDigitNumber.get(2)) | ||
| ); | ||
| } | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| package baseball.domain; | ||
|
|
||
| import static org.junit.jupiter.api.Assertions.*; | ||
|
|
||
| import java.util.List; | ||
| import org.junit.jupiter.api.Assertions; | ||
| import org.junit.jupiter.api.DisplayName; | ||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| class RandomNumberGeneratorTest { | ||
|
|
||
| @Test | ||
| @DisplayName("3자리 랜덤한 숫자를 리스트로 반환") | ||
| void randomThreeDigit() throws Exception { | ||
| List<Integer> randomThreeDigit = RandomNumberGenerator.generate(); | ||
|
|
||
| Assertions.assertEquals(randomThreeDigit.size(), 3); | ||
| } | ||
|
|
||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
매직넘버를 사용하는 이유는 뭘까요?