first programm - NameError

Code-Stücke können hier veröffentlicht werden.
Antworten
SauBär92
User
Beiträge: 2
Registriert: Mittwoch 12. Mai 2021, 22:22

Mittwoch 12. Mai 2021, 22:58

Hallo ihr Lieben :)

Habe zwar bereits einiges in diesem Forum mitgelesen, aber dies ist nun mein erster eigener Beitrag hier.
Es geht um mein allererstes Programm - Ein "number-guessing-game".

Mein Problem besteht darin, dass die variable "player_name" im Laufe des Programms plötzlich nicht mehr definiert ist.

Insgesamt habe ich 3 functions definiert.
In der ersten "name_input" lasse ich den user seinen Namen eingeben und prüfe, ob die Eingabe nur aus Buchstaben besteht. Ist dies der Fall, begrüße ich den User. --> Das funktioniert auch, somit ist die Variable "player_name" noch definiert.

Im Folgenden habe ich die zweite function "wanna_play", in der ich den user frage, ob er noch einmal spielen möchte.
--> in dieser function möchte ich den user erneut mit Namen ansprechen, doch hier ist "player_name" nicht mehr definiert.

Die dritte function ist das "guessing_game" an sich.
In dieser wiederum befindet sich die zweite function.

Das Programm hat komplett funktioniert, bis ich in der "name_input" function die Eingabe auf ausschließlich alphanumerische Zeichen geprüft habe.
Das Prüfen etc. in der "name_input" function an sich funktioniert auch, nur zerschießt es mit dann den "player_name" in der function "wanna_play", was ich nicht verstehe.

Ich hoffe ich habe alles verständlich beschrieben, freue mich auf euren Input und hänge meinen Code noch an.
(in der Vorschau sehe ich gerade, dass keine indentation berücksichtigt wird. Die sollte aber passen, der einzige Error ist der "Name Error")

Lieben Dank im Voraus und beste Grüße!
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
import random

print("\n\n-----------------------")
print("Hello, that's a little number-guessing game.")
print("Choose a number from 1 to 10 and we will see, if you're right.")
print("You have 3 tries. Choose whisely.")
print("-----------------------\n\n")

def name_input():
player_name = input("Please enter your name: ")

if player_name.isalpha() == True:
print("\n\nHello " + player_name.capitalize() + " - Good luck!")
else:
print("So, you're a robot, hm?\n\n")
name_input()


name_input()


def wanna_play():
play_again = str(input("Do you wanna play again? (y/n): "))

if play_again.lower() == "y":
print("\nGood decision, " + player_name.capitalize() + ". Let's try again ;)\n\n") # Fehlercode: Exception has occurred: NameError
guessing_game() # name 'player_name' is not defined

elif play_again.lower() == "n":
print("\nWhat a pity, but see you next time! :)\n\n")

else:
print("That's not a valid input. Please type yes or no\n")
wanna_play()


def guessing_game():
secret_number = random.randint(1,10)
guess_count = 0

while guess_count < 3:
guess_count += 1

try:
guess = int(input("\nMake a guess: "))

if guess == secret_number:
break
else:
print("\nNope, I said: 'Choose whisely'!")

if guess < secret_number:
print("But here's a little hint: ")
print("The secret number ist bigger than your guess.")
else:
print("But here's a little hint: ")
print("The secret number is smaller than your guess.")

except ValueError:
print("You're a prankster.... We're looking for numbers!")
guess_count -= 1


if guess_count == 3 and guess != secret_number:
print(str("\n+++ You LOSE! No more guesses. +++"))
print("The secret number was " + str(secret_number) + ".\n\n")

if guess == secret_number:
print("\n+++ Wow! That was right. You WIN! +++")
print(("+++++++ You needed " + str(guess_count) + " /3 tries +++++++\n\n"))

wanna_play()


guessing_game()
Sirius3
User
Beiträge: 14588
Registriert: Sonntag 21. Oktober 2012, 17:20

Donnerstag 13. Mai 2021, 10:04

Funktionen sind keine Sprungmarken, wo man beliebig hin und herspringen kann. Funktionen sind in sich abgeschlossene Einheiten, die eine bestimmte Aufgabe erfüllen. Sie bekommen Parameter über ihre Argumente übergeben, und haben einen Rückgabewert für das Ergebnis.
Um das nochmal deutlicher zu machen, werden Funktionen nach Tätigkeiten benannt, also play_guessing_game.

