Seite 1 von 1

Hilfe beim programmieren von Tic Tag toe

Verfasst: Freitag 24. Februar 2023, 16:25
von Anomym147
Hallo,
ich programmiere im Moment ein Tic Tac Toe Spiel und leider fehlt mir noch eine Funktion, die ich nicht hinbekomme. Ich möchte, dass der Computer nur Felder besetzt, die frei sind, das heißt, wo kein X oder O gesetzt wurde.
Ich bin mir sicher, dass es einfach ist, jedoch bin ich ein kompletter Anfänger und mag programmieren auch nicht besonders gern.
Wenn mir jemand helfen könnte und vielleicht auch Tipps zum verbessern des Programmes geben könnte, wäre ich sehr dankbar.


Hier ist der Code:

spiel_aktiv = True
aktiver = "X"
aktiver1= "O"
durchgang=0


spielfeld = [" ",
"1", "2", "3",
"4", "5", "6",
"7", "8", "9"]

def spielfeld_ausgeben():
print(spielfeld[1] + " " + spielfeld[2] + " " + spielfeld[3])
print(spielfeld[4] + " " + spielfeld[5] + " " + spielfeld[6])
print(spielfeld[7] + " " + spielfeld[8] + " " + spielfeld[9])

P="Partner"
C="Computer"
PC= input("Möchtest du gegen einen Partner oder gegen den Computer spielen?")
if (PC==P):
print("Der erste Spieler ist X. Der zweite ist O")

def spieler_wechsel(aktiver):
if aktiver == "X":
aktiver = "O"
else:
aktiver = "X"
return aktiver

def spieler_eingabe(aktiver):
spieler = int(input(f"Spieler {aktiver}: Welches Feld möchtest du besetzen?"))
if spielfeld[spieler] == "X" or spielfeld[spieler] == "O":
print("Dieses Feld ist besetzt, probiere ein anderes!")
spieler_eingabe(aktiver)
else:
spielfeld[spieler]=aktiver

def Gewinner(spiel_aktiv):

if spielfeld[1] == spielfeld[2] == spielfeld[3]:
print(f"Spieler {spielfeld[1]} hat gewonnen")
spiel_aktiv = False
if spielfeld[4] == spielfeld[5] == spielfeld[6]:
print(f"Spieler {spielfeld[4]} hat gewonnen")
spiel_aktiv = False
if spielfeld[7] == spielfeld[8] == spielfeld[9]:
print(f"Spieler {spielfeld[7]} hat gewonnen")
spiel_aktiv = False

if spielfeld[1] == spielfeld[4] == spielfeld[7]:
print(f"Spieler {spielfeld[1]} hat gewonnen")
spiel_aktiv = False
if spielfeld[2] == spielfeld[5] == spielfeld[8]:
print(f"Spieler {spielfeld[2]} hat gewonnen")
spiel_aktiv = False
if spielfeld[3] == spielfeld[6] == spielfeld[9]:
print(f"Spieler {spielfeld[3]} hat gewonnen")
spiel_aktiv = False

if spielfeld[1] == spielfeld[5] == spielfeld[9]:
print(f"Spieler {spielfeld[1]} hat gewonnen")
spiel_aktiv = False
if spielfeld[3] == spielfeld[5] == spielfeld[7]:
print(f"Spieler {spielfeld[3]} hat gewonnen")
spiel_aktiv = False
spiel_aktiv = unentschieden(spiel_aktiv)
return spiel_aktiv

def unentschieden(spiel_aktiv):
if (spielfeld[1] == "X" or spielfeld[1] == "O") \
and (spielfeld[2] == "X" or spielfeld[2] == "O") \
and (spielfeld[3] == "X" or spielfeld[3] == "O") \
and (spielfeld[4] == "X" or spielfeld[4] == "O") \
and (spielfeld[5] == "X" or spielfeld[5] == "O") \
and (spielfeld[6] == "X" or spielfeld[6] == "O") \
and (spielfeld[7] == "X" or spielfeld[7] == "O") \
and (spielfeld[8] == "X" or spielfeld[8] == "O") \
and (spielfeld[9] == "X" or spielfeld[9] == "O"):
print("Das Spiel ist unentschieden ausgefallen")
spiel_aktiv = False
return spiel_aktiv


spielfeld_ausgeben()

while spiel_aktiv:
spieler_eingabe(aktiver)
aktiver = spieler_wechsel(aktiver)
spiel_aktiv = Gewinner(spiel_aktiv)
spielfeld_ausgeben()
durchgang = durchgang + 1

if not spiel_aktiv:
print("Sie haben" ,durchgang, "durchgänge gebraucht, um zu gewinnen")

if (PC==C):
import random
z=random.randint(1,9)


def spieler_wechsel(aktiver):
if aktiver== "X":
aktiver= "O"
else:
aktiver = "X"
spielfeld[z]=aktiver1

return aktiver

def spieler_eingabe(aktiver):
spieler = int(input(f"Spieler {aktiver}: Welches Feld möchtest du besetzen?"))
if spielfeld[spieler] == "X" or spielfeld[spieler] == "O":
print("Dieses Feld ist besetzt, probiere ein anderes!")
spieler_eingabe(aktiver)
else:
spielfeld[spieler]=aktiver


