Einfaches Hangman-Spiel

76170
acardnell24

Auf meiner Suche nach einem Masterprogrammierer habe ich ein einfaches Hangman-Spiel entwickelt, und ich dachte, ich würde es hier hochladen und sehen, wie es verfeinert werden kann.

Eine Frage, die ich hatte, war meine Ausnahmebehandlung. Ich habe versucht, es hier zu nutzen, aber ich habe den Eindruck, dass es übertrieben gewesen sein könnte. Soll ich try / nur verwenden, wenn ich weiß, dass es Ausnahmen geben wird, oder ist es eine gute Praxis, sie trotzdem zu verwenden?

"""Hangman
Standard game of Hangman. A word is chosen at random from a list and the
user must guess the word letter by letter before running out of attempts."""

import random

def main():
    welcome = ['Welcome to Hangman! A word will be chosen at random and',
               'you must try to guess the word correctly letter by letter',
               'before you run out of attempts. Good luck!'
               ]

    for line in welcome:
        print(line, sep='\n')

    # setting up the play_again loop

    play_again = True

    while play_again:
        # set up the game loop

        words = ["hangman", "chairs", "backpack", "bodywash", "clothing",
                 "computer", "python", "program", "glasses", "sweatshirt",
                 "sweatpants", "mattress", "friends", "clocks", "biology",
                 "algebra", "suitcase", "knives", "ninjas", "shampoo"
                 ]

        chosen_word = random.choice(words).lower()
        player_guess = None # will hold the players guess
        guessed_letters = [] # a list of letters guessed so far
        word_guessed = []
        for letter in chosen_word:
            word_guessed.append("-") # create an unguessed, blank version of the word
        joined_word = None # joins the words in the list word_guessed

        HANGMAN = (
"""
-----
|   |
|
|
|
|
|
|
|
--------
""",
"""
-----
|   |
|   0
|
|
|
|
|
|
--------
""",
"""
-----
|   |
|   0
|  -+-
|
|
|
|
|
--------
""",
"""
-----
|   |
|   0
| /-+-
|
|
|
|
|
--------
""",
"""
-----
|   |
|   0
| /-+-\ 
|
|
|
|
|
--------
""",
"""
-----
|   |
|   0
| /-+-\ 
|   | 
|
|
|
|
--------
""",
"""
-----
|   |
|   0
| /-+-\ 
|   | 
|   | 
|
|
|
--------
""",
"""
-----
|   |
|   0
| /-+-\ 
|   | 
|   | 
|  |
|
|
--------
""",
"""
-----
|   |
|   0
| /-+-\ 
|   | 
|   | 
|  | 
|  | 
|
--------
""",
"""
-----
|   |
|   0
| /-+-\ 
|   | 
|   | 
|  | | 
|  | 
|
--------
""",
"""
-----
|   |
|   0
| /-+-\ 
|   | 
|   | 
|  | | 
|  | | 
|
--------
""")

        print(HANGMAN[0])
        attempts = len(HANGMAN) - 1


        while (attempts != 0 and "-" in word_guessed):
            print(("\nYou have {} attempts remaining").format(attempts))
            joined_word = "".join(word_guessed)
            print(joined_word)

            try:
                player_guess = str(input("\nPlease select a letter between A-Z" + "\n> ")).lower()
            except: # check valid input
                print("That is not valid input. Please try again.")
                continue                
            else: 
                if not player_guess.isalpha(): # check the input is a letter. Also checks an input has been made.
                    print("That is not a letter. Please try again.")
                    continue
                elif len(player_guess) > 1: # check the input is only one letter
                    print("That is more than one letter. Please try again.")
                    continue
                elif player_guess in guessed_letters: # check it letter hasn't been guessed already
                    print("You have already guessed that letter. Please try again.")
                    continue
                else:
                    pass

            guessed_letters.append(player_guess)

            for letter in range(len(chosen_word)):
                if player_guess == chosen_word[letter]:
                    word_guessed[letter] = player_guess # replace all letters in the chosen word that match the players guess

            if player_guess not in chosen_word:
                attempts -= 1
                print(HANGMAN[(len(HANGMAN) - 1) - attempts])

        if "-" not in word_guessed: # no blanks remaining
            print(("\nCongratulations! {} was the word").format(chosen_word))
        else: # loop must have ended because attempts reached 0
            print(("\nUnlucky! The word was {}.").format(chosen_word))

        print("\nWould you like to play again?")

        response = input("> ").lower()
        if response not in ("yes", "y"):
            play_again = False

