Ergebnisse auswerten und Schleife weiterlaufen lassen

Fragen zu Tkinter.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

Das offensichtliche ist ja, alle Ein- und Ausgaben durch GUI-Elemente zu ersetzen.
Also aus

Code: Alles auswählen

            bruch = Bruch()
            bruch.ausgabe()
            bruch.kuerze_bruch()
            bruch.ausgabe()
            z = eingaberoutine(bruch)
            print (z)
            self.statistik(z,anzahl)
müssen drei Teile werden:
1. einen neuen Bruch erzeugen und diesen in der GUI anzeigen (also Labelinhalte entsprechend setzen).
2. Du brauchst Eingabefelder und einen Ok-Button und beim Druch auf Ok muß die Eingabe geprüft werden (also die Schleife in eingaberoutine kann so auch nicht bestehen bleiben).
3. Statistik: das ist ja auch nur eine Ausgabe, also das setzen von entsprechenden Labelinhalten.
Cortez
User
Beiträge: 115
Registriert: Montag 31. Dezember 2018, 15:28

Ok, vielen Dank für den Input.

Die statistikfunktion lassen wir vielleicht erstmal beiseite und gehen Schritt für Schritt vor.

Das Hauptfenster soll 5 Buttons haben (einfache Aufgabe, schwere Aufgaben, Speedrechnen, Highscore einsehen, Ende).

Darüber hinaus den "OK" Button, von dem du sprachst.

Zur Anzeige / Eingabe der einfachen Aufgabe stehen entsprechend Labels und Entries zur Verfügung.

Namen und Anzahl der Aufgaben würde ich zu Testzwecken mal fix vorgeben. Das könnte man dann in einem weiteren Schritt per Eingabefeld regeln.

Ich codiere mal so weit und würde den Code dann später posten, wenn ich soweit bin. Dann lässt sich sicher am Besten erkennen, wo der Hund begraben liegt.
Cortez
User
Beiträge: 115
Registriert: Montag 31. Dezember 2018, 15:28

So, hier mal mein Code bis jetzt. Ich habe als Start jetzt mal so programmiert, dass beim Klick auf den entsprechenden Button einfach ein Bruch erzeugt und anschließend mit der entsprechenden Methode gekürzt wird.
Aber schon hier gibts Probleme:

Gebe ich ein bruch.kuerze_bruch() ein, erhalte ich die Fehlermedung: kuerze_bruch() missing 1 required positional argument: 'self'

Was bitte soll da übergeben werden?

Kommentiere ich diese Funktion aus, erhalte ich folgende Fehlermeldung:AttributeError: type object 'Bruch' has no attribute 'zähler'

HÄ? Selbstverständlich existiert dieses attribut, wie sich aus der Klasse unschwer ersehen lässt.

EDIT: Habe dafür den Fehler gefunden. Beim Objekterzeugen hat eine Klammer gefehlt.

Hier dennoch mal der Code:

Code: Alles auswählen

import tkinter
import random
import math
import time
import sys




def vorzeichenwahl():    
    return random.choice("+-*/")

def eingaberoutine(bruch):
    ergebnis_zaehler = 0
    ergebnis_nenner = 0
        
    for i in range(1,4):
        ergebnis_zaehler = int(zähler_eingabe.get())
        ergebnis_nenner = int(nenner_eingabe.get())
    
        if ergebnis_zaehler == bruch.zähler and ergebnis_nenner == bruch.nenner:
            print ("richtig. Sie brauchten der Versuche ", i)
            return i
            
        elif (ergebnis_zaehler != bruch.zähler or ergebnis_nenner != bruch.nenner) and i == 3:
            print ("Zu viele Versuche, nämlich ",i,)
            return i
        else:
            print ("falsch")
            
def hole_zeit():
    startzeit = int(round(time.time(),0))
    zielzeit = startzeit +10
    return startzeit,zielzeit

class Spiel:
    def __init__(self):
        #self.anzahl = anzahl
        #self.typ = typ
        self.korrekte_Aufgaben = 0
        self.falsche_Aufgaben = 0
        #self.name = input ("Dein Name?")
        self.name = "Max Mustermann"
        
            
    def speedrechnen(self,hs):
        startzeit,zielzeit = hole_zeit()
        z = 0
        while startzeit < zielzeit:
            #print (startzeit)
            y=self.leichte_aufgabe(1)
            startzeit = int(round(time.time(),0))
            #time.sleep(1)
            if y == True:
                z+=1
            print ("Startzeit: ",startzeit)
            print ("Zielzeit: ",zielzeit)
        print ("Sie haben innerhalb ", zielzeit - startzeit," ",z," Aufgaben gelöst")
        
        hs.dateieintrag(self.name,z)
            
            
    def leichte_aufgabe(self,anzahl):
        for j in range(0, anzahl):
            bruch = Bruch()
            bruch.ausgabe()
            bruch.kuerze_bruch()
            bruch.ausgabe()
            z = eingaberoutine(bruch)
            print (z)
            self.statistik(z,anzahl)
            if (z == 1 and anzahl == 1) or j == anzahl:
                return True
            
            
    def schwere_aufgabe(self, anzahl):
        for j in range(0,anzahl):
            vorzeichen = vorzeichenwahl()
            bruch1 = Bruch()
            bruch2 = Bruch()
            if vorzeichen == "+":
                print (bruch1, " + ",bruch2)
                ergebnis_zaehler,ergebnis_nenner=bruch1.addiere(bruch2)
            elif vorzeichen == "-":
                print (bruch1, " - ", bruch2)
                ergebnis_zaehler,ergebnis_nenner=bruch1.subtrahiere(bruch2)
            elif vorzeichen == "*":
                print (bruch1, " * ", bruch2)
                ergebnis_zaehler,ergebnis_nenner=bruch1.multipliziere(bruch2)
            else:
                print (bruch1, " / ", bruch2)
                ergebnis_zaehler,ergebnis_nenner=bruch1.dividiere(bruch2)
            
            bruch = Bruch(ergebnis_zaehler,ergebnis_nenner)
            bruch.kuerze_bruch()
            bruch.ausgabe()
            z = eingaberoutine(bruch)
            self.statistik(z, anzahl)
            
                
       
    def statistik(self, z, anzahl):
        if z == 1:
            
            self.korrekte_Aufgaben += 1
        elif z == 2:
            
            self.falsche_Aufgaben += 1
        else:
            
            self.falsche_Aufgaben += 1
            
        if self.korrekte_Aufgaben + self.falsche_Aufgaben == anzahl:
            quote = round(self.korrekte_Aufgaben/anzahl*100,2)
            print ("Sie haben ", self.korrekte_Aufgaben, " von ", anzahl, " Aufgaben richtig geloest, also ", quote, " %")
            


