Something wrong without any error - Includes Tkinter
I'm not getting any error but the code doesn't do what I want so there must be somewhere in the code where I have made a mistake. What I want to do is if the words match then the words must be a pair and the two chosen cells should remain "self.hidden = False" and therefore the cells should still show the words behind the two cells. Else if the words doesn't match then the cells should be "self.hidden = True" and the two cells should show "---".
Here are the important parts:
from tkinter import *
import random
class Cell:
def __init__(self, word, hidden):
self.word = word
self.hidden = hidden
def show_word(self):
""" Shows the word behind the cell """
if self.hidden == True:
self.hidden = False
else:
self.hidden = True
self.button["text"] = str(self)
if mem.choice1 == None:
mem.choice1 = [self.word, self.hidden]
else:
mem.choice2 = [self.word, self.hidden]
self.check(mem.choice1, mem.choice2)
def check(self, choice1, choice2):
""" Checks if the chosen words are a pair """
tries = 0
if choice1 == choice2:
pass
else:
self.show_word
tries += 1
def __str__(self):
""" Displays or hides the word """
if self.hidden == True:
return "---"
else:
return self.word
class Memory(Frame):
""" GUI application that creates a Memory game """
def __init__(self, master):
super(Memory, self).__init__(master)
self.grid()
self.create_widgets()
self.tries = 0
self.choice1 = None
self.choice2 = None
def readShuffle(self):
""" Creates and organizes (shuffles) the pairs in a list """
# reads the file and creates a list of the words
words_file = open("memo.txt","r")
row = words_file.readline()
words = list()
while row != "":
row = row.rstrip('\n')
words.append(row)
row = words_file.readline()
words_file.close()
# shuffles the words in the list
random.shuffle(words)
# creates 18 pairs of words in a new list
the_pairs = list()
for i in range(18):
the_pairs.append(Cell(words[i],True))
the_pairs.append(Cell(words[i],True))
# shuffles the words in the new list
random.shuffle(the_pairs)
return the_pairs
def create_widgets(self):
""" Create widgets to display the Memory game """
# instruction text
Label(self,
text = "- The Memory Game -",
font = ("Helvetica", 12, "bold"),
).grid(row = 0, column = 0, columnspan = 7)
# buttons to show the words
column = 0
row = 1
the_pairs = self.readShuffle()
for index in range(36):
temp = Button(self,
text = the_pairs[index],
width = "7",
height = "2",
relief = GROOVE,
command = lambda x = index: Cell.show_word(the_pairs[x])
)
temp.grid(row = row, column = column, padx = 1, pady = 1)
column += 1
the_pairs[index].button = temp
if column == 6:
column = 0
row += 1
# total tries
self.label = Label(self)
Label(self,
text = "Total tries: 0",
font = ("Helvetica", 11, "italic")
).grid(row = 7, columnspan = 7, pady = 5)
# a quit button
Button(self,
text = "Quit",
font = ("Helvetica", 10, "bold"),
width = "25",
height = "1",
command = self.quit
).grid(row = 8, column = 0, columnspan = 7, pady = 5)
## def update_tries(self):
## """ Increase tries count and display new total. """
## self.tries += 1
## self.label["text"] = "Total Tries: " + str(self.tries)
def quit(self):
""" Ends the memory game """
global root
root.destroy()
# main
root = Tk()
root.title("Memory")
root.geometry("365x355")
mem = Memory(root)
root.mainloop()
Asked by: Paul778 | Posted: 30-11-2021
Answer 1
The immediate problem is that you're not calling self.show_word
on line 136 in Cell.check
.
def check(self, choice1, choice2):
""" Checks if the chosen words are a pair """
tries = 0
if choice1 == choice2:
pass
else:
self.show_word
tries += 1
(You should also just use !=
here, instead of having a pass
statement in your if
clause. Additionally, tries
isn't doing anything here...)
However, even if you do call it (i.e. self.show_word()
instead of self.show_word
), you have bigger problems, as you'll set up an infinite loop if the words are not the same once you do.
check
will call show_word
which will then call check
, etc, etc.
What you need to do is reset choice1
and choice2
and their respective buttons inside your else
statement in Cell.check
.
However, to do this, you need to have access to the cell objects in question. As it is, you only pass in their text values and whether or not they're hidden.
The quick fix is to pass around the cell objects themselves.
First, though, let's clean your functions up a bit... You have this:
def show_word(self):
""" Shows the word behind the cell """
if self.hidden == True:
self.hidden = False
else:
self.hidden = True
self.button["text"] = str(self)
if mem.choice1 == None:
mem.choice1 = [self.word, self.hidden]
else:
mem.choice2 = [self.word, self.hidden]
self.check(mem.choice1, mem.choice2)
def check(self, choice1, choice2):
""" Checks if the chosen words are a pair """
tries = 0
if choice1 == choice2:
pass
else:
self.show_word
tries += 1
This is equivalent to:
def show_word(self):
""" Shows the word behind the cell """
self.hidden = not self.hidden
self.button["text"] = str(self)
if mem.choice1 is None:
mem.choice1 = [self.word, self.hidden]
else:
mem.choice2 = [self.word, self.hidden]
self.check(mem.choice1, mem.choice2)
def check(self, choice1, choice2):
""" Checks if the chosen words are a pair """
if choice1 != choice2:
self.show_word() # Infinite recursion!!
Now, let's pass around the Cell
instances themselves, so that we can reset their displayed values.
def show_word(self):
""" Shows the word behind the cell """
self.hidden = not self.hidden
self.button["text"] = str(self)
if mem.choice1 is None:
mem.choice1 = self
else:
mem.choice2 = self
self.check(mem.choice1, mem.choice2)
def check(self, choice1, choice2):
""" Checks if the chosen words are a pair """
mem.choice1, mem.choice2 = None, None
if choice1.word != choice2.word:
for cell in (choice1, choice2):
cell.hidden = True
cell.button['text'] = str(cell)
Now, things will work as you intended. However, the second choice will never be displayed if it doesn't match the first one. (In fact, we could remove the mem.choice2
attribute entirely in this version.)
So, instead, let's only reset the two values on the third click, if they don't match.
def show_word(self):
""" Shows the word behind the cell """
self.hidden = not self.hidden
self.button["text"] = str(self)
if mem.choice1 is None:
mem.choice1 = self
elif mem.choice2 is None:
mem.choice2 = self
else:
choice1, choice2 = mem.choice1, mem.choice2
mem.choice1, mem.choice2 = self, None
self.check(choice1, choice2)
def check(self, choice1, choice2):
""" Checks if the chosen words are a pair """
if choice1.word != choice2.word:
for cell in (choice1, choice2):
cell.hidden = True
cell.button['text'] = str(cell)
Now, things will behave more or less how you want.
from tkinter import *
import random
class Cell:
def __init__(self, word, hidden=True):
self.word = word
self.hidden = hidden
def show_word(self):
""" Shows the word behind the cell """
self.hidden = not self.hidden
self.button["text"] = str(self)
if mem.choice1 is None:
mem.choice1 = self
elif mem.choice2 is None:
mem.choice2 = self
else:
choice1, choice2 = mem.choice1, mem.choice2
mem.choice1, mem.choice2 = self, None
self.check(choice1, choice2)
def check(self, choice1, choice2):
""" Checks if the chosen words are a pair """
if choice1.word != choice2.word:
for cell in (choice1, choice2):
cell.hidden = True
cell.button['text'] = str(cell)
def __str__(self):
""" Displays or hides the word """
if self.hidden == True:
return "---"
else:
return self.word
class Memory(Frame):
""" GUI application that creates a Memory game """
def __init__(self, master):
super(Memory, self).__init__(master)
self.grid()
self.create_widgets()
self.tries = 0
self.choice1 = None
self.choice2 = None
def readShuffle(self):
""" Creates and organizes (shuffles) the pairs in a list """
# reads a list of words from the file
with open('memo.txt', 'r') as infile:
words = [line.strip() for line in infile]
# creates 18 pairs of words in a new list
the_pairs = list()
for i in range(18):
the_pairs.extend([Cell(words[i]), Cell(words[i])])
# shuffles the words in the new list
random.shuffle(the_pairs)
return the_pairs
def create_widgets(self):
""" Create widgets to display the Memory game """
# instruction text
Label(self,
text = "- The Memory Game -",
font = ("Helvetica", 12, "bold"),
).grid(row = 0, column = 0, columnspan = 7)
# buttons to show the words
column = 0
row = 1
the_pairs = self.readShuffle()
for index in range(36):
temp = Button(self,
text = the_pairs[index],
width = "7",
height = "2",
relief = GROOVE,
command = the_pairs[index].show_word
)
temp.grid(row = row, column = column, padx = 1, pady = 1)
column += 1
the_pairs[index].button = temp
if column == 6:
column = 0
row += 1
# total tries
self.label = Label(self)
Label(self,
text = "Total tries: 0",
font = ("Helvetica", 11, "italic")
).grid(row = 7, columnspan = 7, pady = 5)
# a quit button
Button(self,
text = "Quit",
font = ("Helvetica", 10, "bold"),
width = "25",
height = "1",
command = self.quit
).grid(row = 8, column = 0, columnspan = 7, pady = 5)
def quit(self):
""" Ends the memory game """
global root
root.destroy()
# main
root = Tk()
root.title("Memory")
root.geometry("365x355")
mem = Memory(root)
root.mainloop()
However, there's still a lot of cleanup and re-factoring that you could do. It would make much more sense to have the Memory
class handle checking clicks, etc. Also, have a look at the new readShuffle
function. You were reading in the file in an amazingly convoluted way. You should probably read over a few basic examples of file usage in python. It's much simpler than you think.
Similar questions
Large Python Includes
I have a file that I want to include in Python but the included file is fairly long and it'd be much neater to be able to split them into several files but then I have to use several include statements.
Is there some way to group together several files and include them all at once?
import - Python includes, module scope issue
I'm working on my first significant Python project and I'm having trouble with scope issues and executing code in included files. Previously my experience is with PHP.
What I would like to do is have one single file that sets up a number of configuration variables, which would then be used throughout the code. Also, I want to make certain functions and classes available globally. For example, the main file would i...
python - Put bar at the end of every line that includes foo
I have a list with a large number of lines, each taking the subject-verb-object form, eg:
Jane likes Fred
Chris dislikes Joe
Nate knows Jill
To plot a network graph that expresses the different relationships between the nodes in directed color-coded edges, I will need to replace the verb with an arrow and place a color code at the end of each line, thus, somewhat simplified:
Jane -> Fred r...
python - How to check if phone number entered by user includes country code?
Is there an easy way to check whether a phone number entered by the user includes country code and to validate that the number is correct? I don't use any specific formats, the number itself must be only digits, no ('s, -'s and the like. Is such validation possible without asking user for a country? The trick is that I want to work with all numbers world-wide.
I guess it can't be done with regex (googled a bit and...
python - PyCUDA: C/C++ includes?
Something that isn't really mentioned anywhere (at least that I can see) is what library functions are exposed to inline CUDA kernels.
Specifically I'm doing small / stupid matrix multiplications that don't deserve to be individually offloaded to the GPU but am offloading a larger section of the algorithm which includes this multiplication. Noone ever liked using their own linalg functions since someone has always ...
python - Global includes in Django
I want to create a module containing different utility functions and classes to use across different apps. It's not going to define any models or views. What's the best way to do this?
python - my post method returns (u'') and django saves includes the (u'') string when saving it
This is how I retrieve the post data from the webpage. The person models can be saved but it includes the "(u'')" string. For example if change the firstname to "Alex", it gets the raw value u('Alex') and saves it.
def submit_e(req, person_id=None):
if(req.POST):
try:
person_id = req.POST['driver']
person = Person.objects.get(pk=person_id)
...
python - How do I return a string that includes new lines?
I have a question that requires I use return and I do not know how to return on multiple lines. I need to be able to get an output that looks like this
Dear so and so,
kjhagjkahgsdhgl;dslhglk
jkasdhgjkdshkglhds;g
kjdghksadjglkdjslkg
kjgahkjsdhlgkdsjg;lsd
where the gibberish are strings that I have
python - Celery beat queue includes obsolete tasks
I'm using periodic celery tasks with Django. I used to have the following task in my app/tasks.py file:
@periodic_task(run_every=timedelta(minutes=2))
def stuff():
...
But now this task has been removed from my app/tasks.py file. However, I keep seeing call to this task in my celery logs:
[2013-05-21 07:08:37,963: ERROR/MainProcess] Received unregistered task of type u'ap...
Python: mplot3d, plot a 3D solid shape that includes dots inside
I am trying to plot in python using mplot3d, a solid shape that includes inside, a group of dots that are represented in a 3d space. Perhaps the images will clarify my question.
I was thinking of a sphere but also an irregular solid could work. If it is a sphe...
Still can't find your answer? Check out these communities...
PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python