ChatGPT与我们玩游戏_排雷

简介: 以图形方式给出早期Windows挖地雷的python代码

询问

以图形方式给出早期Windows挖地雷的python代码。

回答

以下是一个简单的使用 Python 和 Tkinter 库实现的经典早期 Windows 挖地雷游戏(Minesweeper)的图形化版本。这个程序允许玩家点击格子来探索地雷,标记可能的地雷位置,并判断游戏胜负。

Windows 风格的挖地雷游戏(Python实现)。

import tkinter as tk
import random
import time

class Minesweeper:
    def __init__(self, master, width=10, height=10, num_mines=20):
        self.master = master
        self.master.title("挖地雷")
        self.width = width  # 网格宽度
        self.height = height  # 网格高度
        self.num_mines = num_mines  # 地雷数量
        self.buttons = []
        self.mines = set()  # 存储地雷的坐标
        self.revealed = set()  # 存储已打开的格子
        self.flags = set()  # 存储标记的格子    
        self.game_over = False

        # 创建画布和按钮
        self.canvas = tk.Canvas(self.master, width=width*30, height=height*30)
        self.canvas.pack()
        self.create_grid()
        self.place_mines()

    def create_grid(self):
        """创建按钮网格"""
        for row in range(self.height):
            button_row = []
            for col in range(self.width):
                button = tk.Button(self.master, text='', width=3, height=1, command=lambda r=row, c=col: self.reveal(r, c))
                button.grid(row=row, column=col)
                button_row.append(button)
            self.buttons.append(button_row)

    def place_mines(self):
        """随机放置地雷"""    
        while len(self.mines) < self.num_mines:
            mine = (random.randint(0, self.height-1), random.randint(0, self.width-1))
            self.mines.add(mine)

    def reveal(self, row, col):
        """揭示格子内容"""
        if self.game_over or (row, col) in self.revealed or (row, col) in self.flags:
            return

        self.revealed.add((row, col))
        if (row, col) in self.mines:
            self.buttons[row][col].config(text="💣", bg="red")
            self.game_over = True
            self.show_game_over("游戏失败!")
            return
        else:
            # 计算相邻地雷的数量
            adjacent_mines = self.count_adjacent_mines(row, col)
            if adjacent_mines > 0:
                self.buttons[row][col].config(text=str(adjacent_mines), relief=tk.SUNKEN)    
            else:
                self.buttons[row][col].config(relief=tk.SUNKEN)
                # 如果没有地雷,递归揭示相邻格子
                for r in range(max(0, row-1), min(self.height, row+2)):
                    for c in range(max(0, col-1), min(self.width, col+2)):
                        if (r, c) != (row, col) and (r, c) not in self.revealed:
                            self.reveal(r, c)

        # 检查游戏胜利条件
        if len(self.revealed) == self.width * self.height - self.num_mines:
            self.game_over = True
            self.show_game_over("游戏胜利!")

    def count_adjacent_mines(self, row, col):
        """计算相邻格子的地雷数量"""
        adjacent_mines = 0
        for r in range(max(0, row-1), min(self.height, row+2)):
            for c in range(max(0, col-1), min(self.width, col+2)):
                if (r, c) in self.mines:
                    adjacent_mines += 1
        return adjacent_mines

    def show_game_over(self, message):
        """显示游戏结束的消息"""
        for r in range(self.height):
            for c in range(self.width):
                if (r, c) in self.mines:
                    self.buttons[r][c].config(text="💣", bg="red")
                else:
                    self.buttons[r][c].config(state=tk.DISABLED)
        self.canvas.create_text(self.width*15, self.height*15, text=message, font=("Arial", 20), fill="black")

if __name__ == "__main__":
    root = tk.Tk()
    game = Minesweeper(root, width=10, height=10, num_mines=20)
    root.mainloop()

代码功能和说明:

游戏初始化:

游戏包含一个 10x10 的网格,默认情况下有 20 个地雷。

使用 Tkinter 创建图形界面,每个格子用一个按钮表示。

创建按钮网格并随机放置地雷。

按钮点击和地雷揭示: 玩家点击按钮后会触发 reveal 函数,如果点击的是地雷,游戏结束;否则,按钮显示周围地雷的数量。如果周围没有地雷,会递归揭示周围的按钮。

如果玩家揭示了所有非地雷格子,游戏胜利。

计算周围的地雷数量:

使用 count_adjacent_mines 函数来计算某个格子周围的地雷数量。如果该格子周围没有地雷,则继续递归揭示相邻的格子。

游戏胜负判断:

