-
Notifications
You must be signed in to change notification settings - Fork 0
숫자 야구 게임 [SangBeom-Hahn] #2
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
Open
SangBeom-Hahn
wants to merge
30
commits into
main
Choose a base branch
from
sangbeom
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
d3a43d2
docs(README): list requirements and feature specifications
SangBeom-Hahn 79f3e7b
feat(Computer): 상대방 컴퓨터 객체 구현
SangBeom-Hahn bf40464
test(Computer): 상대방 컴퓨터 객체 테스트
SangBeom-Hahn 3861edb
refactor(Computer): 상대방 컴퓨터 랜덤 수 문자열이었던 것 List로 리팩토링
SangBeom-Hahn ff86b26
feat(User): 사용자 객체 구현
SangBeom-Hahn 7dd776f
feat(User): 숫자를 대입하는 setNumber() 기능 추가
SangBeom-Hahn 6e1f6e5
test(User): 사용자 객체 테스트
SangBeom-Hahn b072ddf
feat(BaseballController): 사용자가 랜덤 수를 맞추면 재시작(1) / 종료(2) 기능 구현
SangBeom-Hahn cd05f8e
test(BaseballController): 사용자가 랜덤 수를 맞추면 재시작(1) / 종료(2) 기능 테스트
SangBeom-Hahn c9f6dab
refactor(BaseballController): 사용자가 랜덤 수를 맞추면 재시작(1) / 종류(2) 기능 리팩토링
SangBeom-Hahn 968677a
feat(BaseballController): 사용자 숫자 입력 시 결과 반환(스트라이크, 볼, 낫싱) 기능 구현
SangBeom-Hahn 8b975fc
test(BaseballController): 사용자 숫자 입력 시 결과 반환(스트라이크, 볼, 낫싱) 기능 테스트
SangBeom-Hahn d498845
feat(BaseballController): 게임 시작 기능 구현
SangBeom-Hahn 8ba8368
feat(BaseballController): 사용자 3자리 숫자 입력 기능 구현
SangBeom-Hahn 3e23707
test(BaseballController): 사용자 3자리 숫자 입력 기능 테스트
SangBeom-Hahn 63e284e
feat(BaseballController): 사용자 3자리 숫자 입력에 따른 결과 반환 기능 구현
SangBeom-Hahn 6faf838
test(BaseballController): 사용자 3자리 숫자 입력에 따른 결과 반환 기능 테스트
SangBeom-Hahn 79a73e2
feat(BaseballController) : 게임 종료 기능 구현
SangBeom-Hahn 45901c9
test(BaseballController) : 게임 종료 기능 테스트
SangBeom-Hahn 7ccf4e9
refactor(BaseballController) : 게임 시나리오를 위한 run 메서드 리팩토링
SangBeom-Hahn 53e2e2f
refactor(OutputView) : 하드코딩 했던 것 view 분리 및 상수로 리팩토링
SangBeom-Hahn 4c24258
refactor(InputView) : 하드코딩 했던 것 view 분리 및 상수로 리팩토링
SangBeom-Hahn c4321d5
refactor(BaseballController) : 하드코딩 했던 것 상수로 리팩토링
SangBeom-Hahn 4aa97f2
refactor(User) : 하드코딩 했던 것 상수로 리팩토링
SangBeom-Hahn c133bc3
refactor(BaseballController) : User, Computer 지역변수에서 전역 변수로 리팩토링
SangBeom-Hahn 787d1e7
refactor(BaseballController) : strikeCount, ballCount 지역변수에서 전역 변수로 리팩토링
SangBeom-Hahn 4e39001
refactor(BaseballController) : strike, ball 카운트 메서드 stream으로 리팩토링
SangBeom-Hahn fbf0807
fix(OutputView) : strike, ball의 갯수가 0일 때 0도 출력되는 버그 수정
SangBeom-Hahn f4391a2
refactor : 접근 지정자 리팩토링
SangBeom-Hahn 0fe1f31
refactor : 검증 추가 리팩토링
SangBeom-Hahn File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| # 요구사항 명세서 | ||
| ### 카테고리 | ||
| 1. 컴퓨터 | ||
| 2. 사용자 | ||
| 3. 시스템 | ||
|
|
||
| ### 요구사항 내용 | ||
| 1. 컴퓨터 | ||
| - 1 ~ 9까지 서로 다른 임의의 수 3개를 선택한다. | ||
| - 사용자가 입력한 숫자에 대한 결과를 출력한다. | ||
|
|
||
|
|
||
|
|
||
| 2. 사용자 | ||
| - 서로 다른 3개의 숫자를 입력한다. | ||
| - 게임을 종료할 때 완전 종료와 다시 시작을 선택한다. | ||
|
|
||
|
|
||
| 3. 시스템 | ||
| - 게임 시작 문구를 출력한다. | ||
| - 사용자와 컴퓨터의 동작을 반복한다. | ||
| - 3개의 숫자를 모두 맞히면 게임을 종료한다. | ||
| 게임이 종료할 때 사용자의 선택에 따라서 완전 종료하거나 다시 시작한다. | ||
| - 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시킨 후 App을 종료한다. | ||
|
|
||
| # 기능 목록 | ||
| 1. 게임 시작 | ||
| - 게임 시작 문구 출력 | ||
|
|
||
|
|
||
| 2. 게임 진행 | ||
| - 컴퓨터는 1 ~ 9까지 서로 다른 임의의 수 선택 | ||
| - 사용자가 서로 다른 3개의 숫자를 입력 | ||
| - 같은 수가 같은 자리에 있으면 스트라이크, 다른 자리에 있으면 볼, 전혀 없으면 낫싱 출력 | ||
|
|
||
|
|
||
| 3. 게임 종료 | ||
| - 사용자가 컴퓨터의 수를 맞추면 게임 종료 출력 | ||
| - 재시작(1) / 종료(2) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,10 @@ | ||
| package baseball; | ||
|
|
||
| import baseball.controller.BaseballController; | ||
|
|
||
| public class Application { | ||
| public static void main(String[] args) { | ||
| // TODO: 프로그램 구현 | ||
| new BaseballController().run(); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| package baseball.controller; | ||
|
|
||
| import baseball.model.Computer; | ||
| import baseball.model.User; | ||
| import baseball.view.InputView; | ||
| import camp.nextstep.edu.missionutils.Console; | ||
| import java.util.List; | ||
| import java.util.stream.Stream; | ||
|
|
||
| import static baseball.view.InputView.inputNumber; | ||
| import static baseball.view.OutputView.*; | ||
|
|
||
| public class BaseballController { | ||
| private static final String RESTART_STATUS = "1"; | ||
| private static final int THREE_STRIKE = 3; | ||
| private static final boolean NOT_THREE_STRIKE = true; | ||
|
|
||
| private User user; | ||
| private Computer computer; | ||
| private int strikeCount; | ||
| private int ballCount; | ||
|
|
||
| public BaseballController() { | ||
| this.strikeCount = 0; | ||
| this.ballCount = 0; | ||
| } | ||
|
|
||
| public void run() { | ||
| printGameStartMessage(); | ||
| do { | ||
| computer = gameStart(); | ||
| playGame(); | ||
| } while (gameOver()); | ||
| } | ||
|
|
||
| private Computer gameStart() { | ||
| return new Computer(); | ||
| } | ||
|
|
||
| private void playGame() { | ||
| user = new User(); | ||
|
|
||
| while (NOT_THREE_STRIKE) { | ||
| user.setNumber(inputNumber()); | ||
| strikeCount = getStrikeCount(user, computer); | ||
| ballCount = getBallCount(user, computer); | ||
|
|
||
| printGameResultMessage(strikeCount, ballCount); | ||
| if (strikeCount == THREE_STRIKE) { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private boolean gameOver() { | ||
| return !isTerminate(InputView.terminateSignUserInput()); | ||
| } | ||
|
|
||
| private int getStrikeCount(final User user, final Computer computer) { | ||
| List<Integer> computerRandomNumber = computer.getRandomNumber(); | ||
| List<Integer> userNumber = user.getNumber(); | ||
|
|
||
| return Stream.iterate(0, n -> n + 1).limit(computerRandomNumber.size()) | ||
| .filter(i -> computerRandomNumber.get(i) == userNumber.get(i)) | ||
| .reduce(0, (cnt, b) -> cnt + 1); | ||
| } | ||
|
|
||
| private int getBallCount(final User user, final Computer computer) { | ||
| List<Integer> computerRandomNumber = computer.getRandomNumber(); | ||
| List<Integer> userNumber = user.getNumber(); | ||
|
|
||
| return Stream.iterate(1, n -> n + 1).limit(9) | ||
| .filter(i -> computerRandomNumber.contains(i) && userNumber.contains(i)) | ||
| .filter(i -> computerRandomNumber.indexOf(i) != userNumber.indexOf(i)) | ||
| .reduce(0, (cnt, b) -> cnt + 1); | ||
| } | ||
|
|
||
| private boolean isTerminate(final String restartStatus) { | ||
| if(restartStatus.equals(RESTART_STATUS)){ | ||
| return false; | ||
| } else { | ||
| return true; | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,55 @@ | ||||||||||||||
| package baseball.model; | ||||||||||||||
|
|
||||||||||||||
| import camp.nextstep.edu.missionutils.Randoms; | ||||||||||||||
|
|
||||||||||||||
| import java.util.ArrayList; | ||||||||||||||
| import java.util.List; | ||||||||||||||
|
|
||||||||||||||
| public class Computer { | ||||||||||||||
| public static final int NUMBER_LENGTH = 3; | ||||||||||||||
| public static final int MIN_RANGE = 1; | ||||||||||||||
| public static final int MAX_RANGE = 9; | ||||||||||||||
| private List<Integer> randomNumber; | ||||||||||||||
|
|
||||||||||||||
| public Computer() { | ||||||||||||||
| saveRandomNumberWithGameStart(); | ||||||||||||||
| } | ||||||||||||||
|
Comment on lines
+14
to
+16
Collaborator
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. save를 통해서 randomNumber에 대한 init을 한다는거는 알겠는데
Suggested change
와 같이 수정하는게 더 가독성이 좋을거 같은데 어떻게 생각하시나요? |
||||||||||||||
|
|
||||||||||||||
| public List<Integer> getRandomNumber() { | ||||||||||||||
| return randomNumber; | ||||||||||||||
| } | ||||||||||||||
|
Comment on lines
+18
to
+20
Collaborator
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. 일반적으로 getter/setter/equals와 같은 메소드들은 클래스 가장 하단에 위치하는게 관례입니다
|
||||||||||||||
|
|
||||||||||||||
| private void saveRandomNumberWithGameStart() { | ||||||||||||||
| randomNumber = new ArrayList<>(); | ||||||||||||||
| Integer digit; | ||||||||||||||
|
|
||||||||||||||
| while (checkLengthSmallThanThree()) { | ||||||||||||||
| digit = getRandomDigit(); | ||||||||||||||
| if (!hasDuplicateDigitInRandomNumber(digit)) { | ||||||||||||||
| randomNumber.add(digit); | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| private boolean checkLengthSmallThanThree() { | ||||||||||||||
| if (randomNumber.size() < NUMBER_LENGTH) { | ||||||||||||||
| return true; | ||||||||||||||
| } | ||||||||||||||
| return false; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| private Integer getRandomDigit() { | ||||||||||||||
| return Randoms.pickNumberInRange(MIN_RANGE, MAX_RANGE); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| private boolean hasDuplicateDigitInRandomNumber(final Integer digit) { | ||||||||||||||
| if (randomNumber.contains(digit)) { | ||||||||||||||
| return true; | ||||||||||||||
| } | ||||||||||||||
| return false; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| public void setRandomNumber(final List<Integer> randomNumber) { | ||||||||||||||
| this.randomNumber = randomNumber; | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| package baseball.model; | ||
|
|
||
|
|
||
| import java.util.List; | ||
| import java.util.Set; | ||
|
|
||
| public class User { | ||
|
|
||
| private static final String INPUT_NUMBER_LENGTH_NOT_THREE_EXCEPTION = "입력 숫자는 3자리입니다."; | ||
| private static final String INPUT_DIGIT_LENGTH_NOT_ONE_EXCEPTION = "입력 숫자는 1 ~ 9입니다."; | ||
| public static final int NUMBER_SIZE = 3; | ||
| public static final int MIN_DIGIT = 1; | ||
| public static final int MAX_DIGIT = 9; | ||
| public static final String INPUT_NUMBER_DUPLICATE_EXCEPTION = "입력숫자의 각 자리는 중복될 수 없습니다."; | ||
|
|
||
| public enum RestartStatus { RESTART, TERMINATE } | ||
|
|
||
| private List<Integer> number; | ||
|
|
||
| public void setNumber(List<Integer> number) { | ||
| validateNumberSize(number); | ||
| validateNumberRange(number); | ||
| validateDuplicateDigit(number); | ||
| this.number = number; | ||
| } | ||
|
|
||
| private void validateNumberSize(final List<Integer> number) { | ||
| if (number.size() > NUMBER_SIZE || number.size() < NUMBER_SIZE) { | ||
| throw new IllegalArgumentException(INPUT_NUMBER_LENGTH_NOT_THREE_EXCEPTION); | ||
| } | ||
| } | ||
|
|
||
| private void validateNumberRange(final List<Integer> number) { | ||
| if (!number.stream().allMatch(digit -> digit >= MIN_DIGIT && digit <= MAX_DIGIT)) { | ||
| throw new IllegalArgumentException(INPUT_DIGIT_LENGTH_NOT_ONE_EXCEPTION); | ||
| } | ||
| } | ||
|
|
||
| private void validateDuplicateDigit(final List<Integer> number) { | ||
| if (Set.copyOf(number).size() != number.size()) { | ||
| throw new IllegalArgumentException(INPUT_NUMBER_DUPLICATE_EXCEPTION); | ||
| } | ||
| } | ||
|
|
||
| public List<Integer> getNumber() { | ||
| return number; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| package baseball.view; | ||
|
|
||
| import camp.nextstep.edu.missionutils.Console; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Arrays; | ||
| import java.util.List; | ||
| import java.util.stream.Collectors; | ||
| import java.util.stream.Stream; | ||
|
|
||
| public class InputView { | ||
|
|
||
| private static final String INPUT_NUMBER_MESSAGE = "숫자를 입력해주세요 : "; | ||
| private static final String CHARACTER_REGEX = "[-+]?\\d*\\.?\\d+"; | ||
| private static final String RESTART_STATUS = "1"; | ||
| private static final String NOT_RESTART_STATUS = "2"; | ||
| private static final String RESTART_OR_END_ONE_OR_TWO_EXCEPTION = "재시작은 1, 완전 종료는 2 입니다."; | ||
| private static final String RESTART_OR_END_NOT_NUMBER_BECAUSE_STRING_EXCEPTION = "재시작은 1, 완전 종료는 2인 정수입니다."; | ||
| private static final String RESTART_OR_END_NOT_NUMBER_BECAUSE_DOUBLE_EXCEPTION = "재시작은 1, 완전 종료는 2인 정수로 소수를 입력할 수 없습니다."; | ||
| public static final String INPUT_NUMBER_SPECIAL_CHARACTER_EXCEPTION = "특수 문자는 입력할 수 없습니다."; | ||
|
|
||
| public static List<Integer> inputNumber() { | ||
| System.out.print(INPUT_NUMBER_MESSAGE); | ||
| String inputNumber = Console.readLine(); | ||
| validateNotSpecialCharacterInUserNumber(inputNumber); | ||
|
|
||
| return Arrays.stream(inputNumber.split("")) | ||
| .map(Integer::parseInt) | ||
| .collect(Collectors.toList()); | ||
| } | ||
|
|
||
| public static String terminateSignUserInput() { | ||
| String inputRestartStatus = Console.readLine(); | ||
| validateRestartStatus(inputRestartStatus); | ||
| return inputRestartStatus; | ||
| } | ||
|
|
||
| private static void validateNotSpecialCharacterInUserNumber(String inputNumber) { | ||
| if (!Arrays.stream(inputNumber.split("")).allMatch(digit -> digit.matches(CHARACTER_REGEX))) { | ||
| throw new IllegalArgumentException(INPUT_NUMBER_SPECIAL_CHARACTER_EXCEPTION); | ||
| } | ||
| } | ||
|
|
||
| private static void validateRestartStatus(final String restartStatus) { | ||
| validateNotStringRestartStatus(restartStatus); | ||
| validateNotDoubleRestartStatus(restartStatus); | ||
| validateRangeRestartStatus(restartStatus); | ||
| } | ||
|
|
||
| private static void validateRangeRestartStatus(final String restartStatus) { | ||
| if (!restartStatus.equals(RESTART_STATUS) && !restartStatus.equals(NOT_RESTART_STATUS)) { | ||
| throw new IllegalArgumentException(RESTART_OR_END_ONE_OR_TWO_EXCEPTION); | ||
| } | ||
| } | ||
|
|
||
| private static void validateNotStringRestartStatus(final String restartStatus) { | ||
| if (!(restartStatus != null && restartStatus.matches(CHARACTER_REGEX))) { | ||
| throw new IllegalArgumentException(RESTART_OR_END_NOT_NUMBER_BECAUSE_STRING_EXCEPTION); | ||
| } | ||
| } | ||
|
|
||
| private static void validateNotDoubleRestartStatus(final String restartStatus) { | ||
| if (!restartStatus.chars().allMatch(Character::isDigit)) { | ||
| throw new IllegalArgumentException(RESTART_OR_END_NOT_NUMBER_BECAUSE_DOUBLE_EXCEPTION); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| package baseball.view; | ||
|
|
||
| public class OutputView { | ||
|
|
||
| private static final String GAME_START_MESSAGE = "숫자 야구 게임을 시작합니다."; | ||
| private static final String STRIKE_MESSAGE = "스트라이크"; | ||
| private static final String GAME_OVER_MESSAGE = "3개의 숫자를 모두 맞히셨습니다! 게임종료"; | ||
| private static final String GAME_RESTART_OR_END_MESSAGE = "게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요"; | ||
| private static final String NOTHING_MESSAGE = "낫싱"; | ||
| private static final String BALL_MESSAGE = "볼 "; | ||
| public static final int THREE_STRIKE = 3; | ||
| public static final int ZERO = 0; | ||
|
|
||
| public static void printGameStartMessage() { | ||
| System.out.println(GAME_START_MESSAGE); | ||
| } | ||
|
|
||
| public static void printGameResultMessage(final int strikeCount, final int ballCount) { | ||
| if (strikeCount == THREE_STRIKE) { | ||
| System.out.println(strikeCount + STRIKE_MESSAGE); | ||
| System.out.println(GAME_OVER_MESSAGE); | ||
| System.out.println(GAME_RESTART_OR_END_MESSAGE); | ||
| } else if (strikeCount == ZERO && ballCount == ZERO) { | ||
| System.out.println(NOTHING_MESSAGE); | ||
| } else if (strikeCount != ZERO && ballCount == ZERO) { | ||
| System.out.println(strikeCount + STRIKE_MESSAGE); | ||
| } else if (strikeCount == ZERO && ballCount != ZERO) { | ||
| System.out.println(ballCount + BALL_MESSAGE); | ||
| } else { | ||
| System.out.println(ballCount + BALL_MESSAGE + strikeCount + STRIKE_MESSAGE); | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
일상적인 관점에서는 컴퓨터가 결과를 출력하지만 이 게임상에서는 컴퓨터 & 사용자를 Player로 보고 결과를 도출하는 것은 다른 컴포넌트에게 위임하는게 좋지 않을까요?