def Gewinner(spiel_aktiv):
if spielfeld[1] == spielfeld[2] == spielfeld[3]:
print(f"Spieler {spielfeld[1]} hat gewonnen")
spiel_aktiv = False
if spielfeld[4] == spielfeld[5] == spielfeld[6]:
print(f"Spieler {spielfeld[4]} hat gewonnen")
spiel_aktiv = False
if spielfeld[7] == spielfeld[8] == spielfeld[9]:
print(f"Spieler {spielfeld[7]} hat gewonnen")
spiel_aktiv = False

if spielfeld[1] == spielfeld[4] == spielfeld[7]:
print(f"Spieler {spielfeld[1]} hat gewonnen")
spiel_aktiv = False
if spielfeld[2] == spielfeld[5] == spielfeld[8]:
print(f"Spieler {spielfeld[2]} hat gewonnen")
spiel_aktiv = False
if spielfeld[3] == spielfeld[6] == spielfeld[9]:
print(f"Spieler {spielfeld[3]} hat gewonnen")
spiel_aktiv = False

if spielfeld[1] == spielfeld[5] == spielfeld[9]:
print(f"Spieler {spielfeld[1]} hat gewonnen")
spiel_aktiv = False
if spielfeld[3] == spielfeld[5] == spielfeld[7]:
print(f"Spieler {spielfeld[3]} hat gewonnen")
spiel_aktiv = False
spiel_aktiv = unentschieden(spiel_aktiv)
return spiel_aktiv

def unentschieden(spiel_aktiv):
if (spielfeld[1] == "X" or spielfeld[1] == "O") \
and (spielfeld[2] == "X" or spielfeld[2] == "O") \
and (spielfeld[3] == "X" or spielfeld[3] == "O") \
and (spielfeld[4] == "X" or spielfeld[4] == "O") \
and (spielfeld[5] == "X" or spielfeld[5] == "O") \
and (spielfeld[6] == "X" or spielfeld[6] == "O") \
and (spielfeld[7] == "X" or spielfeld[7] == "O") \
and (spielfeld[8] == "X" or spielfeld[8] == "O") \
and (spielfeld[9] == "X" or spielfeld[9] == "O"):
print("Das Spiel ist unentschieden ausgefallen")
spiel_aktiv = False
return spiel_aktiv

spielfeld_ausgeben()

while spiel_aktiv:
spieler_eingabe(aktiver)
z=random.randint(1,9)
aktiver = spieler_wechsel(z)
spiel_aktiv = Gewinner(spiel_aktiv)
spiel_aktiv = unentschieden(spiel_aktiv)
spielfeld_ausgeben()
durchgang = durchgang + 1

Re: Hilfe beim programmieren von Tic Tag toe

Verfasst: Freitag 24. Februar 2023, 16:57
von grubenfox
Anomym147 hat geschrieben: Freitag 24. Februar 2023, 16:25 Wenn mir jemand helfen könnte und vielleicht auch Tipps zum verbessern des Programmes geben könnte, wäre ich sehr dankbar.
Bei Programmcode (und auch Ordnerstrukturen oder anderem Texten bei denen die Einrückungen wichtig sind), das ganze in code-Tags packen... oben im Editor der </> Knopf

Re: Hilfe beim programmieren von Tic Tag toe

Verfasst: Freitag 24. Februar 2023, 19:44
von Sirius3
Funktionen werden auf oberster Ebene definiert. Es ist selten sinnvoll, Funktionen in Abhängigkeit einer Bedingung zu definieren.
Zudem sind die Funktionsdefinitionen `spieler_eingabe`, `Gewinner` und `unentschieden` sind in beiden Zweigen identisch, `spieler_wechsel` fast identisch.
Alles was Funktionen brauchen, müssen sie über ihre Argumente bekommen, `spielfeld` fehlt aber meist. Dagegen ist `spiel_aktiv` ein Argument, das eigentlich überflüssig ist, weil immer `True`.
Der Code, der außerhalb von Funktionen steht, sollte auch in eine Funktion wandern.
Damit hätten wir als Zwischenstand:

Code: Alles auswählen

import random 

def spielfeld_ausgeben(spielfeld):
    print(spielfeld[1] + " " + spielfeld[2] + " " + spielfeld[3])
    print(spielfeld[4] + " " + spielfeld[5] + " " + spielfeld[6])
    print(spielfeld[7] + " " + spielfeld[8] + " " + spielfeld[9])


def spieler_wechsel(aktiver):
    if aktiver== "X":
        aktiver= "O"
    else:
        aktiver = "X"
    return aktiver


def spieler_eingabe(spielfeld, aktiver):
    spieler = int(input(f"Spieler {aktiver}: Welches Feld möchtest du besetzen?"))
    if spielfeld[spieler] == "X" or spielfeld[spieler] == "O":
        print("Dieses Feld ist besetzt, probiere ein anderes!")
        spieler_eingabe(aktiver)
    else:
        spielfeld[spieler]=aktiver


