Fragen zu Hangman

Code-Stücke können hier veröffentlicht werden.
Antworten
From The Pits
User
Beiträge: 8
Registriert: Montag 21. Juli 2008, 19:47

Hallo,

hab als allererstes kleines Projekt mal ein Hangman in der Konsole angefangen, weiß allerdings grade nicht weiter.Hier mein Code wie er bis jetzt aussieht:

Code: Alles auswählen

import random

class hangman:
    def play(self):
        counter = 0
        fieldnumber= len(wordlist[random.randint(0,2)])
        field = []
        word = wordlist[random.randint(0,2)]
       
        while counter <= 9:
        
            while fieldnumber > 0:      
                field.append("_ ")     
                fieldnumber -= 1      
            if counter == 1:
                print "/-\_"
            elif counter == 2:
                print "  |  "
                print "  |  "
                print "  |  "
                print "_/-\_"
            elif counter == 3:
                print "  |/ "
                print "  |  "
                print "  |  "
                print "_/-\_"
            elif counter == 4:
                print "  ____"
                print "  |/ "
                print "  |  "
                print "  |  "
                print "_/-\_"
            elif counter == 5:
                print "  ____"
                print "  |/ |"
                print "  |  "
                print "  |  "
                print "_/-\_"
            elif counter == 6:
                print "  ____"
                print "  |/ |"
                print "  |  o "
                print "  |  "
                print "_/-\_"
            elif counter == 7:
                print "  ____"
                print "  |/ |"
                print "  |  o"
                print "  |  0"
                print "_/-\_  "
            elif counter == 8:
                print "  ____"
                print "  |/ |"
                print "  |  o "
                print "  | /0\\"
                print "_/-\_"
            elif counter == 9:
                print "  ____"
                print "  |/ |"
                print "  |  o"
                print "  | /0\\"
                print "_/-\/\\"
             
            print field
            inp = raw_input("Raten sie einen Buchstaben: ")
        
            if len(inp) != 1:
                print "Ungueltige Eingabe!"
            else:
                if inp in word:
                    a = word.find(inp)
                    print a
                else:
                    counter += 1
                    print "Der Buchstabe ist nicht in dem gesuchten Wort."
        
            
             
                
                
        
     
        
        
wordlist = ["nadelwald", "gitarre", "tastatur"]
game = hangman()
game.play()

(Die wordlist ist jetzt noch sehr klein,aber das zu ändern ist ja klein großes Problem.Der Code ist auch sowieso noch sehr unfertig.)

Ich weiß nicht wie ich es anstellen soll, dass die richtig geratenen Buchstaben die Unterstriche in der Liste ersetzen. Ich müsste dafür ja rausfinden wie oft und wo der geratene Buchstabe im Wort vorkommt, wie ich das mache konntich aber nirgendwo herausfinden.

Ne andere Frage,die aber nicht so wichtig ist:
Wie kann ich es machen, das die Ausgabe(also das leere Feld und der Galgen),nicht jedes mal neu augegeben wird, sondern die alte ersetzt bzw. erweitert?

Für Kritik am Code bin ich natürlich auch offen.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

From The Pits hat geschrieben:Ich weiß nicht wie ich es anstellen soll, dass die richtig geratenen Buchstaben die Unterstriche in der Liste ersetzen. Ich müsste dafür ja rausfinden wie oft und wo der geratene Buchstabe im Wort vorkommt, wie ich das mache konntich aber nirgendwo herausfinden.
Ein Beispiel, der User hat a und t geraten (als Set vorgehalten damit man einfach jeweils neue Buchstaben einfach einfügen kann ohne Dubletten zu haben) und das Wort ist 'tastatur':

Code: Alles auswählen

>>> geratene = set(['a', 't'])
>>> ''.join(char if char in geratene else '_' for char in 'tastatur')
'ta_tat__'
From The Pits hat geschrieben:Ne andere Frage,die aber nicht so wichtig ist:
Wie kann ich es machen, das die Ausgabe(also das leere Feld und der Galgen),nicht jedes mal neu augegeben wird, sondern die alte ersetzt bzw. erweitert?
Das geht nicht so einfach, nachdem du eine Zeile abgeschlossen hast. Da müsstest du wohl eher etwas mit curses/urwid machen, was aber für den Anfang etwas hart ist; da zumindest curses ziemlich ätzend zu nutzen ist.
From The Pits hat geschrieben:Für Kritik am Code bin ich natürlich auch offen.
Ne, da habe ich momentan nicht so die Lust drauf, aber ein paar Tipps kann ich dir schon geben: Klassen mit Großbuchstaben beginnen, die einzelnen "Bilder" würde ich eher in einer Liste modulgrobal als jeweils komplette Multiline-Strings speichern. ``print`` kann die Problemlos anzeigen. Mit einer Liste sparst du dir die große ``elif``-Kaskade.

