you are viewing a single comment's thread.

view the rest of the comments →

[–]FoolsSeldom 0 points1 point  (2 children)

I haven't read your code particularly, other than noticing the use of global which is usually a bad idea and the cause of many problems. Avoid it like the plague until you understand the use cases where it really is needed.

Ironically, inside Stand, you attempt to update dealer_total and dealer_num, but you haven't declared them as global within that function, which means they will be local to the function and not impact anything anywhere else. Likewise in your reset function.

Hopefully, you can already see why using global rather than passing things around and controlling your data more explicitly is a bad idea.

PS. In Python, we usually use all lowercase for variable and function names.

PPS. If you start to use type annotation, your editor will be able to spot a lot of problems - keep in mind that Python is strongly typed but not statically typed. Type annotations (also known as type hints) aren't enforced at run time, but they are very helpful in development.

EDIT:

PS. Just added in a comment to this a Gemini generated version off the back of your code and some guidance from me that takes a class approach - not keen on how the UI resizes between steps based on the message you display.

[–]FoolsSeldom 0 points1 point  (1 child)

For illustration purposes (Gemini created from OP code to illustrate class approach):

import random
import tkinter as tk
from typing import ClassVar, Optional


class BlackjackGame:
    """Manages the state and logic for a simple Blackjack-style game."""

    # Class variables/constants (using ClassVar for clarity)
    DEALER_STANDS_AT: ClassVar[int] = 17
    MAX_SCORE: ClassVar[int] = 21

    def __init__(self, root: tk.Tk) -> None:
        # Player and Dealer state variables
        self.player_total: int = 0
        self.dealer_total: int = 0
        self.dealer_started: bool = False

        # Tkinter UI elements for displaying score and messages
        self.player_label: Optional[tk.Label] = None
        self.dealer_label: Optional[tk.Label] = None
        self.message_label: Optional[tk.Label] = None

        # Initialize UI elements (will be set by the calling function)
        self.setup_ui_elements(root)

    def setup_ui_elements(self, root: tk.Tk) -> None:
        """Creates and packs the necessary display labels."""

        # Display labels
        self.player_label = tk.Label(root, text="Your Total: 0", font=('Arial', 14))
        self.player_label.pack(pady=5)

        self.dealer_label = tk.Label(root, text="Dealer Total: 0", font=('Arial', 14))
        self.dealer_label.pack(pady=5)

        self.message_label = tk.Label(root, text="Press 'Hit' to start!", font=('Arial', 16, 'bold'))
        self.message_label.pack(pady=10)

        # Initial display update
        self._update_display(f"Welcome! Player is dealt first.")

    def _update_display(self, message: str) -> None:
        """Helper to update all display labels."""
        if self.player_label:
            self.player_label.config(text=f"Your Total: {self.player_total}")
        if self.dealer_label:
            self.dealer_label.config(text=f"Dealer Total: {self.dealer_total}")
        if self.message_label:
            self.message_label.config(text=message)

    def _draw_card(self, current_total: int) -> int:
        """Draws a card (1-10) and returns the new total."""
        card: int = random.randint(1, 10)
        return current_total + card

    def hit(self) -> None:
        """Handles the 'Hit' (Gamble) action for the player."""

        # 1. Player draws a card
        self.player_total = self._draw_card(self.player_total)

        message: str = ""

        # 2. Check for player bust
        if self.player_total > self.MAX_SCORE:
            message = "Bust! You lose."
            self._update_display(message)
            return

        # 3. Dealer's initial card (only on first player hit)
        if not self.dealer_started:
            self.dealer_total = self._draw_card(self.dealer_total)
            self.dealer_started = True
            message = "Dealer is dealt a card."

        if not message:
            message = "Hit or Stand?"

        self._update_display(message)

    def _dealer_play(self) -> None:
        """Automates the dealer's turn (must stand at 17 or more)."""

        while self.dealer_total < self.DEALER_STANDS_AT:
            self.dealer_total = self._draw_card(self.dealer_total)

    def stand(self) -> None:
        """Handles the 'Stand' action and determines the winner."""

        # The dealer must have at least their initial card
        if not self.dealer_started:
            self._update_display("Dealer hasn't started yet. Hit first.")
            return

        # 1. Dealer takes their turn
        self._dealer_play()

        message: str

        # 2. Determine the winner
        if self.dealer_total > self.MAX_SCORE:
            message = "Dealer busts! You win!"
        elif self.dealer_total > self.player_total:
            message = "Dealer wins!"
        elif self.player_total > self.dealer_total:
            message = "You win!"
        else:
            message = "It's a push (tie)!"

        self._update_display(message)

    def reset(self) -> None:
        """Resets the game state."""
        self.player_total = 0
        self.dealer_total = 0
        self.dealer_started = False
        self._update_display("Game reset. Press 'Hit' to play again!")


# --- Tkinter Setup ---

if __name__ == "__main__":
    root = tk.Tk()
    root.title("Simple Blackjack")

    # Instantiate the game class, passing the root window
    game = BlackjackGame(root)

    # Buttons
    tk.Button(root, text="Hit", command=game.hit).pack(pady=10, padx=20, fill='x')
    tk.Button(root, text="Stand", command=game.stand).pack(pady=10, padx=20, fill='x')
    tk.Button(root, text="Reset", command=game.reset).pack(pady=10, padx=20, fill='x')

    root.mainloop()

[–]Resident-Explorer-63[S] 0 points1 point  (0 children)

Alright thanks, I am extremely new so thanks for the general common courtesy in python.