diff --git a/UNO/README.md b/UNO/README.md new file mode 100644 index 0000000..27d4448 --- /dev/null +++ b/UNO/README.md @@ -0,0 +1,312 @@ +# 🎮 UNO Card Game - Python Edition + +
+ +![UNO Game](uno.png) + +**A Console-Based UNO Card Game Implementation in Python** + +> Play against the computer in this exciting implementation of the classic UNO card game with a beautiful rich terminal UI. + +[![Python](https://img.shields.io/badge/Python-3.7+-blue.svg)](https://www.python.org/) +[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) +[![Status](https://img.shields.io/badge/Status-Active-brightgreen.svg)](https://github.com/mayank-gariya/crazy-python-projects-/tree/main/UNO) + +
+ +--- + +## 📋 Table of Contents + +- [Overview](#overview) +- [Features](#features) +- [UNO Game Rules](#uno-game-rules) +- [Tech Stack](#tech-stack) +- [Project Structure](#project-structure) +- [Installation](#installation) +- [How to Play](#how-to-play) +- [Game Screenshots](#game-screenshots) +- [Future Enhancements](#future-enhancements) +- [Contributing](#contributing) + +--- + +## đŸŽ¯ Overview + +This is a console-based implementation of the classic **UNO card game** developed in Python. Challenge yourself against an intelligent computer opponent in a beautifully formatted terminal interface powered by the **Rich** library. The game provides an interactive experience with real-time card management, game state tracking, and detailed end-game summaries. + +**Current Version:** 1-on-1 gameplay (You vs Computer) +**Future Roadmap:** Multiplayer support, AI vs AI mode, and Online capabilities + +--- + +## ✨ Features + +✅ **Player vs Computer Gameplay** - Test your skills against an AI opponent +✅ **Rich Terminal UI** - Beautiful, colorful console interface with Rich library +✅ **Card Management** - Intuitive card selection and hand management +✅ **Power Cards** - Draw Two, Skip, Reverse, Wild, and Wild Draw Four +✅ **Smart Computer AI** - Computer makes strategic card plays +✅ **Game Summary** - Detailed end-game statistics and winner announcement +✅ **Real-time Feedback** - Instant notifications for game events (UNO!, card plays, etc.) +✅ **Standard UNO Rules** - Fully compliant with official UNO game rules + +--- + +## 🎲 UNO Game Rules + +### Basic Rules +- **Starting Hand:** Each player receives 7 cards +- **Deck:** Standard UNO deck of 108 cards in 4 colors (Red, Yellow, Green, Blue) +- **Objective:** Be the first to get rid of all your cards + +### Card Types + +#### Number Cards (0-9) +- Available in all 4 colors +- Must match either the **color** or **number** of the previous card + +#### Action Cards +- **Skip** đŸšĢ - Next player loses their turn +- **Reverse** â†Šī¸ - Changes direction (acts as Skip in 2-player mode) +- **Draw Two** đŸ“Ĩ - Next player draws 2 cards and loses their turn + +#### Wild Cards +- **Wild** 🌈 - Can be played anytime; choose any color to continue with +- **Wild Draw Four** đŸŽĒ - Can be played only when no other card matches; opponent draws 4 cards and loses turn + +### Winning Condition +- **"UNO!"** is announced when a player has only 1 card left +- First player to empty their hand wins the game +- Game ends with a detailed summary showing rounds played and final statistics + +--- + +## 🛠 Tech Stack + +| Technology | Purpose | +|-----------|---------| +| **Python 3.7+** | Core game logic and implementation | +| **Rich** | Beautiful console UI with colors and formatting | +| **NumPy** | Optional numerical operations | +| **Random** | Card shuffling and AI decision-making | + +### Installation Requirements +```bash +pip install rich +``` + +--- + +## 📁 Project Structure + +``` +UNO/ +├── app.py # Main application entry point +├── logic_rich.py # Enhanced game logic with Rich UI +├── logic.py # Core game logic engine +├── deck.py # UNO deck generation and management +├── UNO_rules.py # Game rules and card validation +├── card_showing_logic.py # Card display and formatting +├── summary.py # Game summary and statistics +├── requirenment.txt # Project dependencies +├── uno.png # UNO game image +├── result.png # Gameplay screenshot 1 +├── result2.png # Gameplay screenshot 2 +└── README.md # This file +``` + +### File Descriptions + +#### 🎮 **app.py** +- **Purpose:** Main entry point for the game +- **Contains:** Game initialization and startup +- **Usage:** Run this file to start playing + +#### 🧠 **logic_rich.py** +- **Purpose:** Enhanced game logic with Rich library integration +- **Contains:** Player turns, computer AI, game flow control +- **Features:** Beautiful console output, real-time status updates + +#### đŸŽ¯ **logic.py** +- **Purpose:** Core game logic implementation +- **Contains:** Game mechanics, turn management, hand tracking +- **Features:** Rule checking, card validation, turn cycling + +#### 🃏 **deck.py** +- **Purpose:** UNO deck generation and management +- **Contains:** Standard deck creation (108 cards) +- **Features:** Card shuffling, deck initialization, custom deck sizes (optional 112-card variant) + +#### âš–ī¸ **UNO_rules.py** +- **Purpose:** Game rules enforcement +- **Contains:** Card validation rules and power card effects +- **Features:** + - `check_rules_for_cards()` - Validates if a card play is legal + - `apply_power_card()` - Handles special card effects + +#### 🎨 **card_showing_logic.py** +- **Purpose:** Card display and formatting +- **Contains:** Console output formatting for cards +- **Features:** Visual card representation, hand display + +#### 📊 **summary.py** +- **Purpose:** Game summary and statistics +- **Contains:** End-game results and player statistics +- **Features:** Winner announcement, game duration, round count + +--- + +## 🚀 Installation + +### Prerequisites +- Python 3.7 or higher +- pip (Python package manager) + +### Steps + +1. **Clone the Repository** +```bash +git clone https://github.com/mayank-gariya/crazy-python-projects-.git +cd crazy-python-projects-/UNO +``` + +2. **Install Dependencies** +```bash +pip install -r requirenment.txt +``` + +Or install Rich directly: +```bash +pip install rich +``` + +3. **Run the Game** +```bash +python app.py +``` + +--- + +## 🎮 How to Play + +### Game Start +1. Run `python app.py` +2. The game initializes with both players receiving 7 cards +3. First card from the deck is placed as the initial discard pile card + +### Your Turn (Player) +1. **View Your Cards:** Enter `show` to display all your cards with numbers +2. **Play a Card:** Enter the card number corresponding to your card + - Valid cards must match the **color** OR **number** OR be a **Wild** card +3. **Draw a Card:** If you can't play, select "N" to draw a card +4. **UNO:** When you have 1 card left, "UNO!" is automatically announced + +### Computer's Turn +- The computer automatically plays valid cards from its hand +- Draws a card if no valid play is available +- Strategic decision-making for card selection + +### Game End +- The game ends when either player empties their hand +- **Winner Announcement** with detailed summary +- Game statistics including: + - Total rounds played + - Cards remaining for each player + - Game duration + +--- + +## 📸 Game Screenshots + +### Gameplay Screenshot 1 +![Result 1](result.png) + +### Gameplay Screenshot 2 +![Result 2](result2.png) + +--- + +## 🚀 Future Enhancements + +### Phase 2: Multiplayer Mode +- [ ] Support for 2-10 players +- [ ] Network-based multiplayer +- [ ] Local multiplayer (hot-seat mode) + +### Phase 3: Advanced AI & Modes +- [ ] **All Robots Mode** - Watch AI players compete autonomously +- [ ] **Difficulty Levels** - Easy, Medium, Hard computer opponents +- [ ] **Improved AI Strategy** - Smarter card selection and blocking tactics + +### Phase 4: Online Capabilities +- [ ] **WebSocket Implementation** - Real-time multiplayer over internet +- [ ] **Server Architecture** - Central game server for matchmaking +- [ ] **Player Authentication** - User accounts and rankings +- [ ] **Web Interface** - Browser-based gameplay +- [ ] **Mobile Support** - Cross-platform compatibility + +### Phase 5: Additional Features +- [ ] Game replay functionality +- [ ] Leaderboards and statistics tracking +- [ ] Custom rule sets +- [ ] Game history and replays +- [ ] Sound effects and animations + +--- + +## 📊 Game Summary Details + +After each game, you'll receive a detailed summary including: +- **Winner:** Who won the game +- **Rounds Played:** Total number of complete rounds +- **Game Duration:** Time taken to complete the game +- **Cards Played:** Total cards used in the game +- **Final Status:** Remaining cards in each player's hand + +--- + +## 🤝 Contributing + +Contributions are welcome! Here's how you can help: + +1. **Fork** the repository +2. **Create** a feature branch (`git checkout -b feature/amazing-feature`) +3. **Commit** your changes (`git commit -m 'Add amazing feature'`) +4. **Push** to the branch (`git push origin feature/amazing-feature`) +5. **Open** a Pull Request + +--- + +## 📝 License + +This project is licensed under the MIT License - see the LICENSE file for details. + +--- + +## 💡 Tips & Tricks + +- 💰 **Strategic Plays:** Save your Wild cards for critical moments +- đŸŽ¯ **Memory:** Keep track of cards played to predict what's in the deck +- ⚡ **Speed:** In competitive mode, think fast and play faster +- đŸ›Ąī¸ **Defense:** Use Skip and Reverse cards to block opponents + +--- + +## 📧 Contact & Support + +**Developer:** Mayank Gariya +**GitHub:** [mayank-gariya](https://github.com/mayank-gariya) +**Repository:** [crazy-python-projects-](https://github.com/mayank-gariya/crazy-python-projects-) + +--- + +
+ +### 🎉 Enjoy the Game! + +**Made with â¤ī¸ in Python** + +![Python](https://img.shields.io/badge/Made%20with-Python-blue?style=for-the-badge&logo=python) + +
diff --git a/UNO/UNO_rules.py b/UNO/UNO_rules.py new file mode 100644 index 0000000..0c5bffd --- /dev/null +++ b/UNO/UNO_rules.py @@ -0,0 +1,60 @@ +# define game rules to follow +def check_rules_for_cards(card,previous_card): + + # check and return true and false + + wild_cards = ['wild', 'wild_draw_four'] + + if card['color'] == previous_card['color']: + return True + + if card['value'] == previous_card['value']: + return True + + if card['value'] in wild_cards: + return True + + return False + + +def apply_power_card(card, current_player, + player_hand, + computer_hand, + deck): + + value = card['value'] + + if value == 'draw_two': + + if current_player == 'player': + for _ in range(2): + computer_hand.append(deck.pop()) + + else: + for _ in range(2): + player_hand.append(deck.pop()) + + return "skip" + + elif value == 'skip': + return "skip" + + elif value == 'reverse': + return "skip" # reverse == skip for 2 players + + elif value == 'wild_draw_four': + + if current_player == 'player': + for _ in range(4): + computer_hand.append(deck.pop()) + + else: + for _ in range(4): + player_hand.append(deck.pop()) + + return "skip" + + elif value == 'wild': + return "wild" + + return None diff --git a/UNO/app.py b/UNO/app.py new file mode 100644 index 0000000..97f6f7b --- /dev/null +++ b/UNO/app.py @@ -0,0 +1,4 @@ +from logic_rich import UNO + +game = UNO() +game.start_game() \ No newline at end of file diff --git a/UNO/card_showing_logic.py b/UNO/card_showing_logic.py new file mode 100644 index 0000000..0df043e --- /dev/null +++ b/UNO/card_showing_logic.py @@ -0,0 +1,44 @@ +import random + +def get_discard(deck): + """retruns the fair uno start card so that no power card on start """ + action_cards = ['skip', 'reverse', 'draw_two','wild_draw_four','wild','wild_six'] + + while True: + + selected_card = random.choice(deck) + + if selected_card['value'] not in action_cards: + deck.remove(selected_card) + return selected_card + + +def get_dicard_card(deck): + + discard_card = get_discard(deck) + + discard_card_layout = f""" + ========================= + | DC + | Color : {discard_card['color']} + | Value : {discard_card['value']} + ========================= + """ + + return discard_card + +def show_players_cards(player_hand): + + for i , card in enumerate(player_hand): + player_card = f''' + ======================== + | {i+1} + |Color : {card['color']} + |Value : {card['value']} + ======================== + ''' + print(player_card,end=' ') + + + + diff --git a/UNO/deck.py b/UNO/deck.py new file mode 100644 index 0000000..9c20d79 --- /dev/null +++ b/UNO/deck.py @@ -0,0 +1,41 @@ +import random + +def get_deck(N=108): + """ + Generates an Uno deck. + + N = 108 -> Standard UNO deck + N = 112 -> Standard deck + 4 extra customizable wild cards + """ + + deck = [] + + colors = ['blue', 'red', 'green', 'yellow'] + action_cards = ['skip', 'reverse', 'draw_two'] + + # Number cards + for color in colors: + # One 0 per color + deck.append({"color": color, "value": "0"}) + + # Two of each 1-9 per color + for num in range(1, 10): + deck.append({"color": color, "value": str(num)}) + deck.append({"color": color, "value": str(num)}) + + # Action cards + for color in colors: + for action in action_cards: + deck.append({"color": color, "value": action}) + deck.append({"color": color, "value": action}) + + # Wild cards + for _ in range(4): + deck.append({"color": "black", "value": "wild"}) + deck.append({"color": "black", "value": "wild_draw_four"}) + + if N == 112: + for _ in range(4): + deck.append({"color": "black", "value": "wild_six"}) + + return deck \ No newline at end of file diff --git a/UNO/logic.py b/UNO/logic.py new file mode 100644 index 0000000..f373901 --- /dev/null +++ b/UNO/logic.py @@ -0,0 +1,186 @@ +from time import time +import numpy as np +import random +from deck import get_deck +from card_showing_logic import get_dicard_card , show_players_cards , show_player_selcted_card,show_computer_selcted_card +from UNO_rules import check_rules_for_cards , apply_power_card + + +class UNO: + + def __init__(self,n_players=2,ncards=108): + self.n_players = n_players + self.ncards = ncards + + def start_game(self): + #all displaying things + # game logic + # first shuffle then draw hands of cards + + deck = get_deck(self.ncards) + deck = self._shuffle(deck) + hands = self._draw_players_cards(deck=deck,players=self.n_players) + + player_hand = hands['player'] + computer_hand = hands['computer'] + + dicard_card = get_dicard_card(deck=deck) #display the discard card + + used_cards = [] + used_cards.append(dicard_card) + + print('player cards....') + + show_players_cards(player_hand=player_hand) # displayes the player cards on screen + + current_player = 'player' + + while player_hand and computer_hand: + + previous_card = used_cards[-1] + + # game logic to and fro + if current_player == 'player': + print('player turn') + + while True: + # check if user have cards or not + have_cards = input('entre Y is have entre N if not ').upper() + get_display = input('entre show if you wanna see your cards ').lower() + + if get_display == 'show': + show_players_cards(player_hand) + + if have_cards == 'Y': + # get user card + + card_num = int(input('entre the card number to play : please note 1 is 0 and so on ')) + + if card_num >= len(player_hand) or card_num < 0: + print("Invalid index") + continue + + current_card = player_hand[card_num] + + + if check_rules_for_cards(current_card,previous_card): + + if card_num < len(player_hand): # must be within range + player_used_card = player_hand.pop(card_num) + used_cards.append(player_used_card) + + effect = apply_power_card( + player_used_card, + current_player, + player_hand, + computer_hand, + deck + ) + + else: + print('sussy boi play vaild ....') + + print('$'*20) + print('now player have these cards') + + show_players_cards(player_hand=player_hand) + + print('$'*20) + show_player_selcted_card(player_used_card) + + if effect == "skip": + print("Computer loses turn") + current_player = "player" + + else: + current_player = "computer" + break + + if len(player_hand) == 1: + print("UNO!") + + break + else: + print('INVALID card try again !!') + else: + print('player draw a card') + + drawn_card = deck.pop() + player_hand.append(drawn_card) + + if effect == "skip": + print("Computer loses turn") + current_player = "player" + else: + current_player = "computer" + break + + else: + played = False + + print('$'*20) + print('computer turn ') + + for i, card in enumerate(computer_hand): + + if check_rules_for_cards(card, previous_card): + + played_card = computer_hand.pop(i) + show_computer_selcted_card(played_card) + used_cards.append(played_card) + + effect = apply_power_card( + played_card, + current_player, + player_hand, + computer_hand, + deck + ) + + if len(player_hand) == 1: + print("UNO!") + + played = True + break + + if not played: + + print("Computer draws a card") + + drawn_card = deck.pop() + computer_hand.append(drawn_card) + + if effect == "skip": + print("Player loses turn") + current_player = "computer" + else: + current_player = "player" + + if len(player_hand) == 0: + print("🎉 PLAYER WINS!") + return + + if len(computer_hand) == 0: + print("💀 COMPUTER WINS!") + return + + + + def _shuffle(self,deck): + random.shuffle(deck) + return deck + + def _draw_players_cards(self,deck,players=2): + hands = { + 'player':[], + 'computer':[] + } + + for _ in range(7): + hands['player'].append(deck.pop()) + hands['computer'].append(deck.pop()) + + return hands + +game = UNO() +game.start_game() \ No newline at end of file diff --git a/UNO/logic_rich.py b/UNO/logic_rich.py new file mode 100644 index 0000000..2d1529e --- /dev/null +++ b/UNO/logic_rich.py @@ -0,0 +1,244 @@ +import random +import time +import numpy as np + +from deck import get_deck +from card_showing_logic import get_dicard_card, show_players_cards +from UNO_rules import check_rules_for_cards , apply_power_card + +from summary import display_game_summary + +from rich import print +from rich.console import Console +from rich.panel import Panel +from rich.table import Table +from rich.columns import Columns + +console = Console() + +class UNO: + + def __init__(self, n_players=2, ncards=108): + self.n_players = n_players + self.ncards = ncards + + self.stats = { + "player_cards_played": 0, + "computer_cards_played": 0, + "player_cards_drawn": 0, + "computer_cards_drawn": 0, + "player_wilds": 0, + "computer_wilds": 0, + "player_final_cards": 0, + "computer_final_cards": 0 + } + + def start_game(self): + start_time = time.time() # Start session timer clock + + deck = get_deck(self.ncards) + deck = self._shuffle(deck) + hands = self._draw_players_cards(deck=deck, players=self.n_players) + + player_hand = hands['player'] + computer_hand = hands['computer'] + + discard_card = get_dicard_card(deck=deck) + used_cards = [] + used_cards.append(discard_card) + + # Track dynamically selected target card or overridden active color string + declared_wild_color = None + + console.print(Panel.fit("[bold blink yellow]đŸ”Ĩ WELCOME TO UNO đŸ”Ĩ[/bold blink yellow]", border_style="magenta")) + current_player = 'player' + + while player_hand and computer_hand: + previous_card = used_cards[-1] + effect = None + + # Formulate current target display based on whether a wild choice is overriding the card + if declared_wild_color: + display_color_status = f"[bold magenta]{previous_card}[/bold magenta] -> [bold yellow]Active Color: {declared_wild_color.upper()}[/bold yellow]" + else: + display_color_status = str(previous_card) + + # Visual State Dashboard + console.print("\n" + "─" * 60, style="dim white") + board_table = Table(title="[bold cyan]CURRENT GAME STATE[/bold cyan]", show_header=False, box=None) + board_table.add_row("[bold]Top Discard Pile Card:[/bold]", f"[bold reverse] {display_color_status} [/bold reverse]") + board_table.add_row("[bold]Computer Cards Left:[/bold]", f"[bold red]{len(computer_hand)}[/bold red] 🎴") + console.print(Panel(board_table, border_style="cyan")) + + # ---------------- REGULAR PLAYER TURN ---------------- + if current_player == 'player': + console.print("[bold green]👉 YOUR TURN[/bold green]") + console.print('\n[bold underline green]Your Current Hand:[/bold underline green]') + + # Render hand layout dynamically matching colors + cards_render = [] + for i, card_obj in enumerate(player_hand): + card_str = str(card_obj).lower() + border_color = "white" + if "red" in card_str: border_color = "red" + elif "blue" in card_str: border_color = "blue" + elif "green" in card_str: border_color = "green" + elif "yellow" in card_str: border_color = "yellow" + elif "wild" in card_str: border_color = "magenta" + + cards_render.append(Panel(f"[bold]{card_obj}[/bold]", title=f"[bold yellow][{i}][/bold yellow]", border_style=border_color)) + + console.print(Columns(cards_render)) + print("") + + while True: + have_cards = console.input("[bold yellow]Do you have a playable card? (Y/N): [/bold yellow]").upper().strip() + + if have_cards == 'Y': + try: + card_num = int(console.input('Enter the index number of the card you want to play: ')) + except ValueError: + console.print("[bold red]Please enter a valid integer choice.[/bold red]") + continue + + if card_num >= len(player_hand) or card_num < 0: + console.print("[bold red]Invalid index! Choice out of bounds.[/bold red]") + continue + + current_card = player_hand[card_num] + + # Validate choice factoring in active wild overrides + is_valid_move = False + if "wild" in str(current_card).lower(): + is_valid_move = True # Wilds are always playable + elif declared_wild_color: + # Must match overridden color choice declaration + is_valid_move = (declared_wild_color.lower() in str(current_card).lower()) + else: + is_valid_move = check_rules_for_cards(current_card, previous_card) + + if is_valid_move: + player_used_card = player_hand.pop(card_num) + used_cards.append(player_used_card) + self.stats["player_cards_played"] += 1 + + # Handle Wild declaration prompt interaction + if "wild" in str(player_used_card).lower(): + self.stats["player_wilds"] += 1 + while True: + choice = console.input("[bold magenta]🌈 WILD PLAYED! Choose active color (Red/Blue/Green/Yellow): [/bold magenta]").strip().lower() + if choice in ["red", "blue", "green", "yellow"]: + declared_wild_color = choice + break + console.print("[bold red]Invalid color selection. Try again.[/bold red]") + else: + # Regular card placement clears out old active wild overrides + declared_wild_color = None + + if len(player_hand) == 1: + console.print(Panel("[bold blink red]đŸ“Ŗ UNO! YOU HAVE ONLY ONE CARD LEFT![/bold blink red]", border_style="red")) + + effect = apply_power_card(player_used_card, current_player, player_hand, computer_hand, deck) + + console.print("\n" + "[bold gold1]$" * 20 + " ACTION CONFIRMED " + "$" * 20 + "[/bold gold1]") + + if effect == "skip": + console.print("[bold orange3]đŸšĢ Computer loses its turn! You get another go.[/bold orange3]") + current_player = "player" + else: + current_player = "computer" + break + else: + console.print('[bold red]❌ INVALID CARD! Match color criteria or drop a Wild.[/bold red]') + else: + console.print('[bold orange1]đŸ“Ĩ Drawing a card from the deck...[/bold orange1]') + if len(deck) == 0: + deck = self._shuffle(used_cards[:-1]) + used_cards = [used_cards[-1]] + + drawn_card = deck.pop() + player_hand.append(drawn_card) + self.stats["player_cards_drawn"] += 1 + + console.print(f"You drew: [bold reverse] {drawn_card} [/bold reverse]") + + if effect == "skip": + console.print("[bold orange3]đŸšĢ Computer loses its turn.[/bold orange3]") + current_player = "player" + else: + current_player = "computer" + break + + # ---------------- COMPUTER TURN ---------------- + else: + played = False + console.print('\n[bold magenta]🤖 COMPUTER\'S TURN[/bold magenta]') + time.sleep(0.8) # Imparts an interactive human thinking buffer + + for i, card in enumerate(computer_hand): + is_valid_move = False + if "wild" in str(card).lower(): + is_valid_move = True + elif declared_wild_color: + is_valid_move = (declared_wild_color.lower() in str(card).lower()) + else: + is_valid_move = check_rules_for_cards(card, previous_card) + + if is_valid_move: + played_card = computer_hand.pop(i) + used_cards.append(played_card) + self.stats["computer_cards_played"] += 1 + + # AI Wild processing rule + if "wild" in str(played_card).lower(): + self.stats["computer_wilds"] += 1 + # Simple smart feature: AI looks at its own hand to match its most frequent color + hand_colors = [c for c in ["red", "blue", "green", "yellow"] if c in str(computer_hand).lower()] + declared_wild_color = random.choice(hand_colors) if hand_colors else random.choice(["red", "blue", "green", "yellow"]) + console.print(f"[bold magenta]🤖 AI played a Wild Card and declared the new active color as: {declared_wild_color.upper()}[/bold magenta]") + else: + declared_wild_color = None + + if len(computer_hand) == 1: + console.print(Panel("[bold blink red]🤖 COMPUTER SHOUTS: UNO![/bold blink red]", border_style="red")) + + console.print(f"Computer laid down: [bold reverse] {played_card} [/bold reverse]") + + effect = apply_power_card(played_card, current_player, player_hand, computer_hand, deck) + played = True + break + + if not played: + console.print("[bold dim orange1]Computer couldn't play. Drawing a card...[/bold dim orange1]") + if len(deck) == 0: + deck = self._shuffle(used_cards[:-1]) + used_cards = [used_cards[-1]] + drawn_card = deck.pop() + computer_hand.append(drawn_card) + self.stats["computer_cards_drawn"] += 1 + + if effect == "skip": + console.print("[bold orange3]đŸšĢ Player loses turn! AI goes again.[/bold orange3]") + current_player = "computer" + else: + current_player = "player" + + # --- GAME END STATE EVALUATION GENERATOR --- + self.stats["player_final_cards"] = len(player_hand) + self.stats["computer_final_cards"] = len(computer_hand) + + winner_declared = "player" if len(player_hand) == 0 else "computer" + + # Fire external execution wrap summary module + display_game_summary(winner_declared, start_time, self.stats) + + def _shuffle(self, deck): + random.shuffle(deck) + return deck + + def _draw_players_cards(self, deck, players=2): + hands = {'player': [], 'computer': []} + for _ in range(7): + hands['player'].append(deck.pop()) + hands['computer'].append(deck.pop()) + return hands diff --git a/UNO/requirenment.txt b/UNO/requirenment.txt new file mode 100644 index 0000000..bb18473 --- /dev/null +++ b/UNO/requirenment.txt @@ -0,0 +1,2 @@ +rich +python diff --git a/UNO/result.png b/UNO/result.png new file mode 100644 index 0000000..c175f34 Binary files /dev/null and b/UNO/result.png differ diff --git a/UNO/result2.png b/UNO/result2.png new file mode 100644 index 0000000..0c5e50f Binary files /dev/null and b/UNO/result2.png differ diff --git a/UNO/summary.py b/UNO/summary.py new file mode 100644 index 0000000..febf2ee --- /dev/null +++ b/UNO/summary.py @@ -0,0 +1,41 @@ +import time +from rich.console import Console +from rich.panel import Panel +from rich.table import Table + +console = Console() + +def display_game_summary(winner, start_time, stats): + """ + Generates a high-visibility post-match analysis report using Rich. + """ + duration = round(time.time() - start_time, 2) + + # Choose theme based on who won + if winner == "player": + banner_text = "[bold blink green]🎉🏆 CHAMPION REVEALED: YOU WIN! 🏆🎉[/bold blink green]" + border_color = "green" + else: + banner_text = "[bold blink red]💀 CHAMPION REVEALED: COMPUTER WINS! 💀[/bold blink red]" + border_color = "red" + + console.print("\n") + console.print(Panel.fit(banner_text, border_style=border_color, padding=1)) + + # Initialize the match facts matrix table + summary_table = Table(title="[bold gold1]📋 UNO MATCH SUMMARY LOG[/bold gold1]", show_lines=True, header_style="bold cyan") + + summary_table.add_column("Metric Description", style="dim white", width=30) + summary_table.add_column("Player (You)", justify="center", style="green") + summary_table.add_column("Computer (AI)", justify="center", style="magenta") + + # Add comparative tracking items + summary_table.add_row("Final Cards Remaining", str(stats["player_final_cards"]), str(stats["computer_final_cards"])) + summary_table.add_row("Total Cards Played", str(stats["player_cards_played"]), str(stats["computer_cards_played"])) + summary_table.add_row("Total Cards Drawn", str(stats["player_cards_drawn"]), str(stats["computer_cards_drawn"])) + summary_table.add_row("Wild Cards Triggered", str(stats["player_wilds"]), str(stats["computer_wilds"])) + + console.print(summary_table) + + # Sub-footer showing chronological data + console.print(Panel(f"[bold white]âąī¸ Match Session Duration:[/bold white] [yellow]{duration} seconds[/yellow]", border_style="cyan", expand=False)) \ No newline at end of file diff --git a/UNO/uno.png b/UNO/uno.png new file mode 100644 index 0000000..c47f029 Binary files /dev/null and b/UNO/uno.png differ diff --git a/UNO/uno_details.txt b/UNO/uno_details.txt new file mode 100644 index 0000000..e69de29