[英]Memory Game in Python with Tkinter
I'm trying to make a memory game using python 3 and tkinter. 我正在尝试使用python 3和tkinter制作记忆游戏。 I'm new to python so this is kind of hard.
我是python的新手,所以很难。 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.
我的问题是我试图从“ Memory”类中调用“ Cell”类中的“ show_word”方法,但我不知道该怎么做。
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 . 你告诉Python在调用函数时打印
index
的值。 By the time a user pushes one of those buttons, causing the function to be called, the value of index
is 35. 当用户按下其中一个按钮,导致调用该函数时,
index
值为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: 我相信你可以弄清楚相应的
show_word
修复,但以防万一:
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)
# ...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.