FAOD-DUI4/blackjack/blackjack.py

274 lines
9.4 KiB
Python
Raw Normal View History

"""
Projet jeu de Blackjack
=======================
2021-06-09 16:33:07 +00:00
Objectif du TP
--------------
2021-06-09 16:33:07 +00:00
L'objectif est de construire une simulation de partie de Blackjack. Pour cela, la structure du programme est donnée. Vous ne pouvez pas la modifier. Des exemples du fonctionnement de chaque fonctions sont donnés et votre implémentation doit correspondre à ces exemples.
2021-06-09 16:33:07 +00:00
Il n'y a pas d'ordre particulier à respecter pour coder ce projet.
2021-06-09 16:33:07 +00:00
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.
Modélisation
------------
Une carte sera un tuple (valeur, couleur). Toutes les valeurs possibles sont déjà codée dans la variable CARD_VALUES et les couleurs dans CARD_COLORS (voir plus bas).
Les joueurs et le croupier seront modélisé par la classe Player qui n'est pas à construire et qui est importé depuis NSI_Bertrand.blackjack.
Ils s'initialisent avec un nom et ont par défaut une main vide.
>>> p = Player("nom")
>>> p
<Player nom: []>
Ils ont deux attributs
- *hand* qui est liste des cartes qu'ils ont en main
>>> p.hand
[]
- *score* qui est le score associé à leur main
>>> p.score
0
Ils ont une méthode: want_continue qui permet de donner le choix au joueur de continue.
>>> p.want_continue([])
True
L'ensemble des joueurs sera une file de mains.
Aide et vérifications
---------------------
Vous avez deux façons de tester vos programmes:
- En écrivant votre utilisation du code dans le "if __name__ == __main__:" puis en exécutant votre script.
- En utilisant pytest
pytest --doctest-modules blackjack.py
Les fonctions à compléter ont déjà été programmées. Si vous avez besoin d'une fonction que vous n'avez pas encore programmée vous même, vous pouvez décommanter les lignes contenant "from NSI_Bertrand.blackjack import ...." à la suite de la fonction.
"""
import random
2021-06-09 16:33:07 +00:00
import itertools
# Pour que ces deux lignes marchent, il faut que vous ayez copié vos modules pile et file à coté de ce fichier
from pile import Pile
from file import File
# CARD_VALUES = {
# 2: 2,
# 3: 3,
# 4: 4,
# 5: 5,
# 6: 6,
# 7: 7,
# 8: 8,
# 9: 9,
# 10: 10,
# "Valet": 10,
# "Dame": 10,
# "Roi": 10,
# "As": 11, # dans la vrai version du BlackJack, l'As peut valoir 1 ou 11 au choix du joueur.
# }
from NSI_Bertrand.blackjack import values as CARD_VALUES
# CARD_COLORS = ["Pique", "Coeur", "Trefle", "Carreau"]
from NSI_Bertrand.blackjack import colors as CARD_COLORS
# Player class
# Cette classe modélise un joueur de carte (un joueur mais aussi le croupier)
#
from NSI_Bertrand.blackjack import Player
def build_deck():
2021-06-09 16:33:07 +00:00
"""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.
2021-06-09 16:33:07 +00:00
:return: Une pile de 52 cartes différentes mélangées
:example:
>>> deck = build_deck()
>>> deck.is_empty()
False
2021-06-09 16:33:07 +00:00
>>> for i in range(52):
... if deck.is_empty():
... print(f"Pas assez de cartes. Il y en uniquement {i}")
... break
... card = deck.pop()
>>> deck.is_empty()
True
"""
2021-06-09 16:33:07 +00:00
pass
# from NSI_Bertrand.blackjack import build_deck
def build_players(nbr):
"""Construit une file de joueurs avec des mains vides
:param nbr: nombre de joueurs (on se limitera à 4 joueurs)
:return: file de mains vides
:example:
>>> players = build_players(3)
>>> players.is_empty()
False
>>> for _ in range(3):
2021-06-09 16:33:07 +00:00
... print(players.pop())
<Player 0: []>
<Player 1: []>
<Player 2: []>
>>> players.is_empty()
True
"""
2021-06-09 16:33:07 +00:00
pass
2021-06-09 16:33:07 +00:00
# from NSI_Bertrand.blackjack import build_players
2021-06-09 16:33:07 +00:00
def can_play(player):
"""détermine si un joueur peu encore jouer
:param player: une joueur
:return: True if his score is lower than 21
:example:
>>> hand = [(2, "Pique"), ("As", "Coeur"), (8, "Carreau")]
2021-06-09 16:33:07 +00:00
>>> 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
2021-06-09 16:33:07 +00:00
# from NSI_Bertrand.blackjack import can_play
2021-06-09 16:33:07 +00:00
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:
2021-06-09 16:33:07 +00:00
>>> 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
"""
pass
2021-06-09 16:33:07 +00:00
# from NSI_Bertrand.blackjack import won
2021-06-09 16:33:07 +00:00
def draw(player, deck):
"""Distribue 1 carte à un joueur
:param player: Un joueur
:param deck: pile avec toutes les cartes
2021-06-09 16:33:07 +00:00
:return: (player, deck) le joueur a une carte en plus en main
:example:
2021-06-09 16:33:07 +00:00
>>> player = build_players(1).pop()
>>> deck = build_deck()
2021-06-09 16:33:07 +00:00
>>> player, deck = draw(player, deck)
>>> len(player.hand)
1
>>> player, deck = draw(player, deck)
>>> len(player.hand)
2
"""
pass
2021-06-09 16:33:07 +00:00
# from NSI_Bertrand.blackjack import draw
2021-06-09 16:33:07 +00:00
def first_draw(players, deck):
"""Distribue 2 cartes à chaque joueur
:param players: file de joueur avec des mains vides
:param deck: pile avec toutes les cartes
2021-06-09 16:33:07 +00:00
:return: (players, deck) les joueurs ont deux cartes et le deck a été mis à jour.
:example:
>>> players = build_players(3)
>>> deck = build_deck()
2021-06-09 16:33:07 +00:00
>>> players, deck = first_draw(players, deck)
>>> for i in range(3):
2021-06-09 16:33:07 +00:00
... print(len(players.pop().hand))
2
2
2
"""
pass
2021-06-09 16:33:07 +00:00
# from NSI_Bertrand.blackjack import first_draw
def play_backjack(nbr_players):
"""Simule une partie de blackjack entre "nbr_players"
2021-06-09 16:33:07 +00:00
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.
2021-06-09 16:33:07 +00:00
La version de correction ne prend pas en compte toutes les règles du jeux ni tout le déroulement d'une partie.
2021-06-09 16:33:07 +00:00
:param nbr_players: nombre de joueurs
:return: la liste des joueurs gagnants
"""
2021-06-09 16:33:07 +00:00
pass
2021-06-09 16:33:07 +00:00
# from NSI_Bertrand.blackjack import play_backjack
2021-06-09 16:33:07 +00:00
if __name__ == "__main__":
print(play_backjack(3))