Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
23 changes: 23 additions & 0 deletions .github/workflows/codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Run tests and upload coverage
on:
pull_request
jobs:
test:
name: Run tests and collect coverage
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v4
Comment on lines +13 to +14
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Python 버전 명시 필요

Python 버전을 명시하여 일관된 테스트 환경을 보장하세요.

       - name: Set up Python
         uses: actions/setup-python@v4
+        with:
+          python-version: '3.11'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Set up Python
uses: actions/setup-python@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
🧰 Tools
🪛 actionlint (1.7.4)

14-14: the runner of "actions/setup-python@v4" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

- name: Install dependencies
run: pip install pytest pytest-cov
- name: Run tests
run: pytest --cov=. --cov-report=xml --cov-branch
- name: Upload results to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
slug: ${{ github.repository }}
60 changes: 60 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
## 기능 요구 사항
- [X] 입력 기능
- [X] 반복 입력, 1~9 서로다른 3자리의 수 (ex:123)
- [X] 게임이 끝난 경우 재시작/종료를 선택하는 1과 2 중 하나의 수

- [X] 출력 기능
- [X] 게임 시작 문구 "숫자 야구 게임을 시작합니다."
- [X] 숫자 입력 요구 문구 "숫자를 입력해주세요 : "
- [X] 입력한 수에 대한 결과를 볼, 스트라이크 개수로 표시
- [X] 볼 먼저 출력 (ex: 2볼 1스트라이크)
- [X] 모두 0개이면 "낫싱"
- [X] 일치 시, 게임 종료 안내 문구 "3개의 숫자를 모두 맞히셨습니다! 게임 종료"
- [X] 게임 새로 시작 여부 확인 질문 "게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."

- [X] 컴퓨터 기능
- [X] 1~9의 서로 다른 임의의 수 3개를 선택
- [X] 입력한 숫자와 비교하여 ball, strike 카운트

- [X] 게임 새로 시작 또는 종료 기능
- [X] 1 입력 시 재시작
- [X] 2 입력 시 종료

- [X] 예외 처리 및 종료 기능
- [X] 사용자가 잘못된 값을 입력할 경우 ValueError를 발생 후 게임 종료
- [X] 3자리 수 입력 시 예외 사항
- [X] 정자가 아닌 것을 포함한 경우
- [X] 3자리 수가 아닌 경우
- [X] 0이 포함된 경우
- [X] 중복 값이 있는 경우
- [X] 게임 새로 시작 여부 확인 질문 시
- [X] 1, 2 이외의 값을 입력한 경우

