Exemple #1
0
def main_loop():
    # Obtain the width and height of the screen.
    width = field_width * tile_width + 10
    height = field_height * tile_height + digit_height + 15
    smiley_offset = (width // 2 - digit_height // 2, 5)

    win = pygame.display.set_mode((width, height))
    pygame.display.set_caption('Minesweeper')
    clock = pygame.time.Clock()

    minesweeper = MineSweeper(field_width, field_height, field_mines)
    steps = solver(minesweeper)

    run = True
    while run:
        for event in pygame.event.get():
            if (event.type == pygame.QUIT
                    or (event.type == pygame.KEYDOWN
                        and event.key in [pygame.K_q, pygame.K_ESCAPE])):
                run = False
            # Handle mouse clicks.
            if handle_clicks(event, minesweeper,
                             offset=(5, digit_height + 10)):
                # On user input, just in case reset the solver.
                steps = solver(minesweeper)

            if handle_click_smiley(event, minesweeper, offset=smiley_offset):
                # On reset, create a new solver.
                steps = solver(minesweeper)

            if event.type == pygame.KEYDOWN and event.key == pygame.K_r:
                # Reset the minesweeper.
                minesweeper.reset()
                print('RESET')
                steps = solver(minesweeper)

            if event.type == pygame.KEYDOWN and event.key == pygame.K_n:
                # Try twice if in case generator was exhausted in which case we use a newer one.
                # If solver can't solve it in second try don't simply keep calling it.
                tries = 0
                while tries <= 1:
                    try:
                        # Obtain the step from the solver.
                        position, operation = next(steps)
                        if operation == MARK:
                            print(f'[AI] MARK {position[0]}, {position[1]}')
                            minesweeper.toggle(position, force_mark=True)
                        elif operation == UNCOVER:
                            print(f'[AI] UNCOVER {position[0]}, {position[1]}')
                            minesweeper.uncover(position)
                        break
                    except StopIteration:
                        # reset the solver in case previous one exhausted and check if it can solve
                        steps = solver(minesweeper)
                        tries += 1

        win.fill((255, 255, 255))
        # Render the time and number of mines.
        count_surf = number_surface(minesweeper.pending_mines())
        win.blit(count_surf, (5, 5))
        time_surf = number_surface(minesweeper.time_progressed())
        time_rect = time_surf.get_rect()
        win.blit(time_surf, (width - time_rect.width - 5, 5))
        # Render the smiley
        draw_smiley(win, minesweeper, offset=smiley_offset)

        # Render the minesweeper field
        draw_minesweeper(win, minesweeper, offset=(5, digit_height + 10))
        pygame.display.update()
        clock.tick(60)
Exemple #2
0
class QMineSweeper(QWidget):

    class QTile(QPushButton):
        def __init__(self, mineSweeper: 'QMineSweeper', tile: MineSweeper.Tile):
            super(QMineSweeper.QTile, self).__init__()
            self.setFocusPolicy(Qt.NoFocus)
            self.setContextMenuPolicy(Qt.CustomContextMenu)
            self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
            self.mineSweeper = mineSweeper
            self.marked = False
            self.tile = tile

        def leftClick(self):
            if self.marked:
                return
            self.tile.reveal()
            self.mineSweeper.score()
            self.repaint()

        def rightClick(self):
            self.marked = not self.marked
            self.refresh()

        def resizeEvent(self, resizeEvent: QResizeEvent):
            font = self.font()
            font.setBold(True)
            font.setPixelSize(round(0.50 * min(self.width(), self.height())))
            self.setFont(font)

        def refresh(self):
            self.setEnabled(not self.tile.revealed)
            text = "★" if self.marked else str(self.tile)
            self.setText(text)

        def sizeHint(self) -> QSize:
            return QSize(40, 40)

    def __init__(self, size: int):
        super(QMineSweeper, self).__init__()
        self.size = size
        self.mineSweeper = MineSweeper(self.size, 0.10)
        self.initUI()
        self.show()

    def initUI(self):
        self.setWindowTitle(self.tr("Minesweeper"))
        layout = QGridLayout()
        layout.setSpacing(5)
        self.setLayout(layout)

        for tile in self.mineSweeper:
            qTile = QMineSweeper.QTile(self, tile)
            layout.addWidget(qTile, tile.row, tile.column)
            qTile.clicked.connect(qTile.leftClick)
            qTile.customContextMenuRequested.connect(qTile.rightClick)
            tile.delegate = qTile

    def score(self):
        score = self.mineSweeper.score()
        if score is not None:
            self.mineSweeper.reveal()
            if score == +1:
                QMessageBox.information(self, self.tr("Victory!"), self.tr("You won :)"), QMessageBox.Ok)
            if score == -1:
                QMessageBox.critical(self, self.tr("Defeat!"), self.tr("You lost :("), QMessageBox.Ok)
            for tile in self.mineSweeper:
                tile.delegate.marked = False
            self.mineSweeper.reset()

    def sizeHint(self) -> QSize:
        return QSize(300, 300)
Exemple #3
0
class QMineSweeper(QWidget):
    class QTile(QPushButton):
        def __init__(self, mineSweeper: 'QMineSweeper',
                     tile: MineSweeper.Tile):
            super(QMineSweeper.QTile, self).__init__()
            self.setFocusPolicy(Qt.NoFocus)
            self.setContextMenuPolicy(Qt.CustomContextMenu)
            self.setSizePolicy(QSizePolicy.MinimumExpanding,
                               QSizePolicy.MinimumExpanding)
            self.mineSweeper = mineSweeper
            self.marked = False
            self.tile = tile

        def leftClick(self):
            if self.marked:
                return
            self.tile.reveal()
            self.mineSweeper.score()
            self.repaint()

        def rightClick(self):
            self.marked = not self.marked
            self.refresh()

        def resizeEvent(self, resizeEvent: QResizeEvent):
            font = self.font()
            font.setBold(True)
            font.setPixelSize(round(0.50 * min(self.width(), self.height())))
            self.setFont(font)

        def refresh(self):
            self.setEnabled(not self.tile.revealed)
            text = "★" if self.marked else str(self.tile)
            self.setText(text)

        def sizeHint(self) -> QSize:
            return QSize(40, 40)

    def __init__(self, size: int):
        super(QMineSweeper, self).__init__()
        self.size = size
        self.mineSweeper = MineSweeper(self.size, 0.10)
        self.initUI()
        self.show()

    def initUI(self):
        self.setWindowTitle(self.tr("Minesweeper"))
        layout = QGridLayout()
        layout.setSpacing(5)
        self.setLayout(layout)

        for tile in self.mineSweeper:
            qTile = QMineSweeper.QTile(self, tile)
            layout.addWidget(qTile, tile.row, tile.column)
            qTile.clicked.connect(qTile.leftClick)
            qTile.customContextMenuRequested.connect(qTile.rightClick)
            tile.delegate = qTile

    def score(self):
        score = self.mineSweeper.score()
        if score is not None:
            self.mineSweeper.reveal()
            if score == +1:
                QMessageBox.information(self, self.tr("Victory!"),
                                        self.tr("You won :)"), QMessageBox.Ok)
            if score == -1:
                QMessageBox.critical(self, self.tr("Defeat!"),
                                     self.tr("You lost :("), QMessageBox.Ok)
            for tile in self.mineSweeper:
                tile.delegate.marked = False
            self.mineSweeper.reset()

    def sizeHint(self) -> QSize:
        return QSize(300, 300)