如果玩家点击到地雷,显示“游戏失败”。

如果玩家揭示了所有非地雷格子,显示“游戏胜利”。

地雷显示:游戏结束时,所有地雷会显示在对应的按钮上,玩家无法再点击其他格子。

运行游戏:

将代码复制到 Python 环境中并运行,确保已安装 tkinter 库。

游戏会弹出窗口,玩家可以点击格子来探索,避免点击到地雷。

游戏会根据玩家的表现显示“游戏胜利”或“游戏失败”。

扩展功能:

标记功能:玩家可以右键点击格子标记疑似地雷的位置。

难度设置:根据玩家选择的难度改变网格的大小和地雷的数量。

计时功能:为游戏添加一个计时器,记录玩家完成游戏的时间。

如果您有其他问题或想进一步扩展这个游戏,随时告诉我!

运行代码,失败。

Traceback (most recent call last):
File "C:\Users\xiang\Desktop\Minesweeper.py", line 90, in
game = Minesweeper(root, width=10, height=10, num_mines=20)
File "C:\Users\xiang\Desktop\Minesweeper.py", line 21, in init
self.create_grid()
File "C:\Users\xiang\Desktop\Minesweeper.py", line 30, in create_grid
button.grid(row=row, column=col)
File "C:\Users\xiang\AppData\Local\Programs\Python\Python312\Lib\tkinter_init_.py", line 2569, in grid_configure
self.tk.call(
_tkinter.TclError: cannot use geometry manager grid inside . which already has slaves managed by pack这个错误发生是因为在Tkinter中,你不能同时使用pack和grid布局管理器。你要么使用pack()来管理控件的位置,要么使用grid()来管理。

在你的代码中,self.canvas.pack()使用了pack(),而self.buttons[row][col].grid()则使用了grid()。这就导致了冲突,因为一个窗口不能同时使用两种布局管理器。

import tkinter as tk
from tkinter import messagebox
import random

class Minesweeper:
    def __init__(self, master, size=10, mines=10):
        self.master = master
        self.size = size
        self.mines = mines
        self.board = [[0] * size for _ in range(size)]
        self.buttons = [[None] * size for _ in range(size)]
        self.revealed = [[False] * size for _ in range(size)]
        self.flags = [[False] * size for _ in range(size)]
        self.game_over = False

        self.create_widgets()
        self.place_mines()
        self.calculate_numbers()

    def create_widgets(self):
        for row in range(self.size):
            for col in range(self.size):
                button = tk.Button(self.master, width=2, height=1,
                                   command=lambda r=row, c=col: self.reveal(r, c))
                button.bind('', lambda e, r=row, c=col: self.toggle_flag(r, c))    
                button.grid(row=row, column=col)
                self.buttons[row][col] = button

    def place_mines(self):
        count = 0
        while count < self.mines:
            row = random.randint(0, self.size - 1)
            col = random.randint(0, self.size - 1)
            if self.board[row][col] != 'M':
                self.board[row][col] = 'M'
                count += 1

    def calculate_numbers(self):
        for row in range(self.size):
            for col in range(self.size):
                if self.board[row][col] == 'M':
                    continue
                mines_count = 0
                for dr in [-1, 0, 1]:
                    for dc in [-1, 0, 1]:
                        if 0 <= row + dr < self.size and 0 <= col + dc < self.size:    
                            if self.board[row + dr][col + dc] == 'M':
                                mines_count += 1
                self.board[row][col] = mines_count

    def reveal(self, row, col):
        if self.game_over or self.flags[row][col] or self.revealed[row][col]:
            return

        self.revealed[row][col] = True
        if self.board[row][col] == 'M':
            self.buttons[row][col].config(text='M', bg='red')
            self.game_over = True
            messagebox.showinfo("游戏结束", "你踩到地雷了!")
            return

        self.buttons[row][col].config(text=str(self.board[row][col]), relief=tk.SUNKEN)
        if self.board[row][col] == 0:
            for dr in [-1, 0, 1]:
                for dc in [-1, 0, 1]:
                    if 0 <= row + dr < self.size and 0 <= col + dc < self.size:
                        if not self.revealed[row + dr][col + dc]:    
                            self.reveal(row + dr, col + dc)

        if self.check_win():
            self.game_over = True
            messagebox.showinfo("胜利", "恭喜,你赢了!")

    def toggle_flag(self, row, col):
        if self.game_over or self.revealed[row][col]:
            return

        if self.flags[row][col]:
            self.buttons[row][col].config(text='', bg='SystemButtonFace')
            self.flags[row][col] = False
        else:
            self.buttons[row][col].config(text='F', bg='yellow')
            self.flags[row][col] = True

    def check_win(self):
        for row in range(self.size):
            for col in range(self.size):
                if self.board[row][col] != 'M' and not self.revealed[row][col]:
                    return False    
        return True

if __name__ == "__main__":
    root = tk.Tk()
    root.title("扫雷游戏")
    game = Minesweeper(root, size=10, mines=10)
    root.mainloop()

解决方案:

你有两种方法可以解决这个问题:

统一使用 grid() 布局管理器:将所有组件的布局都改为grid()。

统一使用 pack() 布局管理器:将所有组件的布局都改为pack()。

在这种情况下,由于你的按钮是按网格排列的,推荐使用 grid() 来管理按钮的布局。对于canvas,你也可以使用grid(),而不是pack(),这样就可以避免布局冲突。

主要修改:

canvas.grid():将 canvas 使用 grid() 布局,而不是 pack()。

按钮 grid():所有按钮都使用 grid() 来管理,而不是 pack()。

这样就避免了布局冲突,确保所有组件都通过相同的布局管理器(grid())进行管理。您可以尝试运行这段代码,看看是否解决了问题。

目录
相关文章
|
7月前
|
人工智能 缓存 算法
ChatGPT与我们玩游戏_五子棋
ChatGPT与我们玩游戏_五子棋
315 0
|
7月前
|
人工智能 JavaScript 算法
Playwright携手MCP:AI智能体实现自主化UI回归测试
MCP 协议使得 AI 能够通过 Playwright 操作浏览器,其中快照生成技术将页面状态转化为 LLM 可理解的文本,成为驱动自动化测试的关键。该方式适用于探索性测试和快速验证,但目前仍面临快照信息缺失、元素定位不稳定、成本高、复杂场景适应性差以及结果确定性不足等挑战。人机协同被认为是未来更可行的方向,AI 负责执行固定流程,人类则专注策略与验证。
|
人工智能 自然语言处理 IDE
童心码力—小游戏场景
仅需一句自然语言描述就能快速生成!借助通义灵码强大的 AI 代码理解与生成能力,即使是编程新手也能轻松创作属于自己的小游戏~
|
8月前
|
数据可视化
90% 的团队效率问题,都能通过流程优化解决
团队效率低下,往往不是努力不够,而是流程卡壳。本文探讨如何通过构建“结构化工作流程体系”,实现责任清晰、流程可视、协作高效,结合实用工具让流程真正落地,提升团队整体执行力。
90% 的团队效率问题,都能通过流程优化解决
|
7月前
|
Python
ChatGPT与我们玩游戏_贪吃蛇
ChatGPT与我们玩游戏_贪吃蛇
280 0
|
4月前
|
机器学习/深度学习 移动开发 缓存
陪玩系统源码小程序带语音房模块:小程序闲聊 / APP 开黑,搭子匹配无延迟
一款基于UniApp+TP6开发的线上线下游戏陪玩代练小程序,支持多端同步。涵盖100+热门游戏及线下陪伴服务,集成智能匹配、语音视频通讯、直播互动等功能,打造全场景陪玩生态平台。
567 0
陪玩系统源码小程序带语音房模块:小程序闲聊 / APP 开黑,搭子匹配无延迟
|
7月前
|
测试技术 开发者
基础测试用例
顾翔 作者相关精选 基础测试用例 关注作者 腾讯云 开发者社区 免费试用云直播,了解直播推流的操作方式 文档 建议反馈 控制台 登录/注册 首页 学习 活动 专区 圈层 工具 MCP广场 文章/答案/技术大牛 搜索 发布 社区首页 > 专栏 > 基础测试用例 基础测试用例
299 40
|
5月前
|
Kubernetes API 开发工具
深入浅出K8S技术原理,搞懂K8S?这一篇就够了!
本文以“K8S帝国”为喻,系统解析Kubernetes核心技术原理。从声明式API、架构设计到网络、存储、安全、运维生态,深入浅出揭示其自动化编排本质,展现K8S如何成为云时代分布式操作系统的基石。(239字)
2457 6
|
6月前
|
算法 搜索推荐 大数据
当“爆款书”遇上大数据:出版业的老路,正在被算法改写
当“爆款书”遇上大数据:出版业的老路,正在被算法改写
749 8
|
7月前
|
Java Python
介绍一款更好用的selenium自愈工具ReCheck
前面介绍了GUI自动化自愈工具Healenium,现在介绍另一个自愈工具ReCheck
401 7