## 기능 추가
1. make_computer_num()
> 1에서 9까지 서로 다른 임의의 수 3개 생성 기능 함수 추가 [\#1]
2. player_input()
> 플레이어에게 3개의 숫자 입력 받는 기능 함수 추가 [\#2]
3. check_input()
> 플레이어가 입력한 숫자에 대한 결과를 출력하는 함수 추가 [\#3]
4. loop_check()
> 1에서 3까지의 과정을 반복해 3개의 숫자를 모두 맞히면 게임이 종료되는 기능 함수 추가 [\#4]
5. restart_baseball()
> 게임 종료 후 '1' 입력시 다시 시작, '2' 입력시 완전히 종료하는 기능 함수 추가 [\#5]
6. validate_input()
> 잘못된 값을 입력한 경우 ValueError가 발생하여 프로그램을 종료하는 기능 함수 추가 [\#6]
7. same_num_check()
> 입력 값에서 중복되는 수를 인식하는 기능 함수 추가 [\#6]

## 오류 수정
1. make_computer_num() 수정
> 랜덤 숫자 생성 과정에서 숫자 범위가 1에서 8인 오류 1에서 9 정상 작동하도록 수정 [\#7]
>> random.sample(range(1, ~~9~~10), 3)
2. same_num_check() 수정
> 첫 번째 숫자만 확인하고 바로 반환하는 오류를 전체 배열의 중복을 확인하도록 수정 [\#7]

## 기능 수정
1. loop_check() 재귀 호출에서 while 루프로 변경
> 재귀 호출은 스택 오버플로우를 일으킬 수 있으므로, while 루프로 변경 [\#8]
2. validate_input() ValueError 발생 시 에러 메시지 추가
> 입력 길이, 입력 숫자, 중복 유무 3가지로로 나눠 에러 메시지 출력 [\#8]
74 changes: 74 additions & 0 deletions src/baseball/main.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,83 @@
import random

def same_num_check(check_array): # list에서 중복되는 수를 인식하는 기능 함수
for i in check_array:
if check_array.count(i) != 1:
return 0
return 1

def validate_input(compare_array, want_len): # 잘못된 값을 입력한 경우 ValueError가 발생하여 프로그램을 종료하는 기능 함수
if (len(compare_array) != want_len): # 플레이어가 입력한 값이 예상되는 값의 길이가 아니거나, 0이 포함되거나, 중복되는 수가 입력되어도 예외 처리
raise ValueError("3개의 숫자를 입력해주세요.")
elif (0 in compare_array):
raise ValueError("1 ~ 9의 숫자만 입력해주세요.")
elif (same_num_check(compare_array) == 0):
raise ValueError("중복되는 수가 있습니다.")
Comment on lines +9 to +15
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

입력값 범위 검증 추가 필요

1부터 9까지의 숫자만 허용하도록 명시적인 검증이 필요합니다.

 def validate_input(compare_array, want_len):    # 잘못된 값을 입력한 경우 ValueError가 발생하여 프로그램을 종료하는 기능 함수
     if (len(compare_array) != want_len):    # 플레이어가 입력한 값이 예상되는 값의 길이가 아니거나, 0이 포함되거나, 중복되는 수가 입력되어도 예외 처리
         raise ValueError("3개의 숫자를 입력해주세요.")
     elif (0 in compare_array):
         raise ValueError("1 ~ 9의 숫자만 입력해주세요.")
+    elif any(num > 9 for num in compare_array):
+        raise ValueError("1 ~ 9의 숫자만 입력해주세요.")
     elif (same_num_check(compare_array) == 0):
         raise ValueError("중복되는 수가 있습니다.")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def validate_input(compare_array, want_len): # 잘못된 값을 입력한 경우 ValueError가 발생하여 프로그램을 종료하는 기능 함수
if (len(compare_array) != want_len): # 플레이어가 입력한 값이 예상되는 값의 길이가 아니거나, 0이 포함되거나, 중복되는 수가 입력되어도 예외 처리
raise ValueError("3개의 숫자를 입력해주세요.")
elif (0 in compare_array):
raise ValueError("1 ~ 9의 숫자만 입력해주세요.")
elif (same_num_check(compare_array) == 0):
raise ValueError("중복되는 수가 있습니다.")
def validate_input(compare_array, want_len): # 잘못된 값을 입력한 경우 ValueError가 발생하여 프로그램을 종료하는 기능 함수
if (len(compare_array) != want_len): # 플레이어가 입력한 값이 예상되는 값의 길이가 아니거나, 0이 포함되거나, 중복되는 수가 입력되어도 예외 처리
raise ValueError("3개의 숫자를 입력해주세요.")
elif (0 in compare_array):
raise ValueError("1 ~ 9의 숫자만 입력해주세요.")
elif any(num > 9 for num in compare_array):
raise ValueError("1 ~ 9의 숫자만 입력해주세요.")
elif (same_num_check(compare_array) == 0):
raise ValueError("중복되는 수가 있습니다.")


def make_computer_num(): # random 모듈을 사용하여 임의의 수 생성하는 함수 (요구사항)
computer = random.sample(range(1, 10), 3) # basecode
return computer

def player_input(): # 플레이어에게 3개의 숫자 입력 받는 기능 함수
get_array = list(map(int, input("숫자를 입력해주세요 : ")))
validate_input(get_array, 3)
return get_array
Comment on lines +21 to +24
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

숫자가 아닌 입력에 대한 예외 처리 필요

현재 구현에서는 숫자가 아닌 값을 입력할 경우 명확하지 않은 에러가 발생할 수 있습니다.

다음과 같이 예외 처리를 추가하는 것을 제안합니다:

 def player_input(): # 플레이어에게 3개의 숫자 입력 받는 기능 함수
-    get_array = list(map(int, input("숫자를 입력해주세요 : ")))
-    validate_input(get_array, 3)
-    return get_array
+    try:
+        get_array = list(map(int, input("숫자를 입력해주세요 : ")))
+        validate_input(get_array, 3)
+        return get_array
+    except ValueError:
+        raise ValueError("숫자만 입력해주세요")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def player_input(): # 플레이어에게 3개의 숫자 입력 받는 기능 함수
get_array = list(map(int, input("숫자를 입력해주세요 : ")))
validate_input(get_array, 3)
return get_array
def player_input(): # 플레이어에게 3개의 숫자 입력 받는 기능 함수
try:
get_array = list(map(int, input("숫자를 입력해주세요 : ")))
validate_input(get_array, 3)
return get_array
except ValueError:
raise ValueError("숫자만 입력해주세요")


def check_input(get, com): # 플레이어가 입력한 숫자에 대한 결과를 출력하는 함수
ball, strike = 0, 0
for i in range(0,3):
if get[i] == com[i]:
strike += 1
elif get[i] in com:
ball += 1
else:
continue
if strike == 3:
return "3스트라이크"
elif ball + strike == 0:
return "낫싱"
elif ball == 0:
return "{0}스트라이크".format(strike)
elif strike == 0:
return "{0}볼".format(ball)
else:
return "{0}볼 {1}스트라이크".format(ball, strike)

def loop_check(com): # 1에서 3까지의 과정을 반복해 3개의 숫자를 모두 맞히면 게임이 종료되는 기능 함수
while True:
get = player_input()
result_check_input = check_input(get, com)
print(result_check_input)
if result_check_input == "3스트라이크": # check_input()의 결과가 "3스트라이크"일 경우 게임을 종료하고, 아닐 경우 다시 loop_check() 수해
print("3개의 숫자를 모두 맞히셨습니다! 게임 종료")
return 0

def restart_baseball(): # 게임 종료 후 '1' 입력시 다시 시작, '2' 입력시 완전히 종료하는 기능 함수
print("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.")
try:
user_key = int(input())
if user_key in [1, 2]:
return user_key
else: # 잘못된 값을 입력할 경우 'ValueError'를 발생
raise ValueError("1 또는 2만 입력 가능합니다")
except ValueError:
raise ValueError("올바른 숫자를 입력해주세요 (1 또는 2)")

def main():
"""
프로그램의 진입점 함수.
여기에서 전체 프로그램 로직을 시작합니다.
"""
# 프로그램의 메인 로직을 여기에 구현
print("숫자 야구 게임을 시작합니다.")
while True:
com_num = make_computer_num()
loop_check(com_num)
restart = restart_baseball()
if restart == 1:
continue
else:
break

if __name__ == "__main__":
# 프로그램이 직접 실행될 때만 main() 함수를 호출
Expand Down
6 changes: 3 additions & 3 deletions tests/test_application.py → tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ def test_게임종료_후_재시작(capsys):
# 랜덤값 임의 정의
with patch('random.sample', side_effect=[[1, 3, 5], [5, 8, 9]]):
# 입력값 모의 처리
with patch('builtins.input', side_effect=["246", "135", "1", "597", "589", "2"]):
with patch('builtins.input', side_effect=["246", "135", "1", "512", "894", "597", "589", "2"]):
main()

# 출력값 캡처
캡처된_출력 = capsys.readouterr().out

# 결과 검증
assert all(예상_출력 in 캡처된_출력 for 예상_출력 in ["낫싱", "3스트라이크", "1볼 1스트라이크", "3스트라이크", "게임 종료"])
assert all(예상_출력 in 캡처된_출력 for 예상_출력 in ["낫싱", "3스트라이크", "1볼 1스트라이크", "1스트라이크", "2볼", "3스트라이크", "게임 종료"])


# 예외 테스트
def test_예외_테스트():
with pytest.raises(ValueError):
# 잘못된 입력 처리
with patch('builtins.input', side_effect=["1234"]):
with patch('builtins.input', side_effect=["1234", "012", "233", "3", "ㄱ"]):
main()