if __name__ == "__main__":
    main()
Antworten
12
Schöne Bestätigung und gut gemacht mit der Wiederholungsfrage! Sie können es in mehrere Funktionen aufteilen, den Hangman programmatisch zeichnen, ein vollständiges Wörterbuch herunterladen und Emoji hinzufügen. Siehe Quellen für http://richardsgames.com/hangman.html F. Malina vor einem Jahr 0

4 Antworten auf die Frage

9
alexwlchan

Sie haben eine bloße Ausnahme-Klausel. dh

try:
     some_code()
except:
     clean_up()

Das Problem mit einer bloßen Ausnahme ist, dass alle Ausnahmen erfasst werden, einschließlich derer, die Sie wirklich nicht ignorieren möchten (wie KeyboardInterrupt und SystemExit). Es wäre viel besser, wenn Ihr Ausnahmeblock nur die von Ihnen erwartete Ausnahme erfasste und alle anderen wie normal aufblähen würde.

Einige andere allgemeine Kommentare zu Ihrem Code:

  • In Zeile 200 haben Sie diese Konstruktion:

    for letter in range(len(chosen_word)):
        if player_guess == chosen_word[letter]:
            word_guessed[letter] = player_guess
    

    Sie durchlaufen die Indexvariable, verwenden aber auch das Listenelement. Es wäre besser zu schreiben:

    for idx, letter in enumerate(chosen_word):
        if player_guess == letter:
            word_guessed[idx] = player_guess
    
  • Anstatt den Flag-Wert zu verwenden play_again, können Sie eine break-Anweisung verwenden. Das heißt, strukturieren Sie Ihren Code wie folgt:

    while True:
        # play the game
    
        if not player_response_is_play_again():
            break
    

    Das ist ein bisschen sauberer und leichter zu folgen, da ich der play_againVariablen nicht folgen muss .

  • Ihre Hauptfunktion () ist enorm . Der größte Teil dieses Codes ist nicht wiederverwendbar, da er in einer einzigen monolithischen Funktion gebunden ist. Es wäre viel besser, wenn Sie es in kleine, unterschiedliche Einheiten von Code aufteilen: Diese sind einfacher zu testen und zu debuggen, und es wäre für den Wiederverwendungsprozess besser geeignet.

Wenn Sie die Schleife geändert haben, ist Ihr "Brief" jetzt ein Element der Liste anstelle eines Index. Sie müssen die Art und Weise ändern, in der die Datenstruktur "word_guessed" verwendet wird, wenn Sie ihr etwas Neues zuweisen möchten. Dies ist nicht immer sauberer, wenn Sie das Gesamtbild in Betracht ziehen. ShreevatsaR vor 4 Jahren 0
@ShreevatsaR Guter Ort, mein Fehler. Fest. alexwlchan vor 4 Jahren 0
5
Ethan Bierlein

Sie haben viel zu viel Code in Ihrer mainFunktion. Versuchen Sie herauszufinden, ob Sie die Logik in separate Funktionen mit jeweils eigenen Argumenten aufteilen können. Zum Beispiel den folgenden Codeblock:

words = ["hangman", "chairs", "backpack", "bodywash", "clothing",
                 "computer", "python", "program", "glasses", "sweatshirt",
                 "sweatpants", "mattress", "friends", "clocks", "biology",
                 "algebra", "suitcase", "knives", "ninjas", "shampoo"
                 ]

