【问题标题】:Memory Game in Python with Tkinter使用 Tkinter 在 Python 中进行记忆游戏
【发布时间】:2011-11-17 22:30:24
【问题描述】:

我正在尝试使用 python 3 和 tkinter 制作一个记忆游戏。我是 python 新手,所以这有点难。我的问题是我试图从“Memory”类中调用“Cell”类中的方法“show_word”,但我不知道该怎么做。

记忆游戏:

    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

【问题讨论】:

  • 那么,你想在什么时候/在什么条件下打电话给show_word?另外,请删除与您的问题无关的部分代码(将来,请考虑不要一次编写太多代码 - 先制作一小部分,然后逐步构建)。
  • 亚马逊,我发布了 show_word 版本的修复,以防万一。

标签: python tkinter


【解决方案1】:

您遇到了一个微妙的范围界定问题。当您创建一个引用包含范围内的变量的函数时,这些变量的值在函数定义时不是固定的,而是在函数执行时固定的。换句话说,当你这样做时:

command = lambda: print(index) 

当函数被调用时,您告诉 Python 打印 index 的任何值。当用户按下其中一个按钮,导致函数被调用时,index 的值是 35。

要在函数定义时固定值,您必须使用默认值,如下所示:

command = lambda x=index: print(x)

我相信你可以找出相应的show_word 修复,但以防万一:

command = lambda x=index: Cell.show_word(the_pairs[x])

【讨论】:

  • 还有其他方法可以修复该值,但肯定没有那么优雅。无论如何,他似乎想在这里使用show_cell 方法,所以你也应该表明这一点。
【解决方案2】:

在我可以直接帮助您之前,我的评论需要一个答案,但同时,这里有一些提示可以更优雅地编写代码:

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)

        # ...

【讨论】:

  • 呃。我最终弄清楚了您的意思,而 senderle 的答案正是您所需要的。不过,我希望我是有教育意义的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-14
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-24
相关资源
最近更新 更多