class Bruch:
    def __init__(self,zähler=0,nenner=0):
        self.zähler=zähler
        self.nenner=nenner
        if zähler==0 or nenner ==0:
            wert_zähler = self.generiere_bruchzahl()
            wert_nenner = self.generiere_bruchzahl()
            self.zähler += wert_zähler
            self.nenner += wert_nenner
        
        prob = 2,2,2,2,3,3,3,5,5,7
        
    def __str__(self):
        return str(self.zähler) + "/" + str(self.nenner)
    
    def generiere_bruchzahl(self):
        prob = 2,2,2,2,3,3,3,5,5,7
        wert = 1
        #random.choice(prob)
        random.seed()
        anz = random.randint(2,5)
    
        for i in range(1,anz):
            wert *=random.choice(prob)
        #print (wert)
        
        return wert
    
    def kuerze_bruch(self):
        ggt = math.gcd(self.zähler,self.nenner)
        self.zähler = self.zähler // ggt
        self.nenner = self.nenner // ggt
        self.zähler = int(self.zähler)
        self.nenner = int(self.nenner)
        
    def mache_nennergleich(self,other):
        self.kuerze_bruch()
        other.kuerze_bruch()
        
        print (self)
        print (other)
        
        
        counter=1
        counter_b=1
    
        while self.nenner != other.nenner:
        
            if self.nenner < other.nenner:
                self.nenner += (self.nenner / counter)
                #print ("Nenner_a ", self.nenner)
                counter +=1
            
            if other.nenner < self.nenner:
                other.nenner += (other.nenner / counter_b)
                #print ("Nenner_b ", other.nenner)
                counter_b +=1
        
            if self.nenner == other.nenner:
                break
            
        self.zähler *= counter
        other.zähler *= counter_b
        self.nenner = int(self.nenner)
        other.nenner = int(other.nenner)
        return self, other
        
    def addiere(self,other):
        if self.nenner != other.nenner:
            self,other=self.mache_nennergleich(other)
        
        ergebnis = self.zähler + other.zähler
        nenner = self.nenner
        return ergebnis,nenner
        
    def subtrahiere(self, other):
        if self.nenner != other.nenner:
            self, other = self.mache_nennergleich(other)
    
        ergebnis = self.zähler -other.zähler
        nenner = self.nenner
        return ergebnis,nenner
    
    def multipliziere(self, other):
        self.kuerze_bruch()
        other.kuerze_bruch()
        
        erg_z = self.zähler*other.zähler
        erg_n = self.nenner*other.nenner
        return erg_z, erg_n
    
    def dividiere(self,other):
        self.kuerze_bruch()
        other.kuerze_bruch()
        
        erg_z = self.zähler*other.nenner
        erg_n = self.nenner*other.zähler
        return erg_z, erg_n
            
    def ausgabe(self):
        print (self.zähler, " / ", self.nenner)
        
        
class Highscore():
    #def __init__(self):
        
    def dateieintrag(self, name, z):
        lt = time.localtime()
        try:
            datei = open("rekorde.txt","a")
        except:
            print ("Konnte Datei nicht oeffnen")
            
        datei.write(name+" hat am " +time.strftime("%d.%m.%Y",lt) + " "+str(z)+" Aufgaben richtig" + "\n")
        datei.close()
        
        
        try:
            datei2 = open("daten.csv","a")
        except:
            print ("Konnte Datei nicht oeffnen")
            
        datei2.write(name + ";" + str(z) + "\n")
        datei2.close()
        
    def lesen(self):
        try:
            datei = open("rekorde.txt")
        except:
            print ("Dateizugriff nicht erfolgreich")
        allezeilen = datei.readlines()
        datei.close()
        such = " "


        print (f"{'Name':>11}{'Aufgaben':>30}")
        for zeile in allezeilen:
            anzahl = zeile.count(such)
            pos = zeile.find(such)
            anfpos = pos
            #print (anzahl, " ", pos)
            for i in range(1,5):
                #print (zeile)
                pos = zeile.find(such, pos+1)
                #print (pos)
            #print (zeile[0:anfpos], " ",zeile[pos-1], " Aufgaben")
            name = zeile[0:anfpos]
            zahl = zeile[pos-1]
            print (f"{zeile[0:anfpos]:>10}{int(zeile[pos-1]):20.0f}")
            
        try:
            datei2 = open("daten.csv")
        except:
            print ("Dateizugriff nicht erfolgreich")
            
        gesamt = datei2.read()
        datei2.close()
        
        zeilen=gesamt.split(chr(10))
        li = []
        for zeile in zeilen:
            zwliste = zeile.split(";")
            print (zwliste)
            li.append(zwliste)
            print (li)
        li2 = []
        for s in range(0,len(li)):
            sort = sorted(li[s])
            li2.append(sort)
            print (li2)
            
        li = sorted(li2)
        print (li)
        for p in range(len(li)-1,0,-1):
            print(f"{li[p][1]:<20}{int(li[p][0]):>2}")
            

