failed to resolve some method of tkinter
Question:
I am creating 2048 game on python with tkinter but I have a issue
I don’t know what is wrong in left, right, up and down methods created in PageOne class.
In another class (StartPage), bind function calls these methods but this don’t work
So I don’t know how toresolve the mistakes, in bind functions or in the left, right, up and down methods?
In particular I get this error when I press the right key:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:UsersfabioAppDataLocalProgramsPythonPython310libtkinter__init__.py", line 1921, in __call__
return self.func(*args)
File "C:UsersfabioPycharmProjects2048gametk2048gametk.py", line 198, in right
self.reverse()
AttributeError: 'Event' object has no attribute 'reverse'
And similar error for the other key (up, left and down):
Traceback (most recent call last):
File "C:UsersfabioAppDataLocalProgramsPythonPython310libtkinter__init__.py", line 1921, in __call__
return self.func(*args)
File "C:UsersfabioPycharmProjects2048gametk2048gametk.py", line 208, in up
self.transpose()
AttributeError: 'Event' object has no attribute 'transpose'
Exception in Tkinter callback
Traceback (most recent call last):
File "C:UsersfabioAppDataLocalProgramsPythonPython310libtkinter__init__.py", line 1921, in __call__
return self.func(*args)
TypeError: PageOne.left() missing 1 required positional argument: 'event'
Exception in Tkinter callback
Traceback (most recent call last):
File "C:UsersfabioAppDataLocalProgramsPythonPython310libtkinter__init__.py", line 1921, in __call__
return self.func(*args)
File "C:UsersfabioPycharmProjects2048gametk2048gametk.py", line 218, in down self.transpose()
AttributeError: 'Event' object has no attribute 'transpose'
The left one is different because i put event instead of event = None as argument in the left module.
A small problem concern the score_frame that appears also in the StartPage and not only in the PageOne, so i don’t know how to combine the frames on the code
Below you can find the entire code
Can anyone help me?
Thanks in advance
import os
import random
import sys
import tkinter as tk
from math import floor
class MyButton(tk.Button):
def __init__(self, *args, **kwargs):
tk.Button.__init__(self, *args, **kwargs, bg='brown', fg='white',
font="Helvetica 12 bold", width=8, pady='1m')
self.pack(pady="3m")
class Game(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.title("2048 game")
self.dim = 4
self.main_grid = None
container = tk.Frame(self, width=500, height=600)
container.grid(pady=(100, 0))
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, PageOne):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
self.bind("<Left>", PageOne.left)
self.bind("<Right>", PageOne.right)
self.bind("<Up>", PageOne.up)
self.bind("<Down>", PageOne.down)
self.mainloop()
def show_frame(self, controller): #page_name al posto di controller
frame = self.frames[controller]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.dim = controller.dim
label = tk.Label(self, text="2048", font="Helvetica 48 bold", fg="orange")
label.pack(side="top", fill="x")
button1 = MyButton(self, text="3x3", command=self.dim_3)
button1.pack()
button1.bind("<Return>", self.dim_3)
button2 = MyButton(self, text="4x4", command=self.dim_4)
button2.focus_force()
button2.pack()
button2.bind("<Return>", self.dim_4)
button3 = MyButton(self, text="5x5", command=self.dim_5)
button3.pack()
button3.bind("<Return>", self.dim_5)
button4 = MyButton(self, text="8x8", command=self.dim_8)
button4.pack()
button4.bind("<Return>", self.dim_8)
def dim_3(self):
self.dim = 3
self.controller.show_frame(PageOne)
def dim_4(self):
self.dim = 4
self.controller.show_frame(PageOne)
def dim_5(self):
self.dim = 5
self.controller.show_frame(PageOne)
def dim_8(self):
self.dim = 8
self.controller.show_frame(PageOne)
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.matrix = None
self.score = None
self.cells = []
for i in range(self.controller.dim):
row = []
for j in range(self.controller.dim):
cell_frame = tk.Frame(self, bg="light grey",
width=500 / self.controller.dim, height=500 / self.controller.dim)
cell_frame.grid(row=i+10, column=j, padx=10 / self.controller.dim, pady=10 / self.controller.dim)
cell_number = tk.Label(self, bg="light grey")
cell_number.grid(row=i+10, column=j)
cell_data = {"frame": cell_frame, "number": cell_number}
row.append(cell_data)
self.cells.append(row)
score_frame = tk.Frame(controller.main_grid)
score_frame.place(relx=0.5, y=50, anchor="center")
tk.Label(score_frame, text="Score", font="Helvetica 18 bold").grid(row=0)
self.score_label = tk.Label(score_frame, text="0", font="Helvetica 24 bold")
self.score_label.grid(row=1)
self.start_game()
def start_game(self):
self.matrix = [[0] * self.controller.dim for _ in range(self.controller.dim)]
row = random.randint(0, self.controller.dim - 1)
col = random.randint(0, self.controller.dim - 1)
self.matrix[row][col] = 2
self.cells[row][col]["frame"].configure(bg="white")
self.cells[row][col]["number"].configure(bg="white", fg="black", font="Helvetica 24 bold", text="2")
while self.matrix[row][col] != 0:
row = random.randint(0, self.controller.dim - 1)
col = random.randint(0, self.controller.dim - 1)
self.matrix[row][col] = 2
self.cells[row][col]["frame"].configure(bg="white")
self.cells[row][col]["number"].configure(bg="white", fg="black", font="Helvetica 24 bold", text="2")
self.score = 0
# move all numbers on the left side
def stack(self):
new_matrix = [[0] * self.controller.dim for _ in range(self.controller.dim)]
for i in range(self.controller.dim):
fill_pos = 0
for j in range(self.controller.dim):
if self.matrix[i][j] != 0:
new_matrix[i][fill_pos] = self.matrix[i][j]
fill_pos += 1
self.matrix = new_matrix
# sum numbers horizontally and combine equal numbers
def combine(self):
for i in range(self.controller.dim):
for j in range(self.controller.dim - 1):
if self.matrix[i][j] != 0 and self.matrix[i][j] == self.matrix[i][j + 1]:
self.matrix[i][j] *= 2
self.matrix[i][j + 1] = 0
self.score += self.matrix[i][j]
# this function reverses the order of each row
def reverse(self):
new_matrix = []
for i in range(self.controller.dim):
new_matrix.append([])
for j in range(self.controller.dim):
new_matrix[i].append(self.matrix[i][self.controller.dim - 1 - j])
self.matrix = new_matrix
def transpose(self):
new_matrix = [[0] * self.controller.dim for _ in range(self.controller.dim)]
for i in range(self.controller.dim):
for j in range(self.controller.dim):
new_matrix[i][j] = self.matrix[j][i]
self.matrix = new_matrix
def add_number(self):
if any(0 in row for row in self.matrix):
row = random.randint(0, self.controller.dim - 1)
col = random.randint(0, self.controller.dim - 1)
while self.matrix[row][col] != 0:
row = random.randint(0, self.controller.dim - 1)
col = random.randint(0, self.controller.dim - 1)
self.matrix[row][col] = random.choice([2, 2, 2, 2, 4])
def update_GUI(self):
for i in range(self.controller.dim):
for j in range(self.controller.dim):
cell_value = self.matrix[i][j]
if cell_value == 0:
self.cells[i][j]["frame"].configure(bg="light grey")
self.cells[i][j]["number"].configure(bg="light grey", text="")
else:
self.cells[i][j]["frame"].configure(bg=NUMBER_COLOR[cell_value])
self.cells[i][j]["number"].configure(bg=NUMBER_COLOR[cell_value], fg="black",
font="Helvetica 24 bold", text=str(cell_value))
self.score_label.configure(text=self.score)
self.update_idletasks()
self.game_over()
def left(self, event):
self.stack()
self.combine()
self.stack()
self.add_number()
self.update_GUI()
self.game_over()
def right(self, event=None):
self.reverse()
self.stack()
self.combine()
self.stack()
self.reverse()
self.add_number()
self.update_GUI()
self.game_over()
def up(self, event=None):
self.transpose()
self.stack()
self.combine()
self.stack()
self.transpose()
self.add_number()
self.update_GUI()
self.game_over()
def down(self, event=None):
self.transpose()
self.reverse()
self.stack()
self.combine()
self.stack()
self.reverse()
self.transpose()
self.add_number()
self.update_GUI()
def horiz_moves(self):
for i in range(self.controller.dim):
for j in range(self.controller.dim - 1):
if self.matrix[i][j] == self.matrix[i][j + 1]:
return True
return False
def vert_moves(self):
for i in range(self.controller.dim - 1):
for j in range(self.controller.dim):
if self.matrix[i][j] == self.matrix[i + 1][j]:
return True
return False
def number(self):
if self.controller.dim == 3:
return 8
elif self.controller.dim == 4:
return 2048
elif self.controller.dim == 5:
return 8192
else:
return 16384
def restart(self):
self.bind("<Return>", os.execl(sys.executable, sys.executable, *sys.argv))
def game_over(self):
tk.Frame(self).place(relx=0.5, rely=0.5, anchor="center")
if not any(0 in row for row in self.matrix) and not self.horiz_moves() and not self.vert_moves():
top = tk.Toplevel()
top.geometry("300x100")
top.title("toplevel")
l2 = tk.Label(top, text="Game Overn What do you want do?",
fg="white", font="Helvetica 12 bold")
l2.pack()
tk.Button(top, text="Restart", bg="green",
fg="white", font="Helvetica 10 bold",
command=self.restart).pack(side='left')
tk.Button(top, text="Quit", bg="red",
fg='white', font="Helvetica 10 bold", command=self.bind("<Return>", quit)).pack(side="right")
elif any(self.number() in row for row in self.matrix):
top = tk.Toplevel()
top.geometry("180x100")
top.title("toplevel")
l2 = tk.Label(top, text="You Win!n What do you want do?", font="Helvetica 12 bold")
l2.pack()
tk.Button(top, text="Restart", bg="green",
fg="white", font="Helvetica 10 bold",
command=self.restart).pack(side='left')
tk.Button(top, text="Quit", bg="red",
fg='white', font="Helvetica 10 bold", command=self.bind("<Return>", quit)).pack(side="right")
def savegame(self):
f = open("savedata", "w")
line1 = " ".join(
[str(self.matrix[floor(x / self.controller.dim)][x % self.controller.dim])
for x in range(0, self.controller.dim ** 2)])
f.write(line1 + "n")
f.write(str(self.controller.dim) + "n")
f.write(str(self.score))
f.close()
def loadgame(self):
# self.score
# self.dim
# self.matrix
f = open("savedata", "r")
mat = (f.readline()).split(' ', self.controller.dim ** 2)
self.controller.dim = int(f.readline())
self.score = int(f.readline())
for i in range(0, self.controller.dim ** 2):
self.matrix[floor(i / self.controller.dim)][i % self.controller.dim] = int(mat[i])
f.close()
NUMBER_COLOR = {
2: "#fcefe6",
4: "#f2e8cb",
8: "#f5b682",
16: "#f29446",
32: "#ff775c",
64: "#e64c2e",
128: "#ede291",
256: "#fce130",
512: "#ffdb4a",
1024: "#f0b922",
2048: "#fad74d",
4096: "brown",
8192: "silver",
16384: "gold"
}
def main():
Game()
if __name__ == "__main__":
main()
Answers:
Replace the code with the following:
self.bind("<Left>", self.frames[PageOne].left)
self.bind("<Right>", self.frames[PageOne].right)
self.bind("<Up>", self.frames[PageOne].up)
self.bind("<Down>", self.frames[PageOne].down)
The reason for your odd behavior is that you try to reach instances variables and methods but on the level of a class. It’s not easy to explain in a few words, but you should research the difference between class an regular methods, the purpose of self and of course the documentation for classes and instances
Update
In order to make your dimensions work you need to create your matrix after you defined the dimensions, not when you initialize your Frame. The shortest way to achive this, is to create a function that is called when your dimension is defined.
In your PageOne you would do something like:
...
self.cells = []
def create_matrix(self):
for i in range(self.controller.dim):
...
score_frame = tk.Frame(self.controller.main_grid) #add self.
...
call this function when the user has chosen by (e.g):
def dim_3(self):
self.controller.dim = 3 #use self.controller dim
self.controller.frames[PageOne].create_matrix() #call create_matrix
self.controller.show_frame(PageOne)
and while you use the variable in your controller the following is not effective:
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
#self.dim = controller.dim
#is not a link to your var self.dim stores whats in controller.dim
Update2
in order to make your quit and restart work and with little improvements I have changed your code below. The code is left as an exercise since I still try to figure out the rules of the game. Happy codeing!
def restart(self):
for widget in self.winfo_children():
widget.destroy()
self.cells = []
self.controller.show_frame(StartPage)
def game_over(self):
tk.Frame(self).place(relx=0.5, rely=0.5, anchor="center")
if not any(0 in row for row in self.matrix) and not self.horiz_moves() and not self.vert_moves():
geo_string = "300x100"
title = "Game Over!"
text = "Game Overn What do you want do?"
self.message(geo_string,title,text)
elif any(self.number() in row for row in self.matrix):
geo_string = "180x100"
title = "Congratulation!"
text = "You Win!n What do you want do?"
self.message(geo_string,title,text)
def message(self, geo_string,title,text):
top = tk.Toplevel()
top.geometry(geo_string)
top.title(title)
l2 = tk.Label(top, text=text, font="Helvetica 12 bold")
l2.pack()
rbutton = tk.Button(top, text="Restart", bg="green",
fg="white", font="Helvetica 10 bold",
command=self.restart)
rbutton.bind('<ButtonRelease-1>',lambda e: self.controller.after(20,top.destroy))
rbutton.pack(side='left')
qbutton = tk.Button(top, text="Quit", bg="red",
fg='white', font="Helvetica 10 bold",
command=self.controller.destroy)
qbutton.pack(side="right")
I am creating 2048 game on python with tkinter but I have a issue
I don’t know what is wrong in left, right, up and down methods created in PageOne class.
In another class (StartPage), bind function calls these methods but this don’t work
So I don’t know how toresolve the mistakes, in bind functions or in the left, right, up and down methods?
In particular I get this error when I press the right key:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:UsersfabioAppDataLocalProgramsPythonPython310libtkinter__init__.py", line 1921, in __call__
return self.func(*args)
File "C:UsersfabioPycharmProjects2048gametk2048gametk.py", line 198, in right
self.reverse()
AttributeError: 'Event' object has no attribute 'reverse'
And similar error for the other key (up, left and down):
Traceback (most recent call last):
File "C:UsersfabioAppDataLocalProgramsPythonPython310libtkinter__init__.py", line 1921, in __call__
return self.func(*args)
File "C:UsersfabioPycharmProjects2048gametk2048gametk.py", line 208, in up
self.transpose()
AttributeError: 'Event' object has no attribute 'transpose'
Exception in Tkinter callback
Traceback (most recent call last):
File "C:UsersfabioAppDataLocalProgramsPythonPython310libtkinter__init__.py", line 1921, in __call__
return self.func(*args)
TypeError: PageOne.left() missing 1 required positional argument: 'event'
Exception in Tkinter callback
Traceback (most recent call last):
File "C:UsersfabioAppDataLocalProgramsPythonPython310libtkinter__init__.py", line 1921, in __call__
return self.func(*args)
File "C:UsersfabioPycharmProjects2048gametk2048gametk.py", line 218, in down self.transpose()
AttributeError: 'Event' object has no attribute 'transpose'
The left one is different because i put event instead of event = None as argument in the left module.
A small problem concern the score_frame that appears also in the StartPage and not only in the PageOne, so i don’t know how to combine the frames on the code
Below you can find the entire code
Can anyone help me?
Thanks in advance
import os
import random
import sys
import tkinter as tk
from math import floor
class MyButton(tk.Button):
def __init__(self, *args, **kwargs):
tk.Button.__init__(self, *args, **kwargs, bg='brown', fg='white',
font="Helvetica 12 bold", width=8, pady='1m')
self.pack(pady="3m")
class Game(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.title("2048 game")
self.dim = 4
self.main_grid = None
container = tk.Frame(self, width=500, height=600)
container.grid(pady=(100, 0))
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, PageOne):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
self.bind("<Left>", PageOne.left)
self.bind("<Right>", PageOne.right)
self.bind("<Up>", PageOne.up)
self.bind("<Down>", PageOne.down)
self.mainloop()
def show_frame(self, controller): #page_name al posto di controller
frame = self.frames[controller]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.dim = controller.dim
label = tk.Label(self, text="2048", font="Helvetica 48 bold", fg="orange")
label.pack(side="top", fill="x")
button1 = MyButton(self, text="3x3", command=self.dim_3)
button1.pack()
button1.bind("<Return>", self.dim_3)
button2 = MyButton(self, text="4x4", command=self.dim_4)
button2.focus_force()
button2.pack()
button2.bind("<Return>", self.dim_4)
button3 = MyButton(self, text="5x5", command=self.dim_5)
button3.pack()
button3.bind("<Return>", self.dim_5)
button4 = MyButton(self, text="8x8", command=self.dim_8)
button4.pack()
button4.bind("<Return>", self.dim_8)
def dim_3(self):
self.dim = 3
self.controller.show_frame(PageOne)
def dim_4(self):
self.dim = 4
self.controller.show_frame(PageOne)
def dim_5(self):
self.dim = 5
self.controller.show_frame(PageOne)
def dim_8(self):
self.dim = 8
self.controller.show_frame(PageOne)
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.matrix = None
self.score = None
self.cells = []
for i in range(self.controller.dim):
row = []
for j in range(self.controller.dim):
cell_frame = tk.Frame(self, bg="light grey",
width=500 / self.controller.dim, height=500 / self.controller.dim)
cell_frame.grid(row=i+10, column=j, padx=10 / self.controller.dim, pady=10 / self.controller.dim)
cell_number = tk.Label(self, bg="light grey")
cell_number.grid(row=i+10, column=j)
cell_data = {"frame": cell_frame, "number": cell_number}
row.append(cell_data)
self.cells.append(row)
score_frame = tk.Frame(controller.main_grid)
score_frame.place(relx=0.5, y=50, anchor="center")
tk.Label(score_frame, text="Score", font="Helvetica 18 bold").grid(row=0)
self.score_label = tk.Label(score_frame, text="0", font="Helvetica 24 bold")
self.score_label.grid(row=1)
self.start_game()
def start_game(self):
self.matrix = [[0] * self.controller.dim for _ in range(self.controller.dim)]
row = random.randint(0, self.controller.dim - 1)
col = random.randint(0, self.controller.dim - 1)
self.matrix[row][col] = 2
self.cells[row][col]["frame"].configure(bg="white")
self.cells[row][col]["number"].configure(bg="white", fg="black", font="Helvetica 24 bold", text="2")
while self.matrix[row][col] != 0:
row = random.randint(0, self.controller.dim - 1)
col = random.randint(0, self.controller.dim - 1)
self.matrix[row][col] = 2
self.cells[row][col]["frame"].configure(bg="white")
self.cells[row][col]["number"].configure(bg="white", fg="black", font="Helvetica 24 bold", text="2")
self.score = 0
# move all numbers on the left side
def stack(self):
new_matrix = [[0] * self.controller.dim for _ in range(self.controller.dim)]
for i in range(self.controller.dim):
fill_pos = 0
for j in range(self.controller.dim):
if self.matrix[i][j] != 0:
new_matrix[i][fill_pos] = self.matrix[i][j]
fill_pos += 1
self.matrix = new_matrix
# sum numbers horizontally and combine equal numbers
def combine(self):
for i in range(self.controller.dim):
for j in range(self.controller.dim - 1):
if self.matrix[i][j] != 0 and self.matrix[i][j] == self.matrix[i][j + 1]:
self.matrix[i][j] *= 2
self.matrix[i][j + 1] = 0
self.score += self.matrix[i][j]
# this function reverses the order of each row
def reverse(self):
new_matrix = []
for i in range(self.controller.dim):
new_matrix.append([])
for j in range(self.controller.dim):
new_matrix[i].append(self.matrix[i][self.controller.dim - 1 - j])
self.matrix = new_matrix
def transpose(self):
new_matrix = [[0] * self.controller.dim for _ in range(self.controller.dim)]
for i in range(self.controller.dim):
for j in range(self.controller.dim):
new_matrix[i][j] = self.matrix[j][i]
self.matrix = new_matrix
def add_number(self):
if any(0 in row for row in self.matrix):
row = random.randint(0, self.controller.dim - 1)
col = random.randint(0, self.controller.dim - 1)
while self.matrix[row][col] != 0:
row = random.randint(0, self.controller.dim - 1)
col = random.randint(0, self.controller.dim - 1)
self.matrix[row][col] = random.choice([2, 2, 2, 2, 4])
def update_GUI(self):
for i in range(self.controller.dim):
for j in range(self.controller.dim):
cell_value = self.matrix[i][j]
if cell_value == 0:
self.cells[i][j]["frame"].configure(bg="light grey")
self.cells[i][j]["number"].configure(bg="light grey", text="")
else:
self.cells[i][j]["frame"].configure(bg=NUMBER_COLOR[cell_value])
self.cells[i][j]["number"].configure(bg=NUMBER_COLOR[cell_value], fg="black",
font="Helvetica 24 bold", text=str(cell_value))
self.score_label.configure(text=self.score)
self.update_idletasks()
self.game_over()
def left(self, event):
self.stack()
self.combine()
self.stack()
self.add_number()
self.update_GUI()
self.game_over()
def right(self, event=None):
self.reverse()
self.stack()
self.combine()
self.stack()
self.reverse()
self.add_number()
self.update_GUI()
self.game_over()
def up(self, event=None):
self.transpose()
self.stack()
self.combine()
self.stack()
self.transpose()
self.add_number()
self.update_GUI()
self.game_over()
def down(self, event=None):
self.transpose()
self.reverse()
self.stack()
self.combine()
self.stack()
self.reverse()
self.transpose()
self.add_number()
self.update_GUI()
def horiz_moves(self):
for i in range(self.controller.dim):
for j in range(self.controller.dim - 1):
if self.matrix[i][j] == self.matrix[i][j + 1]:
return True
return False
def vert_moves(self):
for i in range(self.controller.dim - 1):
for j in range(self.controller.dim):
if self.matrix[i][j] == self.matrix[i + 1][j]:
return True
return False
def number(self):
if self.controller.dim == 3:
return 8
elif self.controller.dim == 4:
return 2048
elif self.controller.dim == 5:
return 8192
else:
return 16384
def restart(self):
self.bind("<Return>", os.execl(sys.executable, sys.executable, *sys.argv))
def game_over(self):
tk.Frame(self).place(relx=0.5, rely=0.5, anchor="center")
if not any(0 in row for row in self.matrix) and not self.horiz_moves() and not self.vert_moves():
top = tk.Toplevel()
top.geometry("300x100")
top.title("toplevel")
l2 = tk.Label(top, text="Game Overn What do you want do?",
fg="white", font="Helvetica 12 bold")
l2.pack()
tk.Button(top, text="Restart", bg="green",
fg="white", font="Helvetica 10 bold",
command=self.restart).pack(side='left')
tk.Button(top, text="Quit", bg="red",
fg='white', font="Helvetica 10 bold", command=self.bind("<Return>", quit)).pack(side="right")
elif any(self.number() in row for row in self.matrix):
top = tk.Toplevel()
top.geometry("180x100")
top.title("toplevel")
l2 = tk.Label(top, text="You Win!n What do you want do?", font="Helvetica 12 bold")
l2.pack()
tk.Button(top, text="Restart", bg="green",
fg="white", font="Helvetica 10 bold",
command=self.restart).pack(side='left')
tk.Button(top, text="Quit", bg="red",
fg='white', font="Helvetica 10 bold", command=self.bind("<Return>", quit)).pack(side="right")
def savegame(self):
f = open("savedata", "w")
line1 = " ".join(
[str(self.matrix[floor(x / self.controller.dim)][x % self.controller.dim])
for x in range(0, self.controller.dim ** 2)])
f.write(line1 + "n")
f.write(str(self.controller.dim) + "n")
f.write(str(self.score))
f.close()
def loadgame(self):
# self.score
# self.dim
# self.matrix
f = open("savedata", "r")
mat = (f.readline()).split(' ', self.controller.dim ** 2)
self.controller.dim = int(f.readline())
self.score = int(f.readline())
for i in range(0, self.controller.dim ** 2):
self.matrix[floor(i / self.controller.dim)][i % self.controller.dim] = int(mat[i])
f.close()
NUMBER_COLOR = {
2: "#fcefe6",
4: "#f2e8cb",
8: "#f5b682",
16: "#f29446",
32: "#ff775c",
64: "#e64c2e",
128: "#ede291",
256: "#fce130",
512: "#ffdb4a",
1024: "#f0b922",
2048: "#fad74d",
4096: "brown",
8192: "silver",
16384: "gold"
}
def main():
Game()
if __name__ == "__main__":
main()
Replace the code with the following:
self.bind("<Left>", self.frames[PageOne].left)
self.bind("<Right>", self.frames[PageOne].right)
self.bind("<Up>", self.frames[PageOne].up)
self.bind("<Down>", self.frames[PageOne].down)
The reason for your odd behavior is that you try to reach instances variables and methods but on the level of a class. It’s not easy to explain in a few words, but you should research the difference between class an regular methods, the purpose of self and of course the documentation for classes and instances
Update
In order to make your dimensions work you need to create your matrix after you defined the dimensions, not when you initialize your Frame. The shortest way to achive this, is to create a function that is called when your dimension is defined.
In your PageOne you would do something like:
...
self.cells = []
def create_matrix(self):
for i in range(self.controller.dim):
...
score_frame = tk.Frame(self.controller.main_grid) #add self.
...
call this function when the user has chosen by (e.g):
def dim_3(self):
self.controller.dim = 3 #use self.controller dim
self.controller.frames[PageOne].create_matrix() #call create_matrix
self.controller.show_frame(PageOne)
and while you use the variable in your controller the following is not effective:
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
#self.dim = controller.dim
#is not a link to your var self.dim stores whats in controller.dim
Update2
in order to make your quit and restart work and with little improvements I have changed your code below. The code is left as an exercise since I still try to figure out the rules of the game. Happy codeing!
def restart(self):
for widget in self.winfo_children():
widget.destroy()
self.cells = []
self.controller.show_frame(StartPage)
def game_over(self):
tk.Frame(self).place(relx=0.5, rely=0.5, anchor="center")
if not any(0 in row for row in self.matrix) and not self.horiz_moves() and not self.vert_moves():
geo_string = "300x100"
title = "Game Over!"
text = "Game Overn What do you want do?"
self.message(geo_string,title,text)
elif any(self.number() in row for row in self.matrix):
geo_string = "180x100"
title = "Congratulation!"
text = "You Win!n What do you want do?"
self.message(geo_string,title,text)
def message(self, geo_string,title,text):
top = tk.Toplevel()
top.geometry(geo_string)
top.title(title)
l2 = tk.Label(top, text=text, font="Helvetica 12 bold")
l2.pack()
rbutton = tk.Button(top, text="Restart", bg="green",
fg="white", font="Helvetica 10 bold",
command=self.restart)
rbutton.bind('<ButtonRelease-1>',lambda e: self.controller.after(20,top.destroy))
rbutton.pack(side='left')
qbutton = tk.Button(top, text="Quit", bg="red",
fg='white', font="Helvetica 10 bold",
command=self.controller.destroy)
qbutton.pack(side="right")