[파이썬 프로그래밍 19] 간단한 포커 게임 만들기 1. 튜플(tuple)과 목록을 연결하는 더하기(+) 기호

Home / 파이썬 프로그래밍 / [파이썬 프로그래밍 19] 간단한 포커 게임 만들기 1. 튜플(tuple)과 목록을 연결하는 더하기(+) 기호

간단한 포커 게임 만들기 1.
튜플(tuple)과 목록을 연결하는 더하기(+) 기호

지금까지 공부한 파이썬 기초를 기반으로 간단한 게임 프로그램을 만들 수 있습니다. 간단한 게임은 여러가지가 있는데, 그중에서 포커 게임을 한번 만들어보겠습니다.

게임용 카드 한 팩(deck)에는 4개의 세트(suit)가 있습니다. 각각의 세트는 그려있는 심볼의 무늬가 스페이드(♠), 하트(♥), 다이아몬드(♦), 클로바(♣)로 구분할 수 있습니다. 그리고 각 세트는 13개의 카드가 있습니다. A,2,3, … ,9,10,J,Q,K 이렇게 13개입니다. 편의상 A는 1로, J는 11로, Q는 12로, K는 13으로 표시하겠습니다. 그려면 1,2,3, … , 12,13 표시하게 되어 모두 숫자로 나타낼 수 있습니다.

카드 한장은 세트무늬와 숫자의 쌍으로 나타낼 수 있습니다. 스페이드 무늬에 2라면 (“s”, 2), 하트 무늬에 10이면 (“h”, 10) 인 식으로 나타내면 됩니다.

여기에서 파이썬의 새로운 개념을 설명하겠습니다. 위에서 목록을 나타내는 대괄호[]대신 소괄호()를 사용했습니다. 파이썬에서 소괄호를 목록처럼 사용하면 이는 목록이라고 부르지 않고 튜플(tuple)이라고 부릅니다. 목록과 거의 같지만 튜플은 내용을 바꿀 수 없다고 보면 되겠습니다. 아래의 예를 보죠. 변수 a에 튜플 (1, “a”, “가”)를 저장하고 목록처럼 튜플에 첫번째 값은 a[0]로, 두번째 값은 a[1]로, 세번쨰 값은 a[2]로 어떤 값이 들어있는지 확인할 수 있습니다.

a = (1, "a", "가")
print(a[0])
print(a[1])
print(a[2])

그런데 수정은 불가능합니다. 목록일때는 b[0] = 1 과 같은 식으로 목록안에 있는 값 하나하나를 수정할 수 있고, 새로운 값을 첨가할 수 있습니다(목록안에 있는 값을 삭제할 수도 있는 이건 나중에 한번 다루겠습니다).

하지만 튜플은 이게 불가능합니다. 아래의 코드처럼 튜플안의 값을 바꾸려고 하거나, 값을 더 첨가하려고 하면 에러 메시지가 출력됩니다.

a[0] = 8
a.append(123)

이제 카드를 처음 샀을때 처럼 카드가 무늬 별로 숫자가 정렬돼서 들어 있는 것을 파이썬의 목록안에 튜플로  나열해 보겠습니다. 조커 같은 카드는 빼고 4세트의 13장 총 4×13 = 52개의 카드만 있다고 가정하겠습니다.

deck = []
for k in range(1,14):
    deck.append(("s", k))
for k in range(1,14):
    deck.append(("h", k))
for k in range(1,14):
    deck.append(("d", k))
for k in range(1,14):
    deck.append(("c", k))
print(deck)

첫줄은 변수 deck에 빈 목록을 만들어 저장합니다. 둘째줄과 셋째줄은 스페이드 무늬의 카드 13장을 튜플로 만들어 목록에 추가하는 코드입니다. range(1,14)는 for속에서 숫자의 목록 [1,2, … ,13]을 만듭니다. 이를 이용한 for 블록안에서는 각각의 카드에 해당하는 튜플 (‘s’, 1), (‘s’, 2), …, (‘s’,13)을 만들어 deck에 저장된 목록에 추가합니다. 똑같은 방법으로 다른 나머지 무늬의 카드 3×13=393×13=39장 각각의 카드에 해당하는 튜플을 만들어 deck에 저장괸 목록에 추가합니다. 총 13×4=5213×4=52개의 튜플이 deck의 목록에 들어갑니다.

위의 코드를 더 간단하게 만들어보겠습니다.

deck1 = [("s", k) for k in range(1,14)]
deck2 = [("h", k) for k in range(1,14)]
deck3 = [("d", k) for k in range(1,14)]
deck4 = [("c", k) for k in range(1,14)]
deck = deck1+deck2+deck3+deck4
print(deck)

