【问题标题】:Tkinter: Win check in scalable tic tac toe not workingTkinter:Win check in 可扩展井字游戏不工作
【发布时间】:2019-12-10 20:44:55
【问题描述】:

我正在 Tkinter 中制作一个可扩展的井字游戏(这意味着棋盘大小可以是 2x2 到任何适合屏幕的大小)。我正在使用cget("image") 来查找按钮的标记。出于某种原因,获胜检查会显示非常随机的内容。我已经尝试了很多半随机的东西来修复它,但没有成功修复它。代码如下:

from tkinter import *

class XOGame:
    def main_game(self):
        self.__game_window = Tk()
        self.__grid_size = 3 # User inputted in a different part of the code
        self.__game_window.title("Tic Tac Toe (" + str(self.__grid_size) + "x"
                                     + str(self.__grid_size) + ")")

        # this is user inputted in a different part of the program.
        self.__players = ["p1", "p2"]
        self.__player1 = self.__players[0]
        self.__player2 = self.__players[1]

        self.build_board(self.__game_window)

        self.__game_window.mainloop()


    def build_board(self, window):
        self.__size = self.__grid_size ** 2
        self.__turn_nr = 1
        self.__win = False

        self.__empty_square = PhotoImage(master=window,
                                         file="rsz_empty.gif")
        self.__x = PhotoImage(master=window,
                              file="rsz_cross.gif")
        self.__o = PhotoImage(master=window,
                              file="rsz_nought.gif")

        self.__squares = [None] * self.__size
        self.create_win_check_lists()

        # Building the buttons and gridding them
        for i in range(self.__size):
            self.__squares[i] = (Button(window, image=self.__empty_square))
        row = 0
        column = 0
        number = 1
        for j in self.__squares:

            j.grid(row=row, column=column)
            j.config(command=lambda index=self.__squares.index(j):
                     self.change_mark(index))
            column += 1
            if number % 3 == 0:
                row += 1
                column = 0
            number += 1

# This is the part where the picture changing happens.
    def change_mark(self, i):
        """
            Function changes mark of empty button to either X or O depending on the
            player in turn. It also checks if the change in mark results in a win.
            :param i: The button number, whose mark is being changed
            :return: None
        """
        if self.__turn_nr % 2 == 1:
            self.__player_in_turn = self.__player1

        else:
            self.__player_in_turn = self.__player2

        if self.__player_in_turn == self.__player1:
            self.__mark = self.__x
        else:
            self.__mark = self.__o

        self.__squares[i].configure(image=self.__mark, state=DISABLED)

        self.__turn_nr += 1

        self.check_win(i)

        if self.__win is True:
            print("this is thought to be a win")
        else:
            print("the game thinks this is not a win")

        # Checking if the game tied.
        if self.__turn_nr == self.__size + 1 and not self.__win:
            print("the game thinks it tied.")

    def check_win(self, i):
        """
        Checks if mark placement leads to a win.
        :param i: i is the button location.
        :return: None
        """

                # checks row
        if self.__win == False:
            for row in self.__rows:
                if i + 1 in row:
                    self.__win = self.checksameimage(row)
                    if self.__win == True:
                        break

        # checks column
        if self.__win == False:
            for column in self.__columns:
                if i + 1 in column:
                    self.__win = self.checksameimage(column)
                    if self.__win == True:
                        break

        # if i is in a diagonal, checks one/both diagonals
        if self.__win == False:
            for diag in self.__diagonals:
                if i + 1 in diag:
                    self.__win = self.checksameimage(diag)
                    if self.__win == True:
                        break

        return self.__win

    # checking if all the images are same
    # This is likely where the issue is. Either this part or checkEqual.
    def checksameimage(self, lst):
        images = []
        for nr in lst:
            try:
                images.append(self.__squares[nr].cget("image"))
            except IndexError:
                pass

        return self.checkEqual(images)

    def checkEqual(self, lst):
        """
        Function checks if all elements in a list are equal. Used for checking
        if the dice throws are the same.
        :param lst: The list the check is performed on
        :return: True/False, True if all elements are equal.
        """
        if all(x == lst[0] for x in lst):
            return True
        else:
            return False

    def create_win_check_lists(self):
        """
        Creates lists whose elements are lists of the locations of each spot
        of the game board that belongs to a row/column/diagonal
        :return:
        """

        self.__rows = [[] for _ in range(self.__grid_size)]

        for i in range(self.__grid_size):
            self.__rows[i].append(i + 1)
            for k in range(1, self.__grid_size):
                self.__rows[i].append(i + 1 + self.__grid_size * k)

        self.__columns = [[] for _ in range(self.__grid_size)]

        for i in range(self.__grid_size):
            for j in range(1, self.__grid_size + 1):
                self.__columns[i].append(i * self.__grid_size + j)

        self.getDiagonals(self.__columns)

    def getDiagonals(self, lst):

        self.__diagonals = [[], []]
        self.__diagonals[0] = [lst[i][i] for i in range(len(lst))]
        self.__diagonals[1] = [lst[i][len(lst) - i - 1] for i in
                               range(len(lst))]

    def start(self):
        # Function starts the first window of the game.
        self.main_game()


def main():
    ui = XOGame()
    ui.start()


main()

代码中使用的图像为 125x125。这是一个 24 小时有效的链接:https://picresize.com/b5df006025f0d8

【问题讨论】:

  • if self.__win == True: break 不会阻止它在下一个循环中将 self.__win 覆盖为 false。生成获胜行和列的代码也很不可读,我怀疑这可能是错误的。
  • @TadhgMcDonald-Jensen 抱歉,修复了 self.__win 最重要的问题。行、列和对角线的生成效果很好,我已经对其进行了广泛的测试。我认为问题特别在于函数 checksameimage 或 checkEqual。
  • 您说“相信”,但肯定有一些打印语句会很快证明您的checksameimage 最终会得到一个包含"pyimage1" 的2-3 个元素的列表,它对应于空白空间图像。
  • @TadhgMcDonald-Jensen 是的,我知道,我在调试器中看到过。作为初学者,我很难看到按钮中的信息,这让我有时感到有些困惑。问题是,即使 checksameimage 有 pyimage1 的实例,程序仍认为游戏赢了。我真的不明白为什么,因为这是我第一次做一个更大的程序,老实说,我有点难以理解这一切。任何帮助将不胜感激。也感谢您抽出宝贵的时间 :)

标签: python tkinter tic-tac-toe


【解决方案1】:

毫无疑问,您的问题与索引有关。我们可以通过将图像更改为索引对应的文本来查看每个正方形对应的索引:

尝试在build_board 中更改此循环:

    for i in range(self.__size):
        self.__squares[i] = (Button(window, image=self.__empty_square))

改为显示它对应的索引:

    for i in range(self.__size):
        self.__squares[i] = (Button(window, text=str(i)))

然后打印出lst 传递给checksameimage,你会看到你检查的索引都比你预期的高一个。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-18
    • 1970-01-01
    • 2018-02-25
    • 2015-06-12
    • 2015-01-08
    相关资源
    最近更新 更多