I'm trying to make a memory game using python 3 and tkinter. I'm new to python so this is kind of hard. My problem is that I'm trying to call the method "show_word" in the class "Cell" from the class "Memory" but I don't know exactly how to do it.
the memory game:
def create_widgets(self):
""" Create widgets to display the Memory game """
# buttons to show the words
column = 0
row = 1
the_pairs = self.readShuffle()
for index in range(36):
Button(self,
text = "hidden",
width = "7",
height = "2",
relief = GROOVE,
command = WHAT SHOULD I WRITE HERE???
).grid(row = row, column = column, padx = 1, pady = 1)
column += 1
if column == 6:
column = 0
row += 1
You've run into a subtle scoping problem. When you create a function that refers to variables from a containing scope, the value of those variables isn't fixed at the time of function definition, but at the time of function execution . In other words, when you do this:
command = lambda: print(index)
You're telling Python to print whatever the value of index
is when the function is called . By the time a user pushes one of those buttons, causing the function to be called, the value of index
is 35.
To fix the value at the time of function definition , you have to use default values, like so:
command = lambda x=index: print(x)
I'm sure you can figure out the corresponding show_word
fix, but just in case:
command = lambda x=index: Cell.show_word(the_pairs[x])
I need an answer for my comment before I can help you directly, but in the mean time, here are some hints for writing the code more elegantly:
from tkinter import *
# `tkinter` is meant to be used that way, but `random` isn't really - the names
# can be confusing without an explicit module reference. So instead:
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 """
self.hidden = not self.hidden
# no need to take this logic apart into cases
self.button.set(str(self))
def __str__(self):
""" Displays or hides the word """
# A simpler form of conditional; also, don't compare things
# explicitly to True or False
return "---" if self.hidden else 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
def readShuffle(self):
""" Creates and organizes (shuffles) the pairs in a list """
# The modern idiom for handling files and ensuring they are closed
with open("memo.txt","r") as words_file:
# The file can be iterated over directly, and is treated as
# a list of lines. Since we just want all the rstrip()ped
# lines, we can do the file processing all at once with a list
# comprehension.
# Let's also grab 18 random words while we're at it. We don't
# really want to *shuffle* the words, but instead *sample* them -
# we don't care about the words that we didn't select.
words = random.sample(
[line.rstrip('\n') for line in words_file], 18
)
# Instead of making 18 pairs of cells, we can make 18 cells and then
# pair them up. The set of 18 cells can also be made easily with a
# list comprehension. Notice how we get to iterate directly now,
# instead of messing around with indices into lists.
the_pairs = [Cell(word, True) for word in words] * 2
shuffle(the_pairs)
return the_pairs
def create_widgets(self):
""" Creates 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
the_pairs = self.readShuffle()
self.buttons = []
# Again, we can iterate in a more Pythonic way.
for i, pair in enumerate(the_pairs):
# Instead of having extra counters to work out the row and column,
# we can simply do math on the index value.
column, row = i % 6, i // 6
temp = StringVar()
temp.set(str(pair))
# Instead of adding the button to a list and then reaching into the
# list to configure it, get everything set up first.
button = Button(self,
textvariable = temp,
width = "7",
height = "2",
relief = GROOVE,
command = lambda: print(index)
))
button.grid(row = row, column = column, padx = 1, pady = 1)
buttons.append(button)
pair.button = temp
# total tries
self.label = Label(self) # Don't abbreviate!
Label(self,
text = "Total tries: 0",
font = ("Helvetica", 11, "italic")
).grid(row = 7, columnspan = 7, pady = 5)
# ...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.