def main():
    def typ1():
    #spiel = Spiel()
        #spiel.leichte_aufgabe(3)
        bruch = Bruch()
        bruch.kuerze_bruch()
        zähler_anzeige["text"] = str(bruch.zähler)
        nenner_anzeige["text"] = str(bruch.nenner)
        
    def typ2():
        pass
    
    def speedrechnen():
        pass
    
    def siehe_highscore():
        pass
        
    def ende():
        haupt.destroy()
    
    haupt = tkinter.Tk()


    framelinks = tkinter.Frame(haupt, width=50)
    #framelinks["bg"] = "#FF0000"
    framelinks.pack(side="left", pady=0)


    zähler_anzeige = tkinter.Label(framelinks, text = "3")
    zähler_anzeige["width"] = 2
    zähler_anzeige["height"] = 0
    zähler_anzeige["font"] = "Arial 70 bold"
    zähler_anzeige["bg"] = "cyan"
    zähler_anzeige["anchor"] = "s"
    zähler_anzeige.pack(pady = 30)

    bruchstrich = tkinter.Label(framelinks, text = "_____")
    bruchstrich["width"] = 0
    bruchstrich["height"] = 0
    bruchstrich["font"] = "Arial  40 bold"
    #bruchstrich["anchor"] = "n"
    bruchstrich.pack(pady = 0)

    nenner_anzeige = tkinter.Label(framelinks, text = "4")
    nenner_anzeige["width"] = 2
    nenner_anzeige["bg"] = "cyan"
    nenner_anzeige["height"] = 0
    nenner_anzeige["font"] = "Arial 70 bold"
    nenner_anzeige.pack(pady = 50)


    framemitte = tkinter.Frame(haupt, width=50)
    #framemitte["bg"] = "red"
    framemitte.pack(side="left",pady=0)

    istgleich = tkinter.Label(framemitte, text = "=")
    istgleich["font"] = "Arial 70 bold"
    istgleich["height"] = 0
    istgleich["bg"] = "white"
    istgleich["anchor"] = "n"
    istgleich.pack(padx = 20)

    framebuttons = tkinter.Frame(haupt, width=50)
    framebuttons.pack(side="right",pady=0)

    buttonende = tkinter.Button(framebuttons, text = "Ende", command = ende)
    buttonende.pack(pady=0)

    buttonaufgabe1 = tkinter.Button(framebuttons, text =" Kuerzen", command = typ1)
    buttonaufgabe1.pack(pady=0,side="left")
    
    buttonaufgabe2 = tkinter.Button(framebuttons, text = "Bruchrechnen", command = typ2)
    buttonaufgabe2.pack()
    
    buttonspeed = tkinter.Button(framebuttons, text = "Speedrechnen", command = speedrechnen)
    buttonspeed.pack()
    
    buttonhighscore = tkinter.Button(framebuttons, text = "Highscore ansehen", command = siehe_highscore)
    buttonhighscore.pack()

    framerechts = tkinter.Frame(haupt,width=500)
    framerechts.pack(side="left",pady=2)

    zähler_eingabe = tkinter.Entry(framerechts)
    zähler_eingabe["bg"] = "white"
    zähler_eingabe["font"] = "Arial 70 bold"
    zähler_eingabe["width"] = 2
    #zehler_eingabe["anchor"] = "center"
    zähler_eingabe.pack(padx = 20,pady = 0)

    bruchstrich2 = tkinter.Label(framerechts, text = "_____")
    bruchstrich2["width"] = 0
    bruchstrich2["height"] = 0
    bruchstrich2["font"] = "Arial  40 bold"
    #bruchstrich["anchor"] = "n"
    bruchstrich2.pack(pady = 30)

    nenner_eingabe = tkinter.Entry(framerechts)
    nenner_eingabe["bg"] = "white"
    nenner_eingabe["font"] = "Arial 70 bold"
    nenner_eingabe["width"] = 2
    #nenner_eingabe["anchor"] = "center"
    nenner_eingabe.pack(padx = 20,pady = 20)

    ausgabelabel = tkinter.Label(haupt, text = "ausgabe")
    ausgabelabel.pack()



    print ("Hauptprogramm")


    hs = Highscore()  
    #anzahl = int(input ("Wieviel Aufgaben?"))
    #typ = int(input ("Aufgabentyp?"))
    spiel = Spiel()
    haupt.mainloop()
    #if typ == 1:
        #spiel.leichte_aufgabe(anzahl)
    #elif typ == 2:
        #spiel.schwere_aufgabe(anzahl)
    #elif typ == 3:
        #hs = Highscore()
        #spiel.speedrechnen(hs)
        #hs.lesen()
        
    

if __name__ == '__main__':
    main()



#s = Spiel(5,1)
Soweit, sogut.

Nun habe ich eine OK-Button erstellt und möchte, dass beim Klick darauf die Ergebniskontrollroutine kommt. Aber das funktioniert nicht, weil das Objekt "bruch" nicht erkannt wird. Müsste ich daher die Variable "bruch" global setzen?

