I've written up some generic code for a card-game and would like to hear any and all suggestions for how to improve this code further, in any way shape or form.
The code is on github or pasted directly below:
Card class:
class AbstractCard:
"""Abstract class for handling comparisons between cards based on rank"""
def __init__(self, value=None, suit=None, rank=None):
self.value = value
self.suit = suit
self.rank = rank
def __lt__(self, other):
if isinstance(other, AbstractCard):
return self.rank < other.rank
raise TypeError("Cannot compare to non-card types")
def __le__(self, other):
if isinstance(other, AbstractCard):
return self.rank <= other.rank
raise TypeError("Cannot compare to non-card types")
def __eq__(self, other):
if isinstance(other, AbstractCard):
return self.rank == other.rank
raise TypeError("Cannot compare to non-card types")
def __ne__(self, other):
if isinstance(other, AbstractCard):
return self.rank != other.rank
raise TypeError("Cannot compare to non-card types")
def __gt__(self, other):
if isinstance(other, AbstractCard):
return self.rank > other.rank
raise TypeError("Cannot compare to non-card types")
def __ge__(self, other):
if isinstance(other, AbstractCard):
return self.rank >= other.rank
raise TypeError("Cannot compare to non-card types")
def __repr__(self):
data = (self.value, self.suit, self.rank)
return "(value:{}, suit:{}, rank:{})".format(*data)
def __str__(self):
data = (self.value, self.suit)
return "{} of {}".format(*data)
CardFactory class
from AbstractCard import AbstractCard
class AbstractCardFactory:
"""Factory for making AbstractCards"""
def __init__(self, values=None, suits=None, rank_function=None):
self.values = values
self.suits = suits
self.rank_function = rank_function
def __repr__(self):
return "Values: {}\nSuits: {}".format(self.values, self.suits)
def __str__(self):
return self.__repr__()
def generate(self):
if self.rank_function:
for suit in self.suits:
for value in self.values:
card = AbstractCard(value, suit)
card.rank = rank_function(card)
yield card
else:
for suit in self.suits:
for value in self.values:
yield AbstractCard(value, suit)
Deck class
from random import *
class AbstractDeck:
"""Abstract class for shuffling and iterating over a collection of cards"""
def __init__(self, cards=None):
self.cards = cards
def __len__(self):
return len(cards)
def __iter__(self):
return iter(self.cards)
def shuffle(self):
"""Shuffles the deck with the Fisher-Yates shuffle"""
num_cards = len(self.cards)
for i in range(0, num_cards):
j = randint(i, num_cards - 1)
self.cards[i], self.cards[j] = self.cards[j], self.cards[i]
Player class
class AbstractPlayer:
"""Abstract class for containing basic player information"""
def __init__(self, name=None, cards=[]):
self.name = name
self.cards = list(cards)
def name(self):
return self.name
def hand(self):
"""Returns a copy of the player's hand"""
return self.cards
def add_card(self, card):
"""Adds the given card to the existing cards"""
self.cards.append(card)
def remove_card(self, card):
"""Removes the given card from the player's hand"""
self.cards.remove(card)
def __repr__(self):
return self.name
def __str__(self):
return str(self.name)
Game class
class AbstractGame:
"""Abstract class for running a card game"""
def __init__(self, players=[], deck=None):
self.players = list(players)
self.deck = deck
def play_game(self):
"""Override this function for custom game logic"""
pass
How to use
- Construct a deck using a
AbstractCardFactory
- Extend the
AbstractGame
class with custom game logic in theplay_game()
method - Add a
if __name__ == "__main__":
block with player initialization logic