파이썬 실습/게임 만들기

파이썬 숫자 야구 게임 만들기

파기차차 2022. 8. 15. 09:39
728x90
반응형
SMALL
728x90

이번에는 파이썬을 이용하여 숫자 야구 게임을 만들어 보겠습니다.

(본 블로그의 내용은 유튜브 동영상(파이썬 숫자 야구 게임 만들기)에서 더욱 자세히 보실 수 있습니다.)

 

 

숫자야구게임의 규칙은 컴퓨터가 생성한 숫자 3개와 내가 입력한 숫자 3개의 값과 위치가

같으면 끝나는 게임입니다.(자세한 설명은 아래 그림 참고)

 

 

아래는 완성된 소스코드입니다.

 

from random import randint
import sys

# 여기서부터 게임 시작

##########################################################
# 1. 컴퓨터가 지정한 정답 스트라이크 숫자
##########################################################
numbers = []                                        # 컴퓨터가 지정한 스트라이크 숫자를 담을 리스트 numbers[] 선언

while len(numbers) < 3:                             # 스트라이크 3개면 아웃으로 종료되므로, 리스트의 길이가 3보다 작을때까지만 루프를 돈다.
    new_number = randint(0,9)                       # 숫자는 0~9 사이의 숫자만 사용해서 랜덤한 수를 new_number 변수에 삽입
    if new_number not in numbers:                   # numbers[] 리스트에 없는 숫자만 넣고
        numbers.append(new_number)
ANSWER = numbers                                    # numbers[]에 들어간 3개의 숫자가 정답이므로 ANSWER 리스트 변수로 변경
print("컴퓨터가 지정한 스트라이크 숫자 : ", ANSWER)     # print()로 찍어서 확인해 본다.


tries = 0
while True:
    try:
        ##########################################################
        # 2. 내가 입력한 스트라이크 숫자
        ##########################################################
        new_guess = []                              # 내가 입력한 스트라이크 숫자를 담을 리스트 new_guess[] 선언
        while len(new_guess) < 3:                   # 스트라이크 3개를 맞추면 종료되므로, 리스트의 길이가 3보다 작을때까지(즉, 3번만) 루프를 돈다.
            num = int(input("{}번째 수를 입력하세요: ".format(len(new_guess) + 1))) # new_guess[]는 처음에는 길이가 0이므로  +1을 시작으로 세번까지 num변수에 숫자가 입력된다.

            if num < 0 or num > 9:                  # 숫자는 0~9 사이의 숫자만 사용, 아니면 경고메시지 출력
                print("0에서 9까지의 수를 입력해 주세요!")
            elif num in new_guess:                  # 중복되는 숫자는 입력하지 못하도록 설정
                print("중복되는 숫자입니다. 다시 입력하세요.")
            else:
                new_guess.append(num)               # 정상적인 숫자 입력시 new_guess[]리스트에 넣는다.

        user_guess = new_guess                      # while루프를 빠져나오면 new_guess[]에 들어간 3개의 숫자는 내가 입력한 값이므로 user_guess로 변수명 수정(변경하지 않아도 상관은 없음)
        print("내가 입력한 스트라이크 숫자 : ", user_guess) # print()로 잘 나오는지 찍어서 확인해 본다.
    except KeyboardInterrupt:
        # Ctrl+C 입력시 예외 발생(해당 위치를 빠져 나옴)
        sys.exit()                                  # 종료(빠져나옴)


    ##########################################################
    # 3. 컴퓨터의 스트라이크 숫자와 내가 입력한 숫자를 비교
    ##########################################################
    strike_count = 0                                # 스트라이크 갯수를 담을 변수
    ball_count = 0                                  # 볼을 담을 변수

    for i in range(3):                              # 컴퓨터가 지정한 수와 내가 입력한 수를 총 3번 비교해야 하므로 range(3)으로 설정
        if user_guess[i] == ANSWER[i]:              # 0부터 2까지 내가 입력한 숫자와 컴퓨터가 지정한 숫자와 위치가 같으면 strike_count를 1증가
            strike_count += 1
        elif user_guess[i] in ANSWER:               # 그렇지 않고 ANSWER 리스트내에 내가 입력했던 숫자가 존재하면 ball_count를 1증가
            ball_count += 1
    s, b = strike_count, ball_count


    tries += 1                                      # 게임을 시도한 횟수를 남기기 위해 tries의 카운트를 1 증가

    if s == 3:                                      # 스트라이크 3개면 모두 맞추었으므로 종료(최종 결과를 출력)
        break
    else:                                           # 못 맞추면 관련 메시지 출력
        print("\n아쉽습니다.!! ",s," 스트라이크 ",b, " 볼 입니다. ",tries,"번째 시도 하셨습니다.")
        print("스트라이크 3개를 맞추지 못하여 다시 시도 합니다.\n(게임을 종료하시려면 Ctrl+C를 눌러주세요.)\n")