Hier mal der hinzugefügte Code:
buttonok = tkinter.Button(framebuttons, text = "OK", command = eingaberoutine(bruch))
Benutzeravatar
__blackjack__
User
Beiträge: 13111
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Cortez: ``global`` ist da gar nichts zu setzen. Grundsätzlich nicht!

`command` erwartet etwas Aufrufbares das kein Argument bekommt. Du rufst da `eingaberoutine()` auf und übergibst den *Rückgabewert* davon als `command`. Das geht nicht. Also das ginge nicht einmal wenn `bruch` definiert wäre.

Lokale Funktionen so wie in der `main()` macht man nicht. Du brauchst für die GUI eine Klasse. Und für die Programmlogik Code der keinen GUI-Code enthält. Deine `eingaberoutine()` fragt in einer Schleife immer wieder die gleichen Eingabeelemente ab — das funktioniert so nicht weil der Benutzer nie die Möglichkeit hat da andere Werte einzugeben, da werden also direkt hintereinander weg jedes mal die gleichen Werte abgefragt und verarbeitet bis die Versuche aufgebraucht sind.

GUI-Programmierung funktioniert wirklich komplett anders als der lineare Programmablauf bei einer Konsolananwendung. Ich denke nicht, dass es Sinn macht, dass Du versuchst den alten Code, der ja auch schon deutliche Probleme mit OOP hatte, jetzt irgendwie in eine GUI-Anwendung umzubauen. Die solltest Du besser von Grund auf neu schreiben. Oder zumindest mit dem Zwischenschritt die Konsolenanwendung zuerst einmal so umzuschreiben das es immer noch eine Konsolenanwendung ist, aber Programmlogik und Benutzerinteraktion komplett getrennt sind, und man ein Objekt mit der Programmlogik hat, das so gestaltet ist, dass man es sowohl von einer Konsolenanwendung als auch von einer GUI-Anwendung benutzen kann.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Cortez
User
Beiträge: 115
Registriert: Montag 31. Dezember 2018, 15:28

Ok, das sehe ich ein. Mein Programm scheint für den GUI-Gebrauch nicht geeignet zu sein. Also für diesen Zweck neumachen.

Das Problem, das ich dabei habe ist nur Folgendes: Wie kann man eigene Klassen (wie bei mir z.B. Bruch) in die GUI-Programmierung miteinbringen? Alles, was man so an Tutorials findet, erklärt lediglich, wie man Buttons mit Funktionen außerhalb von Klassen verknüpft-

Aber ich müsste ja mit einem Buttondruck Methoden der Klasse aufrufen. Und Übergabewerte (die Nutzereingaben) brauche ich ja auch...
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

Dafür hat man eine GUI-Klasse, die den Zustand enthält, bei Dir also ein Attribut spiel vom Typ Spiel. Aber dieses Spiel muß komplett über Methoden spielbar sein, ohne dass innerhalb der Klasse irgendwo direkt Nutzerabfragen stattfinden.
Cortez
User
Beiträge: 115
Registriert: Montag 31. Dezember 2018, 15:28

Ok, das bedeutet also, wenn ich dich recht verstanden habe, dass die GUI-Klasse sämtliche Interaktion mit dem Nutzer übernimmt. Die anderen Klassen (nenne ich einfach mal so) berechnen und verwerten usw., aber können selbst keine Nutzereingaben fordern.

Habe ich das so einigermaßen korrekt verstanden? Und ist die GUI-Klasse die mainloop-Funktion?
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

JA soweit richtig. Aber wie kann eine Klasse eine Funktion sein? Es gibt eine Funktion main, die erzeugt die GUI-Klasse und ruft zum Schluß auf der Tk-Instanz mainloop auf.
Cortez
User
Beiträge: 115
Registriert: Montag 31. Dezember 2018, 15:28

Hallo,

ich habe jetzt mal versucht, das Programm ein wenig GUI-freundlicher zu gestalten. Das Problem, das ich habe, ist nun, dass Datentypen (in meinem Fall Objekte der Klasse Bruch) sich von einer Funktion nicht in die andere übertragen lassen.

Ich hätte 2 Lösungsansätze, weiß aber nicht, ob die gut sind:

1.) In der init-Methode der Spiel-Klasse wird automatisch ein Bruch erzeugt, in dem dann auch das Ergebnis gespeichert wird.

2.) Ich lese die Ausgabe in den labels aus, erstelle daraus einen neuen Bruch und nehme diesen dann als Grundlage zur Ergebnisüberprüfung.

Ich nehme an, da gibts sicherlich bessere Möglichkeiten. Hier mal der Code bis hierher:

Code: Alles auswählen

import tkinter
import random
import sys
import os
import math

