Added Collections module; modified class Hand, added methods to get all melds and best meld combo; added function to find non-overlapping meld combos; fleshed out game start

This commit is contained in:
Donald Calloway 2025-09-24 19:33:58 -07:00
parent e179d71d41
commit 5406155c5d

View File

@ -1,7 +1,8 @@
import random import random
from collections import defaultdict from collections import defaultdict
from itertools import combinations
# Define card ranks and their order for runs
RANK_ORDER = {str(n): n for n in range(2, 11)} RANK_ORDER = {str(n): n for n in range(2, 11)}
RANK_ORDER.update({"A": 1, "J": 11, "Q": 12, "K": 13}) RANK_ORDER.update({"A": 1, "J": 11, "Q": 12, "K": 13})
class Card: class Card:
@ -42,6 +43,7 @@ class DiscardPile:
self.cards.append(card) self.cards.append(card)
class Hand: class Hand:
def __init__(self): def __init__(self):
self.cards = [] self.cards = []
@ -51,12 +53,25 @@ class Hand:
def remove(self, card): def remove(self, card):
self.cards.remove(card) self.cards.remove(card)
def melds(self): def get_all_melds(self):
"""Returns all valid sets and runs from current hand."""
return find_sets(self.cards) + find_runs(self.cards) return find_sets(self.cards) + find_runs(self.cards)
def best_meld_combo(self):
"""Returns the optimal non-overlapping meld combination."""
all_melds = self.get_all_melds()
combos = non_overlapping_meld_combos(all_melds)
best = max(combos, key=lambda combo: len(set(c for meld in combo for c in meld)), default=[])
return best
def deadwood(self):
"""Returns list of cards not used in best meld combo."""
used = set(c for meld in self.best_meld_combo() for c in meld)
return [c for c in self.cards if c not in used]
def deadwood_points(self): def deadwood_points(self):
return sum(c.value for c in self.cards) # placeholder return sum(c.value for c in self.deadwood())
def __repr__(self): def __repr__(self):
return f"Hand({self.cards})" return f"Hand({self.cards})"
@ -107,7 +122,6 @@ def find_sets(cards):
groups[c.rank].append(c) groups[c.rank].append(c)
return [group for group in groups.values() if len(group) >= 3] return [group for group in groups.values() if len(group) >= 3]
# Function to detect runs # Function to detect runs
def find_runs(cards): def find_runs(cards):
runs = [] runs = []
@ -133,7 +147,34 @@ def find_runs(cards):
if len(temp) >= 3: if len(temp) >= 3:
runs.append(temp) runs.append(temp)
return runs return runs
def non_overlapping_meld_combos(all_melds):
"""
Given a list of all possible melds (sets and runs),
return all combinations where no card is used more than once.
"""
valid_combos = []
for r in range(1, len(all_melds) + 1):
for combo in combinations(all_melds, r):
used = set()
overlap = False
for meld in combo:
for card in meld:
if card in used:
overlap = True
break
used.add(card)
if overlap:
break
if not overlap:
valid_combos.append(combo)
return valid_combos
# start a game with two players
if __name__ == "__main__":
players = [Player("Alice"), Player("Bob")]
game = Game(players)
game.play_round()
# Further game logic would go here