简体   繁体   English

使用Tkinter在Python中进行记忆游戏

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM