Wie rufe ich eine Funktion, die nicht innerhalb der Klasse ist?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
NoBody2
User
Beiträge: 12
Registriert: Mittwoch 8. November 2017, 01:49

Ich habe eine Klasse MyApp, in der ich eine Funktion namens "add" rufen möchte, die allerdings nicht in der Klasse drin ist. Wie mache ich das?
Die Klasse:

Code: Alles auswählen

class MyApp(tkinter.Frame):
    
    
    def __init__(self, master):
        super().__init__(master)
        self.pack()
        ...
        
    def funktionen(z):
        add(False, DasSpielfeld, z)
        add(True, DasSpielfeld, Start(True, DasSpielfeld, 5) )
    Eingabe=input("Wo?")
    funktionen(Eingabe)
     
und außerhalb der Klasse ist add:

Code: Alles auswählen

def add(S12, Spielfeld, x):
    a=0
    while Spielfeld[x][a]!=0:
        a+=1
    if S12==True:
        Spielfeld[x][a]=1
    else:
        Spielfeld[x][a]=2
Benutzeravatar
noisefloor
User
Beiträge: 3854
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

wo liegt denn `add`? In der gleichen Datei? Oder wird es importiert?

Grundsätzlich sollte der oben gezeigt Code funktionieren... Die Frage ist aber, warum `add` nicht Teil der Klasse sein darf, ist doch scheinbar ein Baustein der Spiellogik. Oder bist du gerade dabei, dein Projekt zu modularisieren und kommst nicht weiter?

Wieso ist `Eingabe=input("Wo?")` und `funktionen(Eingabe)` Teil der Klasse? In Klassen sollte sowas nicht vorkommen, sondern alles in Methoden stehen.

Gruß, noisefloor
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@NoBody2: wie sieht die Struktur Deines Programms aus? DasSpielfeld scheint eine globale Variable zu sein. Gibt es eine extra Spielfeld-Klasse, wo solche Dinge wie `add` drinstehen sollten? Diese Spielfeldklasse sollte dann ein Attribut von `MyApp` sein.

Halte Dich bitte an die Namenskonvention, das hilft Dir und anderen auch später noch den Code zu lesen, denn Namen wie S12 sind so kryptisch, dass man nur mit viel Wissen weiß, für was das S oder die 12 steht. Variablennamen werden komplett klein geschrieben.
NoBody2
User
Beiträge: 12
Registriert: Mittwoch 8. November 2017, 01:49

hier ist mal mein vollständiger Code:

Code: Alles auswählen

import time
import tkinter
import numpy as np

