@kartodis: BASIC vor 30 Jahren auf dem PC könnte ja noch GW-BASIC gewesen sein. Das hat ja schon nicht mehr die Einschränkung, dass bei Namen nur die ersten beiden Zeichen signifikant sind, aber es war aus verschiedenen Gründen unüblich das auszunutzen. Also hier die gute Nachricht: Man ist bei Python nicht mehr darauf beschränkt ein oder zweibuchstabige Namen zu verwenden! Wenn man Spieler meint sollte man `spieler` schreiben und nicht `s` und bei Punkten `punkte` und nicht `p`.
Kommentare sollten dem Leser einen Mehrwert über den Code geben. Faustregel: Kommentare beschreiben nicht *was* der Code macht, denn das steht da ja bereits als Code, sondern *warum* er das *so* macht, sofern das nicht offensichtlich ist. Insbesondere der ``# Schleife``-Kommentar vor der ``while``-Schleife ist überflüssig, aber auch ``# Eingabe der Namen`` ist etwas was dem Leser nichts sagt was er da nicht auch am Code ablesen kann. Der erste Kommentar würd einen guten Docstring für das Modul abgeben.
Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst, und nur aufgerufen wird wenn das Modul als Programm ausgeführt wird, aber nicht wenn es importiert wird.
Ein paar von den kurzen kryptischen Namen wird man los wenn man nicht jedes noch so kleine Zwischenergebnis an einen Namen bindet.
”Magischen” Zahlen sollte man einen Konstantennamen spendieren, damit der Leser weiss was die bedeuten und damit man sie einfacher ändern kann.
Erster Zwischenstand:
Code: Alles auswählen
#!/usr/bin/env python3
"""
Programm zum Zusammenzählen von Punkten in einem Kartenspiel
"""
GEWINNPUNKTZAHL = 100
def main():
print("Bitte geben Sie den Namen des ersten Spielers ein:")
spieler_1 = input()
print("Bitte geben Sie den Namen des zweiten Spielers ein:")
spieler_2 = input()
punkte_1 = punkte_2 = 0
while punkte_1 <= GEWINNPUNKTZAHL and punkte_2 <= GEWINNPUNKTZAHL:
print("Wie viele Punkte hat", spieler_1, "in dieser Runde gemacht?")
punkte_1 += int(input())
print("Wie viele Punkte hat", spieler_2, "in dieser Runde gemacht?")
punkte_2 += int(input())
print(spieler_1, "hat insgesamt", punkte_1, " Punkte.")
print(spieler_2, "hat insgesamt", punkte_2, " Punkte.")
print("Das Spiel ist beendet.")
if __name__ == "__main__":
main()
Was hier noch unschön ist sind die Codewiederholungen und die nummerierten Namen. Nummerierte Namen sind in der Regel ein Warnzeichen das man sich entweder bessere Namen ausdenken will, oder das man gar keine einzelnen Namen haben will, sondern eine Datenstruktur. Oft eine Liste. Wenn man statt der nummerierten Namen Listen für Spielernamen und Punkte verwendet, dann wird man nicht nur die Codewiederholungen los, sondern kann das auch sehr einfach auf drei oder mehr Spieler erweitern in dem man einfach nur eine Konstante ändert, welche die Spieleranzahl enthält.
Code: Alles auswählen
#!/usr/bin/env python3
"""
Programm zum Zusammenzählen von Punkten in einem Kartenspiel
"""
SPIELERANZAHL = 2
GEWINNPUNKTZAHL = 100
def main():
spielernamen = [
input(f"Bitte geben Sie den Namen des {i}. Spielers ein:\n")
for i in range(1, SPIELERANZAHL + 1)
]
spielerpunkte = [0] * SPIELERANZAHL
while all(punkte <= GEWINNPUNKTZAHL for punkte in spielerpunkte):
for i in range(SPIELERANZAHL):
print(
"Wie viele Punkte hat",
spielernamen[i],
"in dieser Runde gemacht?",
)
spielerpunkte[i] += int(input())
for name, punkte in zip(spielernamen, spielerpunkte):
print(name, "hat insgesamt", punkte, " Punkte.")
print("Das Spiel ist beendet.")
if __name__ == "__main__":
main()
An der Lösung ist noch unschön, das zusammengehörende Daten — Namen und Punkte — nicht zusammengefasst sondern in zwei parallelen Datenstrukturen gespeichert sind. Das ist Stand GW-BASIC, oder was die meisten Heimcomputer vor 30 Jahren gemacht haben. 1991 kam dann mit DOS 5 nicht mehr GW-BASIC sondern QBasic und das hatte die Möglichkeit eigene Datentypen aus den vorhandenen zusammen zu setzen. Das sind in Python Klassen. Was ich auch noch ändern würde ist die Sprache für die Namen, denn im deutschen kommt es leider zu häufig vor das Einzahl und Mehrzahl das gleiche Wort benutzen. Bei `spieler` weiss man so nicht ob das *ein* Spieler ist, oder ein Container mit *allen* Spielern. Bei `player` vs. `players` ist das eindeutiger.
Code: Alles auswählen
#!/usr/bin/env python3
"""
Programm zum Zusammenzählen von Punkten in einem Kartenspiel
"""
PLAYER_COUNT = 2
WINNING_POINT_COUNT = 100
class Player:
def __init__(self, name):
self.name = name
self.points = 0
def main():
players = [
Player(input(f"Bitte geben Sie den Namen des {i}. Spielers ein:\n"))
for i in range(1, PLAYER_COUNT + 1)
]
while all(player.points <= WINNING_POINT_COUNT for player in players):
for player in players:
print(
"Wie viele Punkte hat", player.name, "in dieser Runde gemacht?"
)
player.points += int(input())
for player in players:
print(player.name, "hat insgesamt", player.points, " Punkte.")
print("Das Spiel ist beendet.")
if __name__ == "__main__":
main()
In QBasic würde das beispielsweise so aussehen:
Code: Alles auswählen
DECLARE FUNCTION WirHabenEinenGewinner% ()
CONST Spieleranzahl = 2, Gewinnpunktzahl = 100
TYPE SpielerTyp
Spielername AS STRING * 80
Punkte AS INTEGER
END TYPE
DIM SHARED Spieler(Spieleranzahl) AS SpielerTyp
DIM i AS INTEGER, Punkte AS INTEGER
FOR i = 1 TO Spieleranzahl
PRINT "Bitte geben sie den Namen des "; STR$(i) + ". Spielers ein:";
INPUT " ", Spieler(i).Spielername
NEXT
DO UNTIL WirHabenEinenGewinner
FOR i = 1 TO Spieleranzahl
PRINT "Wie viele Punkte hat "; RTRIM$(Spieler(i).Spielername);
PRINT " in dieser Runde gemacht:";
INPUT " ", Punkte
Spieler(i).Punkte = Spieler(i).Punkte + Punkte
NEXT
FOR i = 1 TO Spieleranzahl
PRINT "Spieler "; RTRIM$(Spieler(i).Spielername); " hat insgesamt";
PRINT Spieler(i).Punkte; "Punkte."
PRINT
NEXT
LOOP
PRINT "Das Spiel ist beendet!"
FUNCTION WirHabenEinenGewinner%
DIM i AS INTEGER, r AS INTEGER
FOR i = 1 TO Spieleranzahl
IF Spieler(i).Punkte > Gewinnpunktzahl THEN
r = -1
EXIT FOR
END IF
NEXT
WirHabenEinenGewinner = r
END FUNCTION