if s == 3:
    print("\n축하합니다.!! ",tries," 만에 ",s," 스트라이크로 모두 맞추셨습니다.")

 

추가로 아래는 소스를 함수형태로 개선한 완전한 소스입니다.

 

from random import randint
import sys


def generate_numbers():
    numbers = []

    while len(numbers) < 3:
        new_number = randint(0,9)
        if new_number not in numbers:
            numbers.append(new_number)
    # ANSWER = numbers
    # print("컴퓨터가 지정한 스트라이크 숫자 : ", ANSWER)

    return numbers


def take_guess():
    try:
        pass
        new_guess = []
        while len(new_guess) < 3:
            num = int(input("{}번째 수를 입력하세요: ".format(len(new_guess) + 1)))

            if num < 0 or num > 9:
                print("0에서 9까지의 수를 입력해 주세요!")
            elif num in new_guess:
                print("중복되는 숫자입니다. 다시 입력하세요.")
            else:
                new_guess.append(num)

        user_guess = new_guess
        print("내가 입력한 스트라이크 숫자 : ", user_guess)
    except KeyboardInterrupt:
        sys.exit()
    
    return new_guess


def get_score(user_guess, ANSWER):
    strike_count = 0
    ball_count = 0

    for i in range(3):
        if user_guess[i] == ANSWER[i]:
            strike_count += 1
        elif user_guess[i] in ANSWER:
            ball_count += 1
    s, b = strike_count, ball_count

    return strike_count, ball_count




ANSWER = generate_numbers()
print("컴퓨터가 지정한 스트라이크 숫자 : ", ANSWER)

tries = 0
while True:
    user_guess = take_guess()
    s, b = get_score(user_guess, ANSWER)

    tries += 1

    if s == 3:
        break
    else:
        print("\n아쉽습니다.!! ",s," 스트라이크 ",b, " 볼 입니다. ",tries,"번째 시도 하셨습니다.")
        print("스트라이크 3개를 맞추지 못하여 다시 시도 합니다.\n(게임을 종료하시려면 Ctrl+C를 눌러주세요.)\n")

if s == 3:
    print("\n축하합니다.!! ",tries," 만에 ",s," 스트라이크로 모두 맞추셨습니다.")

먼저, 컴퓨터가 생성할 스트라이크 숫자 3개를 만듭니다.

그 다음 내가 입력한 숫자 3개를 만듭니다.

마지막으로 컴퓨터의 숫자 3개와 내가 입력한 숫자 3개를 비교하여 맞는지, 틀리는지 확인합니다.

위의 코드는 내가 입력한 숫자 3개가 모두 스트라이크가 되지 않으면 계속 실행되므로(끝나지 않으므로) 사용자가 끝내고 싶을때 끝낼 수 있도록 예외(Ctrl+C)를 만들어 줍니다.

그리고 몇번이나 시도하여 맞추었는지를 표시하기 위해 tries변수를 사용하여 시도 횟수를 추가해 주었습니다.

위의 소스도 잘 돌아가지만 나중에 소스가 길어지고 복잡해지면 알아보고 어려우므로 기능별(모듈별)로 함수를 사용하여 만들어 주었습니다.(이전 소소와 동작내용은 동일함)

 

 

 

이렇게 해서 숫자 야구 게임을 작성하는 소스코드를 잘게 쪼개서 실행해 보고 실습을 통해 이해해 보았습니다.

 

위의 내용 중 이해가 가지 않는 부분은 실제 코딩을 해보면서 반복적으로 실행시켜 보면서 이해를 도울 수 있습니다.

 

그렇게 하더라도 내용 중 이해가 되지 않거나, 더 좋은 방법들이 있다면 댓글로 의견을 주시기 바라며,

내용이 유익하셨다면, 좋아요와 구독 부탁드립니다.

 

 

감사합니다.

728x90
반응형
LIST