class MyApp(tkinter.Frame):
    """
    Klasse, gedacht für das Anzeigen des Spiels
    Es geht um ein Programm, dass einem einen Vorschlag für Vier-Gewinnt geben soll. Es ist sehr uneffizient, das weiß ich, es ist auch mein erstes 	
    Programm.
    """
    def __init__(self, master):
        super().__init__(master)
        self.pack()
	
	# Wenn ihr mir sagen könnt, wie ich das kürzer aufschreiben kann, wäre ich dankbar
        self.label = tkinter.Label(self)
        self.label.pack()
        self.label["text"] = "Vier Gewinnt\nComputerprogramm"
    	
    	# einfach ein Rahmen um die Buttons
        f1 = tkinter.Frame(self)
        f1.pack(fill='x',ipady=30)

	# Sie sollten dazu da sein, dass ich eingeben kann, was der Gegner bzw. ich mache. Die Funktion geht aber nicht.
        self.button1 = tkinter.Button(f1)
        self.button1.place(x=42, y=20)
        self.button1["text"] = "1"
        #self.button1["command"] = funktionen(0)

        self.button2 = tkinter.Button(f1)
        self.button2.place(x=142, y=20)
        self.button2["text"] = "2"
        #self.button2["command"] = funktionen(1)

        self.button3 = tkinter.Button(f1)
        self.button3.place(x=242, y=20)
        self.button3["text"] = "3"
        #self.button3["command"] = funktionen(2)

        self.button4 = tkinter.Button(f1)
        self.button4.place(x=342, y=20)
        self.button4["text"] = "4"
        #self.button4["command"] = funktionen(3)

        self.button5 = tkinter.Button(f1)
        self.button5.place(x=442, y=20)
        self.button5["text"] = "5"
        #self.button5["command"] = funktionen(4)

        self.button6 = tkinter.Button(f1)
        self.button6.place(x=542, y=20)
        self.button6["text"] = "6"
        #self.button6["command"] = funktionen(5)

        self.button7 = tkinter.Button(f1)
        self.button7.place(x=642, y=20)
        self.button7["text"] = "7"
        #self.button1["command"] = funktionen(6)
        
        # Das Zeichnen des Feldes
        self.cv=tkinter.Canvas(self, width=700, height=600)
        self.cv.pack()
        self.cv.create_line(100,0,100,600, width=3)
        self.cv.create_line(200,0,200,600, width=3)
        self.cv.create_line(300,0,300,600, width=3)
        self.cv.create_line(400,0,400,600, width=3)
        self.cv.create_line(500,0,500,600, width=3)
        self.cv.create_line(600,0,600,600, width=3)

        
        self.cv.create_line(0,100,700,100, width=3)
        self.cv.create_line(0,200,700,200, width=3)
        self.cv.create_line(0,300,700,300, width=3)
        self.cv.create_line(0,400,700,400, width=3)
        self.cv.create_line(0,500,700,500, width=3)

    # damit die Buttons mit einer Methode alles erledigen, weil ich nicht weiß, wie man Buttons mehrere Methoden zuweist
    def funktionen(z):
        add(False, DasSpielfeld, z)
        add(True, DasSpielfeld, Start(True, DasSpielfeld, 5) )
        
    # Ich habe es versucht außerhalb zu machen, ich wusste aber nicht wo, da das aber die Buttons übernehmen sollten, sollte das ignoriert werden
    #Eingabe=input("Wo?")
    #funktionen(Eingabe)
        

# Zeichnet die gesetzten Steine in das Canvas-Widget ein
def paint(app):
    for i in range(7):
        for j in range(6):
            # 1 steht für 1. Spieler, also ich, 2 steht für den 2. Spieler, also den Gegner
            # Ich habe X und der Gegner hat Kreis
            if DasSpielfeld[i][j]==1:
                app.cv.create_line(100*i+15,600-100*j-15 , 100*i+85,600-100*j-85 , width=5)
                app.cv.create_line(100*i+15,600-100*j-85 , 100*i+85,600-100*j-15 , width=5)
            if DasSpielfeld[i][j]==2:
                app.cv.create_oval(100*i+15,600-100*j-85 , 100*i+85,600-100*j-15 , width=5)
                
# erste Zahl ist Spalte, zweite ist Zeile
DasSpielfeld = np.zeros((7,6))

# setzt die Steine in die jeweilige Spalte des übergenenen Spielfelds, S12 steht für Spieler 1/2: True=Spieler 1->1, False=Spieler 2->2
def add(S12, Spielfeld, x):
        a=0
        # sucht höchstes leeres Feld in der Spalte und setzt Stein, falls nicht möglich (Spalte voll): return False
        try:
            while Spielfeld[x][a]!=0:
                a+=1
            if S12==True:
                Spielfeld[x][a]=1
            else:
                Spielfeld[x][a]=2
            return True
        except:
            return False

