feat: début de la correction pour le blackjack

This commit is contained in:
Bertrand Benjamin 2021-06-09 14:32:04 +02:00
parent e613a95712
commit 7d301e7019
2 changed files with 177 additions and 74 deletions

0
__init__.py Normal file
View File

View File

@ -12,11 +12,30 @@ Chaque joueur sera représenter par une main de carte c'est à dire une liste (a
L'ensemble des joueurs sera une file de mains. On ne fera pas de différence entre un jour et le croupier. L'ensemble des joueurs sera une file de mains. On ne fera pas de différence entre un jour et le croupier.
Règles du jeu (depuis Wikipédia):
La partie oppose individuellement chaque joueur contre la banque. Le but est de battre le croupier sans dépasser 21. Dès qu'un joueur fait plus que 21, on dit qu'il « Brûle » ou qu'il « crève » et il perd sa mise initiale. La valeur des cartes est établie comme suit :
de 2 à 9 valeur nominale de la carte
chaque figure + le 10 surnommées "bûche" 10 points
l'As → 1 ou 11 (au choix)
Un Blackjack est composé d'un As et d'une « buche » (carte ayant pour valeur 10, donc 10, J, Q ou K). Cependant, si le joueur atteint le point 21 en 3 cartes ou plus on compte le point 21 et non pas Blackjack; de même lorsque le joueur sépare deux as et qu'il reçoit une buche pour l'un d'eux.
Au début de la partie, le croupier distribue une carte face visible à chaque joueur et tire une carte face visible également pour lui. Il tire ensuite pour chacun une seconde carte face visible et tire une seconde carte face cachée pour lui au Blackjack américain. Au blackjack européen, le croupier tire sa seconde carte après le tour de jeu des joueurs.
Puis, il demande au premier joueur de la table (joueur situé à sa gauche) l'option qu'il désire choisir. Si le joueur veut une carte, il doit l'annoncer en disant « Carte ! ». Le joueur peut demander autant de cartes qu'il le souhaite pour approcher la valeur sans la dépasser. Si après le tirage d'une carte, il a dépassé 21, il perd sa mise et le croupier passe au joueur suivant. S'il décide de s'arrêter, en disant « Je reste », le croupier passe également au joueur suivant.
Le croupier répète cette opération jusqu'à ce que tous les joueurs soient servis.
Ensuite, il joue pour lui selon une règle simple et codifiée « la banque tire à 16, reste à 17 ». Ainsi, le croupier tire des cartes jusqu'à atteindre un nombre compris entre 17 et 21 que l'on appelle un point. S'il fait plus de 21, tous les joueurs restants gagnent mais s'il fait son point, seuls gagnent ceux ayant un point supérieur au sien (sans avoir sauté). Dans cette situation, le joueur remporte l'équivalent de sa mise. En cas d'égalité le joueur garde sa mise mais n'empoche rien en plus. À noter que le blackjack (une bûche et un as en deux cartes) est plus fort que 21 fait en ayant tiré plus de deux cartes. Si un joueur fait blackjack et que le banquier fait 21 en 3 cartes ou plus, le joueur fait blackjack et remporte une fois et demi de sa mise. Le banquier lui gagne contre tous les joueurs ayant 20 ou moins. Réciproquement si la banque a un as et une bûche, elle gagne contre tout joueur ayant 21 en ayant tiré plus de deux cartes. Dans ce cas, si un joueur fait également blackjack, il peut récupérer sa mise mais n'est pas payé, le jeu étant à égalité. Un joueur ayant fait blackjack (sauf blackjack à la banque auquel cas il y a égalité) remporte une fois et demi sa mise.
""" """
import random import random
from .pile import Pile import itertools
from .file import File from pile import Pile
from file import File
values = { values = {
2: 2, 2: 2,
@ -27,6 +46,7 @@ values = {
7: 7, 7: 7,
8: 8, 8: 8,
9: 9, 9: 9,
10: 10,
"Valet": 10, "Valet": 10,
"Dame": 10, "Dame": 10,
"Roi": 10, "Roi": 10,
@ -35,25 +55,59 @@ values = {
colors = ["Pique", "Coeur", "Trefle", "Carreau"] colors = ["Pique", "Coeur", "Trefle", "Carreau"]
class Player:
def __init__(self, name, hand=None):
self.name = str(name)
if hand is None:
self.hand = []
else:
self.hand = hand
@property
def score(self):
"""Calcule le score du joueur"""
if self.hand:
return sum([values[c[0]] for c in self.hand])
return 0
def want_continue(self, croupier_cards):
"""Fait le choix de demander ou non des cartes
Pour cela, le joueur peut voir les cards du croupier
:param croupier_cards: cartes du croupier
:return: booléen en fonction de s'il veut ou non continuer
"""
if self.score >= 17:
return False
return True
def __repr__(self):
return f"<Player {self.name}: {self.hand}>"
def build_deck(): def build_deck():
"""Construit une pile de 54 cartes mélangés """Construit une pile de 52 cartes mélangés
Pour mélanger les cartes de façon aléatoire, vous pouvez utiliser la bibliothèque random. Pour mélanger les cartes de façon aléatoire, vous pouvez utiliser la bibliothèque random.
:return: Une pile de 54 cartes différentes mélangées :return: Une pile de 52 cartes différentes mélangées
:example: :example:
>>> deck = build_deck() >>> deck = build_deck()
>>> deck.is_empty() >>> deck.is_empty()
False False
>>> for i in range(54): >>> for i in range(52):
deck.pop() ... if deck.is_empty():
... print(f"Pas assez de cartes. Il y en uniquement {i}")
... break
... card = deck.pop()
>>> deck.is_empty() >>> deck.is_empty()
True True
""" """
deck = Pile() deck = Pile()
cards = zip(values, colors) cards = list(itertools.product(values, colors))
random.shuffle(cards) random.shuffle(cards)
for card in cards: for card in cards:
deck.append(card) deck.append(card)
@ -71,36 +125,19 @@ def build_players(nbr):
>>> players.is_empty() >>> players.is_empty()
False False
>>> for _ in range(3): >>> for _ in range(3):
print(players.pop()) ... print(players.pop())
[] <Player 0: []>
[] <Player 1: []>
[] <Player 2: []>
>>> players.is_empty() >>> players.is_empty()
True True
""" """
players = File() players = File()
# ----------------------- for n in range(nbr):
players.append(Player(n))
# -----------------------
return players return players
def compute_score(hand):
"""Calculer le score d'une main
:param hand: liste de cartes
:return: le score associé
:example:
>>> hand = [(2, "Pique"), ("As", "Coeur"), (8, "Carreau")]
>>> compute_score(hand)
11
>>> compute_score([])
0
"""
pass
def can_play(player): def can_play(player):
"""détermine si un joueur peu encore jouer """détermine si un joueur peu encore jouer
@ -108,15 +145,71 @@ def can_play(player):
:return: True if his score is lower than 21 :return: True if his score is lower than 21
:example: :example:
>>> >>> hand = [(2, "Pique"), ("As", "Coeur"), (8, "Carreau")]
>>> p = Player(1, hand)
>>> can_play(p)
True
>>> hand = [(2, "Pique"), ("As", "Coeur"), (6, "Carreau")]
>>> p = Player(1, hand)
>>> can_play(p)
True
>>> hand = [(2, "Pique"), ("As", "Coeur"), ("Valet", "Carreau")]
>>> p = Player(1, hand)
>>> can_play(p)
False
""" """
pass if player.score <= 21:
return True
return False
def won(player):
"""Détermine si un jour a gagné c'est à dire qu'il a atteint les 21 points
:param player: une joueur avec une main
:return: True si le joueur a exactement 21 points
:example:
>>> hand = [(2, "Pique"), ("As", "Coeur"), (8, "Carreau")]
>>> p = Player(1, hand)
>>> won(p)
True
>>> hand = [(2, "Pique"), ("As", "Coeur"), (6, "Carreau")]
>>> p = Player(1, hand)
>>> won(p)
False
"""
if player.score == 21:
return True
return False
def draw(player, deck):
"""Distribue 1 carte à un joueur
:param player: Un joueur
:param deck: pile avec toutes les cartes
:return: (player, deck) le joueur a une carte en plus en main
:example:
>>> player = build_players(1).pop()
>>> deck = build_deck()
>>> player, deck = draw(player, deck)
>>> len(player.hand)
1
>>> player, deck = draw(player, deck)
>>> len(player.hand)
2
"""
player.hand.append(deck.pop())
return (player, deck)
def first_draw(players, deck): def first_draw(players, deck):
"""Distribue 2 cartes à chaque joueur """Distribue 2 cartes à chaque joueur
:param players: pile de joueur avec des mains vides :param players: file de joueur avec des mains vides
:param deck: pile avec toutes les cartes :param deck: pile avec toutes les cartes
:return: (players, deck) les joueurs ont deux cartes et le deck a été mis à jour. :return: (players, deck) les joueurs ont deux cartes et le deck a été mis à jour.
@ -124,64 +217,74 @@ def first_draw(players, deck):
:example: :example:
>>> players = build_players(3) >>> players = build_players(3)
>>> deck = build_deck() >>> deck = build_deck()
>>> players, deck = fist_draw(players, deck) >>> players, deck = first_draw(players, deck)
>>> for i in range(3): >>> for i in range(3):
print(len(players.pop())) ... print(len(players.pop().hand))
2 2
2 2
2 2
""" """
pass drawn = File()
while not players.is_empty():
p = players.pop()
def draw(players, deck): p, deck = draw(p, deck)
"""Distribue 1 carte à chaque joueur p, deck = draw(p, deck)
drawn.append(p)
:param players: pile de joueur avec des mains non vides return drawn, deck
:param deck: pile avec toutes les cartes
:return: (players, deck) les joueurs ont plus de deux cartes et le deck a été mis à jour.
:example:
>>> players = build_players(3)
>>> deck = build_deck()
>>> players, deck = fist_draw(players, deck)
>>> players, deck = draw(players, deck)
>>> for i in range(3):
print(len(players.pop()))
3
3
3
"""
pass
def play_backjack(nbr_players): def play_backjack(nbr_players):
"""Simule une partie de blackjack entre "nbr_players" """Simule une partie de blackjack entre "nbr_players"
:param nbr_players: nombre de joueurs On ne vous demande pas de reproduire une simulation parfaite du jeu blackjack. Commencez par une version simple les joueur s obtiennent petit à petit les cartes. Puis complexifiez en ajoutant une par une les règles.
:return: File de tuples (joueur, score, tour élimination) dans l'ordre d'élimination La version de correction ne prend pas en compte toutes les règles du jeux ni tout le déroulement d'une partie.
:param nbr_players: nombre de joueurs
:return: la liste des joueurs gagnants
:example: :example:
>>> >>>
""" """
result = File() winners = []
# ----------------------- deck = build_deck()
players = build_players(nbr_players)
dealer = Player("croupier")
# ----------------------- # Première main
return result dealer = draw(dealer, deck)
players, deck = first_draw(players, deck)
still_in_game_players = File()
while not players.is_empty():
p = players.pop()
print(p)
if won(p):
winners.append(p)
elif can_play(p):
still_in_game_players.append(p)
else:
print(f"{p} est éliminé")
if winners:
return winners
dealer = draw(dealer, deck)
if won(dealer):
return [dealer]
players = still_in_game_players
while not players.is_empty():
p = players.pop()
while p.want_continue(dealer.hand):
p, deck = draw(p, deck)
if won(p):
winners.append(p)
break
elif not can_play(p):
break
if can_play(p):
pass
if __name__ == "__main__": if __name__ == "__main__":
play_backjack(3)
# Test : Distribution de toutes les cartes
j = DeckOfCards()
while not j.is_empty():
print(j.depile())
# Test : Calcul de mains de blackjack
j = DeckOfCards()
while not j.is_empty():
mjoueurain_bjack(j)