Schere Stein Papier (Fehler im Code, Anfänger)

Code-Stücke können hier veröffentlicht werden.
Antworten
KevinKre
User
Beiträge: 2
Registriert: Freitag 16. Dezember 2022, 12:05

Guten Tag zusammen,

ich mache gerade eine dieser "100 days of code challenges". Die aktuelle Aufgabe ist das Schere, Stein, Papier Spiel.
Nun habe ich ein Spiel gebaut das keinen Fehlercode produziert, aber dennoch nicht richtig funktioniert.
Egal welche Eingabe ich mache, die Konsole sagt immer es war ein Unentschieden. Wie es in dem ersten if-Statement steht:
print("First round was undecided!",name1,"chose",p1r1,"and",name2,"chose",p2r1) (Zeile 16)

Das Thema Scorewert habe ich bisher so nicht gelernt, es war ein Versuch der leider ebenfalls nicht funktioniert.
Ich habe alle Codezeilen zu dem Thema gelöscht und nochmal probiert. Das löst aber leider das erste Problem auch nicht.
Das hier ist mein Code:

print("\N{smiling face with sunglasses}","!!! Rock - Paper - Scissor !!!!","\N{smiling face with sunglasses}")
print()
name1 = input("Whats your name, player1? ")
name2 = input("Whats your name, player2? ")

from getpass import getpass as input

print("Hey", name1,"and", name2, "we'll play Rock, Paper, Scissor!")
print()
print("This programm wont show your choice to prevent scam")
print()
print("Choose between Rock = R, Paper = P and Scissor = S")
print()

p1r1 = input("Player1, choose R, P or S ")
p2r1 = input("Player2, choose R, P or S ")
score1 = int()
score2 = int()

if p1r1 == "R" or "r" and p2r1 == "R" or "r":
print("First round was undecided!",name1,"chose",p1r1,"and",name2,"chose",p2r1)
elif p1r1 == "R" or "r" and p2r1 == "S" or "s":
score1 + 1
print("Player 1won!",
name1,"chose",p1r1,"and",name2,"chose",p2r1)
elif p1r1 == "R" or "r" and p2r1 == "P" or "p":
score2 + 1
print("Player 2 won!",name1,"chose",p1r1,"and",name2,"chose",p2r1)
elif p1r1 == "S" or "s" and p2r1 == "R" or "R":
score2 + 1
print("Player 2 won!",name1,"chose",p1r1,"and",name2,"chose",p2r1)
elif p1r1 == "S" or "s" and p2r1 == "P" or "p":
score1 + 1
print("Player 1 won!",name1,"chose",p1r1,"and",name2,"chose",p2r1)
elif p1r1 == "S" or "s" and p2r1 == "S" or "s":
print("First round was undecided!" ,name1,"chose",p1r1,"and",name2,"chose",p2r1)
elif p1r1 == "P" or "p" and p2r1 == "R" or "r":
score1 + 1
print("Player 1 won!",name1,"chose",p1r1,"and",name2,"chose",p2r1)
elif p1r1 == "P" or "p" and p2r1 == "P" or "p":
print("First round was undecided!",name1,"chose",p1r1,"and",name2,"chose",p2r1)
elif p1r1 == "P" or "p" and p2r1 == "S" or "s":
score2 + 1
print("Player 2 won!",name1,"chose",p1r1,"and",name2,"chose",p2r1)
else:
print("try again")

print()
print(name1,"has",score1,"points")
print(name2,"has",score2,"points")

Ich könnte meinen Code einfach löschen und den richtigen aus der Lösung nehmen aber dann hätte ich nichts gelernt. Vielleicht hat jemand hier Zeit und Muße mir zu helfen.

Vielen Dank im Voraus!
Kevin
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Eingerückt wird immer mit 4 Leerzeichen pro Ebene, zwei sind zu wenig, da man dann die Einrückung nicht gut genug erkennen kann.
Importe stehen immer ganz oben in der Datei. `input` hat eine feste Bedeutung und sollte nicht mit einer anderen Funktion überschrieben werden.
Bei ganzen Sätzen benutzt man Formatstrings, anstatt die einzelnen Teile mit Komma bei print anzugeben.
Man benutzt keine kryptischen Abkürzungen, was soll plrl denn heißen?
`int()` als Weg 0 einzugeben ist schlecht, weil man da viel zu lange drüber nachdenken muß, was denn das für einen Wert ergibt.
Mit dem Ergebnis der Rechung `score1 + 1` machst Du nichts, das mußt Du noch einer Variable zuweisen.

