python 使用 pyqt5 制作 扫雷游戏

 

在这篇博客中,我们将展示如何使用 Python 和 PyQt5 制作一个简单的扫雷游戏。扫雷游戏是一款经典的益智游戏,玩家需要通过逻辑推理找出隐藏在网格中的所有地雷。

环境准备

首先,我们需要安装 PyQt5 库。可以使用以下命令进行安装:

pip install PyQt5

代码详解

1. 初始化游戏界面

我们首先创建一个 Minesweeper 类,继承自 QMainWindow。在 __init__ 方法中,我们初始化了游戏界面的大小和地雷数量,并调用 initUI 方法来设置用户界面。

 
def initUI(self):
    self.central_widget = QWidget()
    self.grid_layout = QGridLayout()
    self.central_widget.setLayout(self.grid_layout)
    self.setCentralWidget(self.central_widget)
    self.setWindowTitle('Minesweeper')

2. 生成地雷

我们使用 generate_mines 方法来随机生成地雷的位置,并将这些位置存储在一个集合中。

 
def generate_mines(self):
    while len(self.mine_positions) < self.mines:
        mine = (random.randint(0, self.rows - 1), random.randint(0, self.cols - 1))
        self.mine_positions.add(mine)

3. 生成按钮

我们使用 generate_buttons 方法在网格中生成按钮,每个按钮代表一个网格单元。我们还为每个按钮设置了一个点击事件。

 
def generate_buttons(self):
    for row in range(self.rows):
        for col in range(self.cols):
            button = QPushButton('')
            button.setFixedSize(40, 40)
            button.clicked.connect(self.make_move(row, col))
            self.grid_layout.addWidget(button, row, col)
            self.buttons[row][col] = button

4. 处理点击事件

make_move 方法中,我们定义了按钮点击后的行为。如果点击的位置有地雷,我们就显示红色并结束游戏;否则,我们显示该位置周围的地雷数量。

 
def make_move(self, row, col):
    def callback():
        if (row, col) in self.mine_positions:
            self.buttons[row][col].setStyleSheet('background-color: red')
            self.game_over(False)
        else:
            self.reveal_cell(row, col)
            if self.check_win():
                self.game_over(True)
    return callback

5. 显示单元格信息

reveal_cell 方法中,我们显示点击位置周围的地雷数量。如果该位置周围没有地雷,我们递归显示周围的空白单元格。

 
def reveal_cell(self, row, col):
    if self.buttons[row][col].text() != '':
        return
    mine_count = self.count_mines(row, col)
    self.buttons[row][col].setText(str(mine_count))
    self.buttons[row][col].setStyleSheet('background-color: lightgrey')
    if mine_count == 0:
        for r, c in self.get_neighbors(row, col):
            self.reveal_cell(r, c)

 

实现扫雷游戏

下面是实现扫雷游戏的完整代码。我们将从一个简单的用户界面开始,并逐步添加游戏逻辑。

import sys
import random
from PyQt5.QtWidgets import QApplication, QMainWindow, QGridLayout, QPushButton, QWidget, QMessageBox

class Minesweeper(QMainWindow):
    def __init__(self, rows, cols, mines):
        super().__init__()
        self.rows = rows
        self.cols = cols
        self.mines = mines
        self.initUI()

    def initUI(self):
        self.central_widget = QWidget()
        self.grid_layout = QGridLayout()
        self.central_widget.setLayout(self.grid_layout)
        self.setCentralWidget(self.central_widget)
        self.setWindowTitle('Minesweeper')

        self.buttons = [[None for _ in range(self.cols)] for _ in range(self.rows)]
        self.mine_positions = set()
        self.generate_mines()
        self.generate_buttons()

    def generate_mines(self):
        while len(self.mine_positions) < self.mines:
            mine = (random.randint(0, self.rows - 1), random.randint(0, self.cols - 1))
            self.mine_positions.add(mine)

    def generate_buttons(self):
        for row in range(self.rows):
            for col in range(self.cols):
                button = QPushButton('')
                button.setFixedSize(40, 40)
                button.clicked.connect(self.make_move(row, col))
                self.grid_layout.addWidget(button, row, col)
                self.buttons[row][col] = button

    def make_move(self, row, col):
        def callback():
            if (row, col) in self.mine_positions:
                self.buttons[row][col].setStyleSheet('background-color: red')
                self.game_over(False)
            else:
                self.reveal_cell(row, col)
                if self.check_win():
                    self.game_over(True)
        return callback

    def reveal_cell(self, row, col):
        if self.buttons[row][col].text() != '':
            return
        mine_count = self.count_mines(row, col)
        self.buttons[row][col].setText(str(mine_count))
        self.buttons[row][col].setStyleSheet('background-color: lightgrey')
        if mine_count == 0:
            for r, c in self.get_neighbors(row, col):
                self.reveal_cell(r, c)

    def count_mines(self, row, col):
        return sum((r, c) in self.mine_positions for r, c in self.get_neighbors(row, col))

    def get_neighbors(self, row, col):
        neighbors = [(row + i, col + j) for i in range(-1, 2) for j in range(-1, 2)
                     if 0 <= row + i < self.rows and 0 <= col + j < self.cols and (i != 0 or j != 0)]
        return neighbors

    def game_over(self, won):
        msg = QMessageBox()
        if won:
            msg.setText('You won!')
        else:
            msg.setText('Game Over!')
        msg.exec_()
        self.close()

    def check_win(self):
        for row in range(self.rows):
            for col in range(self.cols):
                if (row, col) not in self.mine_positions and self.buttons[row][col].text() == '':
                    return False
        return True

if __name__ == '__main__':
    app = QApplication(sys.argv)
    game = Minesweeper(10, 10, 10)  # 10x10 grid with 10 mines
    game.show()
    sys.exit(app.exec_())

运行结果:

总结

这篇博客展示了如何使用 PyQt5 制作一个简单的扫雷游戏。通过这个项目,你可以学习到如何使用 PyQt5 创建用户界面,处理事件,以及实现游戏逻辑。希望你能从中学到更多,并享受编程的乐趣!


如果你有任何问题或建议,请在评论区留言。祝你编程愉快!

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值