This is a weird issue which I cannot solve myself. Basically I am making Minesweeper using python 3.6, and Tkinter. The game plays fine, up until about halfway through a hard game (it happens in the other games if they get drawn out longer), where you click a piece, and then an error comes up in the console. A little while later, after being able to play a few more moves, the game crashes. Excuse the 'temporary' code, it's not my best work as it was never meant to be seen by anyone!
(I haven't included all code from the program)
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()
The other weird thing is that it throws up 2 slightly different errors, but they are still part of the same issue. Here are the two problems:
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
And the other one:
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
I've looked up this issue as much as I can, and it's either something to do with the root.mainloop() calling, or the recursive function (CheckNeighbours) doing something wrong, or the fact I'm not using classes. Help is appreciated :)
EDIT - The program seems to throw a slightly different error each time. However, all of them end in the maximum recursion depth exceeded error
CheckNeighboursfunction. If you have an 8x8 board, the maximum number of spots on the board is 64. The default recursion limit is 1000, meaning you are "checking a neighbor" 1000 times when it's impossible for there to be more than 64 neighbors to check.