Exemplo n.º 1
0
class Main(QMainWindow):
    def __init__(self, x, y, btn_size, bombs):
        super().__init__()
        self.start_time = 0
        self.buttons = []
        self.timer = None
        self.colors = {
            '1': '#0000ff',
            '2': '#00ff00',
            '3': '#ff0000',
            '4': '#00007b',
            '5': '#7b0000',
            '6': '#007b7b',
            '7': '#000000',
            '8': '#7b7b7b'
        }
        self.SMILE_DEFAULT = ":)"
        self.SMILE_WIN = ":D"
        self.SMILE_LOSE = "X("
        self.modes = {
            (9, 9, 10): "Новичок",
            (16, 16, 40): "Эксперт",
            (16, 30, 99): "Бывалый",
        }

        self.setWindowTitle("Сапёр))")
        self.init_ui(x, y, btn_size, bombs)

        self.lcd_smile = QPushButton(self)
        self.lcd_smile.setGeometry(self.size().width() // 2 - 25, 26, 50, 50)
        self.lcd_smile.setText(self.SMILE_DEFAULT)
        self.lcd_smile.setFont(
            QtGui.QFont("MS Shell Dlg 2", 14, QtGui.QFont.Bold))
        self.lcd_smile.clicked.connect(self.restart)

        self.lcd_bombs = QLCDNumber(self)
        self.lcd_bombs.display(self.lcd_bombs_num)
        self.lcd_bombs.setGeometry(10, 26, 80, 50)
        self.lcd_bombs.setStyleSheet('color: red; background-color: black')
        self.lcd_bombs.setDigitCount(3)
        self.lcd_bombs.setSegmentStyle(2)

        self.lcd_step = QLCDNumber(self)
        self.lcd_step.display(0)
        self.lcd_step.setGeometry(self.size().width() - 90, 26, 80, 50)
        self.lcd_step.setStyleSheet('color: red; background-color: black')
        self.lcd_step.setDigitCount(3)
        self.lcd_step.setSegmentStyle(2)
        if not OptionsFile().read()[2]:
            self.lcd_step.hide()

        self.menubar = QtWidgets.QMenuBar(self)
        self.setMenuBar(self.menubar)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))

        self.settings = QtWidgets.QMenu(self.menubar)
        self.settings.setTitle('Настройки')

        self.results = QtWidgets.QMenu(self)
        self.results.setTitle("Результаты")

        self.records = QtWidgets.QAction(self)
        self.records.setText("Рекорды")
        self.results.addAction(self.records)

        self.statisctics = QtWidgets.QAction(self)
        self.statisctics.setText("Статистика")
        self.results.addAction(self.statisctics)

        self.difficulty = QtWidgets.QAction(self)
        self.difficulty.setText("Сложность")
        self.settings.addAction(self.difficulty)

        self.options = QtWidgets.QAction(self)
        self.options.setText("Геймплей")
        self.settings.addAction(self.options)

        self.menubar.addAction(self.settings.menuAction())
        self.menubar.addAction(self.results.menuAction())

        self.difficulty.triggered.connect(self.change_difficulty)
        self.records.triggered.connect(self.records_click)
        self.options.triggered.connect(self.gameplay_settings)
        self.statisctics.triggered.connect(self.stats)

    # перерисовка поля
    def init_ui(self, x, y, size, bombs):
        self.setGeometry(300, 300, x * size, y * size + 86)
        self.setFixedSize(x * size, y * size + 86)
        self.rows, self.cols, self.btn_size, self.bombs = y, x, size, bombs
        self.lcd_bombs_num = bombs

        if self.buttons:
            for l in self.buttons:
                for b in l:
                    b.hide()
            self.lcd_bombs.display(bombs)
            self.lcd_step.display(0)
            self.lcd_smile.setGeometry(self.size().width() // 2 - 25, 26, 50,
                                       50)
            self.lcd_step.setGeometry(self.size().width() - 90, 26, 80, 50)
            self.buttons = []
            if self.timer is not None:
                self.timer.stop()

        for i in range(self.rows):
            line = []
            for j in range(self.cols):
                button = QPushButton('', self)
                button.setGeometry(j * self.btn_size, i * self.btn_size + 86,
                                   self.btn_size, self.btn_size)
                button.setFont(
                    QtGui.QFont("MS Shell Dlg 2", 10, QtGui.QFont.Bold))
                button.clicked.connect(partial(self.move, i, j))
                button.show()
                line.append(button)
            self.buttons.append(line)

        self.field = GameField(y, x, bombs)
        self.mode = self.modes[(y, x,
                                bombs)] if (y, x,
                                            bombs) in self.modes else "Особый"

    # смена режима сложности
    def change_difficulty(self):
        clicked, rows, cols, bombs = DifficultyWindow().get_values()
        if clicked:
            self.init_ui(cols, rows, self.btn_size, bombs)

    # нажатие на кнопку поля
    def move(self, row, col):
        if not self.field.generated:
            self.field.generate_field(row, col)
            self.stopwatch()
        elif self.field.get_field()[row][col] == self.field.cell["flag"]:
            return
        else:
            self.field.open(row, col, "o")

        self.update_field()

    # отображение массива GameField на кнопочное поле
    def update_field(self):
        if self.field.det in (0, 1):
            for i in range(self.rows):
                for j in range(self.cols):
                    symbol = self.field.get_field()[i][j]
                    if symbol in [
                            self.field.cell[i]
                            for i in ["flag", "untouched", "question"]
                    ]:
                        self.buttons[i][j].setText(symbol)
                    elif symbol:
                        if self.buttons[i][j].isEnabled():
                            self.buttons[i][j].setEnabled(False)
                            self.buttons[i][j].setStyleSheet(
                                'color: rgb(204, 204, 204)')
                        if symbol.isdigit(
                        ) and not self.buttons[i][j].text().isdigit():
                            self.buttons[i][j].setText(symbol)
                            self.buttons[i][j].setStyleSheet(
                                f'color: {self.colors[symbol]}')

            if self.field.det == 1:
                # Победа
                flags, win = 0, 1
                for r, c in self.field.b_coords:
                    if self.field.get_field()[r][c] == self.field.cell["flag"]:
                        flags += 1
                    self.buttons[r][c].setText(self.field.cell["flag"])
                self.lcd_smile.setText(self.SMILE_WIN)
                self.lcd_bombs.display(0)
                self.show_win_dialog()
                GameStat().update_stats(self.mode, win, flags, flags,
                                        self.lcd_step.intValue())

        elif self.field.det == -1:
            # Поражение
            flags, defused, win = 0, 0, 0
            for i in range(self.rows):
                for j in range(self.cols):
                    if self.field.get_field()[i][j] == self.field.cell["flag"]:
                        flags += 1
                        if (i, j) in self.field.b_coords:
                            defused += 1
                        else:
                            self.buttons[i][j].setStyleSheet('color: red')
                    else:
                        if (i, j) in self.field.b_coords:
                            self.buttons[i][j].setText("X")
            self.lcd_smile.setText(self.SMILE_LOSE)
            GameStat().update_stats(self.mode, win, flags, defused,
                                    self.lcd_step.intValue())

    # Нажатие на смайлик - заново
    def restart(self):
        self.field = GameField(self.rows, self.cols, self.bombs)
        for i in range(self.rows):
            for j in range(self.cols):
                self.buttons[i][j].setText("")
                self.buttons[i][j].setStyleSheet('')
                self.buttons[i][j].setEnabled(True)
        self.lcd_step.display(0)
        self.lcd_bombs_num = self.bombs
        self.lcd_bombs.display(self.lcd_bombs_num)
        self.lcd_smile.setText(self.SMILE_DEFAULT)
        self.timer.stop()

    # Запуск секундомера
    def stopwatch(self):
        self.timer = QtCore.QTimer(self)
        self.timer.setSingleShot(False)
        self.timer.timeout.connect(self.update_timer)
        self.timer.start()
        self.start_time = time.time()

    # Обновление дисплея времени
    def update_timer(self):
        if self.field.det != 0:
            self.timer.stop()
        self.lcd_step.display(round(time.time() - self.start_time))

    # Обработка нажатия правой кнопкой мыши
    def mousePressEvent(self, event):
        if not self.field.generated:
            return
        if self.lcd_bombs_num == 0:
            return
        if event.button() == QtCore.Qt.RightButton:
            x, y = event.x(), event.y()
            if y < 0:
                return
            row, col = (y - 86) // self.btn_size, x // self.btn_size
            if self.buttons[row][col].text().isdigit():
                return
            self.field.open(row, col, mode="f")
            if self.field.get_field()[row][col] == self.field.cell["flag"]:
                self.lcd_bombs_num -= 1
            elif self.lcd_bombs_num < self.bombs:
                self.lcd_bombs_num += 1
            self.lcd_bombs.display(self.lcd_bombs_num)
            self.update_field()

    # Показать диалоговое окно с победой
    def show_win_dialog(self):
        time = self.lcd_step.intValue()
        wd = WinDialog(self.mode, self.lcd_step.intValue())
        name = wd.show()
        GameStat().put_record(self.mode, name, time)

    # Показать диалоговое окно с таблицей рекордов
    def records_click(self):
        RecordWindow().show()

    # Показать диалоговое окно со статистикой
    def stats(self):
        StatsDialog().show()

    # Показать диалоговое окно с опциями и изменить видимость дисплея времени
    def gameplay_settings(self):
        args = OptionsWindow().show()
        time = args[2]
        if not time:
            self.lcd_step.hide()
        else:
            self.lcd_step.show()
