Schere, Stein, Papier, Echse, Spock

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
edebec
User
Beiträge: 20
Registriert: Donnerstag 9. Juli 2020, 14:36

Hallo,

programmiere gerade mein erstes Programm, ein kleines Spiel. Habe meine Probleme mit dem Hauptprogramm und der Umsetzung.
Denke meine Funkionen sind so weit fertig..
Kann mir da jemand weiter helfen?
..bekomme es einfach nicht zum laufen..

#Schere Stein Papier Echse Spock

import random



stein = 1
papier = 2
schere = 3
echse = 4
spock = 5

"""
Regeln:
Schere schneidet Papier
Papier bedeckt Stein
Stein zerquetscht Echse
Echse vergiftet Spock
Spock zertrümmert Schere
Schere köpft Echse
Echse frisst Papier
Papier widerlegt Spock
Spock verdampft Stein
Stein schleift Schere
"""


names = {stein: "Stein", papier: "Papier", schere: "Schere", echse: "Echse", spock: "Spock"}
rules = {
schere: papier,
papier: stein,
stein: echse,
echse: spock,
spock: schere,
schere: echse,
echse: papier,
papier: spock,
spock: stein,
stein: schere
}


player_score = 0
computer_score = 0


def start():
print("Lass uns eine Runde Schere, Stein, Papier, Echse, Spock spielen!")
while game():
pass
score()


def game():
player = move()
computer = random.randint(1, 5)
result(player, computer)
return play_again()


def move():
while True:
player = raw_input("Stein = 1\nPapier = 2\nSchere = 3\nEchs = 4\nSpock = 5\nWähle weise: ") #raw liefert str zurück
try:
player = int(player)
if player in (1, 2, 3, 4, 5):
return player                                                                               
except ValueError:
pass
print("Falsche Eingabe: Bitte 1, 2, 3, 4 oder 5 eingeben.")


def result(player, computer):
print("Schere...")
print("Stein...")
print("Papier..")
print("Echse...")
print("Spock?!")
print("Computer hat {0} gewählt!".format(names[computer]))
global player_score, computer_score
if player == computer:
print("Unentschieden")
else:
if rules[player] == computer:
print("Du hast gewonnen!")
player_score += 1
else:
print("Du hast verloren!")
computer_score += 1


def play_again():
antwort = raw_input("Willst du noch eine Runde spielen? J/N: ")
if antwort in ("j", "J", "ja", "Ja"):
return anwort
else:
print("Danke, dass du mein Spiel gespielt hast.")


def score():
   global player_score, computer_score
   print("HIGH SCORES")
   print("Player: ", player_score)
   print("Computer: ", computer_score)

#Hauptprogramm
...
Benutzeravatar
__blackjack__
User
Beiträge: 14030
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@edebec: Die Funktionen sind soweit fertig und es nicht zum laufen bekommen wiederspricht sich ja. Und was heisst das denn konkret? An welcher Stelle macht das Programm denn nicht das was Du erwartest?

Was schon mal überhaupt nicht gut ist, ist das da noch Python 2 verwendet wird. Das wird nicht mehr unterstützt, da gibt es nicht einmal mehr Sicherheitsupdates. Also als erstes mal Python 3 installieren und schauen was da geändert werden muss. Also auf jeden Fall schon mal `raw_input()` durch `input()` ersetzen.

Eingerückt wird mit vier Leerzeichen pro Ebene.

Vergiss bitte sofort das es ``global`` überhaupt gibt.

Funktionen sollte man testen bevor man sie irgendwo verwendet. `play_again()` funktioniert nicht wegen einem Fipptehler.

Konstanten werden KOMPLETT_GROSS geschrieben und Variablen haben auf Modulebene nichts zu suchen.

Die Indirektion mit den Zahlen für die Spielzüge ist unnötig, da kann man auch gleich die Zeichenketten als Werte verwenden.

Funktions- und Methodennamen beschreiben üblicherweise die Tätigkeit die von der Funktion oder Methode durchgeführt wird. `game()` und `result()` sind keine Tätigkeiten, und `score()` und `play_again()` sind zwar Tätigkeiten, die von den beiden Funktionen aber gar nicht durchgeführt werden.

`play_again()` gibt entweder explizit eine nicht-leere Zeichenkette zurück oder implizit `None` und der Aufrufer nutzt das dann als Wahrheitswert. Die Funktion sollte also eigentlich `True` oder `False` als Ergebnis liefern.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
edebec
User
Beiträge: 20
Registriert: Donnerstag 9. Juli 2020, 14:36