class Spiel:
    
    #Spiel spielen
    
    def __init__(self):
        # das Hauptfenster
        self.hauptfenster = tkinter.Tk()
        
        
    # definiere Darstellung des zu kürzenden Bruches
        self.framelinks = tkinter.Frame(self.hauptfenster, width = 50)
        self.framelinks.pack(side = "left", pady = 0)
        
        self.zähler_anzeige = tkinter.Label(self.framelinks, text = "3")
        self.zähler_anzeige["width"] = 2
        self.zähler_anzeige["height"] = 0
        self.zähler_anzeige["font"] = "Arial 70 bold"
        self.zähler_anzeige["bg"] = "cyan"
        self.zähler_anzeige["anchor"] = "s"
        self.zähler_anzeige.pack(pady = 30)
        
        self.bruchstrich = tkinter.Label(self.framelinks, text = "_____")
        self.bruchstrich["width"] = 0
        self.bruchstrich["height"] = 0
        self.bruchstrich["font"] = "Arial  40 bold"
        #bruchstrich["anchor"] = "n"
        self.bruchstrich.pack(pady = 0)
        
        self.nenner_anzeige = tkinter.Label(self.framelinks, text = "4")
        self.nenner_anzeige["width"] = 2
        self.nenner_anzeige["bg"] = "cyan"
        self.nenner_anzeige["height"] = 0
        self.nenner_anzeige["font"] = "Arial 70 bold"
        self.nenner_anzeige.pack(pady = 50)
        
        self.framemitte = tkinter.Frame(self.hauptfenster, width=50)
        #framemitte["bg"] = "red"
        self.framemitte.pack(side="left",pady=0)

        self.istgleich = tkinter.Label(self.framemitte, text = "=")
        self.istgleich["font"] = "Arial 70 bold"
        self.istgleich["height"] = 0
        self.istgleich["bg"] = "white"
        self.istgleich["anchor"] = "n"
        self.istgleich.pack(padx = 20)
        
        self.framerechts = tkinter.Frame(self.hauptfenster,width=500)
        self.framerechts.pack(side="left",pady=2)
        
        # Definition Ergebniseingabe
        
        self.zähler_eingabe = tkinter.Entry(self.framerechts)
        self.zähler_eingabe["bg"] = "white"
        self.zähler_eingabe["font"] = "Arial 70 bold"
        self.zähler_eingabe["width"] = 2
        #zehler_eingabe["anchor"] = "center"
        self.zähler_eingabe.pack(padx = 20,pady = 0)

        self.bruchstrich2 = tkinter.Label(self.framerechts, text = "_____")
        self.bruchstrich2["width"] = 0
        self.bruchstrich2["height"] = 0
        self.bruchstrich2["font"] = "Arial  40 bold"
        #bruchstrich["anchor"] = "n"
        self.bruchstrich2.pack(pady = 30)

        self.nenner_eingabe = tkinter.Entry(self.framerechts)
        self.nenner_eingabe["bg"] = "white"
        self.nenner_eingabe["font"] = "Arial 70 bold"
        self.nenner_eingabe["width"] = 2
        #nenner_eingabe["anchor"] = "center"
        self.nenner_eingabe.pack(padx = 20,pady = 20)
        
        
        # Definition Buttons
        
        self.framebuttons = tkinter.Frame(self.hauptfenster, width=50)
        self.framebuttons.pack(side="right",pady=0)

        self.buttonende = tkinter.Button(self.framebuttons, text = "Ende", command = self.ende)
        self.buttonende.pack(pady=0)

        self.buttonaufgabe1 = tkinter.Button(self.framebuttons, text =" Kuerzen", command = self.typ1)
        self.buttonaufgabe1.pack(pady=0,side="left")
    
        self.buttonaufgabe2 = tkinter.Button(self.framebuttons, text = "Bruchrechnen", command = self.typ2)
        self.buttonaufgabe2.pack()
        
        self.buttonspeed = tkinter.Button(self.framebuttons, text = "Speedrechnen", command = self.speedrechnen)
        self.buttonspeed.pack()
    
        self.buttonhighscore = tkinter.Button(self.framebuttons, text = "Highscore ansehen", command = self.siehe_highscore)
        self.buttonhighscore.pack()
    
        self.buttonok = tkinter.Button(self.framebuttons, text = "OK", command = self.ergebnisroutine)
        self.buttonok.pack()
        
        # Ausgabelabel
        self.infoausgabe = tkinter.Label(self.hauptfenster, text = " ", bg = "yellow", width = 50)
        self.infoausgabe.pack()
        
        # Anzeige des Hauptfensters
        self.hauptfenster.mainloop()
        
    def typ1(self):
        bruch = Bruch()
        self.zähler_anzeige["text"] = str(bruch.zähler)
        self.nenner_anzeige["text"] = str(bruch.nenner)
        bruch.kuerze_bruch()
        print (bruch)
        
        
    def typ2(self):
        pass
    
    def speedrechnen(self):
        pass
    
    def siehe_highscore(self):
        pass
        
    def ende(self):
        self.hauptfenster.destroy()
        
    def ergebnisroutine(self,bruch):
        print (bruch)
        
