Wortraten (Anfang)

Code-Stücke können hier veröffentlicht werden.
Antworten
addi
User
Beiträge: 28
Registriert: Donnerstag 29. März 2018, 22:54

Hey Leute, habe jetzt wieder Zeit gefunden mich mit Python zu befassen, habe als Übung kleines Galgenraten/Wortraten geschrieben. Ich wäre euch erneut sehr dankbar, wenn ihr mir Tipps/hinweise geben könntet. Im Allgemeinen soll es mit dem Programm möglich sein, entweder ein vorgegebenes Wort zu erraten oder eins selbst einzugeben, d.h. auch die "Spielmodis".

Code: Alles auswählen

import random

def eingabe(wort):
    nicht_erlaubt = "!§%&()=}{()[]}´`#*+-0123456789\"\'-.,<>|^°/@;:_ "
    eingabe = str(input("Hey, bitte gebe deinen Buchstaben ein! >"))
    if eingabe == "exit()":
        eingabe = "exit()"
    elif (len(eingabe) > 1 or eingabe in nicht_erlaubt) and eingabe.upper() != wort.upper():
        eingabe = "ERROR"
    elif eingabe.upper() == wort.upper():
        eingabe = "GEWONNEN"
    return eingabe

def wort_zufall():
    wortliste = ["Affe", "Lappen", "Frosch", "Döner", "Ich", "Dadam"]
    wort = random.choice(wortliste)
    return wort


def finden(suchen, suchen_in):
    pos_aus = []
    for i in range(len(suchen_in)):
        pos = suchen_in.find(suchen, i)
        if pos != -1:
            pos_aus.append(pos)
    return pos_aus

def leerzeichen(wort):
    linien = "-"*len(wort)
    if " " in wort:
        pos_leerzeichen = []
        for leerzeichen in range(len(wort)):
            pos_leer = wort.find(" ", leerzeichen)
            if pos_leer != -1:
                linien = list(linien)
                linien[pos_leer] = " "
    return "".join(linien)

def leerzeichen_zahl(wort):
    linienzahl = 0
    if " " in wort:
        for leerzeichen in range(len(wort)):
            pos_leer = wort.find(" ", leerzeichen)
            if pos_leer != -1:
                linienzahl += 1
    return linienzahl

def wortcheck(wort):
    nicht_erlaubt = "!§%&()=}{()[]}´`#*+-0123456789"
    valide = True
    for i in range(len(wort)):
        if wort[i] in nicht_erlaubt:
            valide = False
    return valide


def spielmodus():
    print("Hey welchen Spielmodus möchtest du nehmen. 'E' für Einzelspieler und 'M' für Mehrspieler")
    while True:
        modi = input(">")
        if modi.upper() in ("E", "M"):
            return modi.upper()
        print("Bitte gebe was gültiges ein [E|M]!")

def multiplayer():
    print("Bitte gebe das zu erratende Wort ein!")
    while True:
        wort_eingabe = input(">")
        if len(wort_eingabe) > 3 and wortcheck(wort_eingabe):
            return wort_eingabe
        print("Gebe bitte ein Wort ein, welches aus mehr als 3 Buchstaben besteht!")

if spielmodus() == "E":
    wort_eingabe = wort_zufall().upper()
    wort_eingabe_org = wort_eingabe
    linien = leerzeichen(wort_eingabe)
    s = list(linien)
    print(f"\n{linien}\n")
    gewonnen = False
    erraten = []
else:
    wort_eingabe = multiplayer().upper()
    wort_eingabe_org = wort_eingabe
    linien = leerzeichen(wort_eingabe)
    s = list(linien)
    print(f"\n{linien}\n")
    gewonnen = False
    erraten = []


for versuche in range(len(wort_eingabe_org)+3):
    exit = False
    check = eingabe(wort_eingabe_org)
    if check == "GEWONNEN":
        gewonnen = True
        break
    elif check == "exit()":
        exit = True
        break
    elif check == "ERROR":
        print("Gebe bitte nur einen BUCHSTABEN ein!")
        print(f"Versuche über: {len(wort_eingabe_org) + 2 - versuche}\n")
    else:
        check_gross = check.upper()
        if check_gross in wort_eingabe:
            erraten.append(check)
            print("\nYES!")
            position = finden(check_gross, wort_eingabe_org)
            for vorhanden in range(len(position)):
                a = position[vorhanden]
                s[a] = check
            wort_eingabe = wort_eingabe.replace(check_gross, "")
            ausgabe = "".join(s)
            print(f"\n{ausgabe}\n")
            print(f"Verusche über: {len(wort_eingabe_org) + 2 - versuche}\n")
        elif check in erraten:
            print("\nDu hast den Buchstaben bereits erraten!\n")
            print(f"Verusche über: {len(wort_eingabe_org) + 2 - versuche}\n")
        else:
            print(f"\"{check}\" ist kein Buchstabe des Wortes!\n")
            print(f"Verusche über: {len(wort_eingabe_org) + 2 - versuche}\n")
        if (len(wort_eingabe) - leerzeichen_zahl(wort_eingabe)) == 0:
            gewonnen = True
            break


