Package uk.co.iscoding.freecell.game

Source Code of uk.co.iscoding.freecell.game.CardCollection

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package uk.co.iscoding.freecell.game;

import com.google.common.base.Objects;
import uk.co.iscoding.freecell.cards.PlayingCard.Suit;
import uk.co.iscoding.freecell.cards.PlayingCard.Rank;
import uk.co.iscoding.freecell.cards.PlayingCard;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
*
* @author   Stuart David James McHattie
* @version  1.0 2011-06-30
* @since    2011-06-30
*/
public class CardCollection {
    protected enum RankOrder {
        ANY(0),
        ASCENDING(1),
        DESCENDING(-1);

        public final int factor;

        private RankOrder(int factor) {
            this.factor = factor;
        }
    }

    protected enum Cycle {
        CAN,
        CANNOT,
    }

    protected enum AllowedSuit {
        ANY,
        SAME_SUIT,
        SAME_COLOUR,
        ALTERNATING_SUIT,
        ALTERNATING_COLOUR,
    }

    protected enum AllowedColour {
        IDENTICAL,
        ALTERNATING,
    }

    protected enum StartingRank {
        ANY,
        ACE(Rank.ACE),
        KING(Rank.KING);

        public final Rank rank;

        private StartingRank() {
            this.rank = null;
        }

        private StartingRank(Rank rank) {
            this.rank = rank;
        }
    }

    protected enum StartingSuit {
        ANY,
        SPADE(Suit.SPADES),
        HEART(Suit.HEARTS),
        CLUB(Suit.CLUBS),
        DIAMOND(Suit.DIAMONDS);

        public final Suit suit;

        private StartingSuit() {
            this.suit = null;
        }

        private StartingSuit(Suit suit) {
            this.suit = suit;
        }
    }

    protected enum SortMode {
        ASCENDING,
        DESCENDING,
    }

    public static void moveCards(CardCollection from, CardCollection to, int numCards) {
        to.addCollection(from.getTopCards(numCards));
        from.removeTopCards(numCards);
    }

    private final List<PlayingCard> cards;
    private final int maxCards;
    private String name = "";

    RankOrder rankMode = RankOrder.ANY;
    Cycle cycleMode = Cycle.CANNOT;
    AllowedSuit suitMode = AllowedSuit.ANY;
    StartingRank startingRank = StartingRank.ANY;
    StartingSuit startingSuit = StartingSuit.ANY;

    CardCollection(int maxCards) {
        cards = new ArrayList<PlayingCard>(maxCards);
        this.maxCards = maxCards;
    }

    public void setName(String name) {
        this.name = name;
    }

    boolean addCard(PlayingCard card, boolean ignoreRules) {
        if (cards.size() == maxCards) {
            return false;
        }
        if (ignoreRules || canAddCard(card)) {
            cards.add(card);
            return true;
        } else {
            return false;
        }
    }

    public boolean addCard(PlayingCard card) {
        return addCard(card, false);
    }

    public boolean addCollection(CardCollection newCards) {
        if (cards.size() + newCards.getNumberOfCards() > maxCards) {
            return false;
        } else if (canAddCard(newCards.getBottomCard())) {
            while (newCards.getNumberOfCards() > 0) {
                addCard(newCards.getBottomCard(), true);
                newCards.removeCardAt(0);
            }
        } else {
            return false;
        }

        return true;
    }

    boolean canAddCard(PlayingCard card) {
        if (cards.size() == maxCards) {
            // Collection is full
            return false;
        }

        if (cards.size() == 0) {
            if (startingRank != StartingRank.ANY && card.getRank() != startingRank.rank) return false;
            if (startingSuit != StartingSuit.ANY && card.getSuit() != startingSuit.suit) return false;
        } else {
            PlayingCard topCard = getTopCard();

            int rankDifference = card.rankDifference(topCard);
            if (cycleMode == Cycle.CAN && Math.abs(rankDifference) == 12) rankDifference += 13 * rankMode.factor;
            if (rankMode != RankOrder.ANY && rankDifference != rankMode.factor) return false;

            if (suitMode == AllowedSuit.ALTERNATING_COLOUR &&  card.isSameColourAs(topCard)) return false;
            if (suitMode == AllowedSuit.SAME_COLOUR        && !card.isSameColourAs(topCard)) return false;
            if (suitMode == AllowedSuit.ALTERNATING_SUIT   &&  card.isSameSuitAs(topCard)) return false;
            if (suitMode == AllowedSuit.SAME_SUIT          && !card.isSameSuitAs(topCard)) return false;
        }

        return true;
    }

