You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Tkinter扫雷开发:零周边地雷方块点击触发无限循环问题求助

解决Tkinter扫雷游戏0方块自动展开的无限循环问题

嘿,我明白你遇到的麻烦了——点击周边无雷的方块时触发无限循环,这确实挺头疼的。咱们先来揪出问题根源,再一步步修复它!

问题分析

你猜的没错,无限循环的核心原因是没有标记哪些方块已经被打开过。当你点击一个0方块后,openSurroundings会调用所有相邻方块的click函数;而如果相邻方块也是0,它又会反过来调用原方块的click,如此反复就陷入了无限递归。另外,你的边界检查也有点小问题,只判断了a<81,没处理负数索引的情况,可能会导致其他错误。

修复方案

我们需要添加一个「已打开标记矩阵」,用来记录每个方块是否已经被处理过,同时完善边界检查:

  1. 新增opened矩阵:用来追踪哪些方块已经被点击展开,避免重复调用click
  2. 在click函数开头加判断:如果方块已经打开,直接返回,不再执行后续逻辑
  3. 完善openSurroundings的边界检查:确保索引在合法范围内(0到80,因为9x9=81个方块)

修改后的完整代码

import tkinter as tk
from random import choices
from math import floor

def openSurroundings(i):
    # 所有相邻方块的索引偏移
    neighbors = [i+1, i+9, i+8, i+10, i-1, i-9, i-8, i-10]
    for a in neighbors:
        # 完善边界检查:确保索引在0-80之间
        if 0 <= a < 81:
            row = floor(a / 9)
            col = a - (row * 9)
            # 只有未打开的方块才调用click
            if not opened[row][col]:
                click(row, col)

def click(row, col):
    # 如果已经打开过,直接返回,避免重复处理
    if opened[row][col]:
        return
    
    # 标记为已打开
    opened[row][col] = True
    
    text = numbers[row][col]
    widget = buttons[row][col]
    widget.grid_forget()
    clickSurrounding = False
    
    if text == 0:
        text = ''
        clickSurrounding = True
    
    lab = tk.Label(window, text=text, height=2, width=5)
    lab.grid(row=row, column=col)
    
    if clickSurrounding:
        openSurroundings((row*9)+col)

def placeBombs():
    global widgets, bombs
    numOfBombs = 10
    # 修正:索引从0开始更合理(对应0-80,共81个方块)
    widgets = list(range(81))
    bombs = choices(widgets, k=numOfBombs)

def findNumbers():
    global numbers
    numbers = []
    lis_num = []
    for i in widgets:
        if i in bombs:
            lis_num.append('•')
            continue
        else:
            neighbors = [i+1, i+9, i+8, i+10, i-1, i-9, i-8, i-10]
            num = 0
            for a in neighbors:
                if 0 <= a < 81 and a in bombs:
                    num += 1
            lis_num.append(num)
    # 按9个一组分割成二维数组
    for i in range(0, len(lis_num), 9):
        numbers.append(lis_num[i:i + 9])

window = tk.Tk()
window.title('Minesweeper')
sideLen = 9
row_index = 0
cell_index = 0
buttons = []

# 初始化已打开标记矩阵:所有方块初始为未打开
opened = [[False for _ in range(sideLen)] for _ in range(sideLen)]

while row_index != sideLen:
    button_row = []
    while cell_index != sideLen:
        button = tk.Button(window, width=5, height=2, 
                          command=lambda row=row_index, col=cell_index: click(row, col))
        button_row.append(button)
        button.grid(row=row_index, column=cell_index)
        cell_index += 1
    buttons.append(button_row)
    cell_index = 0
    row_index += 1

placeBombs()
findNumbers()
window.mainloop()  # 别忘了加这个,不然窗口会一闪而过!

关键修改点说明

  • opened矩阵:每次点击方块前先检查是否已打开,是的话直接返回,从根源切断了无限递归的可能
  • 边界检查优化:确保相邻索引不会超出0-80的范围,避免数组越界错误
  • 修正widgets的起始索引:原来从1开始,现在改成0开始,和方块的行列索引逻辑更统一,减少混淆
  • 添加window.mainloop():你原来的代码漏掉了这个,会导致窗口无法正常运行

这样修改后,点击0方块时就会正确自动展开所有相邻的无雷区域,不会再出现无限循环啦!

内容的提问来源于stack exchange,提问作者Manav Desai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 11:08:12