164 lines
5.9 KiB
Python
Executable File
164 lines
5.9 KiB
Python
Executable File
import customtkinter as ctk
|
|
from game_logic import can_split, get_split_decision, get_correct_decision
|
|
from .utils import load_card_images
|
|
from .components.cards import CardDisplay
|
|
from .components.buttons import ActionButtons
|
|
from .components.notifications import NotificationSystem
|
|
from .components.hints import HintSystem
|
|
from .components.stats import StatsDisplay
|
|
|
|
class BlackjackGUI:
|
|
def __init__(self, blackjackGame):
|
|
self.game_logic = blackjackGame
|
|
self.card_images = load_card_images()
|
|
self._setup_main_window()
|
|
self._create_components()
|
|
self.start_new_round()
|
|
|
|
def _setup_main_window(self):
|
|
"""Initialize main application window"""
|
|
self.app = ctk.CTk()
|
|
self.app.title("Blackjack Theory Trainer")
|
|
self.app.geometry("600x650+800+200")
|
|
self.app.protocol("WM_DELETE_WINDOW", self._on_main_window_close)
|
|
ctk.set_appearance_mode("dark")
|
|
|
|
def _create_components(self):
|
|
"""Create all UI components"""
|
|
# Card display
|
|
self.card_display = CardDisplay(self.app, self.card_images)
|
|
|
|
# Buttons (pass reference to self for callbacks)
|
|
self.buttons = ActionButtons(self.app, self)
|
|
|
|
# Notifications
|
|
self.notifications = NotificationSystem(self.app)
|
|
|
|
# Hint system
|
|
self.hints = HintSystem(self.app)
|
|
self.hints.set_hint_button(self.buttons.hint_button)
|
|
|
|
# Stats display
|
|
self.stats = StatsDisplay(self.app)
|
|
|
|
# Feedback label (only remaining widget in main file)
|
|
self.feedback_label = ctk.CTkLabel(
|
|
self.app,
|
|
text="",
|
|
font=("Arial", 20),
|
|
wraplength=550,
|
|
anchor="w"
|
|
)
|
|
self.feedback_label.pack(pady=20, padx=10, fill="x")
|
|
|
|
def start_new_round(self):
|
|
"""Start a new round of the game"""
|
|
self._reset_ui()
|
|
self.game_logic.start_new_round()
|
|
self._update_display()
|
|
|
|
def _reset_ui(self):
|
|
"""Reset UI for new round"""
|
|
self.hints._close_hint_window()
|
|
self.buttons.hint_button.configure(state="normal")
|
|
self.feedback_label.configure(text="")
|
|
self.buttons.next_round_button.configure(state="disabled")
|
|
self.buttons._enable_action_buttons(True)
|
|
self.buttons._reset_button_colors()
|
|
|
|
if hasattr(self.notifications, 'streak_label') and self.notifications.streak_label:
|
|
self.notifications.streak_label.configure(text="")
|
|
|
|
def _update_display(self):
|
|
"""Update all display elements"""
|
|
# Update card display
|
|
self.card_display.update_display(
|
|
self.game_logic.dealer_card,
|
|
self.game_logic.player_hand
|
|
)
|
|
|
|
# Handle blackjack
|
|
if self.game_logic.has_blackjack:
|
|
self.feedback_label.configure(
|
|
text="Blackjack! You win or get a push!",
|
|
text_color="green"
|
|
)
|
|
self.buttons._enable_action_buttons(False)
|
|
self.buttons.next_round_button.configure(state="normal")
|
|
|
|
# Handle split possibility
|
|
can_split_bool = can_split(self.game_logic.player_hand)
|
|
if can_split_bool:
|
|
self.buttons.split_button.configure(state="normal")
|
|
self.feedback_label.configure(
|
|
text="You have a pair! Consider splitting.",
|
|
text_color="white"
|
|
)
|
|
else:
|
|
self.buttons.split_button.configure(state="disabled")
|
|
|
|
# Update notifications
|
|
stats = self.game_logic.get_stats()
|
|
self.notifications._update_streak_display(stats["current_streak"])
|
|
if stats.get("pending_streak_notification"):
|
|
self.notifications._show_streak_notification(stats["pending_streak_notification"])
|
|
|
|
def _hit(self):
|
|
self._handle_action("Hit", self.buttons.hit_button)
|
|
|
|
def _stand(self):
|
|
self._handle_action("Stand", self.buttons.stand_button)
|
|
|
|
def _double(self):
|
|
self._handle_action("Double", self.buttons.double_button)
|
|
|
|
def _split(self):
|
|
self._handle_action("Split", self.buttons.split_button)
|
|
|
|
def _handle_action(self, action, button):
|
|
"""Process player actions"""
|
|
# Determine scenario type
|
|
scenario_type = "hard_totals"
|
|
if can_split(self.game_logic.player_hand):
|
|
scenario_type = "pairs"
|
|
elif 'A' in [card.split('_')[-1] for card in self.game_logic.player_hand]:
|
|
scenario_type = "soft_totals"
|
|
|
|
# Check if player can split
|
|
if can_split(self.game_logic.player_hand):
|
|
decision, feedback = get_split_decision(
|
|
self.game_logic.player_hand,
|
|
self.game_logic.dealer_card
|
|
)
|
|
correct = action == decision
|
|
else:
|
|
decision, feedback = get_correct_decision(
|
|
self.game_logic.player_hand,
|
|
self.game_logic.player_total,
|
|
self.game_logic.dealer_card
|
|
)
|
|
correct = action == decision
|
|
|
|
# Update UI
|
|
color = "green" if correct else "red"
|
|
self.feedback_label.configure(text=feedback, text_color=color)
|
|
self.buttons._mark_button(button, correct)
|
|
self.game_logic.update_stats(correct, scenario_type)
|
|
|
|
# Update button states
|
|
self.buttons._enable_action_buttons(False)
|
|
self.buttons.next_round_button.configure(state="normal")
|
|
|
|
def _on_main_window_close(self):
|
|
"""Handle window close event"""
|
|
self.app.configure(state="disabled")
|
|
self.stats._show_final_stats(self.game_logic.get_stats())
|
|
|
|
def show_hint(self):
|
|
"""Delegate hint display to the HintSystem"""
|
|
self.hints._disable_hint_button()
|
|
self.hints.show_hint()
|
|
|
|
def run(self):
|
|
"""Start application main loop"""
|
|
self.app.mainloop() |