-
Notifications
You must be signed in to change notification settings - Fork 0
[조윤호] 야구 게임 미션 #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
base: main
Are you sure you want to change the base?
Changes from 13 commits
c0abb19
f449f83
714d713
3ac7ecc
292c25c
e4f003c
6e8eec3
6b2fc50
dcc759f
483d073
6a580a1
9a837a4
d6fb92a
756a633
951f6b7
2169607
3198cf6
fec8802
9336696
d5d7ade
4472181
cc19a60
314e127
1b3f09b
7e9f562
6472f4a
dc3d36f
9d64f96
af4d49d
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,20 @@ | ||
| # 기능 목록 | ||
|
|
||
| 입출력 | ||
| - [ ] 사용자 입력 | ||
| - [ ] 숫자 입력 | ||
| - [ ] 예외처리 | ||
| - [ ] 게임 진행(1 or 2) 입력 | ||
| - [ ] 예외처리 | ||
| - [ ] 메시지 출력 | ||
| - [ ] 시작 메시지 | ||
| - [ ] (b, s) -> 볼/스트라이크 출력 | ||
| - [ ] 종료 메시지 | ||
|
|
||
| 게임 진행 | ||
| - [ ] main | ||
| - [ ] 게임 시작 | ||
| - [ ] 게임 종료, 결과 출력 | ||
| - [ ] singleGame | ||
| - [ ] init : 난수 생성 | ||
| - [ ] singleTurn (xxx) -> 판정 후 결과 리턴 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,44 @@ | ||
| package baseball; | ||
|
|
||
| import baseball.game.GameStatus; | ||
| import baseball.game.SingleGame; | ||
| import baseball.inout.UserInput; | ||
| import baseball.inout.UserOutput; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public class Application { | ||
| private static UserInput userInput; | ||
| private static UserOutput userOutput; | ||
|
||
|
|
||
| public static void main(String[] args) { | ||
| // TODO: 프로그램 구현 | ||
| boolean isContinue = true; | ||
|
|
||
| startGame(); | ||
| while (isContinue) | ||
| isContinue = playSingleGame(); | ||
|
||
| } | ||
|
|
||
| private static void startGame() { | ||
| userInput = new UserInput(); | ||
| userOutput = new UserOutput(); | ||
|
|
||
| userOutput.initMessage(); | ||
| } | ||
|
|
||
| private static boolean playSingleGame() { | ||
| SingleGame singleGame = new SingleGame(); | ||
|
|
||
| boolean isCorrect = false; | ||
|
|
||
| while (!isCorrect) { | ||
| List<Integer> playNum = userInput.getNum(); | ||
| GameStatus gameStatus = singleGame.singleTurn(playNum); | ||
| userOutput.statusMessage(gameStatus); | ||
| isCorrect = gameStatus.isCorrect(); | ||
|
||
| } | ||
|
||
|
|
||
| userOutput.endMessage(); | ||
| return userInput.isContinue(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| package baseball.game; | ||
|
|
||
| import java.util.Objects; | ||
|
|
||
| public class GameStatus { | ||
| public int ball; | ||
| public int strike; | ||
|
|
||
| public GameStatus(int ball, int strike) { | ||
| this.ball = ball; | ||
| this.strike = strike; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean equals(Object o) { | ||
| if (this == o) return true; | ||
| if (o == null || getClass() != o.getClass()) return false; | ||
| GameStatus that = (GameStatus) o; | ||
| return ball == that.ball && strike == that.strike; | ||
| } | ||
|
|
||
| @Override | ||
| public int hashCode() { | ||
| return Objects.hash(ball, strike); | ||
| } | ||
|
|
||
| public boolean isCorrect() { | ||
| return (strike == 3 && ball == 0); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,32 @@ | ||||||||||
| package baseball.game; | ||||||||||
|
|
||||||||||
| import camp.nextstep.edu.missionutils.Randoms; | ||||||||||
|
|
||||||||||
| import java.util.ArrayList; | ||||||||||
| import java.util.List; | ||||||||||
|
|
||||||||||
| public class SingleGame { | ||||||||||
| List<Integer> computer = new ArrayList<>(); | ||||||||||
|
||||||||||
|
|
||||||||||
| public SingleGame() { | ||||||||||
| while(computer.size() < 3) { | ||||||||||
| int randomNumber = Randoms.pickNumberInRange(1, 9); | ||||||||||
| if (!computer.contains(randomNumber)) | ||||||||||
| computer.add(randomNumber); | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
||||||||||
|
|
||||||||||
| public void setComputer (List<Integer> list) { | ||||||||||
| computer = list; | ||||||||||
| } | ||||||||||
|
||||||||||
|
|
||||||||||
| public GameStatus singleTurn(List<Integer> player){ | ||||||||||
| int strike = 0, ball = 0; | ||||||||||
|
||||||||||
| for (int i = 0; i < player.size(); i++) { | ||||||||||
| if (computer.get(i) == player.get(i)) strike ++; | ||||||||||
| else if (computer.contains(player.get(i))) ball ++; | ||||||||||
|
||||||||||
| if (computer.get(i) == player.get(i)) strike ++; | |
| else if (computer.contains(player.get(i))) ball ++; | |
| if (computer.get(i) == player.get(i)) strike++; | |
| else if (computer.contains(player.get(i))) ball++; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| package baseball.inout; | ||
|
|
||
| public class CheckRegex { | ||
|
||
|
|
||
| public static boolean isThreeDigit (String test) { | ||
| String pattern = "\\d{3}"; | ||
| return test.matches(pattern); | ||
| } | ||
| public static boolean isBaseball (String test) { | ||
| String pattern = "^(?!.*(.).*\\1)\\d{3}$"; | ||
| return test.matches(pattern); | ||
| } | ||
|
|
||
| public static boolean isCommand (String test) { | ||
| String pattern = "[12]"; | ||
| return test.matches(pattern); | ||
| } | ||
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| package baseball.inout; | ||
|
|
||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| import static camp.nextstep.edu.missionutils.Console.readLine; | ||
|
||
|
|
||
| public class UserInput { | ||
|
|
||
| /** | ||
| * 숫자 입력 | ||
| */ | ||
| public List<Integer> getNum() { | ||
| System.out.print("숫자를 입력해주세요 : "); | ||
| String input = readLine().trim(); | ||
|
|
||
| if (!CheckRegex.isThreeDigit(input)) | ||
| throw new IllegalArgumentException("3자리의 숫자를 입력해야 합니다."); | ||
| if (!CheckRegex.isBaseball(input)) | ||
|
||
| throw new IllegalArgumentException("중복이 없는 3자리의 숫자를 입력해야 합니다."); | ||
|
|
||
| List<Integer> numbers = new ArrayList<>(); | ||
| for (int i = 0; i < 3; i++) | ||
| numbers.add(input.charAt(i) - '0'); | ||
|
|
||
| return numbers; | ||
| } | ||
|
|
||
| /** | ||
| * 게임 진행여부 입력 | ||
| */ | ||
| public boolean isContinue() { | ||
| System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."); | ||
| String input = readLine().trim(); | ||
| // regex | ||
| if (!CheckRegex.isCommand(input)) | ||
| throw new IllegalArgumentException("1 또는 2를 입력해야 합니다."); | ||
|
|
||
| return input.equals("1"); | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package baseball.inout; | ||
|
|
||
| import baseball.game.GameStatus; | ||
|
|
||
| public class UserOutput { | ||
|
|
||
| public void initMessage() { | ||
| System.out.println("숫자 야구 게임을 시작합니다."); | ||
| } | ||
|
|
||
| public void statusMessage(GameStatus status) { | ||
| if (status.ball == 0 && status.strike == 0) | ||
| System.out.println("낫싱"); | ||
| else if (status.ball == 0) | ||
| System.out.println(status.strike + "스트라이크"); | ||
| else if (status.strike == 0) | ||
| System.out.println(status.ball + "볼"); | ||
| else | ||
| System.out.println(status.ball + "볼 " + status.strike + "스트라이크"); | ||
|
Comment on lines
+15
to
+22
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. view에서 출력 외 로직이 동작하는 것이 어색합니다!
Author
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. 그렇군요..!! GameStatus로 옮기는 것을 고려해봐야겠네요 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. 저는 입출력 클래스는 메인 서비스 로직의 영향을 받지 않아야된다고 생각합니다. |
||
|
|
||
| } | ||
|
|
||
| public void endMessage() { | ||
|
||
| System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료"); | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| package baseball.game; | ||
|
|
||
| import org.junit.jupiter.api.BeforeAll; | ||
| import org.junit.jupiter.api.DisplayName; | ||
| import org.junit.jupiter.api.Test; | ||
| import org.junit.jupiter.api.TestInstance; | ||
| import org.junit.jupiter.params.ParameterizedTest; | ||
| import org.junit.jupiter.params.provider.ValueSource; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| import static org.assertj.core.api.Assertions.assertThat; | ||
| import static org.junit.jupiter.api.Assertions.*; | ||
|
|
||
| @TestInstance(TestInstance.Lifecycle.PER_CLASS) | ||
| class SingleGameTest { | ||
| SingleGame singleGame; | ||
|
|
||
| @BeforeAll | ||
| void setSingleGame() { | ||
| singleGame = new SingleGame(); | ||
| singleGame.setComputer(List.of(1, 2, 3)); | ||
| } | ||
|
|
||
| List<List<Integer>> inputs = new ArrayList<>(List.of( | ||
| List.of(4, 5, 6), // n | ||
| List.of(4, 5, 1), // 1b | ||
| List.of(1, 5, 6), // 1s | ||
| List.of(1, 5, 2), // 1b1s | ||
| List.of(1, 2, 3) // 3s | ||
| )); | ||
|
||
| List<GameStatus> expects = new ArrayList<>(List.of( | ||
| new GameStatus(0, 0), | ||
| new GameStatus(1, 0), | ||
| new GameStatus(0, 1), | ||
| new GameStatus(1, 1), | ||
| new GameStatus(0, 3) | ||
| )); | ||
|
|
||
| @ParameterizedTest | ||
| @DisplayName("singleTurn 동작 테스트") | ||
| @ValueSource(ints = {0, 1, 2, 3, 4}) | ||
| void singleTurn(int i) { | ||
| // when | ||
| GameStatus status = singleGame.singleTurn(inputs.get(i)); | ||
|
|
||
| // then | ||
| assertThat(status).isEqualTo(expects.get(i)); | ||
| } | ||
| } | ||
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| package baseball.inout; | ||
|
|
||
| import org.junit.jupiter.api.AfterEach; | ||
| import org.junit.jupiter.api.BeforeEach; | ||
| import org.junit.jupiter.api.DisplayName; | ||
| import org.junit.jupiter.api.Test; | ||
| import org.junit.jupiter.params.ParameterizedTest; | ||
| import org.junit.jupiter.params.provider.ValueSource; | ||
|
|
||
| import java.io.ByteArrayInputStream; | ||
| import java.io.ByteArrayOutputStream; | ||
| import java.io.PrintStream; | ||
| import java.util.ArrayList; | ||
| import java.util.Arrays; | ||
| import java.util.List; | ||
|
|
||
| import static org.assertj.core.api.Assertions.assertThat; | ||
| import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||
|
|
||
| class UserInputTest { | ||
| private static ByteArrayOutputStream outputMessage; | ||
| private static ByteArrayInputStream inputMessage; | ||
| private static UserInput userInput; | ||
|
|
||
| @BeforeEach | ||
| void setUpStreams() { | ||
| outputMessage = new ByteArrayOutputStream(); // OutputStream 생성 | ||
| System.setOut(new PrintStream(outputMessage)); // 생성한 OutputStream 으로 설정 | ||
|
|
||
| userInput = new UserInput(); | ||
| } | ||
|
|
||
| @AfterEach | ||
| void restoresStreams() { | ||
| System.setOut(System.out); // 원상복귀 | ||
| } | ||
|
|
||
| @ParameterizedTest | ||
| @DisplayName("숫자 입력 동작 테스트") | ||
| @ValueSource(strings = {"123", "145", "671"}) | ||
| void getNum(String input) { | ||
| // given | ||
| enterInput(input); | ||
| List<Integer> compare = new ArrayList<>(); | ||
| for (int i = 0; i < 3; i++) | ||
| compare.add( input.charAt(i) - '0'); | ||
|
|
||
| // when | ||
| List<Integer> list = userInput.getNum(); | ||
|
|
||
| // then | ||
| assertThat(list).isEqualTo(compare); | ||
| } | ||
|
|
||
|
|
||
| @ParameterizedTest | ||
| @DisplayName("숫자 입력 예외 테스트") | ||
| @ValueSource(strings = {"111", "122", "1325", "a11"}) | ||
| void getNumErrors(String input) { | ||
| // given | ||
| enterInput(input); | ||
|
|
||
| // then | ||
| assertThatThrownBy( () -> { | ||
| userInput.getNum(); | ||
| }).isInstanceOf(IllegalArgumentException.class); | ||
| } | ||
|
|
||
|
|
||
| @ParameterizedTest | ||
| @DisplayName("게임진행 입력 동작 테스트") | ||
| @ValueSource(strings = {"1", "2"}) | ||
| void isContinue(String input) { | ||
| // given | ||
| enterInput(input); | ||
|
|
||
| // when | ||
| boolean cmd = userInput.isContinue(); | ||
|
|
||
| // then | ||
| assertThat(cmd).isEqualTo( input.equals("1") ); | ||
| } | ||
|
|
||
|
|
||
| @ParameterizedTest | ||
| @DisplayName("게임진행 입력 예외 테스트") | ||
| @ValueSource(strings = {"111", "3", "0", "a"}) | ||
| void isContinueError(String input) { | ||
| // given | ||
| enterInput(input); | ||
|
|
||
| // then | ||
| assertThatThrownBy( () -> { | ||
| userInput.isContinue(); | ||
| }).isInstanceOf(IllegalArgumentException.class); | ||
| } | ||
|
|
||
| void enterInput(String input){ | ||
| inputMessage = new ByteArrayInputStream(input.getBytes()); | ||
| System.setIn(inputMessage); | ||
| } | ||
| } |
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.
안쓰는 임포트는 지워주세요!
인텔리제이를 사용하신다면, 맥 기준 ctrl+option+o(영어 오) / 윈도우 기준 ctrl+alt+o 임포트 정리 단축키를 사용해서 간편하게 정리할 수 있습니다ㅎㅎ
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.
오오 꿀팁이네요