Schau Dir mal Deine Bedinungen genauer an: `p1r1 == "R" or "r" and p2r1 == "R" or "r"`.
`and` bindet stärker als `or`, was den Ausdruck letztlich so auswertet: (p1r1 == "R") or ("r" and (p2r1 == "R")) or "r"
Es werden also drei Teilausdürcke ver`or`t, das Ergebnis ist der erste Ausdruck, dessen Wert als wahr ausgewertet wird. Also entweder ist p1r1 gleich "R" oder ("r" and (p2r1 == "R")) ist wahr oder "r" ist wahr. Letzteres ist immer wahr, weil es ein nicht-leerer String ist.
Schauen wir uns den Mittleren Ausdruck noch an. "r" ist immer wahr. Damit wird durch das `and` immer der zweite Ausdruck ausgewertet, (p2r1 == "R").
Wir haben also drei Fälle, p1r1 ist gleich "R", dann gibt der Gesamtausdruck True, unabhängig von p2r1.
Wir haben also drei Fälle, p1r1 ist ungleich "R" und p2r1 ist gleich "R", dann gibt der Gesamtausdruck auch True.
Trifft beides nicht zu, dann ist der Gesamtausdruck "r" was auch wahr ist.
Deshalb wird immer der erste if-Block betreten.

Codewiederholungen sollte man vermeiden, die gleichen if-Blöcke sollte man zumindest zu jeweils einem zusammenfassen.
Benutzeravatar
Kebap
User
Beiträge: 687
Registriert: Dienstag 15. November 2011, 14:20
Wohnort: Dortmund

Hey Kevin, sehr gut dass du nachfragst. So lernt man immer mehr dazu!
Du wirst hier von einigen Lesern noch ausführliche Hinweise bekommen, was du alles verbessern kannst.
Vorab von mir nur so viel: Deine Bedingungen bei "if" kann man so nicht schreiben:

if p1r1 == "R" or "r"

Man kann es so schreiben:

if p1r1 == "R" or p1r1 == "r"

Oder auch so:

if p1r1 in "Rr"

Oder beispielsweise so:

if p1r1.upper() == "R"

Aber dein erster Entwurf funktioniert nicht, weil dann auch geprüft wird ob "r" wahr ist, also nicht p1r1 == "r" sondern nur "r" selbst, und das ist zufällig immer wahr. Klingt komisch, ist aber so.
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
KevinKre
User
Beiträge: 2
Registriert: Freitag 16. Dezember 2022, 12:05

erstmal vielen Dank für die schnellen Antworten, das hilft mir wirklich sehr!
Ich habe versucht die Zeilensprünge durch Leerzeichen zu machen, aber es scheint das diese dann gelöscht werden. Ich hoffe in diesem Beitrag klappts.

@Sirius3

Von Formatstrings habe ich bisher noch nichts gehört. Ich google mal damit ich es zukünftig besser machen kann.

p1r1 habe ich für mich als Abkürzung für Player1Round1 genutzt. Für meinen nächsten Beitrag hier schreibe ich es besser aus oder kommentiere es. :)

Der Hinweis auf die Variable hat mir sehr geholfen. Ich habe es nun auf score1 = score1 + 1 geändert und es funktioniert. Danke!
Wie sollte ich die variable score1 denn anders definieren? Benutze ich "score1 = 0" funktioniert der Code wieder nicht mehr. Ich habe es nun auf "score1 = int(0)" geändert oder hättest du eine elegantere Lösung für mich?

Ich habe den Code nun nochmal angepasst um die Wiederholungen zu reduzieren:

Code: Alles auswählen

if player1Round1 == "R" or "r":
    if player2Round1 == "R":
        print("The game was undecided")
    elif player2Round1 == "P":
        print(name2,"won!")
        score2 = score2 +1 
    elif player2Round1 == "S":
        print(name1,"won!")
        score1 = score1 +1 
    else:
        print(name2,"your command were wrong, please try again!")
@Kebap
Danke für die konkreten Tipps.
if p1r1 == "R" or p1r1 == "r"
Interessant das dieser code nicht das selbe ergibt wie meine "Kurzfassung". Aber das muss man sich wohl einfach merken. Danke!


Viele Grüße
Kevin
Benutzeravatar
__blackjack__
User
Beiträge: 13068
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Das ist immer noch falsch mit dem ``or`` denn "r" ist immer noch *immer wahr*, womit der Ausdruck immer wahr ist.

``score1 = 0`` wäre richtigt. Das macht nichts anderes als ``score1 = int()`` oder ``score1 = int(0)``, nur das es eben nicht unnötig verkompliziert ausgedrückt ist.

Weiterer Tipp: Man könnte auch Tupel bilden und die vergleichen, also ``if (player_a_choice, player_b_choice) == ("R", "P"):``. Und das lässt sich mit dem Hinweis von Kebap kombinieren: ``if (player_a_choice, player_b_choice) in [("P", "R"), ("S", "P"), ("R", "S")]:``.

Man würde für die Spielzüge in der Regel auch Konstanten definieren, damit man nicht überlegen muss was "R", "S", und "P" bedeutet, sondern das direkt ablesen kann.

Edit: Namen werden per Konvention übrigens klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase). Und man nummeriert Namen nicht. Die Zahl bei `round` macht ja auch gar keinen Sinn, denn das ist ja nicht nur für Runde 1.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten