Skip to content
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

[202201912 이서인] 1주차 미션을 제출합니다. #1

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 43 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,53 @@
# 미션 - 숫자 야구 게임

## 🔍 진행방식

- 미션은 **기능 요구사항, 프로그래밍 요구사항, 과제 진행 요구사항** 세 가지로 구성되어 있다.
- 세 개의 요구사항을 만족하기 위해 노력한다. 특히 기능을 구현하기 전에 기능 목록을 만들고, 기능 단위로 커밋 하는 방식으로 진행한다.

## ✔️ 과제 제출 전 체크리스트

- 터미널에서 `java -version`을 실행해 자바 21인지 확인한다. 또는 Eclipse, IntelliJ IDEA와 같은 IDE의 자바 21로 실행하는지 확인한다.
- 터미널에서 맥 또는 리눅스 사용자의 경우 `./gradlew clean test`, 윈도우 사용자의 경우 `gradlew.bat clean test` 명령을 실행했을 때 모든 테스트가 통과하는지 확인한다.

---

## 🚀 기능 요구사항

기본적으로 1부터 9까지 서로 다른 수로 이루어진 3자리의 수를 맞추는 게임이다.

- 같은 수가 같은 자리에 있으면 스트라이크, 다른 자리에 있으면 볼, 같은 수가 전혀 없으면 포볼 또는 낫싱이란 힌트를 얻고, 그 힌트를 이용해서 먼저 상대방(컴퓨터)의 수를 맞추면 승리한다.
- 예) 상대방(컴퓨터)의 수가 425일 때
- 123을 제시한 경우 : 1스트라이크
- 456을 제시한 경우 : 1볼 1스트라이크
- 789를 제시한 경우 : 낫싱
- 위 숫자 야구 게임에서 상대방의 역할을 컴퓨터가 한다. 컴퓨터는 1에서 9까지 서로 다른 임의의 수 3개를 선택한다. 게임 플레이어는 컴퓨터가 생각하고 있는 3개의 숫자를 입력하고, 컴퓨터는 입력한 숫자에 대한 결과를 출력한다.
- 이 같은 과정을 반복해 컴퓨터가 선택한 3개의 숫자를 모두 맞히면 게임이 종료된다.
- 게임을 종료한 후 게임을 다시 시작하거나 완전히 종료할 수 있다.
- 사용자가 잘못된 값을 입력할 경우 `IllegalArgumentException`을 발생시킨 후 애플리케이션은 종료되어야 한다.
- 아래의 프로그래밍 실행 결과 예시와 동일하게 입력과 출력이 이루어져야 한다.


---

## 🚀 기능 목록
- 1~9 사이의 겹치지 않는 랜덤 숫자 3개를 생성한다.
- 사용자로부터 3자리 숫자를 받는다.
- 오류를 감지한다.
- 중복되는 숫자가 있는 경우
- 3자리 숫자가 아닌 경우
- 1~9 범위가 아닌 경우
- 입력받은 수로부터 랜덤 숫자와의 비교를 통해 볼, 스트라이크를 알아낸다.
- 볼, 스트라이크, 낫싱의 경우를 결정한다.
- 볼만 출력 : 스트라이크=0, 볼!=0
- 스트라이크만 출력 : 스트라이크!=0, 볼=0
- 3스트라이크 출력 : 스트라이크=3
- 낫싱 출력 : 스트라이크=0, 볼=0
- 볼, 스트라이크 출력 : 스트라이크!=0, 볼!=0
- 3스트라이크일 경우 게임이 종료된다.
- 정답 문구 출력
- 게임 다시하기 기능
- 1 : 게임을 처음부터 다시한다.
- 2 : 프로그램을 종료한다.

<br>

## ✍🏻 입출력 요구사항
## ✍🏻 느낀점
깃에서 리포지토리를 복사해서 가져오는 것은 처음이라 많이 해맸지만, 서치와 질문을 통해 해결해갔습니다. 깃이 참 멀게 느껴졌는데 이제는 쉽게 사용할 수 있을 것 같아 신기하였습니다.