class Bruch:
    def __init__(self,zähler=0,nenner=0):
        self.zähler=zähler
        self.nenner=nenner
        if zähler==0 or nenner ==0:
            wert_zähler = self.generiere_bruchzahl()
            wert_nenner = self.generiere_bruchzahl()
            self.zähler += wert_zähler
            self.nenner += wert_nenner
        
        prob = 2,2,2,2,3,3,3,5,5,7
        
    def __str__(self):
        return str(self.zähler) + "/" + str(self.nenner)
    
    def generiere_bruchzahl(self):
        prob = 2,2,2,2,3,3,3,5,5,7
        wert = 1
        #random.choice(prob)
        random.seed()
        anz = random.randint(2,5)
    
        for i in range(1,anz):
            wert *=random.choice(prob)
        #print (wert)
        
        return wert
    
    def kuerze_bruch(self):
        ggt = math.gcd(self.zähler,self.nenner)
        self.zähler = self.zähler // ggt
        self.nenner = self.nenner // ggt
        self.zähler = int(self.zähler)
        self.nenner = int(self.nenner)
        
    def mache_nennergleich(self,other):
        self.kuerze_bruch()
        other.kuerze_bruch()
        
        print (self)
        print (other)
        
        
        counter=1
        counter_b=1
    
        while self.nenner != other.nenner:
        
            if self.nenner < other.nenner:
                self.nenner += (self.nenner / counter)
                #print ("Nenner_a ", self.nenner)
                counter +=1
            
            if other.nenner < self.nenner:
                other.nenner += (other.nenner / counter_b)
                #print ("Nenner_b ", other.nenner)
                counter_b +=1
        
            if self.nenner == other.nenner:
                break
            
        self.zähler *= counter
        other.zähler *= counter_b
        self.nenner = int(self.nenner)
        other.nenner = int(other.nenner)
        return self, other
        
    def addiere(self,other):
        if self.nenner != other.nenner:
            self,other=self.mache_nennergleich(other)
        
        ergebnis = self.zähler + other.zähler
        nenner = self.nenner
        return ergebnis,nenner
        
    def subtrahiere(self, other):
        if self.nenner != other.nenner:
            self, other = self.mache_nennergleich(other)
    
        ergebnis = self.zähler -other.zähler
        nenner = self.nenner
        return ergebnis,nenner
    
    def multipliziere(self, other):
        self.kuerze_bruch()
        other.kuerze_bruch()
        
        erg_z = self.zähler*other.zähler
        erg_n = self.nenner*other.nenner
        return erg_z, erg_n
    
    def dividiere(self,other):
        self.kuerze_bruch()
        other.kuerze_bruch()
        
        erg_z = self.zähler*other.nenner
        erg_n = self.nenner*other.zähler
        return erg_z, erg_n
            
    def ausgabe(self):
        print (self.zähler, " / ", self.nenner)
        
        

#Hauptprogramm
#if __name__ == '__main':
spiel = Spiel()
        
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Klasse Bruch hat immer noch die selben Fehler, die ich schon zu anfang angemerkt hatte.
Und wie schon geschrieben, ist __init__ zum Initialisieren da, nicht dass darin das ganze Programm läuft. Das mainloop hat darin nichts verloren.
Die ganzen Konfigurationen der Labels gibt man schon beim Erzeugen an.
Und warum ist das if-__main__ auskommentiert? Da fehlt auch noch die main-Funktion.
os und sys werden importiert, aber gar nicht benutzt.

Code: Alles auswählen

import tkinter
import random
import math

class Spiel:
    def __init__(self):
        # das Hauptfenster
        self.hauptfenster = tkinter.Tk()

        self.framelinks = tkinter.Frame(self.hauptfenster, width=50)
        self.framelinks.pack(side=tkinter.LEFT, pady=0)
        
        self.zähler_anzeige = tkinter.Label(self.framelinks,
            text="3", width=2, height=0, font="Arial 70 bold",
            bg="cyan", anchor="s")
        self.zähler_anzeige.pack(pady=30)
        
        self.bruchstrich = tkinter.Label(self.framelinks,
            text="_____", width=0, height=0, font="Arial 40 bold")
        self.bruchstrich.pack(pady=0)
        
        self.nenner_anzeige = tkinter.Label(self.framelinks,
            text="4", width=2, height=0, font="Arial 70 bold")
        self.nenner_anzeige.pack(pady=50)
        
        self.framemitte = tkinter.Frame(self.hauptfenster, width=50)
        self.framemitte.pack(side=tkinter.LEFT, pady=0)

        self.istgleich = tkinter.Label(self.framemitte,
            text="=", height=0, font="Arial 70 bold", bg="white",
            anchor=tkinter.N)
        self.istgleich.pack(padx=20)
        
        self.framerechts = tkinter.Frame(self.hauptfenster, width=500)
        self.framerechts.pack(side=tkinter.LEFT, pady=2)
        
        # Definition Ergebniseingabe
        self.zähler_eingabe = tkinter.Entry(self.framerechts,
            bg="white", font="Arial 70 bold",width=2)
        self.zähler_eingabe.pack(padx=20,pady=0)

        self.bruchstrich2 = tkinter.Label(self.framerechts,
            text="_____", width=0, height=0, font="Arial  40 bold")
        self.bruchstrich2.pack(pady=30)

        self.nenner_eingabe=tkinter.Entry(self.framerechts,
            bg="white", font="Arial 70 bold",width=2)
        self.nenner_eingabe.pack(padx = 20,pady = 20)
        
        
        # Definition Buttons
        self.framebuttons = tkinter.Frame(self.hauptfenster, width=50)
        self.framebuttons.pack(side="right",pady=0)

        self.buttonende = tkinter.Button(self.framebuttons, text = "Ende", command = self.ende)
        self.buttonende.pack(pady=0)

        self.buttonaufgabe1 = tkinter.Button(self.framebuttons, text =" Kuerzen", command = self.typ1)
        self.buttonaufgabe1.pack(pady=0,side="left")
    
        self.buttonaufgabe2 = tkinter.Button(self.framebuttons, text = "Bruchrechnen", command = self.typ2)
        self.buttonaufgabe2.pack()
        
        self.buttonspeed = tkinter.Button(self.framebuttons, text = "Speedrechnen", command = self.speedrechnen)
        self.buttonspeed.pack()
    
        self.buttonhighscore = tkinter.Button(self.framebuttons, text = "Highscore ansehen", command = self.siehe_highscore)
        self.buttonhighscore.pack()
    
        self.buttonok = tkinter.Button(self.framebuttons, text = "OK", command = self.ergebnisroutine)
        self.buttonok.pack()
        
        # Ausgabelabel
        self.infoausgabe = tkinter.Label(self.hauptfenster, text = " ", bg = "yellow", width = 50)
        self.infoausgabe.pack()
        
    ...

        

