KEEP GOING

[python] (3) 블랙잭 GUI 게임 : GUI 구현 본문

project/project4: blackjack GUI programming

[python] (3) 블랙잭 GUI 게임 : GUI 구현

jmHan 2021. 11. 25. 12:35
반응형

수업에서 배운 PyQt5 패키지를 이용하여 블랙잭 GUI를 구현해봤다. 게임 시작 창인 firstWindow 클래스와 메인 윈도우인 secondWindow를 구현하여 Controller를 통해 두 창을 연결시켜주었다. 즉, secondWindow가 게임 중요 로직이 동작하는 메인 윈도우이고 firstWindow는 서브윈도우가 된다.  

 

 

1. mainGame.py

from firstWindow import FirstWindow
from secondWindow import SecondWindow
from PyQt5.QtWidgets import QApplication
import sys


class MyController:
    def __init__(self):
        self.first_window = FirstWindow()
        self.window = SecondWindow()
        self.window.close()

    def show_window1(self):
        self.first_window.switch_window.connect(self.show_window2)
        self.first_window.show()

    def show_window2(self):
        self.first_window.close()
        self.window.show()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    controller = MyController()
    controller.show_window1()
    sys.exit(app.exec_())

 

2. firstWindow.py

from PyQt5.QtGui import QIcon, QPixmap, QCursor
from PyQt5.QtWidgets import QLabel, QPushButton, QHBoxLayout, QGridLayout, QDesktopWidget
from musicPlayer import *
from PyQt5 import QtCore
from PyQt5.QtCore import Qt


def styleButton(button):
    button.setCursor(Qt.PointingHandCursor)
    button.setStyleSheet(
        """QPushButton{background-color: rgb(249, 228, 183);
                    color: black;
                    border-radius: 15px;
                    font-family: 'Georgia';
                    font-size: 25px;
                    padding: 5px 0;}"""
        """QPushButton::hover
        {
        background-color : white;
        }
        """
    )


class FirstWindow(QWidget):
    switch_window = QtCore.pyqtSignal()

    def __init__(self):
        super().__init__()
        self.setWindowTitle("BlackJack Game")
        self.setWindowIcon(QIcon("./PNG-cards-1.3/blackjack.png"))
        self.setGeometry(0, 0, 900, 600)
        self.setStyleSheet('background-color: green')

        self.music = MusicPlayer()
        self.music.playAudioFile()

        self.image = QPixmap("./PNG-cards-1.3/title.png")
        self.label = QLabel()
        self.label.setAlignment(Qt.AlignCenter)
        self.label.setPixmap(self.image)

        self.start_button = QPushButton("PLAY")
        self.volumeUpButton = QPushButton("+")
        self.volumeUpButton.clicked.connect(self.music.volumeUp)
        self.volumeDownButton = QPushButton("-")
        self.volumeDownButton.clicked.connect(self.music.volumeDown)
        self.volumeMuteButton = QPushButton("Mute")
        self.volumeMuteButton.clicked.connect(self.music.volumeMute)

        styleButton(self.volumeUpButton)
        styleButton(self.volumeDownButton)
        styleButton(self.volumeMuteButton)

        self.volume_layout = QHBoxLayout()
        self.volume_layout.addWidget(self.volumeDownButton)
        self.volume_layout.addWidget(self.volumeMuteButton)
        self.volume_layout.addWidget(self.volumeUpButton)

        self.start_button.setCursor(QCursor(Qt.PointingHandCursor))
        self.start_button.setStyleSheet(
            """QPushButton{background-color: rgb(249, 228, 183);
            color: black;
            border-radius: 25px;
            font-family: 'Georgia';
            font-size: 40px;
            margin-bottom: 5px;
            padding: 8px 0;}"""
            """QPushButton::hover
            {
            background-color : white;
            }
            """
        )

        self.start_button.clicked.connect(self.secondWindowEmit)
        self.grid = QGridLayout()
        self.grid.addWidget(self.label, 1, 1)
        self.grid.addWidget(self.start_button, 2, 1)
        self.grid.addLayout(self.volume_layout, 3, 1)
        self.setLayout(self.grid)

        self.center()
        self.show()

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def secondWindowEmit(self):
        self.switch_window.emit()

 

 

3. secondWindow.py

