diff --git a/README.md b/README.md index b50d652cca..f93da98c83 100644 --- a/README.md +++ b/README.md @@ -153,3 +153,34 @@ while (computer.size() < 3) { - **Git의 커밋 단위는 앞 단계에서 `docs/README.md`에 정리한 기능 목록 단위**로 추가한다. - [커밋 메시지 컨벤션](https://gist.github.com/stephenparish/9941e89d80e2bc58a153) 가이드를 참고해 커밋 메시지를 작성한다. - 과제 진행 및 제출 방법은 [프리코스 과제 제출](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse) 문서를 참고한다. + + +## 기능 목록 +1. 숫자 야구 게임 + 1. 컴퓨터(상대방) 숫자 랜덤 추출 + - 예외 : 1에서 9 사이인 중복되지 않는 3자리수 (코드에서 예외처리 완료) + 2. 게임 시작 문구 출력 (숫자 야구 게임을 시작합니다.) + - 최초 1회 실행 + 3. 플레이어(사용자) 숫자 랜덤으로 부여받기 + - [x] 플레이어 입력 숫자가 중복되는 경우. + - [x] 플레이어 입력 숫자가 1에서 9 사이의 숫자가 아닌 경우. + - [x] 플레이어 입력 숫자가 3자리 이외의 경우 + - [x] 플레이어 입력 숫자가 숫자 이외의 경우. + - 예외 발생시 IllegalArgumentException 발생 + 4. 스트라이크와 볼 개수를 바탕으로 출력 + - 하나도 없는 경우 => 낫싱 + - 3개의 숫자를 모두 맞힐 경우 => 3스트라이크 출력후 3개의 숫자를 모두 맞히셨습니다! 게임 종료 문구 출력 + - 0볼 n스트라이크인 경우 => n스트라이크 + - n볼 0스트라이크인 경우 => n 볼 + - n볼 m스트라이크인 경우 => n볼 m스트라이크 +2. 재시작 기능 + 1. 게임 재시작 문구 출력 (게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.) + 2. 플레이어(사용자)에게 숫자 입력 받기 + - 예외 : 1또는 2 이외의 숫자를 입력받으면 IllegalArgumentException 발생 + 3. 재시작 또는 종료 + - 입력 받은 값이 1일 경우 : 재시작 + - 입력 받은 값이 2일 경우 : 게임 종료 + + + + diff --git a/src/main/java/baseball/Application.java b/src/main/java/baseball/Application.java index dd95a34214..f44b17d101 100644 --- a/src/main/java/baseball/Application.java +++ b/src/main/java/baseball/Application.java @@ -1,7 +1,14 @@ package baseball; +import java.util.List; + public class Application { - public static void main(String[] args) { - // TODO: 프로그램 구현 - } + + public static void main(String[] args) { + + GameProgram gameProgram = new GameProgram(); + gameProgram.startGame(); + + + } } diff --git a/src/main/java/baseball/Computer.java b/src/main/java/baseball/Computer.java new file mode 100644 index 0000000000..d888593675 --- /dev/null +++ b/src/main/java/baseball/Computer.java @@ -0,0 +1,25 @@ +package baseball; + +import java.util.ArrayList; +import java.util.List; + + +import camp.nextstep.edu.missionutils.Randoms; + +public class Computer { + + static final int MIN_VALUE = 1; + static final int MAX_VALUE = 9; + + public List addComputerNumber(){ + List computerNumber = new ArrayList<>(); + while(computerNumber.size() < 3){ + int randomNumber = Randoms.pickNumberInRange(MIN_VALUE,MAX_VALUE); + if(!computerNumber.contains(randomNumber)){ + computerNumber.add(randomNumber); + } + } + return computerNumber; + } + +} diff --git a/src/main/java/baseball/GameProgram.java b/src/main/java/baseball/GameProgram.java new file mode 100644 index 0000000000..d423118384 --- /dev/null +++ b/src/main/java/baseball/GameProgram.java @@ -0,0 +1,43 @@ +package baseball; + +import java.util.List; + +public class GameProgram { + + InputView inputView = new InputView(); + Computer computer = new Computer(); + Judge judge = new Judge(); + OutputView outputView = new OutputView(); + Retry retry = new Retry(); + + public void startGame() { + boolean again = true; + inputView.startMessage(); + + while (again) { + inputView.inputMessage(); + List computerNum = computer.addComputerNumber(); + String result = ""; + endPoint(computerNum, result); + outputView.askRetry(); + again = retry.retryOrExit(); + } + } + + public String setting(List computer, List player) { + int totalCount = judge.totalCount(computer, player); + int strike = judge.countStrike(computer, player); + int ball = totalCount - strike; + return outputView.message(strike, ball, totalCount); + } + + public void endPoint(List computerNum, String result) { + while (!result.equals("3스트라이크")) { + result = setting(computerNum, inputView.inputPlayerNumber()); + System.out.println(result); + } + } + + + +} diff --git a/src/main/java/baseball/InputView.java b/src/main/java/baseball/InputView.java new file mode 100644 index 0000000000..5f5f2d81e3 --- /dev/null +++ b/src/main/java/baseball/InputView.java @@ -0,0 +1,62 @@ +package baseball; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +import camp.nextstep.edu.missionutils.Console; + +public class InputView { + + public void startMessage() { + System.out.println("숫자 야구 게임을 시작합니다."); + } + + public void inputMessage() { + System.out.print("숫자를 입력해주세요 : "); + } + + public List inputPlayerNumber() { + List playerNumber = new ArrayList<>(); + String number = Console.readLine(); + playerNumException(number); + for (int i = 0; i < number.length(); i++) { + overLapCheck(playerNumber,number,i); + playerNumber.add(number.charAt(i) - '0'); + } + + return playerNumber; + } + + public void playerNumException(String input) throws IllegalArgumentException{ + inputRangeCheck(input); + sizeCheck(input); + numberCheck(input); + } + + public void inputRangeCheck(String input) throws IllegalArgumentException{ + for (int i = 0; i < input.length(); i++) { + if(input.charAt(i) - '0' == 0){ + throw new IllegalArgumentException("1에서 9 사이의 숫자를 입력해야 합니다."); + } + } + } + + public void overLapCheck(List player, String input, int i) throws IllegalArgumentException{ + if(player.contains(input.charAt(i) - '0')){ + throw new IllegalArgumentException("중복된 수는 입력할 수 없습니다."); + } + } + + public void sizeCheck(String player) throws IllegalArgumentException{ + if (player.length() != 3) { + throw new IllegalArgumentException("입력한 수는 세자리여야 합니다."); + } + } + + public void numberCheck(String player) throws IllegalArgumentException{ + if (!Pattern.matches("^[0-9]*$", player)) { + throw new IllegalArgumentException("숫자만 입력해야 합니다."); + } + } +} diff --git a/src/main/java/baseball/Judge.java b/src/main/java/baseball/Judge.java new file mode 100644 index 0000000000..569a72995d --- /dev/null +++ b/src/main/java/baseball/Judge.java @@ -0,0 +1,27 @@ +package baseball; + +import java.util.List; + +public class Judge { + + public int countStrike(List computer, List player) { + int strike = 0; + for (int i = 0; i < computer.size(); i++) { + if (computer.get(i) == player.get(i)) { + strike++; + } + } + return strike; + } + + public int totalCount(List computer, List player) { + int totalCount = 0; + for (int i = 0; i < computer.size(); i++) { + if (computer.contains(player.get(i))) { + totalCount++; + } + } + return totalCount; + } + +} diff --git a/src/main/java/baseball/OutputView.java b/src/main/java/baseball/OutputView.java new file mode 100644 index 0000000000..998ccf9a40 --- /dev/null +++ b/src/main/java/baseball/OutputView.java @@ -0,0 +1,24 @@ +package baseball; + +public class OutputView { + + public String message(int strike, int ball, int totalCount){ + if (totalCount == 0) { + return "낫싱"; + } + if (ball != 0 && strike == 0) { + return ball + "볼"; + } + if (ball == 0 && strike != 0) { + return strike + "스트라이크"; + } + return ball + "볼 " + strike + "스트라이크"; + } + + public void askRetry() { + System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료"); + System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."); + } +} + + diff --git a/src/main/java/baseball/Retry.java b/src/main/java/baseball/Retry.java new file mode 100644 index 0000000000..e6dce5f865 --- /dev/null +++ b/src/main/java/baseball/Retry.java @@ -0,0 +1,21 @@ +package baseball; + +import camp.nextstep.edu.missionutils.Console; + +public class Retry { + + public boolean retryOrExit() { + String answer = Console.readLine(); + return retry(answer); + } + + public boolean retry(String answer) throws IllegalArgumentException{ + if(Integer.parseInt(answer) != 1 && Integer.parseInt(answer) != 2){ + throw new IllegalArgumentException("1 또는 2를 입력해주세요."); + } + if(Integer.parseInt(answer) == 1){ + return true; + } + return false; + } +} diff --git a/src/test/java/baseball/ApplicationTest.java b/src/test/java/baseball/ApplicationTest.java index 3fa29fa67b..7ab0c0ae6e 100644 --- a/src/test/java/baseball/ApplicationTest.java +++ b/src/test/java/baseball/ApplicationTest.java @@ -32,4 +32,30 @@ class ApplicationTest extends NsTest { public void runMain() { Application.main(new String[]{}); } + + @Test + void 플레이어_입력_중복_테스트() { + assertSimpleTest(() -> + assertThatThrownBy(() -> runException("112")) + .isInstanceOf(IllegalArgumentException.class) + ); + } + + @Test + void 플레이어_입력_영어_테스트() { + assertSimpleTest(() -> + assertThatThrownBy(() -> runException("11a")) + .isInstanceOf(IllegalArgumentException.class) + ); + } + @Test + void 플레이어_입력_범위_테스트() { + assertSimpleTest(() -> + assertThatThrownBy(() -> runException("012")) + .isInstanceOf(IllegalArgumentException.class) + ); + } + + + }