Hilfe bei programmierten Spiel

Fragen zu Tkinter.
Antworten
flooo
User
Beiträge: 1
Registriert: Samstag 18. Februar 2017, 13:48

Hallo,

für die Schule muss ich ein kleines Spiel programmieren: zwei zufällige Zahlen werden angezeigt und müssen multipliziert werden, wofür man 15 Sekunden Zeit hat. Bei jeder richtigen Rechnung erhöht sich der Punktstand um 1, bei einer falschen Eingabe oder bei Ablauf der Zeit wird er auf 0 zurückgesetzt. Der folgende Quelltext funktioniert leider nicht so, wie er sollte, aber ich finde auch keinen Fehler... Ich hoffe, mir kann jemand helfen und ich bedanke mich schonmal im Voraus! :)

Code: Alles auswählen

from tkinter import *
from random import randint
tkFenster = Tk()
tkFenster.title('Spiel')
tkFenster.geometry('400x350')
bildhg=PhotoImage(file="tafel.gif")
canvasHintergrund=Canvas(master=tkFenster)
canvasHintergrund.place(x=0, y=0, width=410, height=510)
canvasHintergrund.create_image(0, 0, image=bildhg, anchor='nw')

ergebnis=None
vltErgeb=None
rueckmeldung=None
m=0
p=None

    

def RechnungUeber():
    if vltErgeb==ergebnis:
        rueckmeldung='Richtig!'
        rueck=Label(master=canvasHintergrund, text=rueckmeldung, bg='#1FD97F', font=('Arial', 90))
        rueck.place(x=20, y=90, width=365, height=80)
        m=m+1
        p=1
        tkFenster.after(3000, spiel)
        
        
    if vltErgeb!=ergebnis:
        rueckmeldung='Falsch!'
        rueck=Label(master=canvasHintergrund, text=rueckmeldung, bg='#D91F1F', font=('Arial', 90))
        rueck.place(x=20, y=90, width=365, height=80)
        m=0
        p=1
        tkFenster.after(3000, spiel)
        
    
def Zeitum():
     rueckmeldung='Vorbei!'
     rueck=Label(master=canvasHintergrund, text=rueckmeldung, bg='#D91F1F', font=('Arial', 90))
     rueck.place(x=20, y=90, width=365, height=80)
     m=0
     tkFenster.after(3000, spiel)
 

if p!=1:
    tkFenster.after(15000, Zeitum)

def spiel():
    p=0
    zufall1=randint(2,20)
    zufall2=randint(2,20)
    ueberschrift = Label(master=canvasHintergrund, text='Speed-Rechnen', fg='#A9282D', bg= '#4F9F4B', font=('Arial', 42))
    ueberschrift.place(x=40, y=5, width=320, height=50)
    rechnung1 = Label(master=canvasHintergrund, text= zufall1, bg='#4B76CD', font=('Arial', 90))
    rechnung1.place(x=20, y=90, width=130, height=80)
    rechnung2 = Label(master=canvasHintergrund, text= 'x', bg='#4B76CD', font=('Arial', 90))
    rechnung2.place(x=145, y=90, width=50, height=80)
    rechnung3 = Label(master=canvasHintergrund, text= zufall2, bg='#4B76CD', font=('Arial', 90))
    rechnung3.place(x=195, y=90, width=100, height=80)
    rechnung4 = Label(master=canvasHintergrund, text= '=', bg='#4B76CD', font=('Arial', 90))
    rechnung4.place(x=295, y=90, width=90, height=80)
    highscore= Label(master=canvasHintergrund, text='Punktzahl:', bg='#F4E800')
    highscore.place(x=20, y=250, width=70, height=25)
    mm=Label(master=canvasHintergrund, text=m, bg='#F4E800')
    mm.place(x=90, y=250, height=25)
    buttonbest = Button(master=canvasHintergrund, text='Okay', command=RechnungUeber)
    buttonbest.place(x=300, y=250)
    entryergeb = Entry(master=canvasHintergrund)
    entryergeb.place(x=230, y=250, width=70)
    vltErgeb = entryergeb.get()
    ergebnis = (zufall1*zufall2)

tkFenster.after(0, spiel)    

tkFenster.mainloop()
Zuletzt geändert von Anonymous am Samstag 18. Februar 2017, 14:03, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@flooo: Da gibt es nicht *den* Fehler den man mal kurz beheben könnte, das funktioniert grundsätzlich nicht so. Für GUI-Programmierung braucht man objektorientierte Programmierung (OOP), weil Du hier Zustand über Funktionsaufrufe, also dann Methodenaufrufe hinweg, brauchst. Und bei GUI-Programmierung kommt dann zur OOP auch nicht ereignisbasierte Programmierung hinzu.

Bevor man sich an eigene Klassen wagt, muss man Funktionen verstanden haben. Du erwartest in einigen der Funktionen offenbar das lokale Namen gar nicht lokal sind, sondern Zuweisungen Namen auf Modulebene an neue Werte binden. Tun sie nicht, und vor allem *sollten* sie auch nicht!

Auf Modulebene sollten zudem keine Variablen oder Programm stehen. Da gehört nur Code hin der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Namen sollten dem Leser vermitteln was der Wert im Programm bedeutet. `m` und `p` tun das ganz sicher nicht und auch kryptische Abkürzungen wie `vltErgeb` sollte man vermeiden.

Was ist `p`? Wenn das nur 0 oder 1 werden kann, dann hat das nicht nur einen falschen Namen, sondern es werden auch die falschen Werte an den Namen gebunden. Für Wahrheitswerte hat Python den Datentyp `bool` mit den Werten `False` und `True`, da sollte man keine Zahlen für missbrauchen.

Beim Programmablauf sind Fehler. Das Ablaufen der Zeit wird nur einmal ”in Auftrag” gegeben, danach nie wieder. Und das auch noch auf Modulebene, versteckt zwischen zwei Funktionsdefinitionen. Das ist unübersichtlich.

`spiel()` erstellt alle möglichen Anzeige- und Eingabeelemente in der GUI und fragt dann auch gleich sofort nach dem erstellen des Eingabefelds für die Antwort den Inhalt ab. Da hatte der Benutzer ja noch gar keine Zeit überhaupt etwas einzugeben, also ist das an der Stelle *immer* die leere Zeichenkette. Und die wird an einen lokalen Namen gebunden und nie wieder verwendet. Selbst wenn das alles an der Stelle so funktionieren würde wie Du denkst: An anderer Stelle vergleichst Du die Eingabe vom Benutzer, eine Zeichenkette, mit dem Produkt der beiden Zufallszahlen, eine Zahl, und eine Zeichenkette und eine Zahl sind niemals gleich. Python wandelt an der Stelle nicht auf automagisch die Datentypen um.

Wenn es diese Fehler nicht gäbe, dann bliebe noch das Problem das Du alle möglichen GUI-Elemente immer wieder neu erstellst, und so in der GUI immer mehr und mehr Elemente übereinander gezeichnet werden, was Speicher und Zeit verbraucht obwohl Du die meisten Elemente weder brauchst, noch siehst. Bei GUIs erstellt man solche Elemente in der Regel *einmal* am Anfang und ändert dann im Programmverlauf deren Inhalt entsprechend.
Antworten