from PyQt5.QtWidgets import QWidget, QMessageBox, QVBoxLayout, QHBoxLayout, QLabel, QDesktopWidget
from PyQt5.QtGui import QIcon,QPixmap
from PyQt5.QtCore import Qt
from button import Button
from innerCode import *


class SecondWindow(QWidget):

    def __init__(self):
        super().__init__()

        self.setWindowTitle("BlackJack Game")
        self.setWindowIcon(QIcon(f"./PNG-cards-1.3/blackjack.png"))
        # setting  the geometry of window
        self.setGeometry(0, 0, 1200, 900)
        self.setStyleSheet("background-color: green")
        self.center()

        self.q_msg_box = QMessageBox()
        self.q_msg_box.setWindowTitle("Result")
        self.q_msg_box.setWindowIcon(QIcon("./PNG-cards-1.3/blackjack.png"))
        self.q_msg_box.setStyleSheet(
            """QMessageBox
            {
            background-color: white;
            font-family: 'Georgia';
            }
            """
        )

        self.money = load()
        self.betting_cost = 1000
        # self.dealCount = 0

        self.display = QLabel()
        self.b_display = QLabel('bet: ' + str(self.betting_cost))
        self.b_display.setStyleSheet(
            """QLabel
            {
            font-size: 18px;
            font-family: 'Georgia';
            color: blue;
            }
            """
        )
        self.m_display = QLabel('money: ' + str(self.money))
        self.m_display.setStyleSheet(
            """QLabel
            {
            font-size: 18px;
            font-family: 'Georgia';
            color: blue;
            }
            """
        )

        self.dealBtn = Button("deal", self.button_clicked)
        self.stayBtn = Button("stay", self.button_clicked)
        self.appendBtn = Button("new card", self.button_clicked)
        self.resetBtn = Button("reset", self.button_clicked)
        self.plusBetBtn = Button("+100", self.button_clicked)
        self.minusBetBtn = Button("-100", self.button_clicked)

        self.styleButton(self.dealBtn)
        self.styleButton(self.stayBtn)
        self.styleButton(self.appendBtn)
        self.styleButton(self.resetBtn)
        self.styleButton(self.plusBetBtn)
        self.styleButton(self.minusBetBtn)

        betting_vbox = QVBoxLayout()
        betting_vbox.addWidget(self.plusBetBtn)
        betting_vbox.addWidget(self.minusBetBtn)

        display_vbox = QVBoxLayout()
        display_vbox.addStretch(1)
        display_vbox.addWidget(self.display)
        display_vbox.addWidget(self.b_display)
        display_vbox.addWidget(self.m_display)

        hbox = QHBoxLayout()
        hbox.addLayout(betting_vbox)
        hbox.addWidget(self.dealBtn)
        hbox.addWidget(self.stayBtn)
        hbox.addWidget(self.appendBtn)
        hbox.addWidget(self.resetBtn)

        vbox = QVBoxLayout()
        vbox.addStretch(1)
        vbox.addLayout(display_vbox)
        vbox.addLayout(hbox)
        self.setLayout(vbox)

        self.cntLst = [0, 150, 300, 450, 600, 750]
        self.dLabel = []
        self.pLabel = []
        for _ in range(len(self.cntLst)):
            pl = QLabel(self)
            dl = QLabel(self)
            self.dLabel.append(dl)
            self.pLabel.append(pl)

        # 카드 배치, 베팅 초기화
        self.clear()
        # show all the widgets
        self.show()

    def loadPlayerCard(self, label, cardsuit, cnt):
        self.pixmap = QPixmap(f"./PNG-cards-1.3/{cardsuit}").scaledToWidth(150)
        label.setPixmap(self.pixmap)
        label.move(cnt,300)
        label.resize(self.pixmap.width(),self.pixmap.height())

    def loadDealerCard(self, label, cardsuit, cnt):
        self.pixmap = QPixmap(f"./PNG-cards-1.3/{cardsuit}").scaledToWidth(150)
        label.setPixmap(self.pixmap)
        label.move(cnt,0)
        label.resize(self.pixmap.width(),self.pixmap.height())

    # 프로그램 센터에 배치
    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def clear(self):
        for pl in self.pLabel:
            idx = self.pLabel.index(pl)
            if idx < 2:
                self.loadPlayerCard(pl, 'background', self.cntLst[idx])
            else:
                self.loadPlayerCard(pl, 'green', self.cntLst[idx])

        for dl in self.dLabel:
            idx = self.dLabel.index(dl)
            if idx < 2:
                self.loadDealerCard(dl, 'background', self.cntLst[idx])
            else:
                self.loadDealerCard(dl, 'green', self.cntLst[idx])

        self.betting_cost = 1000
        self.display.setText('')
        self.b_display.setText('bet: ' + str(self.betting_cost))
        self.stayBtn.setDisabled(True)
        self.appendBtn.setDisabled(True)

    def styleButton(self, button):
        button.setCursor(Qt.PointingHandCursor)
        button.setStyleSheet(
            """QToolButton{background-color: rgb(249, 228, 183);
            color: black;
            border-radius: 5px;
            font-family: 'Georgia';
            font-size: 20px;
            }"""
            """QToolButton::hover
            {
            background-color: white;
            }
            """
        )

    def QMessageBoxExec(self, msg):
        msg_box = self.q_msg_box
        msg_box.setText(msg)
        msg_box.exec()
        self.appendBtn.setDisabled(True)
        self.stayBtn.setDisabled(True)
        self.display.setText('If you wanna restart, click reset button')

    def button_clicked(self):
        button = self.sender()
        key = button.text()
        if key == '+100':
            self.betting_cost += 100
            self.b_display.setText('bet: ' + str(self.betting_cost))
        elif key == '-100':
            self.betting_cost -= 100
            self.b_display.setText('bet: ' + str(self.betting_cost))
        elif key == 'deal':
            if self.betting_cost < 0:
                self.display.setText("Bet on the positive value.")
                self.betting_cost = 1000
                self.b_display.setText('bet: ' + str(self.betting_cost))
                return
            elif self.betting_cost > 0:
                if self.betting_cost < 1000:
                    self.display.setText("betting min is 1000")
                    self.betting_cost = 1000
                    self.b_display.setText('bet: ' + str(self.betting_cost))
                    return
                elif self.betting_cost > self.money:
                    self.display.setText("You don't have much money")
                    self.betting_cost = 1000
                    self.b_display.setText('bet: ' + str(self.betting_cost))
                    return
                else:
                    self.display.setText("let's start!")
                    self.stayBtn.setDisabled(False)
                    self.appendBtn.setDisabled(False)
                    self.plusBetBtn.setDisabled(True)
                    self.minusBetBtn.setDisabled(True)
                    self.dealBtn.setDisabled(True)

                    self.card = set_card()
                    self.intPlayercards = twocard(self.card)
                    # print(self.intPlayercards)
                    # [34, 5]
                    self.intDealercards = twocard(self.card)
                    self.dealercards = intToString_card(self.intDealercards)
                    self.playercards = intToString_card(self.intPlayercards)
                    # print(self.intToString_card)
                    # ['hearts9', 'spades6']
                    self.loadPlayerCard(self.pLabel[0], self.playercards[0], self.cntLst[0])
                    self.loadPlayerCard(self.pLabel[1], self.playercards[1], self.cntLst[1])
                    self.loadDealerCard(self.dLabel[0], self.dealercards[0], self.cntLst[0])
                    # self.loadDealerCard(self.dLabel[1], self.dealercards[1], self.cntLst[1])

                    if count(self.intPlayercards) == 21:
                        self.QMessageBoxExec("Congratulations! \nBlack Jack!")
                        self.money = set_money(self.money, self.betting_cost, 3)
                        self.m_display.setText('money: ' + str(self.money))
                    return
            else:
                self.display.setText("Please click betting number")
                return

        elif key == 'new card':
            cardappend(self.intPlayercards, self.card)
            # print(self.intPlayercards)
            # [34, 5, 7]
            self.playercards = intToString_card(self.intPlayercards)
            for pl in self.pLabel:
                idx = self.pLabel.index(pl)
                if idx < len(self.intPlayercards):
                    self.loadPlayerCard(pl, self.playercards[idx], self.cntLst[idx])
            if burst(count(self.intPlayercards)):
                self.QMessageBoxExec("Burst!")
                self.money = set_money(self.money, self.betting_cost, 0)
                self.m_display.setText('money: ' + str(self.money))
            elif count(self.intPlayercards) == 21:
                self.QMessageBoxExec("Congratulations! \nBlack Jack!")
                self.money = set_money(self.money, self.betting_cost, 3)
                self.m_display.setText('money: ' + str(self.money))
            else:
                return

        elif key == 'stay':
            self.loadDealerCard(self.dLabel[1], self.dealercards[1], self.cntLst[1])
            if count(self.intDealercards) > 21:
                self.QMessageBoxExec("you win!")

                self.money = set_money(self.money, self.betting_cost, 1)
                self.m_display.setText('money: ' + str(self.money))
                return
            else:
                # 딜러 카드 합이 17이상이면 더이상 추가 카드를 받을 수 없음
                while count(self.intDealercards) < 17:
                    cardappend(self.intDealercards, self.card)
                    self.dealercards = intToString_card(self.intDealercards)
                    for dl in self.dLabel:
                        idx = self.dLabel.index(dl)
                        if idx < len(self.intDealercards):
                            self.loadDealerCard(dl, self.dealercards[idx], self.cntLst[idx])
                if count(self.intDealercards) > 21:
                    self.QMessageBoxExec("you win!")
                    self.money = set_money(self.money, self.betting_cost, 3)
                    self.m_display.setText('money: ' + str(self.money))
                    return
                elif count(self.intDealercards) == 21:
                    self.QMessageBoxExec("You lose!")
                    self.money = set_money(self.money, self.betting_cost, 0)
                    self.m_display.setText('money: ' + str(self.money))
                    return
                else:
                    res = fight(count(self.intPlayercards), count(self.intDealercards))
                    if res == 2:
                        self.QMessageBoxExec("Draw!")
                        self.money = set_money(self.money, self.betting_cost, 2)
                        self.m_display.setText('money: ' + str(self.money))
                        return
                    elif res == 1:
                        self.QMessageBoxExec("You win!")
                        self.money = set_money(self.money, self.betting_cost, 3)
                        self.m_display.setText('money: ' + str(self.money))
                        return
                    else:
                        self.QMessageBoxExec("You lose!")
                        self.money = set_money(self.money, self.betting_cost, 0)
                        self.m_display.setText('money: ' + str(self.money))
                        return

        # if key == 'reset':
        else:
            self.stayBtn.setDisabled(True)
            self.appendBtn.setDisabled(True)
            self.dealBtn.setDisabled(False)
            self.plusBetBtn.setDisabled(False)
            self.minusBetBtn.setDisabled(False)
            self.clear()
            self.display.setText('Play more? Click deal button')
            return

 

