Python Tkinter扫雷开发:零周边地雷方块点击触发无限循环问题求助
解决Tkinter扫雷游戏0方块自动展开的无限循环问题
嘿,我明白你遇到的麻烦了——点击周边无雷的方块时触发无限循环,这确实挺头疼的。咱们先来揪出问题根源,再一步步修复它!
问题分析
你猜的没错,无限循环的核心原因是没有标记哪些方块已经被打开过。当你点击一个0方块后,openSurroundings会调用所有相邻方块的click函数;而如果相邻方块也是0,它又会反过来调用原方块的click,如此反复就陷入了无限递归。另外,你的边界检查也有点小问题,只判断了a<81,没处理负数索引的情况,可能会导致其他错误。
修复方案
我们需要添加一个「已打开标记矩阵」,用来记录每个方块是否已经被处理过,同时完善边界检查:
- 新增
opened矩阵:用来追踪哪些方块已经被点击展开,避免重复调用click - 在
click函数开头加判断:如果方块已经打开,直接返回,不再执行后续逻辑 - 完善
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
相关产品推荐
相关产品推荐

