들어가며
오늘은 진도를 거의 나가지 않고, 미니프로젝트인 베이스볼 게임을 구현해보는 시간을 가졌다. 지금까지 접했던 10줄 내외의 예제코드와는 다르게 꽤 많은 기능을 가지고 있는 만큼 흐름을 차근차근 생각해보고 구현해보자.
베이스볼 게임 기능 설명
주요 기능
- 임의의 숫자 생성 : 컴퓨터가 0-9 사이의 서로 다른 3개의 숫자를 임의로 생성합니다.
- 사용자 입력: 사용자가 3자리 숫자를 입력한비다.
- 스트라이크 및 볼 계산 : 사용자가 입력한 숫자와 위치를 비교하여 스트라이크와 볼의 개수를 계산합니다.
- 결과 출력 : 스트라이크와 볼의 개수를 사용자에게 알려줍니다.
- 게임 종료 : 사용자가 숫자를 모두 맞추면 게임을 종료하고, 재시작 여부를 묻습니다.
세부 기능 설명
- 임의의 숫자 생성 : `random` 모듈을 사용하여 0-9 사의 서로 다른 3개의 숫자를 임의로 생성합니다.
- 사용자 입력 : 사용자가 3자리 숫자를 입력할 수 있도록 하고, 입력값이 유효한지 검사합니다.
- 옵션 : 숫자, 길이, 중복 체크
- 스트라이크 및 볼 계산
- 스트라이크 : 숫자와 위치가 모두 맞는 경우
- 볼 : 숫자는 맞지만 위치가 다른 경우
- 예 : 컴퓨터 숫자가 123이고, 사용자가 135를 입력한 경우, 1 스트라이크 1 볼
- 결과 출력 : 스트라이크와 볼의 개수를 출력합니다.
- 예 : `1 스트라이크, 1 볼`
- 게임 종료 : 사용자가 모든 숫자를 맞추면 게임을 종료하고, 재시작 여부를 묻습니다.
- 예 : `3 스트라이크! 정답입니다! 게임을 다시 시작하시겠습니까?(Y/N)`
코드 분석
먼저 랜덤한 수를 생성하기 위해 random 라이브러리를 `import` 해준다.
import random
프로그램은 무한으로 돌면서 값을 입력받기 때문에 `while`문의 조건을 `True`로 설정하여 무한루프를 만든다. 그리고 그 안에 난수를 담을 `randNum`리스트를 초기화해주고, 스트라이크와 볼의 개수를 카운트할 변수도 선언해준다.
while True:
randNum = []
strike, ball = 0,0
이어서 난수를 입력받을 코드를 작성한다. random의 `sample`모듈을 사용하지 않고 서로 다른 수 3개를 입력받기 위해 다음과 같은 로직을 구현했다.
while len(randNum) != 3: # 난수리스트에 3개의 수가 저장될 때까지 반복
tmp = random.randint(0, 9) # 0에서 9사이의 수를 생성 후 tmp에 저장
if tmp not in randNum: # 생성한 난수 tmp가 randNum리스트에 존재하지 않으면,
randNum.append(tmp) # 난수 추가
이제 생성된 3개의 난수와 비교하기 위해 사용자로부터 입력을 받고 입력한 수가 난수와 같아질 때까지 반복하는 과정을 구현한다.
while strike != 3: # 3 스트라이크 즉, 모든 숫자를 맞췄을 때까지 반복
strike, ball = 0,0 # 입력 시도할 때마다 증가 연산된 strike, ball을 0으로 초기화
tmpNum = input('숫자를 입력하세요(0-9)') # 3자리 숫자를 일단 tmpNum에 str형태로 입력받음
userNum = list(map(int, tmpNum)) # tmpNum을 정수 리스트 형태로 변환후 userNum에 저장
자리수 검사와 중복된 수 검사 기능을 가진 코드이다. 중복된 수 검사는 `set`자료형으로 변환하면 중복된 수를 없애고 서로 다른 수들만 남기 때문에 길이 값이 3보다 작으면 중복된 수가 존재한 것으로 판단한다.
# 자리수 검사
if len(tmpNum) != 3 # 자리수가 3이 아니면,
print('세자리 수를 입력해주세요') # 메시지 출력 후,
continue # 아래 코드 무시(다시 입력받는 위치로 이동)
# 중복된 수 검사
elif len(set(userNum)) != 3: # set자료형으로 변환 후 그 길이가 3이 아니면,
print('서로 다른 세자리 숫자를 입력해주세요') # 메시지 출력 후,
continue # 아래 코드 무시(다시 입력받는 위치로 이동)
`for`문으로 3번 반복하면서 `if`문으로 스트라이크와 볼을 판단하고 각 개수를 계산한다. 그리고 계산된 스트라이크와 볼의 개수를 포맷팅하여 직관적인 메시지로 출력해준다.
for i in range(3):
# 위치도 같고, 숫자도 같으면(스트라이크)
if userNum[i] == randNum[i]:
strike += 1 # 스트라이크 1개 증가
# 위치는 다르지만 숫자가 포함되어 있으면(볼)
elif userNum[i] in randNum:
ball += 1 # 볼 1개 증가
# 스트라이크만 존재하면,
if strike > 0 and ball == 0:
print(f'{strike} 스트라이크') # 스트라이크 개수만 출력
# 볼만 존재하면,
elif strike == 0 and ball > 0:
print(f'{ball} 볼') # 볼 개수만 출력
# 스트라이크, 볼 모두 존재하면,
else:
print(f'{strike} 스트라이크 {ball} 볼') # 둘 다 출력
이제 난수와 입력받은 수가 같아질 때까지 반복하는 `while`문은 작성이 끝났고, 정답을 맞춘 후 게임 재시작 여부를 제공하는 기능을 구현하면 완성이다.
# 3스트라이크 알림메시지 출력과 동시에 Y또는 N을 입력받아 ans변수에 저장
ans = input(f'{strike} 스트라이크! 정답입니다! 게임을 다시 시작하시겠습니까? (Y/N)')
if ans == 'Y': continue # 입력 받은게 Y이면, 새로운 게임 시작
elif ans == 'N': break # 입력 받은게 N이면, 프로그램 종료
전체 코드
import random
while True:
randNum = []
strike, ball = 0,0
while len(randNum) != 3:
tmp = random.randint(0, 9)
if tmp not in randNum:
randNum.append(tmp)
while strike != 3:
strike, ball = 0,0
tmpNum = input('숫자를 입력하세요(0-9)')
userNum = list(map(int, tmpNum))
if len(tmpNum) != 3:
print('세자리 수를 입력해주세요')
continue
elif len(set(userNum)) != 3:
print('서로 다른 세자리 숫자를 입력해주세요')
continue
for i in range(3):
if userNum[i] == randNum[i]:
strike += 1
elif userNum[i] in randNum:
ball += 1
if strike > 0 and ball == 0:
print(f'{strike} 스트라이크')
elif strike == 0 and ball > 0:
print(f'{ball} 볼')
else:
print(f'{strike} 스트라이크 {ball} 볼')
ans = input(f'{strike} 스트라이크! 정답입니다! 게임을 다시 시작하시겠습니까? (Y/N)')
if ans == 'Y': continue
elif ans == 'N': break
마무리
다양한 기능이 복합적으로 동작하는 코드이다보니 구현하는 데 생각보다 오래 걸렸고, 어느 때보다 시간도 금방 흘러갔던 것 같다. 또한 조원들과 소통하면서 하나의 문제를 바라보는 다양한 시각을 공유할 수 있던 점이 정말 좋았다.
'ABC부트캠프 테크노트' 카테고리의 다른 글
[8일차] ABC부트캠프 : 파이썬 프로그래밍 데이터 전처리 & 시각화 (2) | 2024.07.16 |
---|---|
[7일차] ABC부트캠프 : 파이썬 프로그래밍 데이터 전처리 기초 (0) | 2024.07.12 |
[5일차] ABC부트캠프 : 파이썬프로그래밍 기초3 (0) | 2024.07.10 |
[4일차] ABC부트캠프 : 파이썬 프로그래밍 기초2 (0) | 2024.07.09 |
[3일차] ABC부트캠프 : 파이썬 프로그래밍 기초1 (0) | 2024.07.08 |