4. musicPlayer.py

from PyQt5.QtWidgets import QWidget
from PyQt5 import QtCore
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
import os


class MusicPlayer(QWidget):
    def __init__(self):
        super().__init__()
        self.player = QMediaPlayer()

    def volumeUp(self):
        current_volume = self.player.volume()
        # print(currentVolume)
        self.player.setVolume(current_volume + 10)

    def volumeDown(self):
        current_volume = self.player.volume()
        # print(currentVolume)
        self.player.setVolume(current_volume - 10)

    def volumeMute(self):
        self.player.setMuted(not self.player.isMuted())

    def playAudioFile(self):
        full_file_path = os.path.join(os.getcwd(), './sounds/bgm.mp3')
        url = QtCore.QUrl.fromLocalFile(full_file_path)
        content = QMediaContent(url)

        self.player.setMedia(content)
        self.player.play()

 

5. button.py

from PyQt5.QtWidgets import *


class Button(QToolButton):
    def __init__(self, text, callback):
        super().__init__()
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        self.setText(text)
        self.clicked.connect(callback)

    def sizeHint(self):
        size = super(Button, self).sizeHint()
        size.setHeight(size.height() + 50)
        size.setWidth(max(size.width(), size.height()))
        return size

 

해당 파일이 저장된 경로에 카드 및 배경 이미지파일이 담긴 /PNG-cards-1.3/ 폴더를 추가해주었다.

PNG-cards-1.3.zip
4.59MB

그리고 게임 음악이 담긴 /sound/ 폴더도 추가하였다.

sounds.zip
1.77MB

 

내부 구현시 작성하였던 innerCode.py까지 추가하면 파일 경로는 다음과 같다. mainGame.py 실행시 money.dat 파일이 존재하지 않는다면 innerCode.y에 구현한 load()메소드에 의해 자동 생성된다. 

 

 

 

 

반응형
Comments