Exemplo n.º 2
0
class Tetrixs(QWidget):
    def __init__(self):
        super(Tetrixs, self).__init__()
        self.initUI()

    def initUI(self):
        #窗口大小固定
        size = self.centerRect(tetrixsWidth, tetrixsHeight)
        self.setGeometry(size)
        self.setWindowTitle('Tetrixs')

        #设置背景色
        self.setStyleSheet(mainWindowColor)


        #LCD和Button
        self.levelNumber = QLCDNumber(self)
        self.scoreNumber = QLCDNumber(self)

        #设置初始值
        self.levelNumber.display(0)
        self.scoreNumber.display(0)

        self.pauseButton = QPushButton('PAUSE', self)
        self.startButton = QPushButton('START', self)

        #设置两个按钮无焦点
        self.pauseButton.setFocusPolicy(Qt.NoFocus)
        self.startButton.setFocusPolicy(Qt.NoFocus)

        #self.setFocusPolicy(Qt.StrongFocus)
        #self.startButton.set

        self.levelNumber.setFixedSize(150, 100)
        self.scoreNumber.setFixedSize(150, 100)
        self.pauseButton.setFixedSize(150, 100)
        self.startButton.setFixedSize(150, 100)

        self.levelNumber.setStyleSheet(lcdNumberColor)
        self.scoreNumber.setStyleSheet(lcdNumberColor)
        self.pauseButton.setStyleSheet(buttonColor)
        self.startButton.setStyleSheet(buttonColor)

        ##LCD和Button绑定action函数
        self.startButton.clicked.connect(self.startButtonAction)
        self.pauseButton.clicked.connect(self.pauseButtonAction)


        vLayout = QVBoxLayout()
        vLayout.addWidget(self.levelNumber)
        vLayout.addWidget(self.scoreNumber)
        vLayout.addWidget(self.pauseButton)
        vLayout.addWidget(self.startButton)

         #画布
        self.canvas = Canvas()
        self.canvas.setFixedSize(500, 800)

        self.canvas.getScoreSignal.connect(self.getScoreAction)
        self.canvas.gameOverSignal.connect(self.gameOverAction)

        hLayout = QHBoxLayout()
        hLayout.addWidget(self.canvas)
        hLayout.addLayout(vLayout)
        
        self.setLayout(hLayout)
        self.setFixedSize(tetrixsWidth, tetrixsHeight)
        self.show()

    def centerRect(self, width, height):
        screen = QGuiApplication.primaryScreen()
        screenWidth = screen.geometry().width()
        screenHeight = screen.geometry().height()
        centerWidth, centerHeight = screenWidth // 2, screenHeight // 2
        startWidth, startHeight = centerWidth - width // 2, centerHeight - height // 2

        return QRect(startWidth , startHeight, width, height)  

    def keyPressEvent(self, event):
        #向左旋转
        if event.key() == Qt.Key_Up:
            self.canvas.rotateLeft()

        #向右旋转
        if event.key() == Qt.Key_Down:
            self.canvas.rotateRight()

        #向左移动
        if event.key() == Qt.Key_Left:
            self.canvas.moveLeft()
            

        #向右移动
        if event.key() == Qt.Key_Right:
            self.canvas.moveRight()

        if event.key() == Qt.Key_Space:
            self.canvas.downDirect()
            

    def startButtonAction(self):
        #设置初始值
        self.levelNumber.display(0)
        self.scoreNumber.display(0)

        self.canvas.start()

    def pauseButtonAction(self):
        self.canvas.pause()
        if self.pauseButton.text() == "PAUSE":
            self.pauseButton.setText("CONTINUE")
        else:
            self.pauseButton.setText("PAUSE")


    def getScoreAction(self, score):

        QApplication.beep()

        value = self.scoreNumber.intValue()

        newValue = value + score

        self.scoreNumber.display(newValue)

        #更新speed
        if value / levelStep != newValue / levelStep:
            self.levelNumber.display(newValue / levelStep)
            self.canvas.speed *= percent

    def gameOverAction(self):
        self.msg()

    def msg(self):
        reply = QMessageBox.information(self, "Tetrixs", "GameOver", QMessageBox.Yes | QMessageBox.No)

        if reply == QMessageBox.Yes:
            self.canvas.start()

        if reply == QMessageBox.No:
            app = QApplication(sys.argv)
            app.exit(0)