if gewonnen == True:
    if versuche == 0:
        print(f"Juhu du hast in {versuche + 1} Zug gewonnen!")
    else:
        print(f"Juhu du hast in {versuche + 1} Zügen gewonnen!")
elif exit == False:
    print("\nDu hast verloren!!")
else:
    print("Du hast das Programm beendet!")
Eine Frage habe ich ich wollte die Funktion

Code: Alles auswählen

def versuchsanzeige(wort, versuche):
    print(f"Verusche über: {len(wort) + 2 - versuche}\n")
einbauen, aber ich erhalte immer folgenden Error:
TypeError: 'int' object is not callable
Beim googlen bin ich jetzt auch nicht wirklich weitergekommen...
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@addi: `eingabe` tut Dinge, die es eigentlich nicht tun sollte. Es sollte prüfen, ob ein Kommando, ein Wort oder ein einzelnes Zeichen eingegeben wurde, aber nicht, ob das Wort stimmt. Bei falscher Zeicheneingabe sollte es selbst nochmal nachfragen. Die zweite if-Bedingung ist auch viel zu kompliziert. Das könnte man durch Umsortieren einfacher schreiben.

In `finden` ist die for-Schleife unsinnig. Du suchst ab Position 0 und findest das Zeichen an Position 3 und suchst ab Position 1 und findest das Zeichen an Position 3 usw. Du brauchst eine while-Schleife. Das Muster wiederholst Du noch ein paar mal.
addi
User
Beiträge: 28
Registriert: Donnerstag 29. März 2018, 22:54

Hey Sirius3, also bei der eingabe soll sie eben dies tun, es soll später ein vollständiges Galgenraten werden und bei diesem ist es nur möglich entweder einen Buchstaben einzugeben oder das ganze Wort aber du hast recht, ich werde es in eine seperate Funktion einbauen und die Schleifen umgestalten.

finden haben ich jetzt mit enumerate() gelöst.

Mit dem Muster meinst du, dass die Schleifen an der Stelle unsinnig sind?
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Das liefert `finden`:

Code: Alles auswählen

>>> finden("H", "FROSCH")
[5, 5, 5, 5, 5, 5]
erwarten würde man ja eine Liste mit nur [5]. Die gleiche Art for-Schleife gibt es nicht nur in `finden` sondern auch in `leerzeichen` und `leerzeichen_zahl`.

Hier die Version mit while-Schleife, die das Problem nicht hat:

Code: Alles auswählen

def finden(suchzeichen, wort):
    positionen = []
    letzte_position = -1
    while True:
        letzte_position = wort.find(suchzeichen, letzte_position + 1)
        if letzte_position < 0:
            break
        positionen.append(letzte_position)
    return positionen
oder eine Variante mit for aber ohne find:

Code: Alles auswählen

def finden(suchzeichen, wort):
    positionen = []
    for pos, zeichen in enumerate(wort):
        if zeichen == suchzeichen:
            positionen.append(pos)
    return positionen
Ich würde mir nur die geratenen Zeichen merken und das Lückenwort jedesmal aus dem Original erzeugen:

Code: Alles auswählen

def generiere_luecken(wort, zeichen):
    return ' '.join(z if z.strip() in zeichen else '_')

print(generiere_luecken("FROSCH", "FOS"))
# F _ O S _ _
Die Zeichen `nicht_erlaubt` werden an zwei Stellen definiert, statt einmal als Konstante. Zeilen 75-80 sind identisch zu 83-88, gehören also nicht in die if-else-Blöcke. Ebenso Zeilen 115, 118 und 121.
addi
User
Beiträge: 28
Registriert: Donnerstag 29. März 2018, 22:54

Hey also also ich habe es auch mit for und enumerate umgesetzt.

Okay, so rum habe ich es noch nicht gedacht. Ich baue es mal ein.
Die Zeichen `nicht_erlaubt` werden an zwei Stellen definiert, statt einmal als Konstante. Zeilen 75-80 sind identisch zu 83-88, gehören also nicht in die if-else-Blöcke. Ebenso Zeilen 115, 118 und 121.
Ja bei 'nicht_erlaubt' war ich mir selbst unschlüssig, da ich vermeiden wollte es "Global" zu verwenden aber es ist eine Konstante und keine Variable.

Und ja habe es geändert.

Nochmals vielen Dank für deine Hilfe!!!
Antworten