Skip to content
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0ad0800
[#1] Add ability to generate 3 different random numbers from 1 to 9
AI-WonYJ Feb 4, 2025
e9b9903
[#2] Add: ability to ask player to enter 3 numbers
AI-WonYJ Feb 4, 2025
fa83c50
[#3] Add: a function to print the results for the numvers entered by …
AI-WonYJ Feb 4, 2025
29aee5c
[#4] Add: a function that repeats the process from 1 to 3 and the gam…
AI-WonYJ Feb 4, 2025
7d16fdc
[#5] Add: a function to restart when you input '1' after ending the g…
AI-WonYJ Feb 4, 2025
63af4f5
[#6] Add & Fix: IF and incorrect value is entered, a Value Error occu…
AI-WonYJ Feb 5, 2025
d67269a
[#7] Fix:
AI-WonYJ Feb 5, 2025
a800292
[#7] Fix:
AI-WonYJ Feb 5, 2025
aec6b51
[#7] Fix: same_num_check() / An error that only check the first numbe…
AI-WonYJ Feb 5, 2025
1909043
Merge commit '7139696ea1957410b2fa83c0a4a16e692d2c9efb' into AI-WonYJ
AI-WonYJ Feb 5, 2025
31f7e15
[#8] Refactor: 재귀 호출 방식 변경 및 에러 메시지 추가
AI-WonYJ Feb 5, 2025
578fa97
Add: ability to generate 3 different random numbers from 1 to 9
AI-WonYJ Feb 4, 2025
806c52b
Add: ability to ask player to enter 3 numbers
AI-WonYJ Feb 4, 2025
34cf964
Add: a function to print the results for the numvers entered by the p…
AI-WonYJ Feb 4, 2025
7e93e04
Add: a function that repeats the process from 1 to 3 and the game end…
AI-WonYJ Feb 4, 2025
5d3fa3a
Add: a function to restart when you input '1' after ending the game, …
AI-WonYJ Feb 4, 2025
5acd13a
Add & Fix: IF and incorrect value is entered, a Value Error occurs an…
AI-WonYJ Feb 5, 2025
78c1da0
Fix: During the random number generation process, errors with number …
AI-WonYJ Feb 5, 2025
da99498
Fix: During the random number generation process, errors with number …
AI-WonYJ Feb 5, 2025
0745578
Fix: same_num_check() / An error that only check the first number and…
AI-WonYJ Feb 5, 2025
d2ba4de
[#0] change actions yml `push` -> `pull_request`
swthewhite Feb 4, 2025
e7a0b7f
[#0] fix actions yml's target slug
swthewhite Feb 4, 2025
2cbddfb
[#0] use context in actions yml's slug
swthewhite Feb 4, 2025
2a66eb8
Refactor: 재귀 호출 방식 변경 및 에러 메시지 추가
AI-WonYJ Feb 5, 2025
6b89471
Test: ValueError 테스트와 입력 경우의 수 테스트 추가
AI-WonYJ Feb 7, 2025
d19d0b9
Update: Improve input validation and error handling함
AI-WonYJ Feb 7, 2025
d83709b
Refactor: 가독성 개선 및 코드 간소화
AI-WonYJ Feb 7, 2025
6876965
Refactor: 예외처리 개선 및 docstring 보완
AI-WonYJ Feb 7, 2025
7588ca7
Merge branch 'AI-WonYJ' of https://github.com/AI-WonYJ/python-basebal…
AI-WonYJ Mar 24, 2025
8ca20d2
Update main.py
AI-WonYJ Mar 24, 2025
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
- 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]
138 changes: 138 additions & 0 deletions src/baseball/main.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,147 @@
import random

def same_num_check(check_array):
"""
리스트에서 중복된 숫자가 있는지 확인하는 함수.
중복된 숫자가 있으면 1을 반환하고, 없으면 0을 반환.
"""
return len(set(check_array)) != len(check_array)

def is_number (Data):
"""
Data가 숫자인지 확인하는 함수.
숫자가 아니면 ValueError를 발생시킴.
"""
try:
int(Data) # Data가 int 형식인지 확인
except ValueError:
raise ValueError("숫자만 입력해주세요.") # 숫자가 아닌 값 입력시 예외 처리

def validate_input(Data, Criteria):
"""
사용자가 입력한 값을 검증하는 함수.
- Data: 사용자가 입력한 값
- Criteria: 예상하는 값의 조건 (정수 또는 리스트 형식()
잘못된 값이 입력되면 ValueError를 발생시킴.
"""
# 숫자 확인
is_number(Data)

if isinstance(Criteria, int): # Criteria가 int일 경우, player_input()에서 사용
compare_array = list(map(int, Data)) # Data를 정수형 리스트로 변환

# 플레이어가 입력한 값이 예상되는 값의 길이가 아닐 경우 예외 처리
if (len(compare_array) != Criteria):
raise ValueError("3개의 숫자를 입력해주세요.")

# 중복된 숫자가 있을 경우 예외 처리
if (same_num_check(compare_array) == 1):
raise ValueError("숫자 중복 없이 입력해주세요.")

# 1~9의 숫자가 아닌 0이 포함된 경우 예외 처리
if (0 in compare_array):
raise ValueError("1 ~ 9의 숫자만 입력해주세요.")

return compare_array # 입력이 정상이면 정수 리스트 변환

elif isinstance(Criteria, list): # Criteria가 list일 경우, restart_baseball()에서 사용
# Data가 Criteria에 포함되지 않은 값일 경우 예외 처리
if int(Data) not in Criteria:
raise ValueError("숫자 1 또는 2만 입력해주세요.")


def make_computer_num():
"""
컴퓨터가 랜덤으로 3개의 숫자를 생성하는 함수.
1에서 9까지의 숫자 중에서 중복 없이 3개를 뽑음.
"""
computer = random.sample(range(1, 10), 3) # 1~9 사이에서 중복 없이 3개 숫자 선택
return computer

def player_input():
"""
플레이어에게 숫자 3개를 입력받는 함수.
입력 값 검증 후 정상적인 값을 반환.
"""
get_array = validate_input(input("숫자를 입력해주세요 : "), 3) # 입력 값 검증
return get_array

def check_input(get, com):
"""
플레이어가 입력한 값과 컴퓨터가 생성한 값을 비교하여 결과를 출력하는 함수.
- 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 # 숫자도 위치도 맞지 않으면 아무것도 하지 않음

# 스트라이크가 3이면 3스트라이크 반환
if strike == 3:
return "3스트라이크"

# 스트라이크와 볼이 모두 없으면 낫싱 반환
elif ball + strike == 0:
return "낫싱"

result = [] # 결과를 저장할 리스트

# 볼이 하나 이상 있으면 볼 정보 추가
if ball > 0:
result.append(f"{ball}볼")

# 스트라이크가 하나 이상 있으면 스트라이크 정보 추가
if strike > 0:
result.append(f"{strike}스트라이크")

# 볼과 스트라이크가 있을 경우 공백으로 구분해서 반환
return " ".join(result)

def loop_check(com):
"""
게임을 반복하여 진행하는 함수.
플레이어가 3개의 숫자를 모두 맞힐 때까지 반복.
"""
while True:
get = player_input() # 플레이어 입력 받기
result_check_input = check_input(get, com) # 입력한 값과 컴퓨터 값 비교
print(result_check_input) # 결과 출력
if result_check_input == "3스트라이크": # 3스트라이크면 게임 종료
print("3개의 숫자를 모두 맞히셨습니다! 게임 종료")
return 0 # 게임 종료

def restart_baseball():
"""
게임 종료 후 '1'을 입력하면 게임을 새로 시작하고, '2'를 입력하면 종료하는 함수.
"""
print("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.")
restart_input = input() # 플레이어 입력 받기
validate_input(restart_input, [1, 2]) # 입력 값 검증
return int(restart_input)


def main():
"""
프로그램의 진입점 함수.
여기에서 전체 프로그램 로직을 시작합니다.
"""
# 프로그램의 메인 로직을 여기에 구현
print("숫자 야구 게임을 시작합니다.")
while True:
com_num = make_computer_num() # 컴퓨터가 생성한 숫자
loop_check(com_num) # 게임 진행
restart = restart_baseball() # 게임 재시작 여부 확인
if restart == 1: # 1을 입력하면 게임 재시작
continue
else: # 2를 입력하면 게임 종료
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()