Generell finde ich auch das Klassendesign künstlich und unnütz. Die Funktion ``play`` braucht die Klasse gar nicht, also kannst du sie loswerden.
Zuletzt geändert von Leonidas am Sonntag 14. Dezember 2008, 16:55, insgesamt 1-mal geändert.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
From The Pits
User
Beiträge: 8
Registriert: Montag 21. Juli 2008, 19:47

Leonidas hat geschrieben:

Code: Alles auswählen

>>> geratene = set(['a', 't'])
>>> ''.join(char if char in geratene else '_' for char in 'tastatur')
'ta_tat__'
Ehrlich gesagt versteh ich nicht was du da geschrieben hast.

Ich hab den Code jetzt mal etwas verbessert, und auch einen eigenen Ansatz zum Einfügen der geratenen Buchstaben eigefügt.Der funktioniert aber nicht ganz, da er den geratenen Buchstaben nur einmal einfügt.Wie ich das beheben soll weißich jetzt aber wieder nicht,ich glaub ich muss da ganz anders ansetzen. Außerdem ist das Feld manchmal zu groß, da weiß ich auch nicht woran es liegt.


Code: Alles auswählen

import random

wordlist = ["nadelwald", "gitarre", "tastatur"]
counter = 0
length = len(wordlist[random.randint(0,2)])
word = wordlist[random.randint(0,2)]
field = []
geraten = []
while length >= 0:
    field.append("_ ")
    length -= 1
    
