如何在Python

时间:2016-08-10 18:01:35

标签: python tkinter

假设我有一个类Game来玩游戏。一旦游戏结束,我想立即开始新游戏。我认为这可能通过在其自己的类定义中实例化新的Game()以递归方式实现。这可能吗?

举一个具体的例子,我使用Tkinter用GUI编写Tic Tac Toe游戏:

import numpy as np
import Tkinter as tk

class Game:
    def __init__(self, master, player1, player2):
        frame = tk.Frame()
        frame.grid()
        self.master = master
        self.player1 = player1
        self.player2 = player2
        self.current_player = player1
        self.empty_text = ""
        self.board = Board()

        self.buttons = [[None for _ in range(3)] for _ in range(3)]
        for i in range(3):
            for j in range(3):
                self.buttons[i][j] = tk.Button(frame, height=3, width=3, text=self.empty_text, command=lambda i=i, j=j: self.callback(self.buttons[i][j]))
                self.buttons[i][j].grid(row=i, column=j)

        self.reset_button = tk.Button(text="Reset", command=self.reset)
        self.reset_button.grid(row=3)

    def callback(self, button):
        if button["text"] == self.empty_text:
            button.configure(text=self.current_player.mark)
            info = button.grid_info()
            move = (info["row"], info["column"])
            self.board.place_mark(move, self.current_player.mark)
            if self.board.over():
                print "The game is over. The player with mark %s won!" % self.current_player.mark
                self.master.quit()
            else:
                self.switch_players()

    def reset(self):
        print "Resetting..."
        self.master.destroy()
        self = Game(self.master, self.player1, self.player2)

    def switch_players(self):
        if self.current_player == self.player1:
            self.current_player = self.player2
        else:
            self.current_player = self.player1


class Board:
    def __init__(self, grid=np.ones((3,3))*np.nan):
        self.grid = grid

    def winner(self):
        rows = [self.grid[i,:] for i in range(3)]
        cols = [self.grid[:,j] for j in range(3)]
        diag = [np.array([self.grid[i,i] for i in range(3)])]
        cross_diag = [np.array([self.grid[2-i,i] for i in range(3)])]
        lanes = np.concatenate((rows, cols, diag, cross_diag))      # A "lane" is defined as a row, column, diagonal, or cross-diagonal

        any_lane = lambda x: any([np.array_equal(lane, x) for lane in lanes])   # Returns true if any lane is equal to the input argument "x"
        if any_lane(np.ones(3)):
            return 1
        elif any_lane(np.zeros(3)):
            return 0

    def over(self):
        return (not np.any(np.isnan(self.grid))) or (self.winner() is not None)

    def place_mark(self, pos, mark):
        num = self.mark2num(mark)
        self.grid[tuple(pos)] = num

    def mark2num(self, mark):
        if mark == "X":
            return 1
        elif mark == "O":
            return 0
        else:
            print "The player's mark must be either 'X' or 'O'."


class HumanPlayer:
    def __init__(self, mark):
        self.mark = mark


root = tk.Tk()
app = Game(root, player1=HumanPlayer(mark="X"), player2=HumanPlayer(mark="O"))
root.mainloop()

我第一次玩游戏时一切都很顺利:按钮标签按预期更改并宣布获胜者(见下文)。

enter image description here enter image description here

问题在于当我按下"重置"按钮,虽然我再次得到一个空白的GUI,Game仍然认为'结束并继续打印获胜者的声明:

enter image description here enter image description here

是否可以重新初始化'该类没有将每个属性重置为其初始值?

1 个答案:

答案 0 :(得分:0)

最后,我只是做了一本手册'重置相关属性而不是重新实例化'班级。以下是生成的代码:

import numpy as np
import Tkinter as tk

class Game:
    def __init__(self, master, player1, player2):
        frame = tk.Frame()
        frame.grid()
        self.master = master
        self.player1 = player1
        self.player2 = player2
        self.current_player = player1
        self.empty_text = ""
        self.board = Board()

        self.buttons = [[None for _ in range(3)] for _ in range(3)]
        for i in range(3):
            for j in range(3):
                self.buttons[i][j] = tk.Button(frame, height=3, width=3, text=self.empty_text, command=lambda i=i, j=j: self.callback(self.buttons[i][j]))
                self.buttons[i][j].grid(row=i, column=j)

        self.reset_button = tk.Button(text="Reset", command=self.reset)
        self.reset_button.grid(row=3, column=0)

        self.quit_button = tk.Button(text="Quit", command=self.quit)
        # self.quit_button.grid(row=3, column=1)

        self.setup_UI()

    def setup_UI(self):
        self.master.title="Tic Tac Toe"


    def callback(self, button):
        if self.board.over():
            pass
        elif button["text"] == self.empty_text:
            button.configure(text=self.current_player.mark)
            info = button.grid_info()
            move = (info["row"], info["column"])
            self.board.place_mark(move, self.current_player.mark)
            if self.board.over():
                print "The game is over. The player with mark %s won!" % self.current_player.mark
            else:
                self.switch_players()

    def reset(self):
        print "Resetting..."
        for i in range(3):
            for j in range(3):
                self.buttons[i][j].configure(text=self.empty_text)
        self.board = Board(grid=np.ones((3,3))*np.nan)
        self.current_player = self.player1

    def quit(self):
        self.master.destroy()

    def switch_players(self):
        if self.current_player == self.player1:
            self.current_player = self.player2
        else:
            self.current_player = self.player1


class Board:
    def __init__(self, grid=np.ones((3,3))*np.nan):
        self.grid = grid

    def winner(self):
        rows = [self.grid[i,:] for i in range(3)]
        cols = [self.grid[:,j] for j in range(3)]
        diag = [np.array([self.grid[i,i] for i in range(3)])]
        cross_diag = [np.array([self.grid[2-i,i] for i in range(3)])]
        lanes = np.concatenate((rows, cols, diag, cross_diag))      # A "lane" is defined as a row, column, diagonal, or cross-diagonal

        any_lane = lambda x: any([np.array_equal(lane, x) for lane in lanes])   # Returns true if any lane is equal to the input argument "x"
        if any_lane(np.ones(3)):
            return 1
        elif any_lane(np.zeros(3)):
            return 0

    def over(self):
        return (not np.any(np.isnan(self.grid))) or (self.winner() is not None)

    def place_mark(self, pos, mark):
        num = self.mark2num(mark)
        self.grid[tuple(pos)] = num

    def mark2num(self, mark):
        if mark == "X":
            return 1
        elif mark == "O":
            return 0
        else:
            print "The player's mark must be either 'X' or 'O'."


class HumanPlayer:
    def __init__(self, mark):
        self.mark = mark


root = tk.Tk()
root.title("Tic Tac Toe")
app = Game(root, player1=HumanPlayer(mark="X"), player2=HumanPlayer(mark="O"))
root.mainloop()

下面的屏幕抓点显示了我多次设法玩Tic Tac Toe。

enter image description here