2017-05-01 10 views
0

これは私の初めての質問ですので、私にご負担ください。 私は、プレイヤーが勝ったときと勝ったときにあなたに知らせることになっている2人のプレイヤーのためのチック・タック・トー・ゲームを書こうとしています。 ゲームはうまくいったが、OOPでやってみたところ、動作が停止した。ご覧のとおり、私はまだそれほど新しくなく、概念を完全に把握していません。 TkInterは私が以前に働いたことのないものです。tkinterボタンがイベント機能を呼び出さない

__init__機能の前後にクリック機能を入れてみましたが、どちらも機能しません。

from tkinter import * 
from tkinter.font import Font 
import tkinter.messagebox 

turn = True 
playerX = False #If True, Player X won 
playerO = False #If True, Player O won 
try: 
    while True: 
     class Game(): 
      def click(self, button): 
       global turn 
       global playerX 
       global playerO 
       ########## Test whether button is blank and then inserts 'X' 
       if(button["text"]=="" and turn == True): 
        button["text"]= "X" 
        if(button_1["text"]=="X" and button_2["text"]=="X" and button_3["text"]=="X" or 
         button_4["text"]=="X" and button_5["text"]=="X" and button_6["text"]=="X" or 
         button_7["text"]=="X" and button_8["text"]=="X" and button_9["text"]=="X" or 
         button_1["text"]=="X" and button_5["text"]=="X" and button_9["text"]=="X" or 
         button_3["text"]=="X" and button_5["text"]=="X" and button_7["text"]=="X" or 
         button_1["text"]=="X" and button_4["text"]=="X" and button_7["text"]=="X" or 
         button_2["text"]=="X" and button_5["text"]=="X" and button_8["text"]=="X" or 
         button_3["text"]=="X" and button_6["text"]=="X" and button_9["text"]=="X"): 
         tkinter.messagebox.showinfo(title="Congrats", message="Player X won!") 
         self.root.update() 
         playerX = True 
         exit() 
        self.root.title("Player O") 
        turn=False 
       ########### Test whether button is blank and then inserts 'O' 
       elif(button["text"]=="" and turn == False): 
        button["text"] = "O" 
        if(button_1["text"]=="O" and button_2["text"]=="O" and button_3["text"]=="O" or 
         button_4["text"]=="O" and button_5["text"]=="O" and button_6["text"]=="O" or 
         button_7["text"]=="O" and button_8["text"]=="O" and button_9["text"]=="O" or 
         button_1["text"]=="O" and button_5["text"]=="O" and button_9["text"]=="O" or 
         button_3["text"]=="O" and button_5["text"]=="O" and button_7["text"]=="O" or 
         button_1["text"]=="O" and button_4["text"]=="O" and button_7["text"]=="O" or 
         button_2["text"]=="O" and button_5["text"]=="O" and button_8["text"]=="O" or 
         button_3["text"]=="O" and button_6["text"]=="O" and button_9["text"]=="O"): 
         tkinter.messagebox.showinfo(title="Congrats", message="Player O won!") 
         self.root.update() 
         playerO = True 
         exit() 
        self.root.title("Player X") 
        turn = True 

      def __init__(self): 
       self.root = Tk() 

       self.root.title("Tic-Tac-Toe") 
       self.root.resizable(width=False, height=False) 
       self.root.font = Font(family="Times 80", size=80) 

       button_1 = Button(self.root, text = "", height = 6, width = 12, command = lambda: self.click) 
       button_2 = Button(self.root, text = "", height = 6, width = 12, command = lambda: self.click) 
       button_3 = Button(self.root, text = "", height = 6, width = 12, command = lambda: self.click) 
       button_4 = Button(self.root, text = "", height = 6, width = 12, command = lambda: self.click) 
       button_5 = Button(self.root, text = "", height = 6, width = 12, command = lambda: self.click) 
       button_6 = Button(self.root, text = "", height = 6, width = 12, command = lambda: self.click) 
       button_7 = Button(self.root, text = "", height = 6, width = 12, command = lambda: self.click) 
       button_8 = Button(self.root, text = "", height = 6, width = 12, command = lambda: self.click) 
       button_9 = Button(self.root, text = "", height = 6, width = 12, command = lambda: self.click) 


       button_1.grid(row=0) 
       button_2.grid(row=0, column=1) 
       button_3.grid(row=0, column=2) 
       button_4.grid(row=1) 
       button_5.grid(row=1, column=1) 
       button_6.grid(row=1, column=2) 
       button_7.grid(row=2) 
       button_8.grid(row=2, column=1) 
       button_9.grid(row=2, column=2) 


     play = Game() 
     play.root.mainloop() 