chosen_word = random.choice(words).lower()

Kann leicht in eine Funktion mit dem folgenden Namen unterteilt choose_wordwerden:

def choose_word(word_list):
    """
    Choose a random word from the word_list
    and return it.
    """
    return random.choice(word_list)

Sie haben auch einige lange Mutlilin-Saiten. Beispielsweise die folgende mehrzeilige Zeichenfolge:

"""
-----
|   |
|
|
|
|
|
|
|
--------
"""

Kann sehr leicht darauf verkürzt werden:

"-----\n|   |\n|\n|\n|\n|\n|\n|\n|\n--------"

Beachten Sie, dies ist jedoch nicht erforderlich. Es ist nur persönliche Vorlieben.


Die Art und Weise, wie Sie mehrere Textteile drucken, ist auch seltsam. Zum Beispiel der folgende Code:

welcome = ['Welcome to Hangman! A word will be chosen at random and',
               'you must try to guess the word correctly letter by letter',
               'before you run out of attempts. Good luck!'
               ]

    for line in welcome:
        print(line, sep='\n')

Kann nochmal darauf verkürzt werden:

print(
    "Welcome to Hangman! A word will be chosen at random and",
    "you must try to guess the word correctly letter by letter",
    "before you run out of attempts. Good luck!",
    sep="\n"
)

Ich habe auch bemerkt, dass Sie die Verwendung von einfachen Anführungszeichen ''und doppelten Anführungszeichen verwenden "". Dies ist zwar keine große Sache, aber ich würde empfehlen, das eine oder das andere zu wählen und dabei zu bleiben.


Die Art, wie Sie Listen gestalten, ist auch seltsam. Obwohl es nicht erforderlich ist, empfehle ich es so:

my_list = [
    value,
    ...
]

Wenn Sie Benutzereingaben erhalten, müssen Sie sie schließlich nicht mithilfe der strFunktion in einen String konvertieren . Sie können es diese nur bekommen: user_input = input("prompt").

Dieser "hässliche Mutlilin-String" ist viel lesbarer, da Sie tatsächlich die tatsächliche Ausgabe sehen Simon Forsberg vor 4 Jahren 9
@ SimonAndré Forsberg Ich habe meinen Beitrag so bearbeitet, dass er optional ist. Ethan Bierlein vor 4 Jahren 0
Einige gute Punkte hier, aber ich stimme nicht damit überein, die Saite zu verdichten. Hosch250 vor 4 Jahren 0
@ SirPython Nope. Versuchen Sie es mit dem Beispiel. Es funktioniert gut. Ethan Bierlein vor 4 Jahren 0
4
SirPython
for line in welcome:
    print(line, sep='\n')

Das sieht aus wie die Art von Code, die in einer Funktion zum Ausdrucken mehrerer Strings in einem Array verwendet werden kann. Da Sie jedoch nur eine Nachricht in einem Array haben, scheint dies eine Art Overkill zu sein, zumal es nur drei Zeilen gibt.

Es wäre viel einfacher, die Nachricht so auszudrucken, wie sie ist:

print "..."
print "..."
...

Anstatt zu versuchen, eine eigene Liste von Wörtern zu erhalten, empfehle ich eine der folgenden drei Optionen:

  • Finden Sie eine API.

Es gibt wahrscheinlich Tonnen von APIs im Internet, die als Wörterbuch für Ihr Programm dienen.

Pro : Sie müssen nichts herunterladen; Rufen Sie einfach eine API auf.

Con : APIs haben ein Limit wie beispielsweise Aufrufe pro Tag. Manchmal kann Ihr Code bei einem API-Aufruf hängen bleiben.

Unix-Wörter in einem Wörterbuch, das mit Unix- und Unix-ähnlichen Betriebssystemen geliefert wird.

Pro : Es ist nur eine Datei auf dem Computer, die ein einziges Wort pro Zeile enthält, was das Lesen sehr einfach macht.

