Blackjack-Skript in Python
Vor kurzem hatte ich einen Python-Test und bin leider gescheitert. Ich werde meinen Test wiederholen und der Lehrer gab mir den Tipp, effizienter und sauberer zu arbeiten. Um dies zu üben, habe ich vor ungefähr 2 Wochen ein Blackjack-Spiel mit Python gemacht und es ihm geschickt, um es zu überprüfen. Er hat noch geantwortet und mein Test ist nächste Woche. Kann jemand einen Blick darauf werfen und vielleicht auf Dinge hinweisen, die verbessert werden müssen? Bitte, ich möchte diesen Test wirklich bestehen.
import itertools
import random as rd
from time import sleep as s
#making 3 decks with playing cards and assign them 2 to 14
cards1 = list(itertools.product(range(2, 15),['spade', 'heart', 'diamond', 'club']))
cards2 = list(itertools.product(range(2, 15),['spade', 'heart', 'diamond', 'club']))
cards3 = list(itertools.product(range(2, 15),['spade', 'heart', 'diamond', 'club']))
#combine the 3 decks to make 1
cards = list(cards1+cards2+cards3)
#shuffle deck
rd.shuffle(cards)
def blackjack(cards):
money = 10
while True:
print('you have', money, 'money')
bet = int(input('select amount to bet: \n'))
if money < bet:
print('you dont have that much money....')
else:
playing = True
#draw first card and remove it from the deck
fcard = rd.choice(cards)
cards.remove(fcard)
first_point, first_name = fcard
#check if first card is 11 points or more (to change back to 10 points unless it's ace)
if first_point == 11:
first_point = 10
first_name = str('Jack'+' of '+first_name)
elif first_point == 12:
first_point = 10
first_name = str('Queen'+' of '+first_name)
elif first_point == 13:
first_point = 10
first_name = str('King'+' of '+first_name)
elif first_point == 14:
first_point = 11
first_name = str('Ace'+' of '+first_name)
#show the first drawn card
print(first_point, first_name)
s(0.7)
#draw second card and remove it from the deck
scard = rd.choice(cards)
cards.remove(scard)
second_point, second_name = scard
#checking second card for the same
if second_point == 11:
second_point = 10
second_name = str('Jack'+' of '+second_name)
elif second_point == 12:
second_point = 10
second_name = str('Queen'+' of '+second_name)
elif second_point == 13:
second_point = 10
second_name = str('King'+' of '+second_name)
elif second_point == 14:
second_point = 11
second_name = str('Ace'+' of '+second_name)
#show second card
print(second_point, second_name)
s(0.7)
points = first_point + second_point
#check if first 2 cards make a blackjack
if points == 21:
print('Blackjack!')
bet *= 2
print('you won', bet, 'money')
money += bet
playing = False
print(points, 'points out of 21')
if money == 0:
print('you are broke!')
exit()
#after the first 2 cards i need to determine if the player wants more cards
while playing:
card = input('press enter to draw a card or type x to stop')
if card != 'x':
a = rd.choice(cards)
x, y = a
#going through the same checking system as the first 2 cards
if x == 11:
y = str('Jack'+' of '+second_name)
x = 10
elif x == 12:
y = str('Queen'+' of '+second_name)
x = 10
elif x == 13:
y = str('King'+' of '+second_name)
x = 10
elif x == 14:
y = str('Ace'+' of '+second_name)
x = 11
print(x, y)
s(0.7)
cards.remove(a)
points += x
if points > 21:
print('BUST')
points = 0
playing = False
#if the player has x as input the player stops drawing
elif card == 'x':
playing = False
print(points, 'points')
#let the dealer do the same card drawing
result = dealer_draw(cards)
print('you scored: ', points, '\n', 'the bank scored: ', result)
s(0.7)
#compare obtained points with the dealer's points
if points > result:
print('you win!')
money += bet
elif points == result:
print('draw')
elif points < result:
print('you lose')
money -= bet
elif points == 0 and result == 0:
print('you lose')
money -= bet
def dealer_draw(cards):
#2 empty prints to maintain clear overview
print()
print()
a = 0
#first 2 cards (same as for the player until.....)
cd1 = rd.choice(cards)
cards.remove(cd1)
points_first, name_first = cd1
if points_first == 11:
name_first = str('Jack'+' of '+name_first)
points_first = 10
elif points_first == 12:
name_first = str('Queen'+' of '+name_first)
points_first = 10
elif points_first == 13:
name_first = str('King'+' of '+name_first)
points_first = 10
elif points_first == 14:
name_first = str('Jack'+' of '+name_first)
points_first = 11
print(points_first, name_first)
s(0.7)
cd2 = rd.choice(cards)
cards.remove(cd2)
points_second, name_second = cd2
if points_second == 11:
name_second = str('Jack'+' of '+name_second)
points_second = 10
elif points_second == 12:
name_second = str('Queen'+' of '+name_second)
points_second = 10
elif points_second == 13:
name_second = str('King'+' of '+name_second)
points_second = 10
elif points_second == 14:
name_second = str('Ace'+' of '+name_second)
points_second = 11
print(points_second, name_second)
s(0.7)
#..... here (scroll up)
full_points = points_first + points_second
a += full_points
#have the minimal bank draw set at 16
while a < 16:
print("bank's total = ", a)
s(0.7)
draw = rd.choice(cards)
cards.remove(draw)
add_number, full_name = draw
if add_number == 11:
full_name = str('Jack'+' of '+full_name)
add_number = 10
elif add_number == 12:
full_name = str('Queen'+' of '+full_name)
add_number = 10
elif add_number == 13:
full_name = str('King'+' of '+full_name)
add_number = 10
elif add_number == 14:
full_name = str('Ace'+' of '+full_name)
add_number = 11
print(add_number, full_name)
s(0.7)
a += add_number
print("bank's total = ", a)
s(0.7)
#check if bank scored more than 21 and if so, return 0
if a > 21:
return 0
else:
return a
blackjack(cards)
Kommentare sind willkommen, aber bitte denken Sie daran, dass dies meine erste Programmiersprache ist und ich noch viel zu lernen habe. Vielen Dank!
Antworten
Es tut mir leid, aber mein Wissen in Kartenspielen ist verrostet. Bitte korrigieren Sie mich, wenn etwas nicht stimmt!
Fangen Sie immer ungültige Eingaben ab
Angenommen, der Benutzer gibt etwas ein, das er über diese Codezeile erhält
print('you have', money, 'money')
bet = int(input('select amount to bet: \n'))
Wählen Sie den zu wettenden Betrag:
Nun, was passiert , wenn der Benutzer versehentlich eingegeben E . In diesem Fall schlägt Ihr Programm fehl, da es eine Eingabe in Form einer Ganzzahl erwartet. Aus diesem Grund sollten Sie ungültige Eingaben immer mit Try and Except in Python abfangen
try:
bet = int(input("select amount to be: "))
except Exception:
print("Invalid input! Please enter a number\n")
Auf diese Weise, wenn der Benutzer eingegeben hat
Wählen Sie den Betrag aus, der sein soll: Ich mag Python
Es würde dem Benutzer geben
Ungültige Eingabe! Bitte gebe eine Nummer ein
Beenden Sie nicht nach ungültiger / schlechter Eingabe
Wenn der Benutzer in Ihrem Programm eine Wette eingibt, die höher ist als das Geld, das er hat, stoppt das Programm einfach. Es wird nicht wieder abgespielt, warum sollte das passieren?
Sie sollten den Benutzer auffordern, erneut eine gültige Eingabe einzugeben, damit ein Fehler von ihm nicht zur sofortigen Beendigung des Programms führt
while True:
try:
bet = int(input("select amount to be: "))
except Exception:
print("Invalid input! Please enter a number\n")
continue
if bet > money:
print("Bet placed higher than balance!")
continue
break
Das Beste, was Sie jetzt tun können, ist, dies in eine separate Funktion zu verschieben, die aufgerufen wird take_input(), damit Ihre blackjack()Funktion sauber bleibt und die Eingabe jetzt einfach ist
bet = take_input()
Ja, Sie haben noch ein paar Codezeilen geschrieben. Aber jetzt wissen Sie, dass Ihr Programm das Richtige tut, wenn Ausnahmen auftreten.
Code vereinfachen - 1
first_name = str('Jack'+' of '+first_name)
Ist das gleiche wie
first_name = "Jack of " + first_name
Sie müssen nicht konvertieren, strda dies first_namebereits eine Zeichenfolge ist.
Gleiches gilt für die folgenden Zeilen, die ich aus Ihrem Code extrahiert habe.
first_name = str('Queen'+' of '+first_name)
first_name = str('King'+' of '+first_name)
first_name = str('Ace'+' of '+first_name)
Vermeiden Sie magische Zahlen
Nehmen Sie dieses Beispiel
if first_point == 11:
first_point = 10
first_name = str('Jack'+' of '+first_name)
elif first_point == 12:
first_point = 10
first_name = str('Queen'+' of '+first_name)
elif first_point == 13:
first_point = 10
first_name = str('King'+' of '+first_name)
elif first_point == 14:
first_point = 11
first_name = str('Ace'+' of '+first_name)
10, 11, 12... sind bekannt als magische Zahlen . Ich musste nachdenken, um zu verstehen, was sie hier taten, bis ich endlich verstand, dass es sich um Karten handelte.
Der gute Weg, um damit umzugehen, ist die Verwendung von Pythons Enums .
from enum import Enum
class Card(Enum):
jack = 11
queen = 12
king = 13
....
Korrigieren Sie die Werte, wenn sie falsch sind.
Jetzt sieht Ihr if-else-Thread für den Leser so viel klarer aus
if first_point == Card.jack.value:
...
elif first_point == Card.queen.value:
...
elif first_point = Card.king.value:
....
Ein weiterer Pluspunkt ist, was ist, wenn Sie den Wert des Königs von xauf ändern möchten y. Würden Sie zu Hunderten von Orten gehen, um herauszufinden, wo Sie im Zusammenhang mit dem König eine numerische Konstante verwendet haben könnten?
Hier können Sie einfach einstellen king.value, was Sie wollen.
import sleep as s
import sleep as ss(0.5)Das hatte mich am Anfang auch verwirrt, ich musste herausfinden was sbedeutete. sist überhaupt nicht sinnvoll, es verwirrt nur jeden, der Ihren Code liest. Dies sleepimpliziert jedoch eindeutig, dass Sie ... schlafen möchten! Verwenden Sie immer aussagekräftige Namen
Arbeit in Funktionen aufteilen
Derzeit ist Ihre blackjack()Funktion mit vielen Aufgaben überfüllt, die in ihre eigenen Funktionen verschoben werden sollten. So wie wir die Eingabeprozedur in eine separate take_input()Funktion verschoben haben , können Sie viele sinnvolle Funktionen erstellen, mit denen Sie draw_new_card()eine neue Karte aus dem Stapel zurückgeben können.
Ist Ihr Code trocken oder nass?
Entschuldigen Sie meine Kenntnisse über Kartenspiele
Sie haben die Prozedur
- ziehe eine Karte
- Überprüfen Sie, ob die Karte
>=11 Punkte hat - Drucken Sie den Punkt und den Namen
Warum dann dasselbe noch einmal für die zweite Karte wiederholen? Sie haben dasselbe zweimal geschrieben. Einmal für die erste Karte und dann für die zweite. du hast dich wiederholt Der beste Weg ist, Wiederholungen in eine Funktion einzubeziehen. Alles was Sie tun müssen, ist
def new_card():
card = draw_new_card()
point, name = card
process_card(point, name)
return point, name
# in the blackjack function #
first_point, first_name = new_card()
print(first_point, first_name)
sleep(0.5)
second_point, second_name = new_card()
print(second_point, second_name)
......
Sie können sehen, dass die Verwendung von Funktionen sehr geholfen hat.
Regeln der Namensgebung
Nur um den Punkt von @Aryan Parekh zu bekräftigen: Verwenden Sie keine bedeutungslosen Abkürzungen, z.
import random as rd
from time import sleep as s
Es gibt keinen Vorteil, Sie haben das Lesen und Verstehen des Codes erschwert. Also: verwenden random.choice(cards)statt : rd.choice(cards). random.choice ist selbsterklärend.
Guter Code sollte intuitiv sein, das beginnt mit den richtigen Namenskonventionen. Selbst wenn Sie faul sind, sollten Sie längere und aussagekräftigere Namen verwenden. Ihre IDE sollte ohnehin automatisch vervollständigt werden.
Sie haben Variablen wie a, cd2, x, y, die mich an Spaghetti Basic aus den 80ern erinnern. Ich mag Kartenspiele total, deshalb kann ich nicht viel zum Algo sagen, aber ich kann den Code kommentieren.
Zum Glück haben Sie einige Kommentare abgegeben.
Konsistenz
Sie verwenden die Auswahlfunktion einige Male, jedoch mit sehr unterschiedlichen Variablennamen:
a = rd.choice(cards)
x, y = a
und später:
draw = rd.choice(cards)
cards.remove(draw)
add_number, full_name = draw
Ich denke, hier ist mehr Konsistenz gefragt. Wenn Sie einige Anweisungen wiederverwenden, können Sie dieselben Variablennamen auch an anderer Stelle verwenden oder sich zumindest an einige sinnvolle Namensmuster halten. Zeichnen ist ein Name, der Sinn macht. Aber add_number sieht wirklich wie ein Funktionsname aus, also würde ich es card_number oder so ähnlich nennen (obwohl Sie diese Variable effektiv zum Inkrementieren eines anderen Werts verwenden).
Wiederholung
Es ist Wiederholung im Code zB:
#making 3 decks with playing cards and assign them 2 to 14
cards1 = list(itertools.product(range(2, 15),['spade', 'heart', 'diamond', 'club']))
cards2 = list(itertools.product(range(2, 15),['spade', 'heart', 'diamond', 'club']))
cards3 = list(itertools.product(range(2, 15),['spade', 'heart', 'diamond', 'club']))
Zunächst einmal sind einige Aussagen überflüssig:
#combine the 3 decks to make 1
cards = list(cards1+cards2+cards3)
Da Sie drei Listen verketten, ist das resultierende Objekt auch ein Listenobjekt. Ist cards = cards1 + cards2 + cards3also ausreichend und ergibt das gleiche Ergebnis.
Karten 1/2/3 sind genau gleich, also wiederholen Sie genau das gleiche dreimal hintereinander. Dies ist offensichtlich falsch und kann vereinfacht werden. Sie könnten einfach schreiben:
cards2 = cards1
cards3 = cards1
Auch wenn das nicht elegant ist, vermeiden Sie zumindest Wiederholungen und Ihre Reichweite wird nur einmal deklariert.
Ein besserer Weg:
cards = list(itertools.product(range(2, 15), ['spade', 'heart', 'diamond', 'club'])) *3
Sie haben Ihre Sequenz also dreimal wiederholt und eine neue Liste erstellt. Da Sie itertools verwenden, können Sie auch itertools.repeat verwenden, wodurch Sie einen Generator erhalten, während * nSie eine Liste erhalten, die hier in Ordnung ist.
Verkettung
draw = rd.choice(cards)
cards.remove(draw)
add_number, full_name = draw
if add_number == 11:
full_name = str('Jack'+' of '+full_name)
add_number = 10
full_name ist eine Zeichenfolge, sodass Sie alle diese Elemente sicher verketten können. Oder noch besser, verwenden Sie einen F-String (Python> = 3.6):
full_name = f"Jack of {full_name}"