def Gewinner(spielfeld):
    if spielfeld[1] == spielfeld[2] == spielfeld[3]:
        print(f"Spieler {spielfeld[1]} hat gewonnen")
        return False
    if spielfeld[4] == spielfeld[5] == spielfeld[6]:
        print(f"Spieler {spielfeld[4]} hat gewonnen")
        return False
    if spielfeld[7] == spielfeld[8] == spielfeld[9]:
        print(f"Spieler {spielfeld[7]} hat gewonnen")
        return False

    if spielfeld[1] == spielfeld[4] == spielfeld[7]:
        print(f"Spieler {spielfeld[1]} hat gewonnen")
        return False
    if spielfeld[2] == spielfeld[5] == spielfeld[8]:
        print(f"Spieler {spielfeld[2]} hat gewonnen")
        return False
    if spielfeld[3] == spielfeld[6] == spielfeld[9]:
        print(f"Spieler {spielfeld[3]} hat gewonnen")
        return False 

    if spielfeld[1] == spielfeld[5] == spielfeld[9]:
        print(f"Spieler {spielfeld[1]} hat gewonnen")
        return False
    if spielfeld[3] == spielfeld[5] == spielfeld[7]:
        print(f"Spieler {spielfeld[3]} hat gewonnen")
        return False  
    return unentschieden(spielfeld)


def unentschieden(spielfeld):
    if (spielfeld[1] == "X" or spielfeld[1] == "O") \
    and (spielfeld[2] == "X" or spielfeld[2] == "O") \
    and (spielfeld[3] == "X" or spielfeld[3] == "O") \
    and (spielfeld[4] == "X" or spielfeld[4] == "O") \
    and (spielfeld[5] == "X" or spielfeld[5] == "O") \
    and (spielfeld[6] == "X" or spielfeld[6] == "O") \
    and (spielfeld[7] == "X" or spielfeld[7] == "O") \
    and (spielfeld[8] == "X" or spielfeld[8] == "O") \
    and (spielfeld[9] == "X" or spielfeld[9] == "O"):
        print("Das Spiel ist unentschieden ausgefallen")
        return False
    return True


def main():
    spiel_aktiv = True
    aktiver = "X"
    aktiver1 = "O"
    durchgang = 0

    spielfeld = [" ",
            "1", "2", "3",
            "4", "5", "6",
            "7", "8", "9"]

    P = "Partner"
    C = "Computer"
    PC = input("Möchtest du gegen einen Partner oder gegen den Computer spielen?")

    if (PC==P):
        print("Der erste Spieler ist X. Der zweite ist O")

        spielfeld_ausgeben(spielfeld)

        while spiel_aktiv:
            spieler_eingabe(spielfeld, aktiver)
            aktiver = spieler_wechsel(aktiver)
            spiel_aktiv = Gewinner(spielfeld)
            spielfeld_ausgeben(spielfeld)
            durchgang = durchgang + 1
        
        if not spiel_aktiv:
            print("Sie haben" ,durchgang, "durchgänge gebraucht, um zu gewinnen")
    else:
        z=random.randint(1,9)

        spielfeld_ausgeben(spielfeld)
        
        while spiel_aktiv:
            spieler_eingabe(spielfeld, aktiver)
            z=random.randint(1,9)
            aktiver = spieler_wechsel(z)
            spielfeld[z]=aktiver1
            spiel_aktiv = Gewinner(spielfeld)
            spielfeld_ausgeben(spielfeld)
            durchgang = durchgang + 1

if __name__ == "__main__":
    main()
Statt Code zu kopieren benutzt man Schleifen.

Code: Alles auswählen

def spielfeld_ausgeben(spielfeld):
    for i in [1, 4, 7]:
        print(" ".join(spielfeld[i:i+3]))


def Gewinner(spielfeld):
    for i in [1, 4, 7]:
        if spielfeld[i] == spielfeld[i+1] == spielfeld[i+2]:
            print(f"Spieler {spielfeld[i]} hat gewonnen")
            return False
    for i in [1, 2, 3]:
        if spielfeld[i] == spielfeld[i+3] == spielfeld[i+6]:
            print(f"Spieler {spielfeld[i]} hat gewonnen")
            return False
    if spielfeld[1] == spielfeld[5] == spielfeld[9]:
        print(f"Spieler {spielfeld[1]} hat gewonnen")
        return False
    if spielfeld[3] == spielfeld[5] == spielfeld[7]:
        print(f"Spieler {spielfeld[3]} hat gewonnen")
        return False  
    return unentschieden(spielfeld)


def unentschieden(spielfeld):
    if all(feld in ["X", "O"] for feld in spielfeld[1:]):
        print("Das Spiel ist unentschieden ausgefallen")
        return False
    return True
Es gibt selten Probleme, die man durch Rekursion einfacher schreiben kann. Eine Schleife ist meist besser:

Code: Alles auswählen

def spieler_eingabe(spielfeld, aktiver):
    while True:
        position = int(input(f"Spieler {aktiver}: Welches Feld möchtest du besetzen?"))
        if spielfeld[position] not in ["X", "O"]:
            break
        print("Dieses Feld ist besetzt, probiere ein anderes!")
    spielfeld[position]=aktiver