danke erst mal für die Antwort!
Habe jetzt auf 3.8.3 upgedatet, das raw_input durch Input ersetzt, merke aber so bisher keinen Unterschied..

durch was könnte ich das "global" ersetzen?
den Tippfehler in play_again habe ich auch gefunden - danke!

Kannst du mir vllt weiterhelfen, wie ich am besten mein Hauptprogramm schreibe, um mein Programm einmal zum laufen zu bekommen?
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Funktionen sollten die benötigten Variablen über Parameter erhalten und Ergebnisse mit Hilfe von return wieder zurück geben.

Hier ein kleines Beispiel, ich hoffe das ist verständlich:

Code: Alles auswählen

def berechne_quadratzahl(zahl):
    return zahl * zahl
    
    
def main():
    eingabe_zahl = int(input("Gib eine Zahl ein: "))
    ergebnis = berechne_quadratzahl(eingabe_zahl)
    print(ergebnis)
    
    
    
main()
Benutzeravatar
sparrow
User
Beiträge: 4535
Registriert: Freitag 17. April 2009, 10:28

@edebec:

Code hier im Forum sollte man in Code-Tags setzen. Die erscheinen automatisch, wenn du in "Vollständiger Editor & Vorschau" auf den "</>"-Button drückst. Zwischen diese Code-Tags gehört dein Code. Das sorgt dafür, dass die Einrückungen erhalten bleiben, was bei Python essentiell.

Ich weiß ehrlich gesagt nicht so richtig, was du mit "Hauptprogramm" meinst. Wenn du das alles selbst geschrieben hast und nun nicht weißt, wie du eine bestimmte Funktion davon aufrufst, wäre das sehr seltsam.

Ein dict ist ein Wörterbuch, das einem Schlüssel einen Wert zuweist. Dabei kann ein Schlüssel aber nur ein Mal vorkommen. Deshalb macht dieser Code von dir nicht was du denkst:

Code: Alles auswählen

>>> stein = 1
>>> papier = 2
>>> schere = 3
>>> echse = 4
>>> spock = 5
>>> rules = {
schere: papier,
papier: stein,
stein: echse,
echse: spock,
spock: schere,
schere: echse,
echse: papier,
papier: spock,
spock: stein,
stein: schere
}

>>> rules
{3: 4, 2: 5, 1: 3, 4: 2, 5: 1}
>>> len(rules)
5
edebec
User
Beiträge: 20
Registriert: Donnerstag 9. Juli 2020, 14:36

Code: Alles auswählen

#Schere Stein Papier Echse Spock

import random



stein = 1
papier = 2
schere = 3
echse = 4
spock = 5

"""
Regeln:
Schere schneidet Papier         
Papier bedeckt Stein                
Stein zerquetscht Echse
Echse vergiftet Spock
Spock zertrümmert Schere
Schere köpft Echse
Echse frisst Papier
Papier widerlegt Spock
Spock verdampft Stein
Stein schleift Schere
"""


names = {stein: "Stein", papier: "Papier", schere: "Schere", echse: "Echse", spock: "Spock"}
rules = { 
    schere: papier, 
    papier: stein, 
    stein: echse, 
    echse: spock, 
    spock: schere, 
    schere: echse, 
    echse: papier, 
    papier: spock, 
    spock: stein, 
    stein: schere 
    }


player_score = 0
computer_score = 0


def start():
    print("Lass uns eine Runde Schere, Stein, Papier, Echse, Spock spielen!")
    while game():
        pass
    score()


def game():
    player = move()
    computer = random.randint(1, 5)
    result(player, computer)
    return play_again()


def move():
    while True:
        player = input("Stein = 1\nPapier = 2\nSchere = 3\nEchs = 4\nSpock = 5\nWähle weise: ") 
        try:
            player = int(player)
            if player in (1, 2, 3, 4, 5):
                return player                                                                               
        except ValueError:
            pass
            print("Falsche Eingabe: Bitte 1, 2, 3, 4 oder 5 eingeben.")


def result(player, computer):
    print("Schere...")
    print("Stein...")
    print("Papier..")
    print("Echse...")
    print("Spock?!")
    print("Computer hat {0} gewählt!".format(names[computer]))
    global player_score, computer_score
    if player == computer:
        print("Unentschieden")
    else:
        if rules[player] == computer:
            print("Du hast gewonnen!")
            player_score += 1
        else:
            print("Du hast verloren!")
            computer_score += 1


