[Kde-games-devel] enums for unified CardCache

Burkhard Lehner burkhard.lehner at googlemail.com
Wed Feb 6 00:22:45 CET 2008


Hello,

Just my .02€ to this thread:



2008/2/5, Andreas Pakulat <apaku at gmx.de>:
>
> Currently this is a QFlags thingie, i.e. an enum with values 2, 4, 8,
> ...  However this is limiting us to 32 elements, and 18 are already
> taken by a 52 card deck.


I don't think that using QFlags here is a good idea, because it wastes so
many bits for invalid combinations. E.g., it doesn't make sense to specify a
card like "Spades | Diamonds | Queen", or "Hearts | Queen | Jack".
The suit of a card can be specified in 2 bits (instead of 4 with QFlags),
that prevents invalid combinations for free, and the value of a 52 cards
deck with wildcards can be specified in 4 bits.
One could use the old technique of just combining bits using "|", and use
enums like

enum Suit {Diamonds = 0x0, Hearts = 0x1, Spades = 0x2, Clubs = 0x3};
enum Value {Joker = 0x0, Ace = 0x4, Two = 0x8, Three = 0xC, Four = 0x10,
Five = 0x14, Six = 0x18, Seven = 0x1C, Eight = 0x20, Nine = 0x24, Ten =
0x28, Jack = 0x2C, Queen = 0x30, King = 0x34};

Then you can specify a card like "Nine | Diamond" (or "Nine + Diamond"). The
advantage is that the cards are sorted automatically (of course not
addressing the problem that the ace is at the same time lower than 2 and
higher than king).

If you want to prevent expressions like "Ace | Jack" or "Three | Diamonds |
Spades", and at the same time get the type safety similar to that of QFlags,
a class for creating a card could be used; something like

class Card
{
    public:
        Card (Suit s, Value v) {card = s|v;}  // create a card like "Card
(Diamonds, Ace)"
        Card (Value v, Suit s) {card = s|v;}  // create a card like "Card
(Ace, Diamonds)"

        operator int () const {return card;}  // return the combined card
value as an int

        Value value () const {return card & 0x3C;}  // return the value of
the card (Joker, Ace, ...)
        Suit suit () const {return card & 0x03;}  // return the suit of the
card (Diamonds, Hearts, ...)

    private:
        int card;
};

Using this class as a parameter type, a card instance can only be created
with exactly one suit and exactly one value. Trying to create a card other
than that results in a compiler error. You could of course add further
methods like "setValue", "setSuit", "operator==", "operator!=", "operator<",
etc.

If you also want to keep "Diamonds | Ace" valid, you can define the
operators

Card operator| (Suit s, Value v) {return Card (s, v);}
Card operator| (Value v, Suit s) {return Card (s, v);}

And this is just the beginning. Thinking of other cards like, e.g., tarrot
cards, one could think of additional enums and additional constructors of
"Card". Or maybe a subclass of "Card" that provides support for other card
types. You just have to keep the value of the internal "card" attribute
unique. This reminds me of unicode: Every type of card deck has a specific
range. The "traditional" card deck of 52 cards plus wildcards occupy the
numbers "0" (Diamonds | Joker) to "55" (Clubs | King). Tarrot cards may
occupy "54" to "82" (I have no idea how many different cards tarrot has).
One could even think of some "Memory" like game to have its own range within
the Card class.
Maybe also a method that returns some kind of class ID could be usefull, to
check whether an svg card deck matches the cards that can be contained
within a Card instance.

Maybe I haven't seen one or the other drawback or pitfall in the approach I
described, but I leave the "work" to you. :-)

Burkhard
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.kde.org/pipermail/kde-games-devel/attachments/20080206/d8d2da8a/attachment.html 


More information about the kde-games-devel mailing list