Listen sind in Python 0-Index-basiert. Das künstlich auf den 1-Index zu heben, ist eine schlechte Idee, weil man gegen die Sprache arbeitet.
Variablennamen und Funktionen werden generell komplett klein geschrieben. Funktionen sollten nach Tätigkeiten benannt werden.

Code: Alles auswählen

import random 


def spieler_wechsel(aktiver):
    if aktiver == "X":
        aktiver = "O"
    else:
        aktiver = "X"
    return aktiver


def spieler_eingabe(spielfeld, aktiver):
    while True:
        position = int(input(f"Spieler {aktiver}: Welches Feld möchtest du besetzen?")) - 1
        if spielfeld[position] not in ["X", "O"]:
            break
        print("Dieses Feld ist besetzt, probiere ein anderes!")
    spielfeld[position] = aktiver


def spielfeld_ausgeben(spielfeld):
    for i in [0, 3, 6]:
        print(" ".join(spielfeld[i:i+3]))


def gewinner_ermitteln(spielfeld):
    for i in [0, 3, 6]:
        if spielfeld[i] == spielfeld[i+1] == spielfeld[i+2]:
            print(f"Spieler {spielfeld[i]} hat gewonnen")
            return False
    for i in [0, 1, 2]:
        if spielfeld[i] == spielfeld[i+3] == spielfeld[i+6]:
            print(f"Spieler {spielfeld[1]} hat gewonnen")
            return False
    if spielfeld[0] == spielfeld[4] == spielfeld[8]:
        print(f"Spieler {spielfeld[4]} hat gewonnen")
        return False
    if spielfeld[2] == spielfeld[4] == spielfeld[6]:
        print(f"Spieler {spielfeld[4]} hat gewonnen")
        return False  
    if all(feld in ["X", "O"] for feld in spielfeld):
        print("Das Spiel ist unentschieden ausgefallen")
        return False
    return True


def main():
    spiel_aktiv = True
    aktiver = "X"
    aktiver1 = "O"
    durchgang = 0

    spielfeld = [
        "1", "2", "3",
        "4", "5", "6",
        "7", "8", "9"
    ]

    zweiter_spieler = input("Möchtest du gegen einen Partner oder gegen den Computer spielen?")

    if zweiter_spieler == "Partner":
        print("Der erste Spieler ist X. Der zweite ist O")

        spielfeld_ausgeben(spielfeld)

        while spiel_aktiv:
            spieler_eingabe(spielfeld, aktiver)
            aktiver = spieler_wechsel(aktiver)
            spiel_aktiv = gewinner_ermitteln(spielfeld)
            spielfeld_ausgeben(spielfeld)
            durchgang += 1
        
        if not spiel_aktiv:
            print(f"Sie haben {durchgang} Durchgänge gebraucht, um zu gewinnen")
    else:
        spielfeld_ausgeben(spielfeld)
        
        while spiel_aktiv:
            spieler_eingabe(spielfeld, aktiver)
            z = random.randint(0,8)
            aktiver = spieler_wechsel(z)
            spielfeld[z] = aktiver1
            spiel_aktiv = gewinner_ermitteln(spielfeld)
            spielfeld_ausgeben(spielfeld)
            durchgang += 1

if __name__ == "__main__":
    main()
Soweit hat sich an der Funktionalität nichts geändert.
Wenn wir uns aber Schleife für den Computer-Spieler anschauen, fallen ein paar Punkte auf:
`spieler_wechsel` mit z aufgerufen, so dass `aktiver` danach eine Zahl ist. Dabei sind X und O beim Computer-Spiel ja fix.
Bei `spieler_eingabe` prüfst Du, ob das Feld frei ist, das selbe mußt Du für den Computerspieler auch machen, auf die selbe Weise.
Da in einem Durchgang sowohl Spieler als auch Computer setzt, ist durchgang falsch und auch die Prüfung, ob jemand gewonnen hat, kommt eventuell zu spät.
Als erstes definieren wir eine Funktion

Code: Alles auswählen

def computer_eingabe(spielfeld, aktiver):
    while True:
        position = random.randint(0, 8)
        if spielfeld[position] not in ["X", "O"]:
            break
    spielfeld[position] = aktiver
Dann wird die Hauptschleife zu:

Code: Alles auswählen

        spielfeld_ausgeben(spielfeld)
        while spiel_aktiv:
            if aktiver == "X":
                spieler_eingabe(spielfeld, aktiver)
            else:
                computer_eingabe(spielfeld, aktiver)
            aktiver = spieler_wechsel(aktiver)
            spiel_aktiv = gewinner_ermitteln(spielfeld)
            spielfeld_ausgeben(spielfeld)
            durchgang += 1

Re: Hilfe beim programmieren von Tic Tag toe

Verfasst: Freitag 24. Februar 2023, 21:04
von Anomym147
Sirius3 hat geschrieben: Freitag 24. Februar 2023, 19:44 Funktionen werden auf oberster Ebene definiert. Es ist selten sinnvoll, Funktionen in Abhängigkeit einer Bedingung zu definieren.
Zudem sind die Funktionsdefinitionen `spieler_eingabe`, `Gewinner` und `unentschieden` sind in beiden Zweigen identisch, `spieler_wechsel` fast identisch.
Alles was Funktionen brauchen, müssen sie über ihre Argumente bekommen, `spielfeld` fehlt aber meist. Dagegen ist `spiel_aktiv` ein Argument, das eigentlich überflüssig ist, weil immer `True`.
Der Code, der außerhalb von Funktionen steht, sollte auch in eine Funktion wandern.
Damit hätten wir als Zwischenstand:

Code: Alles auswählen

import random 

def spielfeld_ausgeben(spielfeld):
    print(spielfeld[1] + " " + spielfeld[2] + " " + spielfeld[3])
    print(spielfeld[4] + " " + spielfeld[5] + " " + spielfeld[6])
    print(spielfeld[7] + " " + spielfeld[8] + " " + spielfeld[9])


def spieler_wechsel(aktiver):
    if aktiver== "X":
        aktiver= "O"
    else:
        aktiver = "X"
    return aktiver


def spieler_eingabe(spielfeld, aktiver):
    spieler = int(input(f"Spieler {aktiver}: Welches Feld möchtest du besetzen?"))
    if spielfeld[spieler] == "X" or spielfeld[spieler] == "O":
        print("Dieses Feld ist besetzt, probiere ein anderes!")
        spieler_eingabe(aktiver)
    else:
        spielfeld[spieler]=aktiver


def Gewinner(spielfeld):
    if spielfeld[1] == spielfeld[2] == spielfeld[3]:
        print(f"Spieler {spielfeld[1]} hat gewonnen")
        return False
    if spielfeld[4] == spielfeld[5] == spielfeld[6]:
        print(f"Spieler {spielfeld[4]} hat gewonnen")
        return False
    if spielfeld[7] == spielfeld[8] == spielfeld[9]:
        print(f"Spieler {spielfeld[7]} hat gewonnen")
        return False

    if spielfeld[1] == spielfeld[4] == spielfeld[7]:
        print(f"Spieler {spielfeld[1]} hat gewonnen")
        return False
    if spielfeld[2] == spielfeld[5] == spielfeld[8]:
        print(f"Spieler {spielfeld[2]} hat gewonnen")
        return False
    if spielfeld[3] == spielfeld[6] == spielfeld[9]:
        print(f"Spieler {spielfeld[3]} hat gewonnen")
        return False 

    if spielfeld[1] == spielfeld[5] == spielfeld[9]:
        print(f"Spieler {spielfeld[1]} hat gewonnen")
        return False
    if spielfeld[3] == spielfeld[5] == spielfeld[7]:
        print(f"Spieler {spielfeld[3]} hat gewonnen")
        return False  
    return unentschieden(spielfeld)


def unentschieden(spielfeld):
    if (spielfeld[1] == "X" or spielfeld[1] == "O") \
    and (spielfeld[2] == "X" or spielfeld[2] == "O") \
    and (spielfeld[3] == "X" or spielfeld[3] == "O") \
    and (spielfeld[4] == "X" or spielfeld[4] == "O") \
    and (spielfeld[5] == "X" or spielfeld[5] == "O") \
    and (spielfeld[6] == "X" or spielfeld[6] == "O") \
    and (spielfeld[7] == "X" or spielfeld[7] == "O") \
    and (spielfeld[8] == "X" or spielfeld[8] == "O") \
    and (spielfeld[9] == "X" or spielfeld[9] == "O"):
        print("Das Spiel ist unentschieden ausgefallen")
        return False
    return True


def main():
    spiel_aktiv = True
    aktiver = "X"
    aktiver1 = "O"
    durchgang = 0

    spielfeld = [" ",
            "1", "2", "3",
            "4", "5", "6",
            "7", "8", "9"]

    P = "Partner"
    C = "Computer"
    PC = input("Möchtest du gegen einen Partner oder gegen den Computer spielen?")

    if (PC==P):
        print("Der erste Spieler ist X. Der zweite ist O")

        spielfeld_ausgeben(spielfeld)

        while spiel_aktiv:
            spieler_eingabe(spielfeld, aktiver)
            aktiver = spieler_wechsel(aktiver)
            spiel_aktiv = Gewinner(spielfeld)
            spielfeld_ausgeben(spielfeld)
            durchgang = durchgang + 1
        
        if not spiel_aktiv:
            print("Sie haben" ,durchgang, "durchgänge gebraucht, um zu gewinnen")
    else:
        z=random.randint(1,9)

        spielfeld_ausgeben(spielfeld)
        
        while spiel_aktiv:
            spieler_eingabe(spielfeld, aktiver)
            z=random.randint(1,9)
            aktiver = spieler_wechsel(z)
            spielfeld[z]=aktiver1
            spiel_aktiv = Gewinner(spielfeld)
            spielfeld_ausgeben(spielfeld)
            durchgang = durchgang + 1

if __name__ == "__main__":
    main()
Statt Code zu kopieren benutzt man Schleifen.

Code: Alles auswählen

def spielfeld_ausgeben(spielfeld):
    for i in [1, 4, 7]:
        print(" ".join(spielfeld[i:i+3]))