Con : Ihr Benutzer verwendet möglicherweise nicht Unix oder ein Unix-ähnliches Betriebssystem.

  • Verwenden Sie PyEnchant.

Ich weiß es nicht. Ich habe gesehen, dass es in einigen Python-Codes verwendet wurde, bevor ein englischer Verweis darauf verwandt wurde, aber ich weiß nicht, wie der Zugriff auf das integrierte Wörterbuch funktioniert.


chosen_word = random.choice(words).lower()

Es hat keinen Sinn, die Methode aufzurufen, .lowerda alle Wörter in Ihrem Wörterbuch bereits in Kleinbuchstaben geschrieben sind.


Wenn Sie gefragt werden, ob der Benutzer erneut spielen möchte:

print("\nWould you like to play again?")

Anstatt eine Bedingung zu haben, bei der Sie später nach zwei Optionen suchen ("yes" und "y"), geben Sie dem Benutzer die gewünschten Optionen:

print("\nWould you like to play again? [Y/N]")

Um noch einen Schritt weiter zu gehen und einen zusätzlichen Funktionsaufruf zu löschen, fügen Sie diese Nachricht in den inputAnruf ein:

input("\nWould you like to play again? [Y/N]\n>")

Die Variable welcomeam Anfang Ihres Codes:

welcome = ['Welcome to Hangman! A word will be chosen at random and',
           'you must try to guess the word correctly letter by letter',
           'before you run out of attempts. Good luck!'
           ]

Sollte nicht in einem Array sein; Es sollte sich in einem Tupel befinden, da sich die Werte darin nicht ändern werden.

Das gleiche gilt für Ihr wordsArray.


Um Ihre Frage zu Ausnahmen zu beantworten, sollten Sie meiner Meinung nach nur dann verwenden, try/exceptionwenn Sie wissen, dass es Fehler gibt. Es ist immer gut, einen Fehler abzufangen und zu stoppen, aber es ist sinnlos, zu versuchen, wenn kein Fehler auftritt.

Wenn Sie wissen, dass Fehler auftreten, können Sie auch die richtige Art von Fehlern einfangen, anstatt nur zu fangen Exception.

Sie haben einen guten Job gemacht, um den Fehler hier abzufangen und zwischen der Verwendung von try/exceptund zu unterscheiden if/else:

try:
    player_guess = str(input("\nPlease select a letter between A-Z" + "\n> ")).lower()
except: # check valid input
    print("That is not valid input. Please try again.")
    continue 

Sie sollten jedoch feststellen, welche Art von Fehler in dieser Zeile auftreten würde.

Ich bin nicht sicher, welcher Fehler herauskommen wird, aber ich denke es ist entweder ein TypeErroroder ein IOError. So oder so ändern Sie Ihre Einstellung try/exceptin etwa wie folgt:

try:
    ...
catch ExceptionType:
    ...
3
Malachi

Sie haben nach Ihrer Ausnahmebehandlung gefragt.

        try:
            player_guess = str(input("\nPlease select a letter between A-Z" + "\n> ")).lower()
        except: # check valid input
            print("That is not valid input. Please try again.")
            continue                
        else: 
            if not player_guess.isalpha(): # check the input is a letter. Also checks an input has been made.
                print("That is not a letter. Please try again.")
                continue
            elif len(player_guess) > 1: # check the input is only one letter
                print("That is more than one letter. Please try again.")
                continue
            elif player_guess in guessed_letters: # check it letter hasn't been guessed already
                print("You have already guessed that letter. Please try again.")
                continue
            else:
                pass

Sie führen zuerst die Eingabe durch, um zu sehen, ob es sich um eine Zeichenfolge handelt, und sagen dann, dass sie keine gültige Eingabe ist. Anschließend prüfen Sie, ob das Zeichen ein Alpha-Zeichen ist oder nicht. Sie sollten nur prüfen, ob es sich um ein Alpha-Zeichen handelt oder nicht, und dann könnten Sie versuchen, es zu versuchen.

Entweder ist es ein Brief oder nicht, oder?