이번 챕터에서는 파이썬의 핵심 제어문인 조건문과 반복문을 활용하여 ‘숫자 맞추기 게임’을 직접 만들어 보겠습니다. 코딩을 전혀 모르는 분들도 쉽게 따라오실 수 있도록 단계별로 자세히 설명하고, 실제 동작하는 프로그램을 만들어보는 과정을 통해 파이썬의 재미와 유용성을 경험하실 수 있을 것입니다. 이 게임은 여러분이 프로그래밍 사고력을 키우는 데 매우 좋은 출발점이 될 것입니다.
이 챕터에서는 파이썬의 핵심 개념인 조건문과 반복문을 실제 프로그램에 적용하여 ‘숫자 맞추기 게임’을 구현합니다. 이 과정을 통해 여러분은 코드가 어떻게 특정 조건에 따라 다르게 동작하고, 또 어떻게 여러 번 반복될 수 있는지를 체감하게 될 것입니다.
숫자 맞추기 게임, 왜 만들어야 하나요?
숫자 맞추기 게임은 파이썬의 핵심 흐름 제어 개념을 익히는 데 매우 효과적인 실습입니다. 처음 파이썬을 배우는 분들에게 가장 추천하는 프로젝트 중 하나로, 저는 이 게임을 만들면서 조건문과 반복문의 중요성을 깨달았습니다. 단순히 문법을 암기하는 것을 넘어, 코드가 특정 상황에서 어떤 결과를 낳는지 직접 확인하며 프로그래밍의 논리를 자연스럽게 익힐 수 있습니다. 파이썬이 컴퓨터와 대화하는 방식의 기초를 튼튼하게 다질 수 있죠.
게임을 시작하기 전에, 파이썬 3.11 이상 버전이 여러분의 컴퓨터에 설치되어 있고 기본적인 파이썬 문법(변수, 데이터 타입 등)을 이해하고 있다고 가정합니다. 만약 아직 설치하지 않으셨다면, 파이썬 설치하기 챕터를 먼저 참고해 주세요.
게임의 핵심, 무작위 숫자 생성하기
우리가 맞춰야 할 비밀 숫자는 파이썬의 random 모듈을 사용해 무작위로 생성합니다. 게임이 재미있으려면 매번 다른 숫자가 나와야겠죠? 파이썬의 표준 라이브러리 중 하나인 random 모듈은 이러한 무작위성을 제공합니다. 저는 데이터 분석 프로젝트에서 샘플 데이터를 만들거나 자동화 스크립트에서 예측 불가능한 요소를 추가할 때 이 random 모듈을 자주 사용합니다. 2024년 현재, 이 모듈은 파이썬 개발에서 매우 광범위하게 활용됩니다.
먼저, random 모듈을 가져와야 합니다. 그리고 randint() 함수를 사용해 1부터 100 사이의 정수 중 하나를 비밀 숫자로 선택합니다.
import random # random 모듈을 가져옵니다.
secret_number = random.randint(1, 100) # 1부터 100 사이의 무작위 정수를 생성합니다.
이 코드는 secret_number라는 변수에 1부터 100까지의 숫자 중 하나를 임의로 할당합니다. 이제 우리가 맞춰야 할 목표 숫자가 생겼습니다.
사용자 입력 처리와 조건문으로 추측 확인하기
input() 함수로 사용자에게 숫자를 입력받고, if-elif-else 조건문을 이용해 입력된 숫자가 비밀 숫자와 일치하는지, 혹은 더 큰지 작은지를 판단합니다. 사용자가 입력한 값은 기본적으로 문자열이기 때문에, 숫자와 비교하려면 int() 함수를 활용해 데이터 타입을 정수형으로 변환해야 합니다. 제가 처음 이 작업을 할 때, 문자열과 숫자를 비교하려다 TypeError를 수없이 만났던 기억이 생생합니다.
guess = input("1에서 100 사이의 숫자를 맞춰보세요: ") # 사용자로부터 숫자를 입력받습니다.
try:
guess = int(guess) # 입력받은 문자열을 정수로 변환합니다.
except ValueError:
print("유효한 숫자를 입력해주세요.")
# 여기서 게임을 다시 시작하거나 다음 기회를 넘길 수 있습니다.
# 일단은 예외 처리만 보여줍니다.
if guess == secret_number: # 추측한 숫자가 비밀 숫자와 같으면
print("축하합니다! 숫자를 맞추셨습니다!")
elif guess < secret_number: # 추측한 숫자가 비밀 숫자보다 작으면
print("너무 작습니다! 다시 시도하세요.")
else: # 추측한 숫자가 비밀 숫자보다 크면 (guess > secret_number)
print("너무 큽니다! 다시 시도하세요.")
try-except 블록은 사용자가 숫자가 아닌 다른 것을 입력했을 때 발생할 수 있는 ValueError를 처리하여 프로그램이 강제로 종료되는 것을 방지합니다. 이런 기본적인 예외 처리는 실제 프로그램을 만들 때 안정성을 높이는 데 필수적입니다.
반복문으로 게임 기회 부여하기
while 반복문을 사용하여 사용자가 정답을 맞출 때까지 여러 번 추측할 기회를 제공합니다. 한 번의 기회만으로는 게임이 너무 싱겁겠죠? while 반복문은 특정 조건이 만족하는 동안 코드 블록을 계속 실행합니다. 저는 보통 자동화 스크립트에서 특정 파일이 생성될 때까지 기다리거나, 특정 웹 페이지의 로딩이 완료될 때까지 반복적으로 확인하는 로직을 구현할 때 while 문을 활용합니다.
attempts = 0 # 시도 횟수를 기록할 변수를 초기화합니다.
while True: # 무한 반복을 시작합니다.
guess = input("1에서 100 사이의 숫자를 맞춰보세요: ")
try:
guess = int(guess)
except ValueError:
print("유효한 숫자를 입력해주세요.")
continue # 숫자가 아니면 다음 반복으로 넘어갑니다.
attempts += 1 # 시도 횟수를 1 증가시킵니다.
if guess == secret_number:
print(f"축하합니다! {attempts}번 만에 숫자를 맞추셨습니다!")
break # 정답을 맞췄으므로 반복문을 종료합니다.
elif guess < secret_number:
print("너무 작습니다! 다시 시도하세요.")
else:
print("너무 큽니다! 다시 시도하세요.")
여기서 while True는 조건이 항상 참이므로 무한히 반복됩니다. 하지만 사용자가 정답을 맞추면 break 키워드를 사용해 반복문을 강제로 종료합니다. break와 continue 같은 키워드는 반복문의 흐름을 제어하는 데 매우 유용합니다.
게임 로직 통합하기: 전체 코드 만들기
지금까지 배운 개념들을 조합하여 숫자 맞추기 게임의 전체 코드를 완성할 수 있습니다. 앞에서 살펴본 무작위 숫자 생성, 사용자 입력 처리, 조건문, 그리고 반복문을 하나의 파이썬 스크립트 파일로 통합하면 됩니다. 저는 이런 식으로 작은 단위의 기능을 먼저 구현하고, 그것들을 합쳐서 하나의 큰 프로그램을 만드는 방식을 선호합니다. 이렇게 하면 각 기능의 오류를 쉽게 찾고 수정할 수 있습니다.
import random
def play_number_guessing_game():
secret_number = random.randint(1, 100)
attempts = 0
max_attempts = 7 # 시도 횟수 제한 (예: 7번)
print("=== 숫자 맞추기 게임을 시작합니다! ===")
print(f"저는 1부터 100 사이의 숫자를 생각하고 있습니다. {max_attempts}번의 기회 안에 맞춰보세요.")
while attempts < max_attempts:
try:
guess = int(input(f"({attempts + 1}번째 시도) 숫자를 입력하세요: "))
except ValueError:
print("⚠️ 유효한 숫자를 입력해주세요!")
continue
if not (1 <= guess <= 100):
print("⛔ 1에서 100 사이의 숫자를 입력해야 합니다!")
continue
attempts += 1
if guess == secret_number:
print(f"🎉 축하합니다! {attempts}번 만에 숫자를 맞추셨습니다!")
break
elif guess < secret_number:
print("⬆️ 너무 작습니다! 더 큰 숫자를 시도해보세요.")
else:
print("⬇️ 너무 큽니다! 더 작은 숫자를 시도해보세요.")
else: # while 루프가 break 없이 종료된 경우 (시도 횟수 초과)
print(f"😭 아쉽습니다! {max_attempts}번의 기회를 모두 사용하셨습니다.")
print(f"정답은 {secret_number}였습니다.")
print("=== 게임 종료 ===")
# 게임 실행
if __name__ == "__main__":
play_number_guessing_game()
이 코드를 number_game.py 같은 이름으로 저장하고 파이썬 인터프리터나 통합 개발 환경에서 실행하면 여러분만의 숫자 맞추기 게임이 시작됩니다. max_attempts 변수를 추가하여 시도 횟수도 제한했습니다. while 문의 else 블록은 반복문이 break 없이 정상적으로 완료되었을 때 실행되는데, 여기서는 시도 횟수를 모두 소진했을 때의 메시지를 출력하는 데 사용되었습니다.
흔히 발생하는 문제점과 해결 팁
코드를 작성하다 보면 예상치 못한 오류에 부딪히기 마련인데, 흔한 문제들의 해결책을 미리 알아두는 것이 좋습니다. 저도 처음에는 오류 메시지 자체를 이해하기 어려워 프로그램 만드는 데 평균 3시간 넘게 걸렸습니다. 특히 입문자들이 많이 겪는 몇 가지 문제들이 있습니다.
ValueError:int(input())을 사용할 때, 사용자가 숫자가 아닌 문자열을 입력하면 발생합니다. 위 코드처럼try-except블록으로 감싸서 처리하는 것이 가장 좋은 방법입니다.- 무한 루프:
while문의 종료 조건이 잘못 설정되거나break문이 실행되지 않으면 프로그램이 계속 반복될 수 있습니다.Ctrl+C를 눌러 강제 종료하거나, 종료 조건을 꼼꼼히 검토해야 합니다.print()문을 중간중간 넣어 변수 값이 어떻게 변하는지 확인해 보면 도움이 됩니다. - 범위 오류:
random.randint(1, 100)처럼 범위를 명확히 지정하지 않거나, 사용자 입력 범위 확인 (1 <= guess <= 100)을 소홀히 하면 의도치 않은 결과가 나올 수 있습니다.
게임 더 개선하기: 난이도 조절과 재시작 기능
기본 게임을 완성했다면, 다음 단계로 난이도 조절, 시도 횟수 제한, 그리고 게임 재시작 기능 등을 추가하여 더욱 풍부한 프로그램을 만들 수 있습니다. 예를 들어, random.randint()의 범위를 1~50, 1~100, 1~200 등으로 바꾸어 난이도를 조절할 수 있습니다. 또한, 사용자에게 게임이 끝난 후 다시 플레이할 것인지 물어보고, ‘Y’를 입력하면 play_number_guessing_game() 함수를 다시 호출하는 로직을 추가할 수도 있습니다. 이런 기능들을 추가해 보면서 여러분의 코딩 실력은 더욱 향상될 것입니다.
자주 묻는 질문(FAQ)
Q1: random 모듈은 어떻게 작동하나요?
A: random 모듈은 의사 난수(pseudo-random numbers)를 생성합니다. 이는 완전히 무작위는 아니지만, 특정한 시작 값(seed)을 바탕으로 예측하기 어려운 수열을 만들어내어 대부분의 용도에 충분한 무작위성을 제공합니다. randint(a, b)는 a와 b를 포함하는 범위 내의 정수를 반환합니다.
Q2: input()으로 받은 값은 왜 int()로 변환해야 하나요?
A: input() 함수는 사용자가 키보드로 입력한 모든 것을 문자열(string) 형태로 반환합니다. 숫자 비교나 산술 연산을 수행하려면 이 문자열을 정수형(integer)으로 명시적으로 변환해야 합니다. 그렇지 않으면 ’10’과 ‘5’를 비교했을 때 문자열로 비교되어 예상치 못한 결과가 나올 수 있습니다.
Q3: while True는 무한 루프 아닌가요?
A: 네, while True 자체는 무한 루프를 의미합니다. 하지만 우리 게임 코드처럼 루프 내부에 특정 조건이 충족되었을 때 break 키워드를 사용하여 루프를 강제로 종료하도록 만들 수 있습니다. 이는 원하는 조건이 만족될 때까지 반복 작업을 수행해야 할 때 유용한 패턴입니다.
Q4: 게임을 더 어렵게 만들려면 어떻게 해야 하나요?
A: 게임의 난이도를 조절하는 몇 가지 방법이 있습니다. random.randint()의 숫자 범위를 넓히거나, 사용자에게 주어지는 max_attempts (시도 횟수)를 줄일 수 있습니다. 또한, 사용자가 추측할 때마다 힌트를 더 적게 주거나, 정답과의 오차 범위를 기반으로 힌트를 주는 방식도 고려해 볼 수 있습니다.
참고 자료
- [1] Python 공식 튜토리얼 — 제어 흐름 도구와 함수 정의 — https://docs.python.org/ko/3/tutorial/controlflow.html
- [2] Python 공식 튜토리얼 — 오류와 예외 — https://docs.python.org/ko/3/tutorial/errors.html
