"""Playing Cards, by Al Sweigart. Displays a scrolling stream of randomly selected playing cards. This program uses the same lane-based approach as Ducklings: each lane can independently start drawing a new multi-line object. """ import random import shutil import time # Pause after each row in seconds. DELAY = 0.15 # Chance from 0 to 1 that an empty lane receives a card on each row. DENSITY = 0.10 # Five characters for the card plus one separating space. CARD_WIDTH = 6 RANKS = ("A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K") SUITS = ("♠", "♥", "♦", "♣") # Chance from 0 to 1 that a new card is shown face down. BACKSIDE_PROBABILITY = 0.15 class Card: """A randomly selected playing card drawn one row at a time.""" def __init__(self): self.rank = random.choice(RANKS) self.suit = random.choice(SUITS) self.is_backside = random.random() < BACKSIDE_PROBABILITY self.next_row = 0 def get_next_row(self): if self.is_backside: rows = (" ___ ", "|###|", "|###|", "|###|") else: rows = ( " ___ ", f"|{self.rank:<3}|", f"| {self.suit} |", f"|_{self.rank:_>2}|", ) row = rows[self.next_row] self.next_row += 1 return row @property def finished(self): return self.next_row == 4 def main(): width = shutil.get_terminal_size()[0] - 1 lanes = [None] * (width // CARD_WIDTH) while True: line = [] for lane_number, card in enumerate(lanes): if card is None and random.random() < DENSITY: card = Card() lanes[lane_number] = card if card is None: line.append(" " * CARD_WIDTH) continue line.append(card.get_next_row() + " ") if card.finished: lanes[lane_number] = None print("".join(line)) time.sleep(DELAY) if __name__ == "__main__": try: main() except KeyboardInterrupt: pass