첫째줄은 대괄호안에 for를 쓰는 방법으로, 튜플 (“s”, 1), (“s”), …, (“s”, 13) 로 목록을 만들어 deck1 변수에 저장합니다. 둘째, 세째, 넷째줄도 같은 방법으로 “h”, “d”, “c”를 “s”대신 튜플에 넣어 목록를 만들고, 각각을 deck2, deck3, deck4 변수에 저장합니다. 다섯번째줄은 앞서 만든 네개의 목록을 더하기(+) 기호를 이용해 연결해 붙인 다음 deck 변수에 저장합니다. 목록과 목록사이에 더하기(+) 기호가 들어가면 두 목록을 복사한다음 연결해 붙여 더 긴 목록을 만듭니다.

목록을 연결하는 더하기(+) 기호를 잘 사용하면 굳이 별도의 변수 deck1, deck2, deck3, deck4를 따로 쓰지 않고도 deck변수에 바로 목록을 덧붙여 나갈 수 있습니다. 아래의 코드를 보죠.

deck = [("s", k) for k in range(1,14)]
deck = deck+[("h", k) for k in range(1,14)]
deck = deck+[("d", k) for k in range(1,14)]
deck = deck+[("c", k) for k in range(1,14)]
print(deck)

처음에는 deck에 스페이드(♠) 무늬의 카드 13개에 해당하는 튜플을 만들어 저장합니다. 두번째줄 부터 네번째 줄까지는 다른 무늬의 카드 목록을 만들어 deck에 저장된 목록에 연결해 붙여 더 긴 새로운 목록을 만들고, 이를 deck변수에 저장하는 작업을 반복합니다. 이전보다 코드가 한줄 더 줄었습니다.

이렇게 거의 동일한 작업을 반복하는 작업은 for를 사용해 더 간단한 코드를 만들 수 있습니다. 아래의 코드가 그렇습니다.

deck = []
for suit in["s", "h", "d", "c"]:
    deck = deck+[(suit, k) for k in range(1,14)]
print(deck)

먼저 첫줄과 같이 빈 목록을 만들어 deck변수에 저장합니다. 네개의 무늬가 들어있는 목록을 이용해 for 블록을 만듭니다. 그리고 그 블록안에서 무늬별로 카드 13장 카드 튜플 목록을 만들어 이전의 deck에 저장된 목록에 덧붙여 다시 deck변수에 저장합니다. print(deck)으로 확인한 결과는 이전 코드와 같은 결과를 출력합니다. 코드는 한줄 더 줄었습니다.

이 코드마저도 더 줄여 한줄의 코드로 똑같은 작업을 할 수 있습니다. 목록안에 for를 한번 더 써서 이중으로 for를 쓰면 이것이 가능합니다. 이전 코드를 한번 더 압축한다고 보면 되겠습니다.

deck = [(s, k) for s in ["s", "h", "d", "c"] for k in range(1,14)]
print(deck)

대괄호안에는 for가 중복으로 들어가 규칙적이면서 반복적으로 값(또는 튜플이나 목록)을 목록에 추가하는 작업을 한 줄만에 만들 수 있습니다. 파이썬을 사용하면 이런 방법으로 목록을 만들어 코드를 짧게 만들 수 있는 경우가 꽤 됩니다.

이제 deck변수에 저장된 목록에는 몇개의 튜플이 있는지 확인해 보겠습니다. 목록안에 값이 있던, 텍스트가 있던, 튜플이 있던, 아니면 또 목록이 있던, 목록안에 몇개의 항목(item)이 있는지를 확인 하려면 len함수를 써서 len(deck) 을 실행하면 됩니다.

print(len(deck))

그리고 deck안의 n번째 카드의 무늬와 숫자는 각각 deck[n-1][0]과 deck[n-1][1]을 써서 확인할 수 있습니다. 여기에서 n대신 n-1을 사용한 이유는 목록의 첫번째 항목은 deck[0]이고, 두번째 항목은 deck[1], .. 이 되는 것과 같이 [] 안에는 숫자 하나가 줄어든 값이 들어가기 때문입니다. 한편 deck에 저장된 항목은 두개의 값이 들어있는 튜플입니다. 따라서 첫번쨰 항목의 무늬를 알아보려면 deck[n-1][0]을 쓰고 두번째 항목의 숫자를 알아보려면 deck[n-1][1]을 써여합니다. 예를 들어 31번쨰 카드의 무늬와 숫자를 알아보려면 아래의 코드와 같이 deck[30][0]과 deck[30][1]으로 확인하시면 됩니다.

print(deck[30][0], deck[30][1])