import os from PIL import Image, ImageTk import tkinter as tk from tkinter import messagebox import random class CardGameGUI: def __init__(self, master): self.master = master self.master.title("Crazy 8s Card Game") self.num_players = None self.players = [] self.current_player = None self.deck = None self.discard_pile = [] self.draw_pile = [] self.selected_suit = None # Create GUI elements self.start_button = tk.Button( self.master, text="Start Game", command=self.show_setup ) self.start_button.pack() self.card_images = self.load_card_images() def show_setup(self): # Create setup window setup_window = tk.Toplevel(self.master) # Number of players selection num_players_label = tk.Label( setup_window, text="Select Number of Players:" ) num_players_label.pack() self.num_players = tk.IntVar() self.num_players.set(2) # Set default value num_players_options = [ (2, "2 Players"), (3, "3 Players"), (4, "4 Players"), (5, "5 Players"), (6, "6 Players"), (7, "7 Players"), ] for option in num_players_options: radio_button = tk.Radiobutton( setup_window, text=option[1], variable=self.num_players, value=option[0], ) radio_button.pack() # Start game button start_button = tk.Button( setup_window, text="Start Game", command=self.start_game ) start_button.pack() # Load card_images def load_card_images(self): card_images = {} suits = ["Spades", "Hearts", "Diamonds", "Clubs"] ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"] # Get the path to the 'card_images' folder within the project directory image_folder = os.path.join(os.path.dirname(__file__), "card_images") for suit in suits: for rank in ranks: # Construct the file name for the current card file_name = f"{rank}{suit[0]}.png" # Combine the folder path and the file name to get the full image path image_path = os.path.join(image_folder, file_name) # Check if the image file exists before loading it if os.path.exists(image_path): image = Image.open(image_path) photo = ImageTk.PhotoImage(image) card_images[(rank, suit)] = photo else: # Replace missing image with a placeholder # In this case, you can use a default image or leave it as None card_images[(rank, suit)] = None return card_images def start_game(self): # Reset game state self.players = [f"Player {i + 1}" for i in range(self.num_players.get())] self.current_player = random.choice(self.players) self.deck = self.create_deck() self.discard_pile = [] self.draw_pile = [] self.selected_suit = None # Shuffle the deck self.shuffle_deck() # Deal 8 cards to each player for player in self.players: self.deal_cards(player, 8) # Create draw pile self.draw_pile = self.deck self.discard_pile.append(self.draw_pile.pop()) # Show game board self.show_game_board() def create_deck(self): # Create a standard 52-card deck suits = ["Spades", "Hearts", "Diamonds", "Clubs"] ranks = ["A","2","3","4","5","6","7","8","9","10","J","Q","K",] deck = [(rank, suit) for suit in suits for rank in ranks] random.shuffle(deck) return deck def shuffle_deck(self): random.shuffle(self.deck) def deal_cards(self, player, num_cards): if len(self.draw_pile) >= num_cards: cards = [self.draw_pile.pop() for _ in range(num_cards)] self.players[player].extend(cards) else: messagebox.showinfo("Error", "No more cards") def show_game_board(self): # Create a new game board window game_board = tk.Toplevel(self.master) # Show current player player_label = tk.Label(game_board, text=f"Current Player: {self.current_player}") player_label.pack() # Show discard pile top_card_label = tk.Label(game_board, text=f"Top Card: {self.discard_pile[-1][0]} of {self.discard_pile[-1][1]}") top_card_label.pack() # Create buttons for each card in the player's hand for card in self.players[self.current_player]: button = tk.Button(game_board, text=f"{card[0]} of {card[1]}", command=lambda c=card: self.play_card(c)) button.pack() def play_card(self, card): if self.is_valid_play(card): self.discard_pile.append(card) self.players[self.current_player].remove(card) self.check_game_over() self.handle_special_cards(card) self.next_player() else: messagebox.showerror("Invalid Play", "You cannot play that card!") def is_valid_play(self, card): if card[0] == "8": return True elif card[0] == self.discard_pile[-1][0] or card[1] == self.discard_pile[-1][1]: return True else: return False def handle_special_cards(self, card): if card[0] == "2": self.draw_cards(self.get_next_player(), 2) elif card[0] == "8": self.select_suit() def draw_cards(self, player, num_cards): cards = [self.draw_pile.pop() for _ in range(num_cards)] self.players[player].extend(cards) messagebox.showinfo("Draw Cards", f"{self.players[player]} drew {num_cards} cards.") def select_suit(self): suit_window = tk.Toplevel(self.master) def select(suit): self.selected_suit = suit suit_window.destroy() suit_label = tk.Label(suit_window, text="Select a Suit:") suit_label.pack() suits = ["Spades", "Hearts", "Diamonds", "Clubs"] for suit in suits: suit_button = tk.Button(suit_window, text=suit, command=lambda s=suit: select(s)) suit_button.pack() def get_next_player(self): current_index = self.players.index(self.current_player) next_index = (current_index + 1) % len(self.players) return next_index def next_player(self): next_player_index = self.get_next_player() self.current_player = next_player_index self.show_game_board() def show_game_board(self): # Create a new game board window game_board = tk.Toplevel(self.master) # Show current player player_label = tk.Label(game_board, text=f"Current Player: {self.players[self.current_player]}") player_label.pack() # Show discard pile top_card_label = tk.Label(game_board, text=f"Top Card: {self.discard_pile[-1][0]} of {self.discard_pile[-1][1]}") top_card_label.pack() # Create buttons for each card in the player's hand for card in self.players[self.current_player]: button = tk.Button(game_board, text=f"{card[0]} of {card[1]}", command=lambda c=card: self.play_card(c)) button.pack() def check_game_over(self): for player in self.players: if len(self.players[player]) == 0: self.end_game() def end_game(self): points = self.calculate_points() messagebox.showinfo("Game Over", f"{self.current_player} wins with {points} points!") def calculate_points(self): points = 0 for player in self.players: for card in self.players[player]: if card[0] in ["J", "Q", "K"]: points += 10 elif card[0] == "A": points += 1 elif card[0] == "8": points += 5 else: points += int(card[0]) return points def main(): root = tk.Tk() CardGameGUI(root) root.mainloop() if __name__ == "__main__": main()