def main():
    spiel = Spiel()
    spiel.hauptfenster.mainloop()

#Hauptprogramm
if __name__ == '__main__':
    main()
Und weder 1 noch 2, denn es gibt Attribute, denen kann man auch neue Werte zuweisen.
Cortez
User
Beiträge: 115
Registriert: Montag 31. Dezember 2018, 15:28

Ok, sehe ich soweit ein. An der Klasse Bruch arbeite ich nach und nach.

Den Fehler habe ich erstmal gefunden. Habe das "self" vergessen - dann kanns mit den Attributen logischerweise nicht klappen.

Das mit der main- Funktion kann ich leider nicht nach deinem Vorschlag machen - dann bekomme ich aus irgendeinem Grund nichts mehr angezeigt. (wenn ich die auskommentierte Zeile nutze).

Nicht mal eine Fehlermeldung. Programm startet, aber ohne irgendeine Anzeige.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

Schau Dir genau die Schreibweise an.
Cortez
User
Beiträge: 115
Registriert: Montag 31. Dezember 2018, 15:28

So, bin heute wieder mal ein bisschen zum Programmieren gekommen.

Ich habs jetzt soweit hinbekommen, dass ein Bruch erzeugt wird und das Ergebnis (der gekürzte Bruch) wird dann überprüft.

Wenn ich mehrere Aufgaben hintereinander möchte, habe ich jetzt eine neue Funktion eingebaut: Sie überprüft, ob die Anzahl der Aufgaben erreicht ist und leitet nur dann zur Ergebnisroutine weiter, wenn dies nicht der Fall ist.
Leider scheitert es daran, dass ich aus dieser Kontrollfunktion die Ergebnisroutine nicht aufrufen kann. Er meint, dass self nicht definiert sei ...

Weiß jemand Abhilfe? Hier mal der Code:

Code: Alles auswählen

import tkinter
import random
import sys
import os
import math

class Spiel:
    
    #Spiel spielen
    
    def __init__(self):
        # das Hauptfenster
        self.hauptfenster = tkinter.Tk()
        
        
    # definiere Darstellung des zu kürzenden Bruches
        self.framelinks = tkinter.Frame(self.hauptfenster, width = 50)
        self.framelinks.pack(side = "left", pady = 0)
        
        self.zähler_anzeige = tkinter.Label(self.framelinks, text = "3")
        self.zähler_anzeige["width"] = 2
        self.zähler_anzeige["height"] = 0
        self.zähler_anzeige["font"] = "Arial 70 bold"
        self.zähler_anzeige["bg"] = "cyan"
        self.zähler_anzeige["anchor"] = "s"
        self.zähler_anzeige.pack(pady = 30)
        
        self.bruchstrich = tkinter.Label(self.framelinks, text = "_____")
        self.bruchstrich["width"] = 0
        self.bruchstrich["height"] = 0
        self.bruchstrich["font"] = "Arial  40 bold"
        #bruchstrich["anchor"] = "n"
        self.bruchstrich.pack(pady = 0)
        
        self.nenner_anzeige = tkinter.Label(self.framelinks, text = "4")
        self.nenner_anzeige["width"] = 2
        self.nenner_anzeige["bg"] = "cyan"
        self.nenner_anzeige["height"] = 0
        self.nenner_anzeige["font"] = "Arial 70 bold"
        self.nenner_anzeige.pack(pady = 50)
        
        self.framemitte = tkinter.Frame(self.hauptfenster, width=50)
        #framemitte["bg"] = "red"
        self.framemitte.pack(side="left",pady=0)

        self.istgleich = tkinter.Label(self.framemitte, text = "=")
        self.istgleich["font"] = "Arial 70 bold"
        self.istgleich["height"] = 0
        self.istgleich["bg"] = "white"
        self.istgleich["anchor"] = "n"
        self.istgleich.pack(padx = 20)
        
        self.framerechts = tkinter.Frame(self.hauptfenster,width=500)
        self.framerechts.pack(side="left",pady=2)
        
        # Definition Ergebniseingabe
        
        self.zähler_eingabe = tkinter.Entry(self.framerechts)
        self.zähler_eingabe["bg"] = "white"
        self.zähler_eingabe["font"] = "Arial 70 bold"
        self.zähler_eingabe["width"] = 2
        #zehler_eingabe["anchor"] = "center"
        self.zähler_eingabe.pack(padx = 20,pady = 0)

        self.bruchstrich2 = tkinter.Label(self.framerechts, text = "_____")
        self.bruchstrich2["width"] = 0
        self.bruchstrich2["height"] = 0
        self.bruchstrich2["font"] = "Arial  40 bold"
        #bruchstrich["anchor"] = "n"
        self.bruchstrich2.pack(pady = 30)

        self.nenner_eingabe = tkinter.Entry(self.framerechts)
        self.nenner_eingabe["bg"] = "white"
        self.nenner_eingabe["font"] = "Arial 70 bold"
        self.nenner_eingabe["width"] = 2
        #nenner_eingabe["anchor"] = "center"
        self.nenner_eingabe.pack(padx = 20,pady = 20)
        
        
        # Definition Buttons
        
        self.framebuttons = tkinter.Frame(self.hauptfenster, width=50)
        self.framebuttons.pack(side="right",pady=0)

        self.buttonende = tkinter.Button(self.framebuttons, text = "Ende", command = self.ende)
        self.buttonende.pack(pady=0)

        self.buttonaufgabe1 = tkinter.Button(self.framebuttons, text =" Kuerzen", command = self.typ1)
        self.buttonaufgabe1.pack(pady=0,side="left")
    
        self.buttonaufgabe2 = tkinter.Button(self.framebuttons, text = "Bruchrechnen", command = self.typ2)
        self.buttonaufgabe2.pack()
        
        self.buttonspeed = tkinter.Button(self.framebuttons, text = "Speedrechnen", command = self.speedrechnen)
        self.buttonspeed.pack()
    
        self.buttonhighscore = tkinter.Button(self.framebuttons, text = "Highscore ansehen", command = self.siehe_highscore)
        self.buttonhighscore.pack()
    
        self.buttonok = tkinter.Button(self.framebuttons, text = "OK", command = self.checkergebnis)
        self.buttonok.pack()
        
        # Ausgabelabel
        self.infoausgabe = tkinter.Label(self.hauptfenster, text = " ", bg = "yellow", width = 50)
        self.infoausgabe.pack()
        
        self.anzahl = 3
        self.aufgabenzähler = 0
        
    def typ1(self):
        self.bruch = Bruch()
        self.zähler_anzeige["text"] = str(self.bruch.zähler)
        self.nenner_anzeige["text"] = str(self.bruch.nenner)
        self.bruch.kuerze_bruch()
        print (self.bruch)
        
        
    def typ2(self):
        pass
    
    def speedrechnen(self):
        pass
    
    def siehe_highscore(self):
        pass
        
    def ende(self):
        self.hauptfenster.destroy()
        
    def checkergebnis(aufgabenzähler):
        if aufgabenzähler == 3:
            self.infoausgabe["text"] = "Alle Aufgaben gelöst"
        else:
            ergebnisroutine()
        
    def ergebnisroutine(self):
        ergebnis_zähler = 0
        ergebnis_nenner = 0
        try:
            ergebnis_zähler = int(self.zähler_eingabe.get())
            ergebnis_nenner = int(self.nenner_eingabe.get())
            #print (ergebnis_zähler)
                
        except:
            self.infoausgabe["text"] = "Bitte Zahl eingeben"
        #self.infoausgabe["text"] = str(ergebnis_zähler)
        else:
            self.infoausgabe["text"] = str(ergebnis_zähler)
            if ergebnis_zähler == self.bruch.zähler and ergebnis_nenner == self.bruch.nenner:
                self.infoausgabe["text"] = "richtig"
                self.aufgabenzähler +=1
                self.typ1()
            else:
                self.infoausgabe["text"] = "falsch"
        
