2016-08-10 22 views
0

ゲームをプレイするクラスGameがあるとします。ゲームが終了したら、すぐに新しいゲームを開始したいと思います。自分自身のクラス定義内に新しいGame()をインスタンス化することで、これが再帰的に可能であると考えました。これは可能ですか?具体的な例を与えることをPythonでクラスを再初期化する方法

、私はTkinterのを使用してGUIでチックタックトーゲームを書いている:

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

は、それが再初期化 'は、その初期値に各属性をリセットすることなくクラスには可能ですか?

+0

新しいインスタンスを作成しますか? –

+2

'ゲーム'インスタンスをクリアしましたが、 '勝った 'ロジックが存在する' Board'はクリアされていません。 – ballsatballsdotballs

答えて

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() 

下の画面のグラブは、私はチックタックトー数回プレイするために管理方法を示しています。

enter image description here