def Gewinner(spielfeld):
    for i in [1, 4, 7]:
        if spielfeld[i] == spielfeld[i+1] == spielfeld[i+2]:
            print(f"Spieler {spielfeld[i]} hat gewonnen")
            return False
    for i in [1, 2, 3]:
        if spielfeld[i] == spielfeld[i+3] == spielfeld[i+6]:
            print(f"Spieler {spielfeld[i]} hat gewonnen")
            return False
    if spielfeld[1] == spielfeld[5] == spielfeld[9]:
        print(f"Spieler {spielfeld[1]} hat gewonnen")
        return False
    if spielfeld[3] == spielfeld[5] == spielfeld[7]:
        print(f"Spieler {spielfeld[3]} hat gewonnen")
        return False  
    return unentschieden(spielfeld)


def unentschieden(spielfeld):
    if all(feld in ["X", "O"] for feld in spielfeld[1:]):
        print("Das Spiel ist unentschieden ausgefallen")
        return False
    return True
Es gibt selten Probleme, die man durch Rekursion einfacher schreiben kann. Eine Schleife ist meist besser:

Code: Alles auswählen

def spieler_eingabe(spielfeld, aktiver):
    while True:
        position = int(input(f"Spieler {aktiver}: Welches Feld möchtest du besetzen?"))
        if spielfeld[position] not in ["X", "O"]:
            break
        print("Dieses Feld ist besetzt, probiere ein anderes!")
    spielfeld[position]=aktiver
Listen sind in Python 0-Index-basiert. Das künstlich auf den 1-Index zu heben, ist eine schlechte Idee, weil man gegen die Sprache arbeitet.
Variablennamen und Funktionen werden generell komplett klein geschrieben. Funktionen sollten nach Tätigkeiten benannt werden.

Code: Alles auswählen

import random 


def spieler_wechsel(aktiver):
    if aktiver == "X":
        aktiver = "O"
    else:
        aktiver = "X"
    return aktiver


def spieler_eingabe(spielfeld, aktiver):
    while True:
        position = int(input(f"Spieler {aktiver}: Welches Feld möchtest du besetzen?")) - 1
        if spielfeld[position] not in ["X", "O"]:
            break
        print("Dieses Feld ist besetzt, probiere ein anderes!")
    spielfeld[position] = aktiver


def spielfeld_ausgeben(spielfeld):
    for i in [0, 3, 6]:
        print(" ".join(spielfeld[i:i+3]))


def gewinner_ermitteln(spielfeld):
    for i in [0, 3, 6]:
        if spielfeld[i] == spielfeld[i+1] == spielfeld[i+2]:
            print(f"Spieler {spielfeld[i]} hat gewonnen")
            return False
    for i in [0, 1, 2]:
        if spielfeld[i] == spielfeld[i+3] == spielfeld[i+6]:
            print(f"Spieler {spielfeld[1]} hat gewonnen")
            return False
    if spielfeld[0] == spielfeld[4] == spielfeld[8]:
        print(f"Spieler {spielfeld[4]} hat gewonnen")
        return False
    if spielfeld[2] == spielfeld[4] == spielfeld[6]:
        print(f"Spieler {spielfeld[4]} hat gewonnen")
        return False  
    if all(feld in ["X", "O"] for feld in spielfeld):
        print("Das Spiel ist unentschieden ausgefallen")
        return False
    return True


def main():
    spiel_aktiv = True
    aktiver = "X"
    aktiver1 = "O"
    durchgang = 0

    spielfeld = [
        "1", "2", "3",
        "4", "5", "6",
        "7", "8", "9"
    ]

    zweiter_spieler = input("Möchtest du gegen einen Partner oder gegen den Computer spielen?")

    if zweiter_spieler == "Partner":
        print("Der erste Spieler ist X. Der zweite ist O")

        spielfeld_ausgeben(spielfeld)

        while spiel_aktiv:
            spieler_eingabe(spielfeld, aktiver)
            aktiver = spieler_wechsel(aktiver)
            spiel_aktiv = gewinner_ermitteln(spielfeld)
            spielfeld_ausgeben(spielfeld)
            durchgang += 1
        
        if not spiel_aktiv:
            print(f"Sie haben {durchgang} Durchgänge gebraucht, um zu gewinnen")
    else:
        spielfeld_ausgeben(spielfeld)
        
        while spiel_aktiv:
            spieler_eingabe(spielfeld, aktiver)
            z = random.randint(0,8)
            aktiver = spieler_wechsel(z)
            spielfeld[z] = aktiver1
            spiel_aktiv = gewinner_ermitteln(spielfeld)
            spielfeld_ausgeben(spielfeld)
            durchgang += 1

if __name__ == "__main__":
    main()
Soweit hat sich an der Funktionalität nichts geändert.
Wenn wir uns aber Schleife für den Computer-Spieler anschauen, fallen ein paar Punkte auf:
`spieler_wechsel` mit z aufgerufen, so dass `aktiver` danach eine Zahl ist. Dabei sind X und O beim Computer-Spiel ja fix.
Bei `spieler_eingabe` prüfst Du, ob das Feld frei ist, das selbe mußt Du für den Computerspieler auch machen, auf die selbe Weise.
Da in einem Durchgang sowohl Spieler als auch Computer setzt, ist durchgang falsch und auch die Prüfung, ob jemand gewonnen hat, kommt eventuell zu spät.
Als erstes definieren wir eine Funktion