어떻게 과제를 해결하면 좋을까 싶어 기능 목록도 자세하게 적어보고, 코드를 간결하게 작성하는 방법에 대해 유튜브 강의도 들어보니 시간이 오래 걸렸지만 앞으로 어떻게 공부하면 되는지 방향성을 잡을 수 있어 보람찬 시간이었습니다. 그동안 코딩하면서 제가 어떤 부분이 부족하였는 지를 깨닫게 되었고 다음 과제에서도 어떤 점을 제가 깨달을까 기대되었습니다.

다른 사람들의 코드를 볼 때 여러 조건문이 중첩되어 있으면 알아보기 힘든 점이 생각나, 최대한 간결하게 작성해보고자 노력하였습니다. 그래서 프로그래밍 요구사항중 인덴트 깊이를 지키는 것에 많이 고민했습니다.

---

## 🔍 과제
- 미션은 기능 요구사항, 프로그래밍 요구사항, 과제 진행 요구사항 세 가지로 구성되어 있다.
- 세 개의 요구사항을 만족하기 위해 노력한다. 특히 기능을 구현하기 전에 기능 목록을 만들고, 기능 단위로 커밋 하는 방식으로 진행한다.

### ✔️ 과제 제출 전 체크리스트

- 터미널에서 java -version을 실행해 자바 21인지 확인한다. 또는 Eclipse, IntelliJ IDEA와 같은 IDE의 자바 21로 실행하는지 확인한다.
- 터미널에서 맥 또는 리눅스 사용자의 경우 ./gradlew clean test, 윈도우 사용자의 경우 gradlew.bat clean test 명령을 실행했을 때 모든 테스트가 통과하는지 확인한다.

### ⌨️ 입력

Expand Down Expand Up @@ -95,9 +113,9 @@

### 프로그래밍 요구사항 - Randoms, Console

- JDK에서 기본 제공하는 Random, Scanner API 대신 `mallang.missionutils` 패키지의 `Randoms`, `Console` API를 활용해 구현해야 한다.
- Random 값 추출은 `mallang.missionutils.Randoms`의 `pickNumberInRange()`를 활용한다.
- 사용자가 입력하는 값은 `mallang.missionutils.Console`의 `readLine()`을 활용한다.
- JDK에서 기본 제공하는 Random, Scanner API 대신 `camp.nextstep.edu.missionutils`에서 제공하는 `Randoms`, `Console` API를 활용해 구현해야 한다.
- Random 값 추출은 `camp.nextstep.edu.missionutils.Randoms`의 `pickNumberInRange()`를 활용한다.
- 사용자가 입력하는 값은 `camp.nextstep.edu.missionutils.Console`의 `readLine()`을 활용한다.
- 프로그램 구현을 완료했을 때 `src/test/java` 디렉터리의 `ApplicationTest`에 있는 모든 테스트 케이스가 성공해야 한다. **테스트가 실패할 경우 0점 처리한다.**

<br>
Expand Down
140 changes: 137 additions & 3 deletions src/main/java/baseball/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,141 @@
package baseball;

import camp.nextstep.edu.missionutils.Console;
import camp.nextstep.edu.missionutils.Randoms;

import java.io.IOException;
import java.util.*;

import camp.nextstep.edu.missionutils.Console;
import camp.nextstep.edu.missionutils.Randoms;

