Schere Stein Papier Spiel

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
computatrum physicus
User
Beiträge: 8
Registriert: Samstag 29. Juli 2017, 16:37

Hi habe heute wieder ein kleines Programm geschrieben;)(Mein 2tes) Wie findet ihr es? Habt ihr noch Ideen für andere Programme (Müssen keine Spiele sein)? <-- Sollten aber auch nicht zu schwer umsetzbar sein :lol:

Code: Alles auswählen

import random
import time
#Einleitung 

print(
"*******************\n"
"SCHERE STEIN PAPIER\n"
"*******************\n"
)

#Main

#Variablen

SSP = ["Schere","Stein","Papier"]

#Regeln

time.sleep(0.7)
print("Schere schneidet Papier\n")
time.sleep(0.7)
print("Papier umwickelt Stein\n")
time.sleep(0.7)
print("Stein schleift Schere\n")
time.sleep(0.7)

#User1
def Main():
	#1 oder 2 Spieler?
	try:
		SpielerAnzahl = int(input("Möchtest du gegen den Computer[1] oder einen 2.ten Spieler[2] spielen?\n"))
	except ValueError:
		print("Du musst eine ganze Zahl (1/2) eingeben!\n")
		SpielerAnzahl = int(input("Möchtest du gegen den Computer[1] oder einen 2.ten Spieler[2] spielen?\n"))
	if SpielerAnzahl == 2:
		UserName1 = input("Wie möchtest du heißen Spieler 1 ?\n")
		print("Willkommen",UserName1+".\n")
		UserName2 = input("Wie möchtest du heißen Spieler 2 ?\n")
		print("Willkommen",UserName2+".\n")
	elif SpielerAnzahl == 1:
		UserName1 = input("Wie möchtest du heißen?")
		print("Willkommen",UserName1+".\n")
		
		
	try:
		time.sleep(0.7)
		UserInput = int(input(UserName1[0].upper()+UserName1[1:len(UserName1)]+" bitte wähle zwischen Schere[1], Stein[2], Papier[3].\n"))

	except ValueError:
		time.sleep(1)
		print("Deine Eingabe war leider falsch!")
		time.sleep(1)
		UserInput = int(input(UserName1[0].upper()+UserName1[1:len(UserName1)]+" bitte wähle eine ganze Zahl zwischen 1 und 3!\n"))

	if UserInput > 3 or UserInput < 1:
		time.sleep(1)
		UserInput = int(input(UserName1[0].upper()+UserName1[1:len(UserName1)]+" bitte wähle eine ganze Zahl zwischen 1 und 3!\n"))
	
#User2	
	if SpielerAnzahl == 2:
		try:
			time.sleep(0.7)
			User2Input = int(input(UserName2[0].upper()+UserName2[1:len(UserName2)]+" bitte wähle zwischen Schere[1], Stein[2], Papier[3].\n"))

		except ValueError:
			time.sleep(1)
			print("Deine Eingabe war leider falsch!")
			time.sleep(1)
			User2Input = int(input(UserName2[0].upper()+UserName2[1:len(UserName2)]+" bitte wähle eine ganze Zahl zwischen 1 und 3!\n"))

		if User2Input > 3 or User2Input < 1:
			time.sleep(1)
			User2Input = int(input(UserName2[0].upper()+UserName2[1:len(UserName2)]+" bitte wähle eine ganze Zahl zwischen 1 und 3!\n"))