# Überprüft, ob durch das letzte Setzen ein Sieg entstand, Spielfeld ist das übergebene Spielfeld, x ist die Spalte, O ist Spieler (True=1, False=2)
def Überprüfung(Spielfeld, x,O):
    if O==True:
        O=1
    else:
        O=2
        
    # sucht höchsten Stein in der Spalte
    y=0
    try:
        while Spielfeld[x][y]!=0:
            y+=1
    except:
        pass
    y-=1
    
    # Überprüfung wenkrecht nach unten
    try:
        if Spielfeld[x][y]==O and Spielfeld[x][y-1]==O and Spielfeld[x][y-2]==O and Spielfeld[x][y-3]==O:
            return True
    except:
        pass
    
    for i in range(4):
    # Überprüfung waagrecht, max. 4 Möglichkeiten (gesetzte Stein kann der 1./2./3. oder 4. Stein der Reihe sein)
        try:
            if Spielfeld[x-3+i][y]==O and Spielfeld[x-2+i][y]==O and Spielfeld[x-1+i][y]==O and Spielfeld[x+i][y]==O:
                return True
        except:
            pass
    # Schräg oben: von unten links nach oben rechts
        try:
            if Spielfeld[x-3+i][y-3+i]==O and Spielfeld[x-2+i][y-2+i]==O and Spielfeld[x-1+i][y-1+i]==O and Spielfeld[x+i][y+i]==O:
                return True
        except:
            pass
    # Schräg unten: von oben links nach unten rechts
        try:
            if Spielfeld[x-3+i][y+3-i]==O and Spielfeld[x-2+i][y+2-i]==O and Spielfeld[x-1+i][y+1-i]==O and Spielfeld[x+i][y-i]==O:
                return True
        except:
            pass
    return False

# Die Methoden zum herausfinden des besten Zugs für die eingestellte Tiefe
# S12 ist wieder welcher Spieler (True=Ich=1, False=Gegner=2), DasSpielfeld ist das übergebene Spielfeld, Tiefe ist die Anzahl der Züge 
# (Tiefe=Anzahl meiner Züge)
def Start(S12, DasSpielfeld, Tiefe):                            # Start-Funktion
    MeineMöglichkeiten=list(range(7))                           #    Möglichkeitenliste
    for i in range(7):                                          # für alle 7 I-Fälle
        Spielfeld=DasSpielfeld.copy()                           #    originales Spielfeld kopieren
        if add(S12, Spielfeld, i)==True:                                  #    mache I-Züge
            if Überprüfung(Spielfeld, i, S12)==True:                #    Gewinn mit einem Zug?
                return i                                            #      -> Zug zurückgeben
        else:
            MeineMöglichkeiten.remove(i)
            continue
        for j in MeineMöglichkeiten:                                      #    für alle 7 G-Züge 
            spiel=Spielfeld.copy()                              #       Spielfeld mit I-Zug kopieren
            add(not S12, spiel, j)                              #       darauf G-Zug machen
            if Überprüfung(spiel, j, not S12)==True:            #       Niederlage durch G-Zug bei diesem I-Zug möglich?
                MeineMöglichkeiten.remove(i)                    #         -> I-Zug aus Möglichkeitenliste entfernen
                break
    if not MeineMöglichkeiten:                              #    alle I-Züge führen zu Niederlage?
        return False                                        #      -> False zurückgeben
                                                                #
    if Tiefe<1:                                                 #  Tiefe erreicht?
        return False                                            #    -> aufhören, False zurückgeben
                                                                #
    for k in MeineMöglichkeiten:                                # für alle I-Möglichkeiten
        print(k)
        Spielfeld=DasSpielfeld.copy()                           #    originales Spielfeld kopieren
        add(S12, Spielfeld, k)                                  #    mache I-Züge
        AnzahlTrue=0                                            #    Anzahl der True
        for l in range(7):                                      #    für alle G-Züge
            spiel=Spielfeld.copy()                              #       Spielfeld mit I-Zug kopieren
            if add(not S12, spiel, l)==True:                              #       darauf G-Zug machen
                if Spieler(S12, spiel, Tiefe-1)==True:              #       Neue Schleife, Sieg?
                    AnzahlTrue+=1                                   #         -> AnzahlTrue erhöhen
            else:
                AnzahlTrue+=1
        if AnzahlTrue==7:                                       #    wenn alle G-Zweige Sieg sind
            return k                                            #      -> Sieg, I-Zug zurückgeben
    return False                                                # ???

