From 5c77974d51700e7a9ae51e4d11255723b2fd30d8 Mon Sep 17 00:00:00 2001 From: KushMiryala <166750473+KushMiryala@users.noreply.github.com> Date: Sat, 7 Jun 2025 21:07:48 -0400 Subject: [PATCH 1/3] Add files via upload --- solitaire.py | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 solitaire.py diff --git a/solitaire.py b/solitaire.py new file mode 100644 index 00000000..e96a2a4c --- /dev/null +++ b/solitaire.py @@ -0,0 +1,118 @@ +import random + +SUITS = ['♠', '♥', '♦', '♣'] +RANKS = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'] +COLOR = {'♠': 'black', '♣': 'black', '♥': 'red', '♦': 'red'} + + +class Card: + def __init__(self, suit, rank, up=False): + self.suit = suit + self.rank = rank + self.up = up # face-up flag + + def __str__(self): + return f'{self.rank}{self.suit}' if self.up else '??' + + +class Solitaire: + def __init__(self): + self.stock = [] + self.waste = [] + self.found = {s: [] for s in SUITS} + self.piles = [[] for _ in range(7)] + self.deal() + + # deal opening layout + def deal(self): + deck = [Card(s, r) for s in SUITS for r in RANKS] + random.shuffle(deck) + for i in range(7): + for j in range(i + 1): + c = deck.pop() + c.up = (j == i) + self.piles[i].append(c) + self.stock = deck + + # helpers + def _rank(self, c): return RANKS.index(c.rank) + def _diff_color(self, a, b): return COLOR[a.suit] != COLOR[b.suit] + + # draw from stock + def draw(self): + if self.stock: + c = self.stock.pop() + c.up = True + self.waste.append(c) + else: + self.stock = list(reversed(self.waste)) + for c in self.stock: + c.up = False + self.waste = [] + + # pile X → foundation + def pile_to_found(self, idx): + pile = self.piles[idx] + if not pile or not pile[-1].up: + return + card = pile[-1] + top = self.found[card.suit][-1] if self.found[card.suit] else None + if (top is None and card.rank == 'A') or (top and self._rank(card) == self._rank(top) + 1): + self.found[card.suit].append(pile.pop()) + if pile and not pile[-1].up: + pile[-1].up = True + + # move pile A → pile B + def pile_to_pile(self, frm, to): + if frm == to: + return + src, dst = self.piles[frm], self.piles[to] + if not src: + return + for cut, c in enumerate(src): + if c.up: + break # first face-up + else: + return + moving = src[cut:] + if not dst: + if moving[0].rank != 'K': + return + dst.extend(moving) + del src[cut:] + else: + top = dst[-1] + if self._diff_color(top, moving[0]) and self._rank(moving[0]) == self._rank(top) - 1: + dst.extend(moving) + del src[cut:] + if src and not src[-1].up: + src[-1].up = True + + # print board + def show(self): + print("\nStock:", len(self.stock), "cards | Waste:", self.waste[-1] if self.waste else 'Empty') + print("Foundations:", {s: (str(p[-1]) if p else 'Empty') for s, p in self.found.items()}) + print("\nPiles:") + for i, p in enumerate(self.piles): + print(f"{i}: ", *p) + + # main loop + def play(self): + while True: + self.show() + print("\nCommands: d = draw f X = pile X→foundation p A B = pile A→pile B q = quit") + cmd = input("> ").split() + if not cmd: + continue + if cmd[0] == 'q': + break + if cmd[0] == 'd': + self.draw() + elif cmd[0] == 'f' and len(cmd) == 2: + self.pile_to_found(int(cmd[1])) + elif cmd[0] == 'p' and len(cmd) == 3: + self.pile_to_pile(int(cmd[1]), int(cmd[2])) + + +if __name__ == "__main__": + Solitaire().play() From 9286f1fbe29834bd2fb54a9cdcc20ef9b2ffb5ed Mon Sep 17 00:00:00 2001 From: KushMiryala <166750473+KushMiryala@users.noreply.github.com> Date: Sat, 7 Jun 2025 21:12:59 -0400 Subject: [PATCH 2/3] Delete solitaire.py --- solitaire.py | 118 --------------------------------------------------- 1 file changed, 118 deletions(-) delete mode 100644 solitaire.py diff --git a/solitaire.py b/solitaire.py deleted file mode 100644 index e96a2a4c..00000000 --- a/solitaire.py +++ /dev/null @@ -1,118 +0,0 @@ -import random - -SUITS = ['♠', '♥', '♦', '♣'] -RANKS = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'] -COLOR = {'♠': 'black', '♣': 'black', '♥': 'red', '♦': 'red'} - - -class Card: - def __init__(self, suit, rank, up=False): - self.suit = suit - self.rank = rank - self.up = up # face-up flag - - def __str__(self): - return f'{self.rank}{self.suit}' if self.up else '??' - - -class Solitaire: - def __init__(self): - self.stock = [] - self.waste = [] - self.found = {s: [] for s in SUITS} - self.piles = [[] for _ in range(7)] - self.deal() - - # deal opening layout - def deal(self): - deck = [Card(s, r) for s in SUITS for r in RANKS] - random.shuffle(deck) - for i in range(7): - for j in range(i + 1): - c = deck.pop() - c.up = (j == i) - self.piles[i].append(c) - self.stock = deck - - # helpers - def _rank(self, c): return RANKS.index(c.rank) - def _diff_color(self, a, b): return COLOR[a.suit] != COLOR[b.suit] - - # draw from stock - def draw(self): - if self.stock: - c = self.stock.pop() - c.up = True - self.waste.append(c) - else: - self.stock = list(reversed(self.waste)) - for c in self.stock: - c.up = False - self.waste = [] - - # pile X → foundation - def pile_to_found(self, idx): - pile = self.piles[idx] - if not pile or not pile[-1].up: - return - card = pile[-1] - top = self.found[card.suit][-1] if self.found[card.suit] else None - if (top is None and card.rank == 'A') or (top and self._rank(card) == self._rank(top) + 1): - self.found[card.suit].append(pile.pop()) - if pile and not pile[-1].up: - pile[-1].up = True - - # move pile A → pile B - def pile_to_pile(self, frm, to): - if frm == to: - return - src, dst = self.piles[frm], self.piles[to] - if not src: - return - for cut, c in enumerate(src): - if c.up: - break # first face-up - else: - return - moving = src[cut:] - if not dst: - if moving[0].rank != 'K': - return - dst.extend(moving) - del src[cut:] - else: - top = dst[-1] - if self._diff_color(top, moving[0]) and self._rank(moving[0]) == self._rank(top) - 1: - dst.extend(moving) - del src[cut:] - if src and not src[-1].up: - src[-1].up = True - - # print board - def show(self): - print("\nStock:", len(self.stock), "cards | Waste:", self.waste[-1] if self.waste else 'Empty') - print("Foundations:", {s: (str(p[-1]) if p else 'Empty') for s, p in self.found.items()}) - print("\nPiles:") - for i, p in enumerate(self.piles): - print(f"{i}: ", *p) - - # main loop - def play(self): - while True: - self.show() - print("\nCommands: d = draw f X = pile X→foundation p A B = pile A→pile B q = quit") - cmd = input("> ").split() - if not cmd: - continue - if cmd[0] == 'q': - break - if cmd[0] == 'd': - self.draw() - elif cmd[0] == 'f' and len(cmd) == 2: - self.pile_to_found(int(cmd[1])) - elif cmd[0] == 'p' and len(cmd) == 3: - self.pile_to_pile(int(cmd[1]), int(cmd[2])) - - -if __name__ == "__main__": - Solitaire().play() From 9cb86d8ede03c49dffe5072c37a605accaf4c6e5 Mon Sep 17 00:00:00 2001 From: KushMiryala <166750473+KushMiryala@users.noreply.github.com> Date: Sat, 7 Jun 2025 21:24:39 -0400 Subject: [PATCH 3/3] Add files via upload This is text based solitaire game that i decided to code on my free time and I thought it would be a great addition to this repo. --- src/freegames/solitaire.py | 118 +++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 src/freegames/solitaire.py diff --git a/src/freegames/solitaire.py b/src/freegames/solitaire.py new file mode 100644 index 00000000..e96a2a4c --- /dev/null +++ b/src/freegames/solitaire.py @@ -0,0 +1,118 @@ +import random + +SUITS = ['♠', '♥', '♦', '♣'] +RANKS = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'] +COLOR = {'♠': 'black', '♣': 'black', '♥': 'red', '♦': 'red'} + + +class Card: + def __init__(self, suit, rank, up=False): + self.suit = suit + self.rank = rank + self.up = up # face-up flag + + def __str__(self): + return f'{self.rank}{self.suit}' if self.up else '??' + + +class Solitaire: + def __init__(self): + self.stock = [] + self.waste = [] + self.found = {s: [] for s in SUITS} + self.piles = [[] for _ in range(7)] + self.deal() + + # deal opening layout + def deal(self): + deck = [Card(s, r) for s in SUITS for r in RANKS] + random.shuffle(deck) + for i in range(7): + for j in range(i + 1): + c = deck.pop() + c.up = (j == i) + self.piles[i].append(c) + self.stock = deck + + # helpers + def _rank(self, c): return RANKS.index(c.rank) + def _diff_color(self, a, b): return COLOR[a.suit] != COLOR[b.suit] + + # draw from stock + def draw(self): + if self.stock: + c = self.stock.pop() + c.up = True + self.waste.append(c) + else: + self.stock = list(reversed(self.waste)) + for c in self.stock: + c.up = False + self.waste = [] + + # pile X → foundation + def pile_to_found(self, idx): + pile = self.piles[idx] + if not pile or not pile[-1].up: + return + card = pile[-1] + top = self.found[card.suit][-1] if self.found[card.suit] else None + if (top is None and card.rank == 'A') or (top and self._rank(card) == self._rank(top) + 1): + self.found[card.suit].append(pile.pop()) + if pile and not pile[-1].up: + pile[-1].up = True + + # move pile A → pile B + def pile_to_pile(self, frm, to): + if frm == to: + return + src, dst = self.piles[frm], self.piles[to] + if not src: + return + for cut, c in enumerate(src): + if c.up: + break # first face-up + else: + return + moving = src[cut:] + if not dst: + if moving[0].rank != 'K': + return + dst.extend(moving) + del src[cut:] + else: + top = dst[-1] + if self._diff_color(top, moving[0]) and self._rank(moving[0]) == self._rank(top) - 1: + dst.extend(moving) + del src[cut:] + if src and not src[-1].up: + src[-1].up = True + + # print board + def show(self): + print("\nStock:", len(self.stock), "cards | Waste:", self.waste[-1] if self.waste else 'Empty') + print("Foundations:", {s: (str(p[-1]) if p else 'Empty') for s, p in self.found.items()}) + print("\nPiles:") + for i, p in enumerate(self.piles): + print(f"{i}: ", *p) + + # main loop + def play(self): + while True: + self.show() + print("\nCommands: d = draw f X = pile X→foundation p A B = pile A→pile B q = quit") + cmd = input("> ").split() + if not cmd: + continue + if cmd[0] == 'q': + break + if cmd[0] == 'd': + self.draw() + elif cmd[0] == 'f' and len(cmd) == 2: + self.pile_to_found(int(cmd[1])) + elif cmd[0] == 'p' and len(cmd) == 3: + self.pile_to_pile(int(cmd[1]), int(cmd[2])) + + +if __name__ == "__main__": + Solitaire().play()