Wenn man etwas wiederholen will, benutzt man eine Schleife. Dieses "ich springe wieder an den Anfang, indem ich die Funktion nochmal aufrufe" ist eben dieses falsche Verständnis von Funktionen.

Code: Alles auswählen

def input_name():
    while True:
        player_name = input("Please enter your name: ")
        if player_name.isalpha() == True:
            break
        else:
            print("So, you're a robot, hm?\n\n")
    print("\n\nHello " + player_name.capitalize() + " - Good luck!")
    return player_name
Explizit auf True muß man nicht prüfen, weil damit ja doch wieder ein Wahrheitswert erzeugt wird.
Statt Strings mit + zusammenzustückeln, benutzt man Formatstrings.
Wenn immer der kapitalizierte Spielername benutzt wird, dann wandelt man das einmal um und nicht jedesmal bei der Ausgabe:

Code: Alles auswählen

def input_name():
    while True:
        player_name = input("Please enter your name: ")
        if player_name.isalpha():
            break
        print("So, you're a robot, hm?\n\n")
    player_name = player_name.capitalize()
    print(f"\n\nHello {player_name} - Good luck!")
    return player_name
In `wanna_play` willst Du player_name benutzen, also muß es als Argument übergeben werden. input liefert schon einen String, das Umwandeln per str ist also überflüssig.
`wanna_play` ist eine Frage, und die Antwort (also der Rückabewert) wäre True oder False. Dass da gleich das Spiel gestartet wird, ist nicht Aufgabe der Funktion.

Code: Alles auswählen

def wanna_play(player_name):
    while True:
        play_again = input("Do you wanna play again? (y/n): ").lower()
        if play_again == "y":
            print(f"\nGood decision, {player_name}. Let's try again ;)\n\n")
            return True
        elif play_again == "n":
            print("\nWhat a pity, but see you next time! :)\n\n")
            return False
        print("That's not a valid input. Please type yes or no\n")
try-Blöcke für Exceptions sollten immer nur den Bereich umfassen, wo der Fehler auftritt, also möglichst kurz sein. Das eingeben einer Zahl ist eine Aufgabe für eine eigene Funktion, wenn man die Fehlerbehandlung noch mit berücksichtigt. Wenn Code doppelt im if- und else-Block vorkommen, dann sollte man versuchen, das außerhalb zu haben.
Wenn guess != secret_number gilt, dann gilt auch immer guess_count == 3, die Bedinungen kann man also vereinfachen.

Code: Alles auswählen

def input_number():
    while True:
        try:
            return int(input("\nMake a guess: "))
        except ValueError:
            print("You're a prankster.... We're looking for numbers!")

def guessing_game():
    secret_number = random.randint(1,10)
    for guess_count in range(1,4):
        guess = input_number()
        if guess == secret_number:
            break
        print("\nNope, I said: 'Choose whisely'!")
        print("But here's a little hint: ")
        if guess < secret_number:
            print("The secret number ist bigger than your guess.")
        else:
            print("The secret number is smaller than your guess.")

    if guess != secret_number:
        print("\n+++ You LOSE! No more guesses. +++")
        print(f"The secret number was {secret_number}.\n\n")
    else:
        print("\n+++ Wow! That was right. You WIN! +++")
        print(f"+++++++ You needed {guess_count}/3 tries +++++++\n\n")
Und schließlich braucht jedes Programm eine Hauptfunktion, die als erstes aufgerufen wird.

Code: Alles auswählen

def main():
    print("\n\n-----------------------")
    print("Hello, that's a little number-guessing game.")
    print("Choose a number from 1 to 10 and we will see, if you're right.")
    print("You have 3 tries. Choose whisely.")
    print("-----------------------\n\n")
    player_name = input_name()
    while True:
        guessing_game()
        if not wanna_play(player_name):
            break

if __name__ == '__main__':
    main()
SauBär92
User
Beiträge: 2
Registriert: Mittwoch 12. Mai 2021, 22:22

Freitag 14. Mai 2021, 08:58

Hey Sirius3,

wow! Also wirklich: Wow!
Ganz lieben Dank für diese umfangreiche, gut erklärte und einleuchtende Erläuterung.
Nicht nur zu meiner Frage, sondern auch direkt zu all den anderen anderen Dingen, mit denen du direkt "aufgeräumt" hast.
Ich werde versuchen mir alles direkt zu verinnerlichen, damit gar nicht erst "schlechte Angewohnheiten" entstehen.

Nochmals lieben Dank und beste Grüße!
Antworten