except: 
    tkinter.messagebox.showinfo(title="Error", message="Sorry there was an error!") 
+0

私はこれがstackoverflowのトピックではないと信じていますが、http://codereview.stackexchange.comで答えられると思います。 –

答えて

1

command = lambda: self.clickあなたが建設Button sが効果的にも、これと同等の無名の機能をそれぞれの束作成するときに使用している。このように書き出されたときに、より簡単に見ることができるように

def _(): 
    return self.click 

を、何も除い起こりません返されるクラスインスタンスのclickメソッドの場合しかし、何が起こる必要があるのは、コールバックが発生したときにメソッド)が返されることです(返される内容は無視されます)。

つまり、問題を解決する代わりにcommand=lambda: self.click()を使用してください。

しかし、そのような機能は、コールバックプロセス - それだけで直接、すべてのことから、再び最後に括弧なし(command=self.clickとメソッドを指定する方が良いだろう意味にオーバーヘッドを追加することを除いて何でもの多くを達成していませんtkinterは、割り当てられた値がパラメータなしで呼び出し可能なものであることを要求します)。そうすることで、何もせずに別の関数を呼び出すという不必要な費用を避けることができます。

@Novelのおかげで、これを否定できない明白な最適化がコメントでわかりました。

+0

引数を指定しないと、ラムダを使用する意味はありません。ちょうど 'command = self.click'を使用してください。 – Novel

+0

@ノベル:非常に良い点、ありがとう。 – martineau

1

あなたは多くの問題があります。

最初に、tkinter(およびすべてのGUI)にGUIを実行するメインループがあるため、CLIの場合と同様にwhile Trueループは必要ありません。 mainloop()に電話すると、そのループが始まります。

ボタン(または任意の変数)を複数の方法(__init__であなたのケースをクリック)で使いたい場合は、それらの名前を "self"にする必要があります。前面に。これらは「インスタンス変数」と呼ばれ、グローバル変数の代わりにクラスが使用するものです。

クラス定義を他のものにネストする必要はありません。 tryブロックを使用したい場合は、クラスインスタンスをtryブロックに入れてください。

ラムダを使用する場合は、末尾に()を追加して関数を呼び出す必要があります。人々は通常、引数を持つ関数を呼び出すためにラムダを使います。たとえば、lambda: self.click(1)です。ここで

が固定あなたのコードです:いくつかの改善のために

from tkinter import * 
from tkinter.font import Font 
import tkinter.messagebox 

