2016-05-24 3 views
-1

Ich habe etwas von einer KI entworfen, um 2048 zu spielen. Ich möchte den Spielstatus nach jedem Zug anzeigen, den die KI macht. Um dies zu tun, habe ich eine GUI mit Tkinter erstellt. Das erste Mal mit Tkinter, und wie der Titel suggeriert, scheint es, als ob meine "updateDisplay" -Methode den Aufruf des Aufrufs von mainloop() blockiert. Jede Hilfe wäre willkommen.
Die GUI wird angezeigt, wenn ich den Anruf zu self.after(1000, self.updateDisplay(ai, game)) entferne. Allerdings wird es dann natürlich nichtTkinter Hauptschleife() nicht ausgeführt - Python

aktualisieren
class GameGrid(Frame): 
    def __init__(self,ai, game): 
     Frame.__init__(self) 
     self.game = game 
     self.ai = ai 
     self.grid() 
     self.master.title('2048') 

     #self.gamelogic = gamelogic 

     self.grid_cells = [] 
     self.init_grid() 
     self.update_grid_cells() 
     self.after(1000, self.updateDisplay(ai, game)) 
     self.mainloop() 


    def updateDisplay(self, ai, game): 
     game.move(ai.nextMove(4)) 
     print "hello" 
     for i in range(GRID_LEN): 
      for j in range(GRID_LEN): 
       new_number = int(game.state[i][j]) 
       if new_number == 0: 
        self.grid_cells[i][j].configure(text="", bg=BACKGROUND_COLOR_CELL_EMPTY) 
       else: 
        self.grid_cells[i][j].configure(text=str(new_number), bg=BACKGROUND_COLOR_DICT[new_number], fg=CELL_COLOR_DICT[new_number]) 
     if game.over: 
      if game.won: 
       print 'You Won!' 
      else: 
       print 'Game Over :(Score:', game.score 
      return 0 
     else: 
      print "test" 
      self.after(10000, self.updateDisplay(ai, game))    



if __name__ == "__main__": 
    game = Game() 
    ai = AlphaBetaRecursive(game) 
    gui = GameGrid(ai, game) 
+0

Vielleicht ruft [ 'update_idletasks()'] (http://infohost.nmt.edu/tcc/help/pubs/ tkinter/web/universal.html) in regelmäßigen Abständen irgendwo in 'updateDisplay()' könnte helfen. Es ist nicht klar, wo die Update-Funktion den größten Teil ihrer Zeit auf Basis dessen, was Sie bisher veröffentlicht haben, ausgibt. – martineau

+0

@martineau Danke für die Antwort. Ich habe nicht den ganzen Code gepostet, um es einfach zu halten. 'updateDisplay()' macht sofort einen Zug, druckt 'hallo' und' test' und ruft sich selbst wieder auf, scheinbar ohne einen gewissen Zeitraum zu warten – user3636636

+0

Sie wissen, dass Sie eine Verzögerung von 10 Sekunden haben) 'Aufruf innerhalb der' updateDisplay' Funktion, richtig? Auch das richtige, was man es nennen würde, wäre 'self.after (1000, self.updateDisplay, self.ai, self.game)' - sonst rufst du es direkt im 'after()' Call selbst an. – martineau

Antwort

2

Wenn Sie das tun self.after(1000, self.updateDisplay(ai, game)), bist du self.updateDisplay sofort und nicht das Bestehen der Funktion als Argument an after aufrufen. Sie müssen die inneren Klammern loswerden! Laut der Dokumentation, after braucht extra *args, aber es sagt nicht wirklich, was mit ihnen gemacht wird (vielleicht sind sie an den Rückruf übergeben? Ich bin mir nicht sicher). Da ai und game bereits Attribute von self sind, müssen Sie sie nicht wirklich als Argumente übergeben. Verwenden Sie einfach:

self.after(1000, self.updateDisplay) 

und die Definition von updateDisplay ändern:

def updateDisplay(self): 
    # use self.ai and self.game rather than ai and game in the implementation of the function 
    ... 
+0

Danke! Das hat funktioniert. Ich habe eine peinliche Zeit damit verbracht, das herauszufinden. Danke nochmal – user3636636

+1

Die zusätzlichen Argumente werden an den Rückruf weitergeleitet. Es ist absolut sicher, 'self.after (1000, self.updateDisplay, ai, game) zu tun, obwohl es keinen Sinn macht, Objektattribute zwischen Methoden derselben Klasse zu übergeben. –