파이썬(Python)으로 더 지니어스 게임 만들기 (2)

더 지니어스:블랙가넷 데스 매치


안녕하세요~ BestEng 입니다 ㅎㅎ


지난 포스팅부터 파이썬(Python)으로 더 지니어스:블랙가넷 데스 매치 중 양면포커를 만들어 보기로 했는데요~ 우선 게임 룰을 살펴 보면서 코딩을 시작해 봅시다ㅎㅎ


# 양면포커 게임 룰

  1. 카드의 앞면, 뒷면이 각기 다른 숫자로 이루어진 90장의 양면숫자카드로 진행된다.
  2. 2명의 플레이어는 각각 칩을 30개를 가지고 게임을 시작한다.
  3. 딜러는 90장의 카드를 섞은 뒤 1장씩 앞면이 보이도록 각 플레이어의 앞에 놓는다.
  4. 두 플레이어의 카드 앞면은 공개된 상태이며 카드 뒷면은 본인만 확인할 수 있다.
  5. 카드가 지금되면 각 플레이어들은 기본 베팅으로 칩 1개씩을 내고 선 플레이어부터 베팅을 시작한다.
  6. 선 플레이어부터 자신의 앞면, 뒷면 중 어떤 면에 베팅을 할 것인지 결정한 뒤 베팅한다. 베팅이 시작되면 선택한 베팅 면을 바꿀 없다.
  7. 상대가 베팅한 칩과 같은 개수의 칩을 베팅할 경우, 베팅이 그 즉시 종료되며 두 플레이어가 베팅한 면의 숫자를 공개, 더 높은 숫자의 플레이어가 승리한다.
  8. 앞서 베팅한 칩보다 더 많은 칩을 베팅했을 경우, 카드를 공개하지 않은 채 베팅을 이어간다.
  9. 베팅을 하지 않고 포기할 경우 무조건 상대방이 승리한다.
  10. 두 플레이어의 숫자가 같은 경우 무승부가 되어, 베팅된 칩은 다음 게임에서 이긴 플레이어가 모두 가져간다.
  11. 자신의 앞면과 뒷면의 숫자 모두가 상대방이 선택한 면의 숫자를 이길 수 있다고 생각한다면 ‘양면베팅’을 선택할 수 있다.
  12. 양면베팅을 할 경우 자신의 카드 앞, 뒷면의 숫자가 상대방이 선택한 면의 숫자보다 모두 높아야 승리한다.
  13. 만약 한 면이라도 상대방이 선택한 면의 숫자와 같거나 적을 경우 상대방이 승리한다.
  14. 또한 양면베팅을 건 플레이어는 상대방이 베팅한 칩과 같은 수의 칩을 앞면, 뒷면 두 곳에 각각 베팅해야 한다. 즉, 2배로 베팅해야 한다.
  15. 양면베팅으로 승리했을 경우 상대방의 칩 10개를 추가로 뺏어온다.
  16. 한 플레이어가 칩을 모두 잃으면 해당 플레이어의 패배로 게임이 종료된다.


# 첫 번째 룰 코딩

그럼 이제 본격적으로 코딩을 시작해 봅시다. 우선 첫 번째 룰입니다.


1. 카드의 앞면, 뒷면이 각기 다른 숫자로 이루어진 90장의 양면숫자카드로 진행된다.


우선 양면숫자카드를 만들어야 겠네요. 파이썬은 객체 지향 언어이므로 우선 Deck 클래스를 만들어 봅시다~


class Deck:


Deck을 호출할 때, 90장의 앞,뒷면이 다른 카드를 만들어야 겠네요~ 다음과 같이 __init__ 함수 안에서 for문을 이용해 봅시다.


class Deck:
    def __init__(self):
        self.cards = []
        for m in xrange(1, 11):
            for n in xrange(1, 11):
                if m != n:
                    self.cards.append((m, n))


자 이제 카드들이 만들어 졌네요~ 그럼 이제 골고루 섞어야 겠죠? random 라이브러리의 shuffle 함수를 이용해 봅시다.


from random import shuffle

class Deck:
    def __init__(self):
        self.cards = []
        for m in xrange(1, 11):
            for n in xrange(1, 11):
                if m != n:
                    self.cards.append((m, n))
        random.shuffle(self.cards)


자 깔끔하게 우리의 카드들이 만들어졌습니다~ㅎㅎ 그럼 이제 다음 룰로 넘어가 봅시다.


# 두 번째 룰 코딩


2. 2명의 플레이어는 각각 칩을 30개를 가지고 게임을 시작한다.


이젠 플레이어 클래스를 만들어야 겠네요~! 다음과 같이 호출되는 순간 칩(여기선 points를 사용하겠습니다) 30개를 가지는 플레이어 클래스를 만들어 봅시다.


class Player:
    def __init__(self):
        self.points = 30