def play_again():
    antwort = input("Willst du noch eine Runde spielen? J/N: ")
    if antwort in ("j", "J", "ja", "Ja"):
        return antwort
    else:
        print("Danke, dass du mein Spiel gespielt hast.")


def score():
   global player_score, computer_score
   print("HIGH SCORES")
   print("Player: ", player_score)
   print("Computer: ", computer_score)

#Hauptprogramm

Hoffe es ist so besser! Danke!
Programmier seit 3 Wochen, brauche es für meine berufliche Weiterbildung und muss es mir selbst aneignen..
Ich würde mein Programm jetzt mal gern zum laufen bringen und mir was vom Terminal ausgeben lassen, dazu muss ich meinen Funktionen Variablen übergeben um es zu starten?!
Benutzeravatar
sparrow
User
Beiträge: 4535
Registriert: Freitag 17. April 2009, 10:28

Na, du hast doch eine Funktion start - ruf sie halt auf?

Es ist aber nicht empfehlenswert 100 Zeilen Code zu schreiben und dann zu hoffen, dass sie funktionieren. Normalerweise kapselt man zwar seinen Code in Funktionen - aber die ruft man während der Entwicklung auch mal auf um zu sehen, ob sie überhaupt tun, was man denkt.
edebec
User
Beiträge: 20
Registriert: Donnerstag 9. Juli 2020, 14:36

wie gesagt, völligst jungfräulich was das Thema Python angeht..ich habe mal in C++ programmiert, allerdings is das schon ein Jahrzehnt her...

wenn ich es mit Start ausführe bekomme ich in der Zeile 67

Code: Alles auswählen

if player in (1, 2, 3, 4, 5):
                return player          
 
eine Fehlermeldung: SyntaxError: invalid character in identifier
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Das Dictionary ist immer noch Falsch, jeder Schlüssel darf nur 1x vorkommen. Ich würde jede wählbare Möglichkeit als Key erstellen und dann als Value zu dem Key eine Liste mit den Möglichkeiten die durch den Key geschlagen werden, also so in der Art:

Code: Alles auswählen

RULES = {"Schere":["Papier", "Echse"],
         "Stein":["Schere", "Echse"],
         "Papier":["Stein", "Spock"],
         "Echse":["Papier", "Spock"],
         "Spock":["Stein", "Schere"]}
Du benutzt ja immer noch global, das sollte nirgends mehr vorkommen.

Hab hier mal ein kleines, rudimentäres Beispiel gebastelt:

Code: Alles auswählen

import random

RULES = {"Schere":["Papier", "Echse"],
         "Stein":["Schere", "Echse"],
         "Papier":["Stein", "Spock"],
         "Echse":["Papier", "Spock"],
         "Spock":["Stein", "Schere"]}

def check_results(player_choice, computer_choice):
    if player_choice != computer_choice:
        if computer_choice in RULES[player_choice]:
            result = "Du hast gewonnen!"
        else:
            result = "Du hast verloren!"
    else:
        result = "Gleichstand!"
    return result


def main():
    while True:
        player_choice = input(f"Bitte wähle ein Gegenstand aus [{', '.join(RULES.keys())}]: ")
        computer_choice = random.choice(list(RULES.keys()))
        print(f"Computer wählt {computer_choice}!")
        winner = check_results(player_choice, computer_choice)
        print(winner)

main()
Wenn du noch nicht so viel mit Python zu tun hattest kann es nicht Schaden das Grundlagentutorial einmal durch zu arbeiten
Zuletzt geändert von Jankie am Freitag 10. Juli 2020, 08:55, insgesamt 1-mal geändert.
edebec
User
Beiträge: 20
Registriert: Donnerstag 9. Juli 2020, 14:36

global player_score, computer_score

meinst du die beiden Variablen? Wo liegt das Problem an globalen Variablen? Alternative?

sorry, für viele ist das hier vllt selbstverständlich aber man lernt auch nicht das schwimmen, wenn man in den See geworfen wird ...
Benutzeravatar
sparrow
User
Beiträge: 4535
Registriert: Freitag 17. April 2009, 10:28

@edebec: Der Vergleich mit dem Schwimmen hinkt. Schwimmen lernt man im Unterricht. Und der Unterricht wäre dann das von Jankie verlinkte Tutorial.