Code: Alles auswählen

def computer_eingabe(spielfeld, aktiver):
    while True:
        position = random.randint(0, 8)
        if spielfeld[position] not in ["X", "O"]:
            break
    spielfeld[position] = aktiver
Dann wird die Hauptschleife zu:

Code: Alles auswählen

        spielfeld_ausgeben(spielfeld)
        while spiel_aktiv:
            if aktiver == "X":
                spieler_eingabe(spielfeld, aktiver)
            else:
                computer_eingabe(spielfeld, aktiver)
            aktiver = spieler_wechsel(aktiver)
            spiel_aktiv = gewinner_ermitteln(spielfeld)
            spielfeld_ausgeben(spielfeld)
            durchgang += 1

Ich danke dir für deine ausführliche Antwort! Leider muss ich zugeben, dass ich es immer noch nicht hinbekomme, das Spiel so zu programmieren, dass der Computer nur freie Felder besetzt :( Gibt es eine andere Methode, ungefähr so eine, wie ich es mit „spieler_eingabe“ gemacht habe, nur für den Computer?
Ich bitte um Verzeihung, wie gesagt, bin kein Fan vom Programmieren

Vielen Dank nochmal!

Re: Hilfe beim programmieren von Tic Tag toe

Verfasst: Freitag 24. Februar 2023, 21:47
von __deets__
Bitte nicht den gesamten Text des Posts davor zitieren. Der steht da schon.

Und wir liefern keine Hausaufgaben frei Haus. Wenn du keinen Bock auf programmieren hast, ist das ok. Es gibt weiß Gott genug Kram, auf den ich keinen Bock habe. Dann lass es eben sein.

Aber wenn es sein muss, dann reiß dich halt zusammen. Nicht jeder ist ein Tom Sawyer, der Seine Aufgaben geschickt an andere delegiert bekommt.

Re: Hilfe beim programmieren von Tic Tag toe

Verfasst: Freitag 24. Februar 2023, 22:33
von Anomym147
Vielen Dank _deets_ für deine sehr hilfreiche Antwort! :)
Vielleicht ist es dir noch nicht klar, deshalb hier nochmal in einfachen Worten:
1. Dir ist bestimmt schon aufgefallen, dass ich das komplette Spiel bereits programmiert habe und mir nur noch eine kleine Funktion fehlt, die ich nicht alleine hinbekomme, oder?
2. Ich reiße mich schon seit Wochen zusammen, um ein funktionierendes Spiel zu programmieren, „Hausaufgaben frei Haus“ ist es dann wohl nicht.
3. Wenn du mir nicht helfen möchtest, ist das vollkommen okay und ein Kommentar ist nicht notwendig, denkst du nicht auch?

Nichtsdestotrotz dankeschön

Re: Hilfe beim programmieren von Tic Tag toe

Verfasst: Freitag 24. Februar 2023, 23:05
von __blackjack__
@Anomym147: Das Spiel ist nicht komplett programmiert und es fehlt auch nicht nur eine kleine Funktion. Das sind offenbar Fehler drin wenn ich den Beitrag von Sirus3 lese.

Re: Hilfe beim programmieren von Tic Tag toe

Verfasst: Freitag 24. Februar 2023, 23:12
von __deets__
Die “kleine Funktion” ist offensichtlich nicht ganz so klein, sonst würdest du die ja ganz einfach selbst hinbekommen, oder?

Und weil dir die fehlt, und andere dir die liefern sollen, ist das sehr wohl deine Hausaufgabe, die wir hier machen sollen. Nur weil du den Besen & Kehrblech hingestellt hast, sollen wir immer noch fegen, sonst wird die Hütte nicht sauber, und du kriegst ne 5.

Auch der Hinweis darauf, was hier die Gepflogenheiten sind, gehört sehr wohl zu den Notwendigkeiten.

Und ganz großes Bitteschön.

Re: Hilfe beim programmieren von Tic Tag toe

Verfasst: Freitag 24. Februar 2023, 23:14
von sparrow
@Anonym147: Du hast nicht wochenlang irgendwas programmiert sondern Code aus einem super schlechten Tutorial kopiert.

Re: Hilfe beim programmieren von Tic Tag toe

Verfasst: Freitag 24. Februar 2023, 23:23
von __deets__
Ada guck: https://www.python-lernen.de/tic-tac-to ... wonnen.htm

Da wirst du wohl noch ein paar Wochen mehr in das googeln einer Lösung inklusive deiner “kleinen Funktion” investieren müssen. Denn selbst dein Lehrer sollte begreifen, dass das nur ein schlechtes Plagiat ist.

Re: Hilfe beim programmieren von Tic Tag toe

Verfasst: Freitag 24. Februar 2023, 23:34
von Anomym147
@_blackjack_ Das Spiel funktioniert, mehr brauche ich nicht.
@_deets_ Ich weiß nicht alles. Jeder bleibt mal wo hängen und braucht etwas Hilfe, nichts falsch daran. Ne 5 gibts schon mal gar nicht, da das programmieren nicht die einzige Aufgabe ist. Etwas offener sein, Freundlichkeit kostet schließlich nichts :)
@sparrow Danke für deine Meinung, meine Partnerin und ich arbeiten seit Wochen an dem Spiel, wir sind keine Programmierer falls dir das noch nicht aufgefallen ist.
Internet und Tutorials sind erlaubt.