그럼 이제 다음과 같이 플레이어와 덱을 설정할 수 있겠네요~


# main
player1 = Player()
player2 = Player()
deck = Deck()


다음 세 번째 룰로 넘어가 봅시다~


# 세 번째 룰 코딩


3. 딜러는 90장의 카드를 섞은 뒤 1장씩 앞면이 보이도록 각 플레이어의 앞에 놓는다.


딜러를 우리가 만든 Deck 클래스라고 생각하고 섞는 것은 위에서 shuffle 함수를 이용해서 이미 했네요~


자, 그럼 이제 1장씩 앞면이 보이도록 각 플레이어에게 주어야죠. 이것은 Game 클래스를 만들어서 게임 내에서 진행되도록 하고 싶네요. 다음과 같이 먼저 Game 클래스를 만들어 봅시다.


class Game:
    def __init__(self):
        pass

    def set(self):
        pass


여기서 set 메쏘드 안에 바로 카드를 뽑아서 각 플레이어에게 나눠주는 일을 하고 싶습니다~ set 메쏘드는 매 턴마다 호출되겠죠.


우선 Player 클래스로 가서 card를 추가해 보죠. card 변수는 앞, 뒤 카드의 숫자를 리스트에 저장합니다. 우선 처음엔 둘 다 0으로 세팅을 해 둡시다.


class Player:
    def __init__(self):
        self.points = 30
        self.card = [0, 0]


자, 다음으로는 Deck 클래스에서 card_pop 메쏘드를 추가해야 겠죠. 리스트의 내장 함수(메쏘드?)인 pop(index)은 리스트에서 index 위치의 요소를 반환(return)하고 리스트에서 해당 요소를 지웁니다.


class Deck:
    def __init__(self):
        self.cards = []
        for m in xrange(1, 11):
            for n in xrange(1, 11):
                if m != n:
                    self.cards.append((m, n))
        random.shuffle(self.cards)

    def card_pop(self):
        return self.cards.pop(0)


Deck 클래스는 이만하면 완성된 것 같군요. 이제 플레이어에게 카드를 주고 싶으면 다음과 같이 하면 됩니다! 그럼 매 턴이 시작될 때, set 메쏘드를 호출하면 각 플레이어들은 deck에서 카드를 하나씩 뽑아 가지게 되겠네요.


class Game:
    def __init__(self):
        pass

    def set(self):
        player1.card = deck.card_pop()
        player2.card = deck.card_pop()


# 네 번째 룰 코딩


4. 두 플레이어의 카드 앞면은 공개된 상태이며 카드 뒷면은 본인만 확인할 수 있다.


세 번째 룰에서 카드를 나누어 주었는데요, 나누어 줄 때, 앞면은 보이지만 뒷면은 안 보이게 놓는 것 같군요! 그래도 카드를 가진 플레이어는 그 카드의 뒷면을 볼 수 있어야 겠죠. Player클래스에 show_back_card 메쏘드를 추가해 봅시다.


from random import shuffle
import ctypes

class Player:
    def __init__(self):
        self.points = 30
        self.card = [0, 0]

    def show_back_card(self):
        ctypes.windll.user32.MessageBoxA(0, "Your back card is "+str(self.card[1]), "Back Card" , 0)


추가로 ctype이라는 라이브러리를 사용하는데요~ 우리는 카드의 뒷면을 윈도우 메세지 창을 이용하여 보여주려고 합니다~ 바로 ctypes.windll.user32.MessageBoxA(0, "Your back card is "+str(self.card[1]), "Back Card" , 0) 이 부분 이죠. 실행하면 다음과 같이 뜹니다.


python ctype MessageBoxA

cytpe 메세지창


이제 카드 뒷면을 보고 싶다면 다음과 같이 호출하면 되겠네요~


player1.show_back_card()


자, 이제 다음 다섯 번째 룰부터는 본격적으로 베팅이 시작되기 때문에 복잡한 코딩이 시작됩니다. 이번 포스팅에서는 여기까지하고 다음 포스팅에 이어서 코딩을 해 보도록 하겠습니다.


# 현재까지의 코딩


from random import shuffle
import ctypes

# Classes
class Player:
    def __init__(self):
        self.points = 30
        self.card = [0, 0]

    def show_back_card(self):
        ctypes.windll.user32.MessageBoxA(0, "Your back card is "+str(self.card[1]), "Back Card" , 0)

class Deck:
    def __init__(self):
        self.cards = []
        for m in xrange(1, 11):
            for n in xrange(1, 11):
                if m != n:
                    self.cards.append((m, n))
        random.shuffle(self.cards)

    def card_pop(self):
        return self.cards.pop(0)

class Game:
    def __init__(self):
        pass

    def set(self):
        player1.card = deck.card_pop()
        player2.card = deck.card_pop()

# Main
player1 = Player()
player2 = Player()
deck = Deck()