    public void removeTopCard() {
        removeTopCards(1);
    }

    void removeTopCards(int nCards) {
        if (nCards > cards.size()) nCards = cards.size();
        for (int i = 0; i < nCards; i++) {
            cards.remove(cards.size() - 1);
        }
    }

    void removeCardAt(int index) {
        if (index >= 0 && index < cards.size()) {
            cards.remove(index);
        }
    }

    public void removeCard(PlayingCard card) {
        cards.remove(card);
    }

    public int getIndexOf(PlayingCard card) {
        return cards.indexOf(card);
    }

    PlayingCard getBottomCard() {
        if (cards.size() == 0) {
            throw new IllegalStateException("The CardCollection is empty");
        }

        return cards.get(0);
    }

    PlayingCard getTopCard() {
        if (cards.size() == 0) {
            throw new IllegalStateException("The CardCollection is empty");
        }

        return cards.get(cards.size() - 1);
    }

    public CardCollection getTopCards(int nCards) {
        if (cards.size() == 0) {
            throw new IllegalStateException("The CardCollection is empty");
        }

        if (nCards > cards.size()) return this;
        CardCollection topCards = new CardCollection(nCards);
        for (int i = cards.size() - nCards; i < cards.size(); i++) {
            topCards.addCard(cards.get(i), true);
        }
        return topCards;
    }

    public CardCollection getLongestSequenceNoLongerThan(int maxCards) {
        for (int numCards = Math.min(maxCards, getNumberOfCards()); numCards > 0 ; numCards--) {
            CardCollection candidates = getTopCards(numCards);

            if (candidates.isDescendingRank() && candidates.isAlternatingColour()) {
                return candidates;
            }
        }

        return null// This only happens if there are no cards in the collection
    }

    public PlayingCard getCard(int index) {
        if (index < 0 || index >= cards.size()) {
            throw new IndexOutOfBoundsException(
                    String.format("Requested index %d was not within CardCollection of size %d", index, cards.size()));
        }

        return cards.get(index);
    }

    public void sortCards(SortMode mode) {
        switch (mode) {
            case ASCENDING:
                Collections.sort(cards, new Comparator<PlayingCard>() {
                    @Override
                    public int compare(PlayingCard o1, PlayingCard o2) {
                        return o1.getCardNumber() - o2.getCardNumber();
                    }
                });
                break;
            case DESCENDING:
                Collections.sort(cards, new Comparator<PlayingCard>() {
                    @Override
                    public int compare(PlayingCard o1, PlayingCard o2) {
                        return o2.getCardNumber() - o1.getCardNumber();
                    }
                });
                break;
        }
    }

    public boolean isAlternatingColour() {
        for (int i = 1; i < cards.size(); i++) {
            if (cards.get(i).isSameColourAs(cards.get(i - 1))) return false;
        }

        return true;
    }

    public boolean isDescendingRank() {
        for (int i = 1; i < cards.size(); i++) {
            if (cards.get(i).rankDifference(cards.get(i-1)) != -1) return false;
        }

        return true;
    }

    public int getNumberOfCards() {
        return cards.size();
    }

    protected void populateDeepClone(CardCollection clone) {
        for (PlayingCard card: cards) {
            clone.addCard(card.deepClone(), true);
        }

        clone.name = name;
        clone.rankMode = rankMode;
        clone.cycleMode = cycleMode;
        clone.suitMode = suitMode;
        clone.startingRank = startingRank;
        clone.startingSuit = startingSuit;
    }

    @Override
    public boolean equals(Object other) {
        if (!(other instanceof CardCollection)) return false;

        CardCollection otherCollection = (CardCollection)other;

        if (maxCards != otherCollection.maxCards) return false;
        if (rankMode != otherCollection.rankMode) return false;
        if (cycleMode != otherCollection.cycleMode) return false;
        if (suitMode != otherCollection.suitMode) return false;
        if (startingRank != otherCollection.startingRank) return false;
        if (startingSuit != otherCollection.startingSuit) return false;

        if (cards.size() != otherCollection.cards.size()) return false;

        for (int i = 0; i < cards.size(); i++) {
            if (!cards.get(i).equals(otherCollection.cards.get(i))) return false;
        }

        return true;
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(cards, maxCards);
    }

    @Override
    public String toString() {
        if (name.length() > 0) {
            return name;
        } else {
            return super.toString();
        }
    }
}
TOP

Related Classes of uk.co.iscoding.freecell.game.CardCollection

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.