diff --git a/README.md b/README.md index 8d7e8aee..739a9bbc 100644 --- a/README.md +++ b/README.md @@ -1 +1,52 @@ -# java-baseball-precourse \ No newline at end of file +# java-baseball-precourse +## 기능 요구 사항 +기본적으로 1~9까지 "서로 다른 수"로 이루어진 3자리의 수를 맞추는 게임. + +같은 수가 같은 자리에 있으면 스트라이크, 다른 자리에 있으면 볼, 같은 수가 전혀 없으면 낫싱이란 힌트를 얻고, 그 힌트를 이용해서 먼저 상대방(컴퓨터)의 수를 맞추면 승리한다. + +### 기능 목록 +0. 기본 골조 마련(while문) +1. 컴퓨터가 임의의 "서로 다른" 숫자 3개를 선택한 후, 해당 숫자를 순서대로 배열에 저장 +2. 게임 플레이어가 "서로 다른" 3개의 숫자를 입력한 후, 해당 숫자를 순서대로 배열에 저장 +3. 게임 플레이어가 입력한 숫자에 대한 결과 판별 + 1. 같은 수가 같은 자리에 있으면 스트라이크 + 2. 다른 자리에 있으면 볼 + 3. 같은 수가 전혀 없으면 낫싱이란 힌트 제공 + +4. (승리 시) 게임 재시작 여부 선택 +5. 유효값 검증 등 오류 처리(IllegalArgumentException) + +### 기본 코드 구조 +유효값 검증 및 에러 처리 생략 +``` + +while(true) { + randNumArray = 랜덤 숫자 입력받아서 순서대로 배열에 저장 (메서드) + + result = false + while(result == false){ + numArray = 사용자 숫자 입력 (메서드) + result = 결과 판별 (메서드) + } + --- 스트라이크인 상태 --- + reStart = 게임 재시작 여부 선택 (메서드) + if(reStart == 1){재시작} + else if(reStart == 2){프로그램 종료} +} + +사용자 숫자 입력 메서드(){ + ... + 배열에 순서대로 저장한 후 반환 +} + +결과 판별 메서드(numArray){ + ... + 결과 화면에 출력 + 결과 반환(t/f) +} + +게임 재시작 여부 선택 메서드(){ + reStart = 선택(1 or 2) + reStart 반환 +} +``` \ No newline at end of file diff --git a/build.gradle b/build.gradle index 20a92c9e..b97ff65c 100644 --- a/build.gradle +++ b/build.gradle @@ -23,3 +23,7 @@ dependencies { test { useJUnitPlatform() } + +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' +} \ No newline at end of file diff --git a/src/main/java/domain/Computer.java b/src/main/java/domain/Computer.java new file mode 100644 index 00000000..70a19d7c --- /dev/null +++ b/src/main/java/domain/Computer.java @@ -0,0 +1,27 @@ +package domain; + +import jdk.jfr.Description; + +import java.util.ArrayList; +import java.util.Random; + +public class Computer { + + /** + * 컴퓨터가 랜덤으로 겹치지 않는 3개의 숫자를 뽑아 순서대로 배열에 저장 + * @return 컴퓨터가 입력한 숫자들이 담긴 배열 + */ + public static ArrayList makeRandNumArray() { + ArrayList numArray = new ArrayList<>(); + while (numArray.size() < 3) { + Random random = new Random(); + int n = random.nextInt(8) + 1; // 1~9 난수 생성 + + if (!numArray.contains(n)) { // 배열에 없는 경우 숫자 추가 + numArray.add(n); + } + } + System.out.println(); + return numArray; + } +} diff --git a/src/main/java/domain/User.java b/src/main/java/domain/User.java new file mode 100644 index 00000000..d3db37d2 --- /dev/null +++ b/src/main/java/domain/User.java @@ -0,0 +1,34 @@ +package domain; + +import jdk.jfr.Description; +import utils.Utils; + +import java.util.ArrayList; +import java.util.Scanner; + +public class User { + + /** + * 플레이어가 겹치지 않는 3개의 숫자를 입력해 순서대로 배열에 저장 + * 내부적으로 유효한 값이 입력되었는지 검사 + * @return 플레이어가 입력한 숫자들이 담긴 배열 + */ + public static ArrayList inputNumArray() { + Scanner scanner = new Scanner(System.in); + System.out.print("숫자를 입력해 주세요 : "); + String nStr = scanner.next(); // 3자리 숫자 입력 + + char[] charArray = nStr.toCharArray(); + ArrayList userNumArray = new ArrayList<>(); + + for (char c : charArray) { + if (Utils.checkDuplicate(charArray, c) || charArray.length != 3) { // 중복인 경우 에러 발생시킴 + throw new IllegalArgumentException("잘못된 값이 입력되었습니다. 프로그램을 종료합니다."); + } else { + userNumArray.add(Integer.parseInt(String.valueOf(c))); + } + } + + return userNumArray; + } +} diff --git a/src/main/java/main.java b/src/main/java/main.java new file mode 100644 index 00000000..b3724653 --- /dev/null +++ b/src/main/java/main.java @@ -0,0 +1,34 @@ +import domain.Computer; +import domain.User; +import jdk.jfr.Description; +import jdk.jshell.execution.Util; +import utils.Utils; + +import java.util.*; + +public class main { + public static void main(String[] args) { + + while (true) { + // 1. 컴퓨터가 랜덤으로 서로 다른 값 3개를 골라 순서대로 배열에 저장 + ArrayList randNumArray = Computer.makeRandNumArray(); + + boolean result = false; + + while (!result) { + // 2. 사용자가 3개의 숫자 입력, 순서대로 배열에 저장 + ArrayList userNumArray = User.inputNumArray(); + + // 3. 게임 플레이어가 입력한 숫자에 대한 결과 판별 + result = Utils.showResult(userNumArray, randNumArray); + } + + // 4. 게임 재시작 여부 선택 + int reStart = Utils.checkReStart(); + if (reStart == 2) { + break; + } + } + + } +} \ No newline at end of file diff --git a/src/main/java/utils/Utils.java b/src/main/java/utils/Utils.java new file mode 100644 index 00000000..a905c65e --- /dev/null +++ b/src/main/java/utils/Utils.java @@ -0,0 +1,113 @@ +package utils; + +import jdk.jfr.Description; + +import java.util.ArrayList; +import java.util.Objects; +import java.util.Scanner; + +public class Utils { + + /** + * 플레이어가 입력한 숫자(현 배열)에서 중복된 문자가 있는지 판별 + * @param charArray 중복을 검사할 배열 + * @param c 해당 배열 내 존재하는 문자, 중복을 확인할 대상 + * @return true: 중복 O, false: 중복 X + */ + public static boolean checkDuplicate(char[] charArray, char c) { + int cnt = 0; + for (char c1 : charArray) { + if (c1 == c) { + cnt++; + } + } + if (cnt > 1) { + return true; + } else { + return false; + } + } + + /** + * 플레이어가 입력한 숫자에 대한 결과 판별 + * @param userNumArray 컴퓨터가 입력한 숫자배열 + * @param randNumArray 사용자가 입력한 숫자 배열 + * 일치 여부를 반별하여 볼, 스트라이크 개수를 출력함 + * @return true: 3 스트라이크, 게임 종료, false: 3 스트라이크가 아닌 경우 + */ + public static Boolean showResult(ArrayList userNumArray, + ArrayList randNumArray) { + int strike = 0; + int ball = 0; + // 1. 스트라이크 개수 계산 + strike = Utils.countStrike(userNumArray, randNumArray); + // 2. 볼 개수 계산 + ball = Utils.countBall(userNumArray, randNumArray); + // 3. 같은 수가 전혀 없으면 낫싱이란 힌트 제공 + if (strike == 0 && ball == 0) { + System.out.println("낫싱"); + } + // 같은 수 있는 경우 결과 제시 + else { + System.out.println(ball + " 볼 " + strike + " 스트라이크"); + } + + if (strike == 3) { // 올 스트라이크 + System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료"); + return true; + } else { // 올 스트라이크가 아닌 경우 + return false; + } + } + + /** + * 볼의 개수를 계산하여 반환 + * @param userNumArray + * @param randNumArray + * @return 볼 개수 + */ + public static int countBall(ArrayList userNumArray, ArrayList randNumArray) { + int ballCnt = 0; + for (int i = 0; i < userNumArray.size(); i++) { + if (randNumArray.contains(userNumArray.get(i)) && !Objects.equals(randNumArray.get(i), + userNumArray.get(i))) { + ballCnt++; + } + } + return ballCnt; + } + + /** + * 스트라이크의 개수를 계산하여 반환 + * @param userNumArray + * @param randNumArray + * @return 스트라이크 개수 + */ + public static int countStrike(ArrayList userNumArray, + ArrayList randNumArray) { + int strikeCnt = 0; + for (int i = 0; i < userNumArray.size(); i++) { + if (Objects.equals(userNumArray.get(i), randNumArray.get(i))) { + strikeCnt++; + } + } + return strikeCnt; + } + + /** + * 게임이 종료되었을 때 호출되어 게임 재시작 여부를 물음 + * @return 1: 게임 재시작, 2: 게임 종료, + * @throws : 잘못된 값이 입력된 경우 + */ + public static int checkReStart() { + System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."); + Scanner scanner = new Scanner(System.in); + int rst = scanner.nextInt(); + + if (rst != 1 && rst != 2) { + throw new IllegalArgumentException("잘못된 값이 입력되었습니다. 프로그램을 종료합니다."); + } else { + return rst; + } + } +} diff --git a/src/test/java/test.java b/src/test/java/test.java new file mode 100644 index 00000000..597b73d9 --- /dev/null +++ b/src/test/java/test.java @@ -0,0 +1,68 @@ +import domain.Computer; +import jdk.jfr.Description; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import utils.Utils; + +import static org.assertj.core.api.Assertions.*; + +import java.util.*; + +public class test { + + @Test + @DisplayName("컴퓨터가 랜덤으로 겹치지 않는 3개의 숫자를 뽑아 순서대로 배열에 저장") + void compRandNumArrayTest(){ + ArrayList numArray = Computer.makeRandNumArray(); + for (Integer integer : numArray) { + System.out.print(integer); + } + } + + @Test + @DisplayName("플레이어가 겹치지 않는 3개의 숫자를 입력해 순서대로 배열에 저장") + void userInputNumArrayTest() { + Scanner scanner = new Scanner(System.in); +// String nStr = scanner.next(); // 3자리 숫자 입력 + String nStr = "243"; + + char[] charArray = nStr.toCharArray(); + ArrayList userNumArray = new ArrayList<>(); + + for (char c : charArray) { + if(Utils.checkDuplicate(charArray, c)){ // 중복인 경우 에러 발생시킴 + throw new IllegalArgumentException(); + } + else{ + userNumArray.add(Integer.parseInt(String.valueOf(c))); + } + } + + for (Integer integer : userNumArray) { + System.out.print(integer); + } + } + @Test + @DisplayName("플레이어가 입력한 숫자(현 배열)에서 중복된 문자가 있는지 판별") + void checkDuplicateTest() { + boolean b1 = Utils.checkDuplicate(new char[]{'1', '3', '4'}, '1'); + assertThat(b1).isEqualTo(false); + boolean b2 = Utils.checkDuplicate(new char[]{'1', '3', '3'}, '3'); + assertThat(b2).isEqualTo(true); + } + + @Test + @DisplayName("플레이어가 입력한 숫자에 대한 결과 판별") + void showResult() { + ArrayList userNumArray = new ArrayList<>(List.of(1, 2, 3)); + ArrayList randNumArray = new ArrayList<>(List.of(2, 1, 3)); + + // 1. 스트라이크 개수 정상 확인 + int strikeNum = Utils.countStrike(userNumArray, randNumArray); + assertThat(strikeNum).isEqualTo(1); + // 2. 볼 개수 정상 확인 + int ballNum = Utils.countBall(userNumArray, randNumArray); + assertThat(ballNum).isEqualTo(2) ; + } + +}