class Game(): 
    def click(self, button_idx): 
     button = self.buttons[button_idx] 
     ########## Test whether button is blank and then inserts 'X' 
     if(button["text"]=="" and self.turn == True): 
      button["text"]= "X" 
      if(self.button_1["text"]=="X" and self.button_2["text"]=="X" and self.button_3["text"]=="X" or 
       self.button_4["text"]=="X" and self.button_5["text"]=="X" and self.button_6["text"]=="X" or 
       self.button_7["text"]=="X" and self.button_8["text"]=="X" and self.button_9["text"]=="X" or 
       self.button_1["text"]=="X" and self.button_5["text"]=="X" and self.button_9["text"]=="X" or 
       self.button_3["text"]=="X" and self.button_5["text"]=="X" and self.button_7["text"]=="X" or 
       self.button_1["text"]=="X" and self.button_4["text"]=="X" and self.button_7["text"]=="X" or 
       self.button_2["text"]=="X" and self.button_5["text"]=="X" and self.button_8["text"]=="X" or 
       self.button_3["text"]=="X" and self.button_6["text"]=="X" and self.button_9["text"]=="X"): 
       tkinter.messagebox.showinfo(title="Congrats", message="Player X won!") 
       self.root.update() 
       self.playerX = True 
       self.root.quit() 
      self.root.title("Player O") 
      self.turn=False 
     ########### Test whether button is blank and then inserts 'O' 
     elif(button["text"]=="" and self.turn == False): 
      button["text"] = "O" 
      if(self.button_1["text"]=="O" and self.button_2["text"]=="O" and self.button_3["text"]=="O" or 
       self.button_4["text"]=="O" and self.button_5["text"]=="O" and self.button_6["text"]=="O" or 
       self.button_7["text"]=="O" and self.button_8["text"]=="O" and self.button_9["text"]=="O" or 
       self.button_1["text"]=="O" and self.button_5["text"]=="O" and self.button_9["text"]=="O" or 
       self.button_3["text"]=="O" and self.button_5["text"]=="O" and self.button_7["text"]=="O" or 
       self.button_1["text"]=="O" and self.button_4["text"]=="O" and self.button_7["text"]=="O" or 
       self.button_2["text"]=="O" and self.button_5["text"]=="O" and self.button_8["text"]=="O" or 
       self.button_3["text"]=="O" and self.button_6["text"]=="O" and self.button_9["text"]=="O"): 
       tkinter.messagebox.showinfo(title="Congrats", message="Player O won!") 
       self.root.update() 
       self.playerO = True 
       self.root.quit() 
      self.root.title("Player X") 
      self.turn = True 

    def __init__(self): 
     self.root = Tk() 
     self.turn = True 
     self.playerX = False #If True, Player X won 
     self.playerO = False #If True, Player O won 

     self.root.title("Tic-Tac-Toe") 
     self.root.resizable(width=False, height=False) 
     self.root.font = Font(family="Times 80", size=80) 

     self.button_1 = Button(self.root, text = "", height = 6, width = 12, command = lambda: self.click(0)) # python is zero-indexed, so 0 is the first button 
     self.button_2 = Button(self.root, text = "", height = 6, width = 12, command = lambda: self.click(1)) 
     self.button_3 = Button(self.root, text = "", height = 6, width = 12, command = lambda: self.click(2)) 
     self.button_4 = Button(self.root, text = "", height = 6, width = 12, command = lambda: self.click(3)) 
     self.button_5 = Button(self.root, text = "", height = 6, width = 12, command = lambda: self.click(4)) 
     self.button_6 = Button(self.root, text = "", height = 6, width = 12, command = lambda: self.click(5)) 
     self.button_7 = Button(self.root, text = "", height = 6, width = 12, command = lambda: self.click(6)) 
     self.button_8 = Button(self.root, text = "", height = 6, width = 12, command = lambda: self.click(7)) 
     self.button_9 = Button(self.root, text = "", height = 6, width = 12, command = lambda: self.click(8)) 

     self.button_1.grid(row=0) 
     self.button_2.grid(row=0, column=1) 
     self.button_3.grid(row=0, column=2) 
     self.button_4.grid(row=1) 
     self.button_5.grid(row=1, column=1) 
     self.button_6.grid(row=1, column=2) 
     self.button_7.grid(row=2) 
     self.button_8.grid(row=2, column=1) 
     self.button_9.grid(row=2, column=2) 

     self.buttons = [self.button_1, self.button_2, self.button_3, self.button_4, self.button_5, self.button_6, self.button_7, self.button_8, self.button_9] 

play = Game() 
play.root.mainloop() 

、なぜあなたは、ボタンを定義するためにループを使用していませんか?場合は、functools.partialではなく、lambdaを使用してコマンドを設定する必要があります。また、self.buttonsリストを使ってチェックを行うこともできます。また、多くのコードを繰り返します。 XやOが勝ったかどうかを確認できる動的な関数を作ってみませんか?

+0

2番目の段落に '__init__'と入力したところで書式を修正する必要があります。アンダースコアをエスケープしない限り、stackoverflowは "init"という単語を太字にしたいと考えています。 –

関連する問題