#Ausgabe des Siegers/Verlierers User vs User2
	
		if UserInput == User2Input:
			print("Unendschieden ihr hattet beide", SSP[UserInput-1],".\n")
		elif UserInput == 1 and User2Input == 2:
			print(UserName2[0].upper()+UserName2[1:len(UserName2)],"du hast gewonnen. Du hattest", SSP[User2Input-1],"genommen und ",UserName1, " hatte", SSP[UserInput-1], "genommen.\n")
		elif UserInput == 1 and User2Input == 3:
			print(UserName1[0].upper()+UserName1[1:len(UserName1)],"du hast gewonnen. Du hattest", SSP[UserInput-1],"genommen und ",UserName2," hatte", SSP[User2Input-1], "genommen.\n")
		elif UserInput == 2 and User2Input == 1:
			print(UserName1[0].upper()+UserName1[1:len(UserName1)],"du hast gewonnen. Du hattest", SSP[UserInput-1],"genommen und ",UserName2," hatte", SSP[User2Input-1], "genommen.\n")
		elif UserInput == 2 and User2Input == 3:
			print(UserName2[0].upper()+UserName2[1:len(UserName2)],"du hast gewonnen. Du hattest", SSP[User2Input-1],"genommen und ",UserName1, " hatte", SSP[UserInput-1], "genommen.\n")
		elif UserInput == 3 and User2Input == 1:
			print(UserName2[0].upper()+UserName2[1:len(UserName2)],"du hast gewonnen. Du hattest", SSP[User2Input-1],"genommen und ",UserName1, " hatte", SSP[UserInput-1], "genommen.\n")
		elif UserInput == 3 and User2Input == 2:
			print(UserName1[0].upper()+UserName1[1:len(UserName1)],"du hast gewonnen. Du hattest", SSP[UserInput-1],"genommen und ",UserName2," hatte", SSP[User2Input-1], "genommen.\n")
		else:
			print("Es scheint ein Fehler aufgetreten zu sein:/ Wir versuchen es so schnell wie möglich zu beheben!\n")
#Computer

	elif SpielerAnzahl == 1:
		ComInput = random.randint(1,3)	

#Ausgabe des Siegers/Verlierers User vs Com

		if UserInput == ComInput:
			print("Unendschieden du und der Computer hatten beide", SSP[UserInput-1],"genommen.\n")
		elif UserInput == 1 and ComInput == 2:
			print(UserName1,"du hast leider verloren. Du hattest", SSP[UserInput-1],"genommen und der Computer hatte", SSP[ComInput-1], "genommen.\n")
		elif UserInput == 1 and ComInput == 3:
			print(UserName1[0].upper()+UserName1[1:len(UserName1)],"du hast gewonnen. Du hattest", SSP[UserInput-1],"genommen und der Computer hatte", SSP[ComInput-1], "genommen.\n")
		elif UserInput == 2 and ComInput == 1:
			print(UserName1[0].upper()+UserName1[1:len(UserName1)],"du hast gewonnen. Du hattest", SSP[UserInput-1],"genommen und der Computer hatte", SSP[ComInput-1], "genommen.\n")
		elif UserInput == 2 and ComInput == 3:
			print(UserName1[0].upper()+UserName1[1:len(UserName1)],"du hast leider verloren. Du hattest", SSP[UserInput-1],"genommen und der Computer hatte", SSP[ComInput-1], "genommen.\n")
		elif UserInput == 3 and ComInput == 1:
			print(UserName1[0].upper()+UserName1[1:len(UserName1)],"du hast leider verloren. Du hattest", SSP[UserInput-1],"genommen und der Computer hatte", SSP[ComInput-1], "genommen.\n")
		elif UserInput == 3 and ComInput == 2:
			print(UserName1[0].upper()+UserName1[1:len(UserName1)],"du hast gewonnen. Du hattest", SSP[UserInput-1],"genommen und der Computer hatte", SSP[ComInput-1], "genommen.\n")
		else:
			print("Es scheint ein Fehler aufgetreten zu sein:/ Wir versuchen es so schnell wie möglich zu beheben!\n")

#Noch eine Runde?
	def Neustart():
		time.sleep(0.7)
		Neustart = input("Willst du noch eine Runde spielen? Ja[Y], Nein[N]\n")
	
		if Neustart.upper() == "Y":
			time.sleep(0.7)
			print("Na dann viel Spaß!\n")
			time.sleep(0.7)
			Main()
		elif Neustart.upper() == "N":
			time.sleep(0.7)
			print("Danke fürs spielen!")
		else:
			time.sleep(0.7)
			Neustart()
	Neustart()
if __name__ == "__main__":
	Main()
BlackJack

@computatrum physicus: Da wo der Kommentar ``# Main`` steht beginnt nicht das Hauptprogramm. Und dort wo der Kommentar ``# Variablen`` steht wird eine Konstante definiert. Alles bis auf diese Konstante gehört auch nicht auf Modulebene sondern mindestens in die `Main()`-Funktion verschoben, deren Name klein geschrieben werden sollte.

Wobei dann das gesamte Programm in *einer* Funktion steht. Das ist sowohl von der Menge als auch von der Komplexität her genug um es sinnvoll auf mehrere Funktionen aufzuteilen.