class Bruch:
    def __init__(self,zähler=0,nenner=0):
        self.zähler=zähler
        self.nenner=nenner
        if zähler==0 or nenner ==0:
            wert_zähler = self.generiere_bruchzahl()
            wert_nenner = self.generiere_bruchzahl()
            self.zähler += wert_zähler
            self.nenner += wert_nenner
        
        prob = 2,2,2,2,3,3,3,5,5,7
        
    def __str__(self):
        return str(self.zähler) + "/" + str(self.nenner)
    
    def generiere_bruchzahl(self):
        prob = 2,2,2,2,3,3,3,5,5,7
        wert = 1
        #random.choice(prob)
        random.seed()
        anz = random.randint(2,5)
    
        for i in range(1,anz):
            wert *=random.choice(prob)
        #print (wert)
        
        return wert
    
    def kuerze_bruch(self):
        ggt = math.gcd(self.zähler,self.nenner)
        self.zähler = self.zähler // ggt
        self.nenner = self.nenner // ggt
        self.zähler = int(self.zähler)
        self.nenner = int(self.nenner)
        
    def mache_nennergleich(self,other):
        self.kuerze_bruch()
        other.kuerze_bruch()
        
        print (self)
        print (other)
        
        
        counter=1
        counter_b=1
    
        while self.nenner != other.nenner:
        
            if self.nenner < other.nenner:
                self.nenner += (self.nenner / counter)
                #print ("Nenner_a ", self.nenner)
                counter +=1
            
            if other.nenner < self.nenner:
                other.nenner += (other.nenner / counter_b)
                #print ("Nenner_b ", other.nenner)
                counter_b +=1
        
            if self.nenner == other.nenner:
                break
            
        self.zähler *= counter
        other.zähler *= counter_b
        self.nenner = int(self.nenner)
        other.nenner = int(other.nenner)
        return self, other
        
    def addiere(self,other):
        if self.nenner != other.nenner:
            self,other=self.mache_nennergleich(other)
        
        ergebnis = self.zähler + other.zähler
        nenner = self.nenner
        return ergebnis,nenner
        
    def subtrahiere(self, other):
        if self.nenner != other.nenner:
            self, other = self.mache_nennergleich(other)
    
        ergebnis = self.zähler -other.zähler
        nenner = self.nenner
        return ergebnis,nenner
    
    def multipliziere(self, other):
        self.kuerze_bruch()
        other.kuerze_bruch()
        
        erg_z = self.zähler*other.zähler
        erg_n = self.nenner*other.nenner
        return erg_z, erg_n
    
    def dividiere(self,other):
        self.kuerze_bruch()
        other.kuerze_bruch()
        
        erg_z = self.zähler*other.nenner
        erg_n = self.nenner*other.zähler
        return erg_z, erg_n
            
    def ausgabe(self):
        print (self.zähler, " / ", self.nenner)
        
        
def main():
    spiel = Spiel()
    spiel.hauptfenster.mainloop()


#Hauptprogramm
if __name__ == '__main__':
    main()
        
        
        
        
    
    
Antworten