gallow = [" ", "_/-\_",
         "  |  \n  |  \n  |  \n_/-\_",
         "  |/ \n  |  \n  |  \n_/-\_", 
         "  ____\n  |/ \n  |  \n  |  \n_/-\_",
         "  ____\n  |/ |\n  |  \n  |  \n_/-\_", 
         "  ____\n  |/ |\n  |  o\n  |  \n_/-\_",
         "  ____\n  |/ |\n  |  o\n  |  0\n_/-\_", 
         "  ____\n  |/ |\n  |  o\n  | /0\ \n_/-\_",
         "  ____\n  |/ |\n  |  o\n  | /0\ \n_/-\/\"]
       
while counter <= 9:
    print gallow[counter]
    print field
    inp = raw_input("Raten sie einen Buchstaben: ")
        
    if len(inp) != 1:
        print "Ungueltige Eingabe!"
    else:
        if inp in word and inp not in geraten:
            a = word.find(inp)
            field.insert(a, inp)
            a += 1
            del field[a]
            geraten.append(inp)
            
            
        else:
            counter += 1
            print "Der Buchstabe ist nicht in dem gesuchten Wort, oder der Buchstabe wurde schon genannt."
            
print "Du hast verloren."

BlackJack

@From The Pits: `length` und `word` müssen nicht zusammen passen. Du solltest die Länge vom `word` nehmen, dass Du auswählst. Und das vielleicht auch besser mit `random.choice()` statt die Länge von `wordlist` für's aussuchen per Hand hart ins Programm zu schreiben.

`length` und die erste ``while``-Schleife sind aber sowieso nicht so toll. Wenn die Obergrenze einer Zählschleife bekannt ist, nimmt man eine ``for``-Schleife. Aber selbst die kann man sich sparen, weil man in Python Zeichenketten mit Zahlen multiplizieren kann:

Code: Alles auswählen

In [5]: 'Ho ' * 5
Out[5]: 'Ho Ho Ho Ho Ho '
Bei der nächsten ``while``-Schleife ist wieder eine hart kodierte "magische" Zahl, die man loswerden sollte. Du willst dort ja nicht auf 9 testen, sondern auf die Länge von `gallow`.

Das der geratene Buchstabe nur einmal eingefügt wird, liegt daran, dass Du das halt auch nur mit dem ersten vorkommen des Buchstabens machst.

In der Zeichenkette würde ich das aber sowieso nicht mit `insert()` und ``del`` lösen, sondern lieber entweder immer eine neue Zeichenkette aufbauen, wie Leonidas das getan hat, oder das geratene Wort direkt ausgeben. Mit einem abschliessenden Komma kann man verhindern, dass ``print`` ein neue Zeile beginnt.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

From The Pits hat geschrieben:
Leonidas hat geschrieben:

Code: Alles auswählen

>>> geratene = set(['a', 't'])
>>> ''.join(char if char in geratene else '_' for char in 'tastatur')
'ta_tat__'
Ehrlich gesagt versteh ich nicht was du da geschrieben hast.
Das ist eine Generator Expression die den ternären Operator verwendet, ich brösel das mal auf:

Code: Alles auswählen

(... for char in 'tastatur')
Iteriert über jeden Buchstaben des Wortes 'tastatur' und führt den Code in ``...`` aus (Generator Expression).

Code: Alles auswählen

char if char in geratene else '_'
Gibt den Buchstaben unverändert zurück, wenn er in der Menge der bereits geratenen Zahlen ist, ansonsten wird '_' zurückgegeben (ternärer Operator).

Code: Alles auswählen

''.join(...)
Die Generator Expression gibt jeden Buchstaben einzeln aus, um diese wieder zu einem String zusammenzubauen wird ``join`` verwendet.

Übrigens hättest du beim umschreiben den Code durchaus in einer Funktion lassen können, statt ihn nun modulglobal rumliegen zu haben.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
From The Pits
User
Beiträge: 8
Registriert: Montag 21. Juli 2008, 19:47

BlackJack hat geschrieben:@From The Pits: `length` und `word` müssen nicht zusammen passen. Du solltest die Länge vom `word` nehmen, dass Du auswählst.
Argh. Klar. Was für ein dummer Fehler.
BlackJack hat geschrieben:`length` und die erste ``while``-Schleife sind aber sowieso nicht so toll. Wenn die Obergrenze einer Zählschleife bekannt ist, nimmt man eine ``for``-Schleife. Aber selbst die kann man sich sparen, weil man in Python Zeichenketten mit Zahlen multiplizieren kann.
Ok, for-Schleife ist eingebaut.
Das man Zeichenketten multiplizieren kann wusste ich zwar, aber ich dachte ich brauche eine Liste um die geratenen Buchstaben einzufügen.

BlackJack hat geschrieben:Bei der nächsten ``while``-Schleife ist wieder eine hart kodierte "magische" Zahl, die man loswerden sollte. Du willst dort ja nicht auf 9 testen, sondern auf die Länge von `gallow`.
Doch, eigentlich will ich schon auf 9 testen :wink: , da der Spieler ja schließlich 9 falsche Versuche machen können soll.
BlackJack hat geschrieben:Das der geratene Buchstabe nur einmal eingefügt wird, liegt daran, dass Du das halt auch nur mit dem ersten vorkommen des Buchstabens machst.
Das war mir klar, ich weiß/wusste nur nicht wie ich das ändern sollte.

@Leonidas:
Danke für die Erklärung, aber was bringt es den Code in einer Funktion zu schreiben wenn diese eh nur einmal aufgerufen wird,und sonst nichts anderes passiert?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

From The Pits hat geschrieben:@Leonidas:
Danke für die Erklärung, aber was bringt es den Code in einer Funktion zu schreiben wenn diese eh nur einmal aufgerufen wird,und sonst nichts anderes passiert?
Das der Code nicht automatisch ausgeführt wird, wenn du das Modul importierst - es kann ja sein, dass du das ganze irgendwann als Modul verwenden willst und da ist es sinnvoll gleich von Anfang an wiederverwendbaren Code zu schreiben.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

@From The Pits: Der Benutzer soll nicht 9 Versuche haben, sondern so viele wie Galgenbilder vorhanden sind. Das mögen in diesem Fall zufällig 9 sein, aber überlege mal was Du wo am Programm ändern musst wenn Du eine Liste mit "Bildern" und eine 9 im Programm hast, und die Anzahl der Rateversuche ändern möchtest, im Gegensatz zu einer Liste mit "Bildern" und eine Längenabfrage als Schleifenbedingung. Man sollte es vermeiden redundante Information, und dann auch noch in Form von "magischen Zahlen", im Programm zu haben.
Antworten