Es sind wieder jede Menge Codewiederholungen auf verschiedenen Ebenen vorhanden die dort nicht sein sollten. Statt beispielsweise immer und immer wieder bei der Ausgabe den ersten Buchstaben der Benutzernamen in einen Grossbuchstaben zu wandeln, könnte man das *einmal* direkt nach der Eingabe machen und spart sich so eine Menge Tipparbeit. Falls Du Dir Tipparbeit durch viel Kopieren und Einfügen gespart hast: Das ist ein Warnzeichen das man gerade dabei ist Code und/oder Daten zu duplizieren statt das an einer Stelle zu lösen oder eine Funktion zu schreiben.

Zum Beispiel die Eingabe eines Namens (und grossschreiben des ersten Buchstabens) kann man in einer Funktion machen, die man dann für jeden der beiden Spieler einmal aufruft. Schon hat man diesen Code nicht doppelt.

Eingabe einer Zahl zwischen 1 und n (inklusive) ist ein Fall für eine Funktion, weil man das sowohl bei der Frage nach der Anzahl der Spieler als auch bei der Frage nach dem Objekt braucht. Zudem sollte man die Frage so lange Wiederholen bis der Benutzer eine korrekte Eingabe gemacht hat, und nicht einmal ``try``/``except`` verwenden und im ``except`` dann den gleichen Code noch mal, aber ohne Ausnahmebehandlung stehen haben.

Das Spiel zwischen zwei Spielern und dem zwischen einem Spieler und dem Computer unterscheidet sich kaum — trotzdem hast Du das alles zweimal im Code stehen. Der Unterschied ist doch nur das beim Spiel gegen den Computer kein zweiter Name eingegeben werden muss, sondern 'Computer' angenommen werden kann, und das man bei zwei Spielern den zweiten Spieler nach dem Gegenstand fragt und beim Spiel gegen den Computer der Gegenstand für Spieler 2 per Zufall gezogen wird. Alles andere kann vom selben Code erledigt werden.

Funktionen innerhalb von Funktionen zu definieren kann manchmal sinnvoll sein, Stichwort „closures“, ist es im Falle von `Neustart()` aber nicht.

Die Funktion enthält ausserdem zwei Fehler: `Neustart` wird innerhalb der Funktion noch mal als lokaler Name definiert an den eine Zeichenkette gebunden wird, womit der Aufruf im letzten ``else``-Zweig scheitern wird, denn Zeichenketten kann man nicht aufrufen.

Zudem ist dieser Aufruf und der von `Main()` innerhalb von `Neustart()` in einer Programmiersprache die keine „tail call optimization“ (TCO) bietet, ein Fehler, denn rekursive Aufrufe sind kein Ersatz für einfache Schleifen. Wenn Du so etwas machst wirst Du früher oder später das Problem bekommen, dass das Programm mit einer Ausnahme abbricht weil Du zu viele rekursive Aufrufe gemacht hast.

Die Kommentare sollten nicht am Zeilenanfang anfangen wenn das was sie kommentieren weiter eingerückt ist. Damit durchbrichst Du die Einrückung optisch, die ja eine wichtige Information vermittelt.

Und die Namen solltest Du wirklich wie im Style Guide for Python Code schreiben, also Konstanten in GROSSBUCHSTABEN, Klassen in MixedCase, und alles andere klein_mit_unterstrichen.
BlackJack

Mal einiges an Redundanz rausgenommen und die `main()`-Funktion ist immer noch deutlich zu lang für meinen Geschmack (völlig ungetestet):

Code: Alles auswählen

import random
import time

DELAY = 0.7
MOVES = ['Schere', 'Stein', 'Papier']


def ask_number(prompt, choices):
    print(prompt)
    for i, choice in enumerate(choices, 1):
        print('[{}] {}'.format(i, choice))

    while True:
        try:
            value = int(input())
        except ValueError:
            print('Bitte eine Zahl eingeben!')
        else:
            if 1 <= value <= len(choices):
                return value
            print('Bitte eine Zahl von 1 bis {}!', len(choices))


def ask_user_name(prompt):
    while True:
        name = input(prompt).strip()
        if name:
            break
        print('Bitte mindestens ein Zeichen eingeben!')

    name = name[0].upper() + name[1:]
    print('Willkommen', name + '.\n')
    return name