public class Application {
public static void main(String[] args) {
//TODO: 숫자 야구 게임 구현
}
private static final int MIN = 1;
private static final int MAX = 9;
private static final int BALL_SIZE = 3;
Copy link
Contributor

@shin-mallang shin-mallang Feb 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

매직 넘버 대신 상수로 정의해서 사용해 주셨네요 💯

변수의 이름을 조금 더 명확하게 지어주는 것은 어떨까요?

MIN이 정확히 어떤 것에 대한 최소인지,
MAX가 정확히 어떤 것에 대한 최대인지 알기 어려워 보입니다!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 수정하겠습니다!


public static void main(String[] args) {
while (true) {
playGame();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

System.exit를 사용하지 않고 게임을 종료하려면 이 부분에 대한 수정이 필요할 것 같네요 :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 수정하겠습니다!

}

/* 게임 메소드 */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

불필요한 주석 같아요!
주석 역시도 유지보수의 대상이 되므로, 주석을 남발하여 작성하지 않고, 꼭 필요한 곳에만 작성해도록 연습해봐요 :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아하 그렇군요! 꼭 필요한 부분에만 주석 작성하도록 하겠습니다 :>

private static void playGame() {
// 랜덤 3자리 숫자 생성
int computerBall[] = generateRandomBall();
System.out.println("랜덤 숫자 : " + Arrays.toString(computerBall));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분도 주석을 사용하기보단, 메서드로 추출하여 랜덤한 숫자를 생성한다는 동작을 진행하도록 바꿔볼까요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵! 메서드로 코드 작성해보겠습니당


while (true) {
// 사용자 입력 3자리 숫자
int[] userBall = getUserInput();
checkBall(userBall);

// 볼, 스트라이크, 낫싱 체크
int ballScore = ballCheck(computerBall, userBall);
int strikeScore = strikeCheck(computerBall, userBall);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ballCheck, strikeCheck 만으로도 이미 무엇을 하는지 의미가 명확하다고 생각해요! 💯
주석은 불필요해 보여요!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵! 주석 삭제해놓겠습니다!


// 힌트 출력
if (strikeScore != 0 && ballScore == 0) {
System.out.println(strikeScore + "스트라이크");
} else if (strikeScore == 0 && ballScore != 0) {
System.out.println(ballScore + "볼");
} else if (strikeScore == 3) {
System.out.println(strikeScore + "스트라이크");
System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료");
playAgain();
} else if (strikeScore == 0 && ballScore == 0) {
System.out.println("낫싱");
} else {
System.out.println(ballScore + "볼" + strikeScore + "스트라이크");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분도 마찬가지로 메서드를 분리하고 주석을 제거해볼까요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵! 수정하겠습니당

}
}

/* 게임 반복 메소드 */
private static void playAgain() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제공드린 코드 컨벤션 문서를 참고하여 메서드 순서를 올바르게 변경해주세요 :)

System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.");
String inputNum = Console.readLine();
if (inputNum.equals("1")) {
playGame();
} else {
System.exit(0);
}
}

/* 랜덤 3자리 숫자 생성 메소드 */
private static int[] generateRandomBall() {
Set<Integer> set = new HashSet<>();
int[] randomBall = new int[3];
int count = 0;
while (count < 3) {
int number = Randoms.pickNumberInRange(1, 9);
if (!set.contains(number)) { // 중복이 없을 경우
randomBall[count] = number;
set.add(number);
count++;
}
}
return randomBall;
}

/* 사용자 입력 3자리 숫자 메소드 */
private static int[] getUserInput() {
System.out.print("숫자를 입력해주세요 : ");
String inputNum = Console.readLine();
if (inputNum.length() != BALL_SIZE) {
throw new IllegalArgumentException("3자리 숫자를 입력해주세요");
}
int[] userBall = new int[BALL_SIZE];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

배열 대신 List를 사용해봐요!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵! 리스트로 변경하겠습니당

for (int i = 0; i < BALL_SIZE; i++) {
userBall[i] = Character.getNumericValue(inputNum.charAt(i));
}
return userBall;
}

/* 오류를 체크하는 메소드*/
private static void checkBall(int[] inputBalls) {
Set<Integer> set = new HashSet<>();
for (int num : inputBalls) {
if (num < MIN || num > MAX) {
throw new IllegalArgumentException("1~9의 범위 내에서 입력해주세요.");
}
if (!set.add(num)) {
throw new IllegalArgumentException("숫자를 중복해서 입력하지 마세요.");
}
}
System.out.println("오류 없음");
}

/* 볼 카운트 메소드 */
private static int ballCheck(int[] computerNum, int[] userNum) {
int ball = 0;
for (int num : userNum) {
if (contains(computerNum, num)) {
ball++;
}
}
return ball;
}

/* 스트라이크 카운트 메소드 */
private static int strikeCheck(int[] computerNum, int[] userNum) {
int strike = 0;
for (int i = 0; i < BALL_SIZE; i++) {
if (computerNum[i] == userNum[i]) {
strike++;
}
}
return strike;
}

/* 배열에 숫자가 포함되어 있는지 확인하는 메소드 */
private static boolean contains(int[] array, int target) {
for (int num : array) {
if (num == target) {
return true;
}
}
return false;
}
}