#!/usr/bin/env python3 """ Assignment 2 - UNO++ CSSE1001/7030 Semester 2, 2018 """ import random __author__ = "Your name & student number here" # Write your classes here class Card: """ A card represents a card in the uno game which has colour and number attributes. """ def __init__(self, number, colour): """ Construct a new card instance based on its number and colour. Parameters: number (int): card number colour (a2_support.CardColour): card colour """ self._number = number self._colour = colour def get_number(self): """ (int) Return the card number """ return self._number def get_colour(self): """ (a2_support.CardColour) Return the card colour """ return self._colour def set_number(self, number): """ Set the number value of the card Parameters: number (int): card number """ self._number = number def set_colour(self, colour): """ Set the colour of the card Parameters: colour (CardColour): card colour """ self._colour = colour def get_pickup_amount(self): """ (int) Returns the amount of cards the next player should pickup """ return 0 def matches(self, card): """ (bool) Determine if the next card to be placed on the pile matches this card. Parameters: card (Card): a card to match """ return (self.get_colour() == card.get_colour() or self.get_number() == card.get_number()) def play(self, player, game): """ Perform a special card action. The base Card class has no special action. Parameters: player (Player): a player to perform an action on game (a2_support.UnoGame): a game instance """ pass def __str__(self): """ (str) Return the string representation of this card. """ return "{}({}, {})".format(self.__class__.__name__, self._number, self._colour) def __repr__(self): """ (str) Return the string representation of this card. """ return str(self) class SkipCard(Card): """ A card which skips the turn of the next player. """ def play(self, player, game): """ Perform a special card action. The base Card class has no special action. Parameters: player (Player): a player to perform an action on game (UnoGame): a game instance """ game.skip() def matches(self, card): """ Determine if the next card to be placed on the pile matches this card. Parameters: card (Card): a card to match """ return self.get_colour() == card.get_colour() class ReverseCard(Card): """ A card which reverses the order of turns. """ def matches(self, card): """ Determine if the next card to be placed on the pile matches this card. Parameters: card (Card): a card to match """ return self.get_colour() == card.get_colour() def play(self, player, game): """ Perform a special card action. The base Card class has no special action. Parameters: player (Player): a player to perform an action on game (UnoGame): a game instance """ game.reverse() class Pickup2Card(Card): """ A card which makes the next player pickup two cards. """ def get_pickup_amount(self): """ Returns the amount of cards the next player should pickup """ return 2 def matches(self, card): """ Determine if the next card to be placed on the pile matches this card. Parameters: card (Card): a card to match """ return self.get_colour() == card.get_colour() def play(self, player, game): """ Perform a special card action. The base Card class has no special action. Parameters: player (Player): a player to perform an action on game (UnoGame): a game instance """ cards = game.pickup_pile.pick(self.get_pickup_amount()) game.next_player().get_deck().add_cards(cards) while game.current_player() != player: game.next_player() class Pickup4Card(Card): """ A card which makes the next player pickup four cards. """ def get_pickup_amount(self): """ Returns the amount of cards the next player should pickup """ return 4 def matches(self, card): """ Determine if the next card to be placed on the pile matches this card. Parameters: card (Card): a card to match """ return True def play(self, player, game): """ Perform a special card action. The base Card class has no special action. Parameters: player (Player): a player to perform an action on game (UnoGame): a game instance """ cards = game.pickup_pile.pick(self.get_pickup_amount()) game.next_player().get_deck().add_cards(cards) while game.current_player() != player: game.next_player() class Deck: """ A collection of ordered Uno cards. """ def __init__(self, starting_cards=None): """ Construct a new deck for card collection. Parameters: starting_cards (list): A list of cards """ self._cards = [] if starting_cards: self._cards.extend(starting_cards) def get_cards(self): """ Returns a list of cards in the deck. """ return self._cards def get_amount(self): """ Returns the amount of cards in a deck. """ return len(self._cards) def shuffle(self): """ Shuffle the order of the cards in the deck. """ random.shuffle(self._cards) def pick(self, amount=1): """ Take the first 'amount' of cards off the deck and return them. Parameters: amount (int): the number of cards to return """ picked = self._cards[-amount:] self._cards = self._cards[:-amount] return picked def add_cards(self, cards): """ Place a list of cards on top of the deck. Parameters: cards (list): a list of cards to add to the deck """ for card in cards: self.add_card(card) def add_card(self, card): """ Place a card on top of the deck. Parameters: card (Card): a card to add to the deck """ self._cards.append(card) def top(self): """ Peaks at the card on top of the deck and returns it or None if the deck is empty. """ if self._cards: return self._cards[-1] class Player: """ A player represents one of the players in a game of uno. """ def __init__(self, name): """ Constructs a new playwer with an empty deck. Parameters: name (str): a player's name """ self._name = name self._deck = Deck() def get_name(self): """ Returns the name of the player. """ return self._name def get_deck(self): """ Returns the players deck of cards. """ return self._deck def is_playable(self): """ Returns True if the players moves aren't automatic. Raises a NotImplementedError on the base Player class. """ raise NotImplementedError("is_playable to be implemented by subclasses") def has_won(self): """ Returns True if the player has an empty deck and has therefore won. """ return self._deck.get_amount() == 0 def pick_card(self, putdown_pile): """ Selects a card to play from the players current deck. Raises a NotImplementedError on the base Player class. Returns None for non-automated players. Parameters: putdown_pile (Deck): a deck to put the used card to. """ raise NotImplementedError("pick_card to be implemented by subclasses") class HumanPlayer(Player): """ A human player that selects cards to play using the GUI. """ def is_playable(self): """ Returns True iff the players moves aren't automatic. """ return True def pick_card(self, putdown_pile): """ Selects a card to play from the players current deck. Raises a NotImplementedError on the base Player class. Returns None for non-automated players. Parameters: putdown_pile (Deck): a deck to put the used card to. """ return None class ComputerPlayer(Player): """ A computer player that selects cards to play automatically. """ def is_playable(self): """ Returns True iff the players moves aren't automatic. """ return False def pick_card(self, putdown_pile): """ (Card) Selects a card to play from the players current deck. Raises a NotImplementedError on the base Player class. Returns None for non-automated players. Parameters: putdown_pile (Deck): a deck to put the played card to. """ top = putdown_pile.top() if top: for card in self.get_deck().get_cards(): if card.matches(top): self.get_deck().get_cards().remove(card) putdown_pile.add_card(card) return card def main(): print("Please run gui.py instead") if __name__ == "__main__": main()