from itepifanio_deck.utils import Hand
from itepifanio_deck.core import FrenchDeck
import ipywidgets as widgets
from fastcore.basics import patch
UI
This nb designs a UI for the blackjack game
You may need to execute jupyter nbextension enable --py widgetsnbextension
and restart the nb to output the widgets.
# !jupyter nbextension enable --py widgetsnbextension
Deck and cards UI
The card and deck are represented as buttons in the UI
def card_button_factory(name: str):
return widgets.Button(
=True,
disable=name,
description=widgets.Layout(height="auto", width="auto"),
layout )
= card_button_factory("test")
card_button card_button
Since the deck is a single button we can define them in a Layout
class GameLayout(widgets.TwoByTwoLayout):
def __init__(self, *args, **kwargs):
self.deck_button = widgets.Button(
="Deck (52)",
description="click me to draw a card!",
tooltip=widgets.Layout(height="100%", width="auto"),
layout
)
self.reset_button = widgets.Button(
="Reset",
description=widgets.Layout(height="auto", width="auto")
layout
)
self.displayer = widgets.Text(
="Pull a card",
value=True,
disabled=widgets.Layout(width="50%")
layout
)
super().__init__(
=self.deck_button,
top_left=widgets.HBox([self.reset_button, self.displayer]),
top_right=widgets.HBox([]),
bottom_right="center",
justify_items="50%",
width="center",
align_items )
GameLayout()
@patch
def on_deck_click(self: GameLayout, callback):
self.top_left.on_click(callback)
@patch
def on_reset_click(self: GameLayout, callback):
= self.top_right.children[0]
reset_button reset_button.on_click(callback)
@patch
def update_num_cards(self: GameLayout, number: int):
self.top_left.description = f"Deck ({number})"
@patch
def clear_hand(self: GameLayout):
self.bottom_right = widgets.HBox([])
@patch
def update_hand(self: GameLayout, hand: Hand):
= {
suits 'diamonds': '♢',
'hearts': '♡',
'spades': '♤',
'clubs': '♧'
}
self.bottom_right = widgets.HBox(
f'{card.rank} {suits[card.suit]}')
[card_button_factory(for card in hand]
)self.update_num_cards(52 - len(hand))
= hand.value() # type: ignore
value
if value > 21:
self.displayer.value = f"Game over ({value})"
elif value == 21:
self.displayer.value = "You won!"
else:
self.displayer.value = str(value)
class BlackJack:
def __init__(self):
self.view = GameLayout()
self.view.on_deck_click(self.on_deck_clicked)
self.view.on_reset_click(self.on_reset_clicked)
self._start()
def _start(self):
self.deck = FrenchDeck()
self.deck.shuffle()
self.hand = Hand()
def on_deck_clicked(self, event):
= self.deck.draw()
card self.hand.draw(card)
self.view.update_hand(self.hand)
def on_reset_clicked(self, event):
self._start()
self.view.update_hand(self.hand)
def __repr__(self):
self.view)
display(return ""
= BlackJack()
blackjack blackjack