这是一个我无法解决的奇怪问题。基本上我使用python 3.6和Tkinter制作扫雷。游戏运行良好,直到硬游戏的大约一半(如果他们被抽出更长时间在其他游戏中发生),你点击一块,然后在控制台中出现错误。不久之后,在能够再玩一些动作之后,游戏崩溃了。请原谅“临时”代码,这不是我最好的工作,因为它从来没有被任何人看到过!
(我没有包括该程序的所有代码)
from tkinter import *
import random
root = Tk()
buttons = []
images = {"X": PhotoImage(file="Mine.gif"), "X/": PhotoImage(file="MineSlash.gif"), "F": PhotoImage(file="Flag.gif")}
colors = {1:"#0008f9", 2:"#10cc00", 3:"#ff4f1e", 4:"#4b00a8", 5:"#bc0000", 6:"#00cbdd"}
board = []
mines = []
buttons = []
minesLeft = 10
numMines = 10
boardSize = 8
dead = False
minesLeftLabel = Label(font="Verdana 10 bold")
startingButtons = []
def ButtonCreate():
Button(root, text="Restart", width=8, height=1, font="Verdana 10 bold", command=Restart).grid(row=0, column=0, columnspan=3)
global minesLeftLabel
minesLeftLabel.grid(row=0, column=4, columnspan=2)
minesLeftLabel.config(text=str(minesLeft))
for y in range(boardSize):
tempList = []
for x in range(boardSize):
button = Button(root, text=board[y][x], bg="#eaeaea", width=2, height=1, font="Verdana 10 bold")
button.bind('<Button-1>', lambda event, x=x, y=y: MinePressed(x, y, False))
button.bind('<Button-3>', lambda event, x=x, y=y: MinePressed(x, y, True))
button.grid(row=y + 2, column=x)
tempList.append(button)
buttons.append(tempList)
def CheckNeighbours(x, y):
buttons[y][x].config(text=" ", fg="grey", bg="#e5e5e5", relief=SUNKEN)
for yPos in range(-1, 2):
for xPos in range(-1, 2):
if y + yPos >= 0 and y + yPos <= boardSize - 1 and x + xPos >= 0 and x + xPos <= boardSize - 1:
if mines[y + yPos][x + xPos] != 0:
board[y + yPos][x + xPos] = mines[y + yPos][x + xPos]
buttons[y + yPos][x + xPos].config(text=board[y + yPos][x + xPos], fg=colors[board[y + yPos][x + xPos]], bg="#e5e5e5", width=2, height=1, relief=SUNKEN)
elif board[y + yPos][x + xPos] == " " and mines[y + yPos][x + xPos] == 0:
board[y + yPos][x + xPos] = mines[y + yPos][x + xPos]
CheckNeighbours(x + xPos, y + yPos)
return
def MinePressed(x, y, flag):
if dead != True:
if flag:
global minesLeft
global minesLeftLabel
if board[y][x] == " ":
board[y][x] = "F"
minesLeft -= 1
minesLeftLabel.config(text=str(minesLeft))
buttons[y][x].config(image=images["F"], width=22, height=22)
elif board[y][x] == "F":
board[y][x] = " "
minesLeft += 1
minesLeftLabel.config(text=str(minesLeft))
buttons[y][x].config(text=board[y][x], image="", width=2, height=1)
else:
if board[y][x] != "F":
board[y][x] = mines[y][x]
if board[y][x] == "X":
GameOver()
buttons[y][x].config(image=images["X"], bg="red", width=21, height=21, relief=SUNKEN)
elif board[y][x] == 0:
CheckNeighbours(x, y)
else:
buttons[y][x].config(text=board[y][x], fg=colors[board[y][x]], bg="#e5e5e5", relief=SUNKEN)
root.update_idletasks()
root.mainloop()
def Restart():
ResetBoards()
global dead
dead = False
global buttons
buttons = []
CreateMines()
MineCalculations()
CreateWindow()
def ResetBoards():
global board
board = []
for y in range(boardSize):
tempList = []
for x in range(boardSize):
tempList.append(" ")
board.append(tempList)
global mines
mines = []
for y in range(boardSize):
tempList = []
for x in range(boardSize):
tempList.append(0)
mines.append(tempList)
def BoardSize(i):
global boardSize
boardSize = i
global numMines
numMines = int(boardSize * boardSize * 0.18)
global minesLeft
minesLeft = numMines
ResetBoards()
CreateMines()
MineCalculations()
CreateWindow()
def CreateWindow():
root.resizable(width=FALSE, height=FALSE)
root.geometry('{}x{}'.format(28 * boardSize, 28 * (boardSize + 1)))
for i in startingButtons:
i.destroy()
ButtonCreate()
def SelectSize():
root.resizable(width=FALSE, height=FALSE)
root.geometry('{}x{}'.format(150, 150))
global startingButtons
button1 = Button(text="Beginner", font="Verdana 10 bold", anchor=N, command=lambda i=8: BoardSize(i))
button1.place(relx=0.5, rely=0.2, anchor=CENTER)
button2 = Button(text="Intermediate", font="Verdana 10 bold", anchor=N, command=lambda i=16: BoardSize(i))
button2.place(relx=0.5, rely=0.45, anchor=CENTER)
button3 = Button(text="Hard", font="Verdana 10 bold", anchor=N, command=lambda i=24: BoardSize(i))
button3.place(relx=0.5, rely=0.7, anchor=CENTER)
startingButtons.append(button1)
startingButtons.append(button2)
startingButtons.append(button3)
SelectSize()
input()
另一个奇怪的是它引发了两个略有不同的错误,但它们仍然是同一个问题的一部分。以下是两个问题:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\aidan\AppData\Local\Programs\Python\Python36-32\lib\idlelib\run.py", line 137, in main
seq, request = rpc.request_queue.get(block=True, timeout=0.05)
File "C:\Users\aidan\AppData\Local\Programs\Python\Python36-32\lib\queue.py", line 172, in get
raise Empty
queue.Empty
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\aidan\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 1698, in __call__
args = self.subst(*args)
File "C:\Users\aidan\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 1428, in _substitute
e.type = EventType(T)
File "C:\Users\aidan\AppData\Local\Programs\Python\Python36-32\lib\enum.py", line 291, in __call__
return cls.__new__(cls, value)
RecursionError: maximum recursion depth exceeded while calling a Python object
另一个:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\aidan\AppData\Local\Programs\Python\Python36-32\lib\idlelib\run.py", line 137, in main
seq, request = rpc.request_queue.get(block=True, timeout=0.05)
File "C:\Users\aidan\AppData\Local\Programs\Python\Python36-32\lib\queue.py", line 172, in get
raise Empty
queue.Empty
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\aidan\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 1699, in __call__
return self.func(*args)
File "C:\Users\aidan\Desktop\MineSweeper\MinesweeperGUI.py", line 108, in Restart
CreateWindow()
File "C:\Users\aidan\Desktop\MineSweeper\MinesweeperGUI.py", line 153, in CreateWindow
ButtonCreate()
File "C:\Users\aidan\Desktop\MineSweeper\MinesweeperGUI.py", line 35, in ButtonCreate
Button(root, text="Restart", width=8, height=1, font="Verdana 10 bold", command=Restart).grid(row=0, column=0, columnspan=3)
File "C:\Users\aidan\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 2363, in __init__
Widget.__init__(self, master, 'button', cnf, kw)
File "C:\Users\aidan\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 2293, in __init__
(widgetName, self._w) + extra + self._options(cnf))
File "C:\Users\aidan\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 1320, in _options
v = self._register(v)
File "C:\Users\aidan\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 1356, in _register
f = CallWrapper(func, subst, self).__call__
RecursionError: maximum recursion depth exceeded
我尽可能地查看了这个问题,这或者与root.mainloop()调用有关,或者是递归函数(CheckNeighbours)做错了什么,或者我不使用的事实类。感谢帮助:)
编辑 - 程序似乎每次都会抛出稍微不同的错误。但是,所有这些都以最大递归深度超过错误结束
答案 0 :(得分:1)
问题或至少一个问题是,您不止一次地调用mainloop
,而是从事件处理程序调用它。这就是最终导致无限递归的原因。
顾名思义,mainloop
本身就是一个无限循环。它会一直运行,直到主窗口被破坏。当您按下某个键或按钮时,mainloop
将运行与该键或按钮关联的命令。如果该命令为MinePressed
,则最终会导致mainloop
从原始调用mainloop
内再次调用mainloop
。
因为mainloop
永不退出(因为根窗口永远不会被销毁),所以你有一个无限循环调用无限循环调用无限循环,......,并且这些内循环都不会退出。最终,当你运行root.mainloop()
一千份副本时,你的堆栈空间就会用尽。
您需要将MinePressed
移出SelectSize()
input()
root.mainloop()
并将其作为文件的最后一行,例如:
input()
虽然,也许它在<div class="spinner" ng-show="loading"></div>
之前 - 我不知道那行代码是什么。