Wie man "global" los wird, wurde hier bereits gesagt: Funktionen bekommen alles, was sie benötigen, als Parameter und geben ihr Ergebnis mittels return zurück. Kein magischer Zugriff auf Variablen außerhalb der Funktion, es sei denn, es handelt sich um Konstanten. Konstanten heißen so, weil sie konstant sind. Die ändern sich nicht. Wenn du global brauchst, stimmt am Design etwas nicht.
Das "Problem" ist, dass niemand Code mit globalen Variablen warten oder nachvollziehen kann, weil die Änderung überall im Code stehen kann.
edebec
User
Beiträge: 20
Registriert: Donnerstag 9. Juli 2020, 14:36

@sparrow

werde mit das Tutorial zu Herzen nehmen und mich in den nächsten Wochen durcharbeiten!

ok, hast du ein konkretes Beispiel wie ich das in meinem Fall umsetzen kann?

vielen Dank euch für die Unterstützung!!!
Benutzeravatar
__blackjack__
User
Beiträge: 14030
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@edebec: Konkretes Beispiel für was? Argumente und Rückgabewerte? Da hat Jankie doch schon etwas gezeigt.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
edebec
User
Beiträge: 20
Registriert: Donnerstag 9. Juli 2020, 14:36

@blackjack

ich bin verwirrt...
Ist mit dem Lösungsvorschlag von Jackie das Problem mit den globalen Variablen bereits gelöst?!
Sirius3
User
Beiträge: 18265
Registriert: Sonntag 21. Oktober 2012, 17:20

@edebec: jackie hat ein Beispiel, gezeigt, wie man korrekt Funktionen schreibt, dieses Beispiel mußt Du natürlich auf Dein Programm anwenden. Also konkret, `result` braucht weitere Argumente und `score` überhaupt erst mal welche. Und da das in `game` aufgerufen wird, braucht `game` diese Argumente auch, und die müssen in `start` passend initialisiert und übergeben werden. Umgekehrt muß `result` die geänderten Score-Werte wieder zurückgeben und das muß `game` genauso tun, und diese müssen in `start` korrekt verarbeitet werden.
edebec
User
Beiträge: 20
Registriert: Donnerstag 9. Juli 2020, 14:36

@Sirius3

habe mir sein Programm mal kopiert und abspielen lassen, läuft ohne Probleme. Habe auch nichts anderes erwartet, wenn ich hier nach Hilfe frage..

Ist jemand so gut von euch und kann mir meins Verbessern?
Sirius3
User
Beiträge: 18265
Registriert: Sonntag 21. Oktober 2012, 17:20

Wer will/muß hier Python lernen?
Wo kommst Du konkret mit den Tipps hier nicht weiter?
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Wie man ohne global auskommt habe ich eher in dem vorheringen Besipiel gezeigt.

Zur Veranschaulichung:

So sieht es mit global aus (global sollte man nicht benutzen):

Code: Alles auswählen

def berechne_quadratzahl():
    global ergebnis
    ergebnis = eingabe_zahl * eingabe_zahl
    
    
def main():
    global eingabe_zahl
    eingabe_zahl = int(input("Gib eine Zahl ein: "))
    berechne_quadratzahl()
    print(ergebnis)
    
main()
und so sieht es ohne global aus, wenn die Funktionen die benötigten Werte per Paramter bekommen und per return zurück geben:

Code: Alles auswählen

def berechne_quadratzahl(zahl):
    return zahl * zahl
    
    
def main():
    eingabe_zahl = int(input("Gib eine Zahl ein: "))
    ergebnis = berechne_quadratzahl(eingabe_zahl)
    print(ergebnis)
    
    
    
main()
edebec
User
Beiträge: 20
Registriert: Donnerstag 9. Juli 2020, 14:36

@Sirius3

Habe Probleme damit, das Geschriebenen von euch in mein Programm umzusetzen..möglicherweise ist es einfacher, wenn ich "richtig mit falsch" vergleichen kann..
Benutzeravatar
__blackjack__
User
Beiträge: 14030
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@edebec: Das hat Jankie doch jetzt auch noch mal gegenübergestellt.

Sorry, aber so langsam kann man den Eindruck gewinnen Du willst einfach nur, dass Dir jemand Deine Hausaufgabenlösung auf dem Silbertablett serviert. Der Verdacht, das der gezeigte Code auch schon nicht von Dir selbst ist, steht ja bereits im Raum.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Antworten