def Spieler(S12, DasSpielfeld, Tiefe):                          # Schleifen-Funktion 
    MeineMöglichkeiten=list(range(7))                           #    Möglichkeitenliste
    for i in range(7):                                          # für alle 7 I-Fälle
        Spielfeld=DasSpielfeld.copy()                           #    originales Spielfeld kopieren
        if add(S12, Spielfeld, i)==True:                                  #    mache I-Züge
            if Überprüfung(Spielfeld, i, S12)==True:                #    Gewinn mit einem Zug?
                return True                                         #      -> Sieg, True zurückgeben
        else:
            MeineMöglichkeiten.remove(i)
            continue
        for j in MeineMöglichkeiten:                                      #    für alle 7 G-Züge 
            spiel=Spielfeld.copy()                              #       Spielfeld mit I-Zug kopieren
            add(not S12, spiel, j)                              #       darauf G-Zug machen
            if Überprüfung(spiel, j, not S12)==True:            #       Niederlage durch G-Zug bei diesem I-Zug möglich?
                MeineMöglichkeiten.remove(i)                    #         -> I-Zug aus Möglichkeitenliste entfernen
                break
    if not MeineMöglichkeiten:                              #    alle I-Züge führen zu Niederlage?
        return False                                        #      -> False zurückgeben
    if Tiefe<1:                                                 #    if Tiefe<1:                                                 #  Tiefe erreicht?
        return False                                            #    -> aufhören, False zurückgeben
                                                                #
    for k in MeineMöglichkeiten:                                # für alle I-Möglichkeiten
        Spielfeld=DasSpielfeld.copy()                           #    originales Spielfeld kopieren
        add(S12, Spielfeld, k)                                  #    mache I-Züge
        AnzahlTrue=0                                            #    Anzahl der True
        for l in range(7):                                      #    für alle G-Züge
            spiel=Spielfeld.copy()                              #       Spielfeld mit I-Zug kopieren
            if add(not S12, spiel, l)==True:                              #       darauf G-Zug machen
                if Spieler(S12, spiel, Tiefe-1)==True:              #       Neue Schleife, Sieg?
                    AnzahlTrue+=1                                   #         -> AnzahlTrue erhöhen
            else:
                AnzahlTrue+=1
        if AnzahlTrue==7:                                       #    wenn alle G-Zweige Sieg sind
            return True                                         #      -> Sieg, I-Zug zurückgeben
    return False                                                # False zurückgeben
            


                       
# kleines Testspiel mit mittelschweren Computer-Gegner im Internet, nach diesem Stand kam die erste Aussage, wo ich etwas setzen muss
# 0 ist erste Spalte
add(True, DasSpielfeld, 3)
add(False, DasSpielfeld, 2)
add(False, DasSpielfeld, 1)
add(False, DasSpielfeld, 3)
add(True, DasSpielfeld, 2)
add(True, DasSpielfeld, 3)
add(True, DasSpielfeld, 3)
add(False, DasSpielfeld, 3)
add(True, DasSpielfeld, 3)
add(False, DasSpielfeld, 2)
add(True, DasSpielfeld, 2)
add(False, DasSpielfeld, 4)
add(True, DasSpielfeld, 4)
add(False, DasSpielfeld, 5)
add(True, DasSpielfeld, 6)
add(False, DasSpielfeld, 4)
add(True, DasSpielfeld, 4)
add(False, DasSpielfeld, 2)


root = tkinter.Tk()
app = MyApp(root)
paint(app)
print(Start(True, DasSpielfeld, 5))
app.mainloop()
So, und wo ich gerade hänge ist das Übergeben der Einfüg-Befehle an die Buttons.
Und die Ausgabe des Programms. Kann ich ein kleines Text-Fenster rechts vom Feld machen, wo die ganzen Ausgaben, die in der Shell wären, reingeschrieben werden?
Antworten