def ask_yes_no(prompt):
    while True:
        time.sleep(DELAY)
        answer = input(prompt).upper()
        if answer == 'Y':
            return True
        elif answer == 'N':
            return False


def main():
    print(
        '*******************\n'
        'SCHERE STEIN PAPIER\n'
        '*******************\n'
    )
    time.sleep(DELAY)
    print('Schere schneidet Papier\n')
    time.sleep(DELAY)
    print('Papier umwickelt Stein\n')
    time.sleep(DELAY)
    print('Stein schleift Schere\n')
    time.sleep(DELAY)

    while True:
        spieleranzahl = ask_number(
            'Gegen wen möchtest Du spielen?', ['Computer', 'zweiter Spieler']
        )

        user_name_1 = ask_user_name('Wie möchtest du heißen Spieler 1?\n')

        if spieleranzahl == 1:
            user_name_2 = 'Computer'
        elif spieleranzahl == 2:
            user_name_2 = ask_user_name('Wie möchtest du heißen Spieler 2?\n')
        else:
            assert False  # `spieleranzahl` has illegal value.

        user_1_move = ask_number('{} bitte wähle.'.format(user_name_1), MOVES)
        
        if spieleranzahl == 1:
            user_2_move = random.randint(1, len(MOVES))
        elif spieleranzahl == 2:
            user_2_move = ask_number(
                '{} bitte wähle.'.format(user_name_2), MOVES
            )
        else:
            assert False  # `spieleranzahl` has illegal value.

        if user_1_move == user_2_move:
            print(
                'Unentschieden ihr hattet beide', MOVES[user_1_move - 1], '.\n'
            )
        else:
            if (
                user_1_move == 1 and user_2_move == 2
                or user_1_move == 2 and user_2_move == 3
                or user_1_move == 3 and user_2_move == 1
            ):
                winner, winner_move, loser, loser_move = (
                    user_name_2, MOVES[user_2_move - 1],
                    user_name_1, MOVES[user_1_move - 1],
                )

            elif (
                user_1_move == 1 and user_2_move == 3
                or user_1_move == 2 and user_2_move == 1
                or user_1_move == 3 and user_2_move == 2
            ):
                winner, winner_move, loser, loser_move = (
                    user_name_1, MOVES[user_1_move - 1],
                    user_name_2, MOVES[user_2_move - 1],
                )
            else:
                assert False  # Unknown result.

            print(
                winner, 'du hast gewonnen. Du hattest', winner_move,
                'genommen und ', loser, ' hatte', loser_move, 'genommen.\n'
            )

        if ask_yes_no('Willst du noch eine Runde spielen? Ja[Y], Nein[N]\n'):
            time.sleep(DELAY)
            print('Na dann viel Spaß!\n')
            time.sleep(DELAY)
        else:
            time.sleep(DELAY)
            print('Danke fürs spielen!')
            break


if __name__ == '__main__':
    main()
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

@computatrum physicus: Hatte das Script gestern kopiert und einmal durchgespielt. Für einen Anfang ist es gut, keine Frage. Damit liegst Du über den Durchschnitt von vielen anderen Einsteigern, würde ich meinen. Doch im nächsten Schritt könntest Du das Script wirklich noch durch die Verwendung von Funktionen weiter entwickeln.
Jetzt hättest Du mehr als eine Möglichkeit. Entweder Du entscheidest Dich die von BlackJack gegebene Version nachzuvollziehen oder Du packst in einem ersten Schritt sich wiederholende Sätze nur einmal in eine Funktion und übergibst die erforderlichen Werte an die Funktion und dort wo die Sätze standen, rufst Du nur noch die Funktion auf. Ist vielleicht anfänglich etwas leichter umsetzbar.

Dann, werfe einmal einen Blick in Lib/..., dort findest Du viele einsehbare Dateien und Du erhältst ein gutes Gefühl für die Schreibweise und für die Zeilenlänge, die nicht mehr als 79 Zeichen betragen sollte. 100 ginge auch noch, doch nehme Dir da im Editor eine Marke, an der Du Dich orientierst. Alles was in Klammern steht, lässt sich meist problemlos auf mehrere Zeilen verteilen, wobei Du Dich dabei ebenfalls an den von BlackJack verlinkten PEP 8 Leitfaden orientieren kannst.
Antworten