Ich genieße das Drama hier, ziemlich lustig wie ernst alle sind.

Re: Hilfe beim programmieren von Tic Tag toe

Verfasst: Freitag 24. Februar 2023, 23:36
von Anomym147
@_deets_ Mensch du steckst wirklich Blut, Schweiß und Tränen in diese Diskussion, ganz ehrlich wirst mir langsam sehr sympathisch.

Wie gesagt, wir dürfen alles benutzen und du hast falsch getappt, ist nicht die Seite, die ich verwendet habe ;)

Re: Hilfe beim programmieren von Tic Tag toe

Verfasst: Freitag 24. Februar 2023, 23:46
von sparrow
@Anonym147: Also wenn du und deine Partnerin Wochen gebraucht habt, das Tutorial stumpf zu kopieren, dann hätte ich die Lebenszeit sinnvoller investiert.
Drama sehe ich hier übrigens nicht. Ich sehe hier nur jemanden, der sich ohne Eigeninitiative durchmogeln möchte. Funktioniert nicht immer im Leben.
Bevor du also weiter hier deine Zeit in Mimimi steckst, wäre die wohl in einem guten Tutorial besser angelegt. Oder in der Entscheidung, es sein zu lassen und lieber etwas zu tun, worauf du Lust hast.

Und doch, das ist die Seite, die du verwendest hast. Der Code ist so schlecht, der ist unverwechselbar.

Also hast du bisher gar nichts selbst gemacht. Außer zu fragen, ob andere deine Aufgaben machen. Ich sag es mal do: toi, toi, toi. Du wirst es brauchen.

Re: Hilfe beim programmieren von Tic Tag toe

Verfasst: Freitag 24. Februar 2023, 23:54
von Anomym147
@sparrow Wenn du genauer hinguckst, ganz ganz genau, dann siehst du, dass es eindeutig nicht der Code ist und ich wage es zu behaupten, dass ich es besser wüsste als du, oder? Ebenso weiß ich, wie viel Zeit ich darin investiert habe, ob mit oder ohne Hilfe, als Anfänger dauert es nun mal länger, um die Funktionen zu verstehen und anwenden zu können.

Ruh dich aus, ist bestimmt anstrengend so viele Behauptungen aufzustellen. 😧

Re: Hilfe beim programmieren von Tic Tag toe

Verfasst: Samstag 25. Februar 2023, 00:20
von __blackjack__
@Anomym147: Fehler bedeutet das Programm funktioniert nicht, und da Lehrer/Dozenten Suchmaschinen bedienen können, solltest Du die Fehler adressieren, denn Du kannst schlecht behaupten Du wüsstest nichts davon, wenn sie Dir hier mitgeteilt wurden.

Ich habe ganz ganz genau hingeschaut, und da ist ein deutlicher Teil drin der aus dem Tutorial abgeschrieben ist. Die Eigenleistung ist nicht so doll. Das wird auch der Lehrer/Dozent feststellen können.

Re: Hilfe beim programmieren von Tic Tag toe

Verfasst: Samstag 25. Februar 2023, 00:41
von __deets__
Leute, von denen du erwartest, dass sie kompetent genug sind, deine “eine kleine Funktion” schreiben, sind auch kompetent genug, um dein kleines bisschen abwandeln als das zu erkennen, was es ist - ein erbärmlicher Verschleierungsversuch.

Und diese anpaulen von Leuten, von denen du dir Hilfe erwartest - wo glaubst du genau führt das hin, hm?

Re: Hilfe beim programmieren von Tic Tag toe

Verfasst: Sonntag 26. Februar 2023, 03:05
von LeSchakal
Kurze Frage zum eigentlichen Thema:
Sirius3 hat geschrieben: Freitag 24. Februar 2023, 19:44

Code: Alles auswählen

def computer_eingabe(spielfeld, aktiver):
    while True:
        position = random.randint(0, 8)
        if spielfeld[position] not in ["X", "O"]:
            break
    spielfeld[position] = aktiver
Besteht hier nicht die Gefahr einer Endlosschleife?
So könnte bspw. spielfeld schon voll besetzt sein.

Re: Hilfe beim programmieren von Tic Tag toe

Verfasst: Sonntag 26. Februar 2023, 03:10
von grubenfox
Dafür gibt es in der Hauptschleife ja nach jeder Eingabe (von Spieler oder Computerseite) die Prüfung auf Spielende.

Re: Hilfe beim programmieren von Tic Tag toe

Verfasst: Sonntag 26. Februar 2023, 10:08
von Sirius3
@LeSchakal: gut erkannt, Schleifen mit undefinierter Laufzeit sollte man, wenn möglich, verhindern. Indem man zum Beispiel erst ermittelt, welche Fehler noch frei sind:

Code: Alles auswählen

    position = random.choice([
        p for p, f in spielfeld
        if f not in ["X", "O"]
    ])