Page 1 of 1

Been a while away from PHP, what SPL interface?

Posted: Thu Nov 08, 2012 2:05 pm
by Luke
Hello Devnet! It's been a long time! I've taken almost a year break from PHP for various reasons (not least of which was a detour into Ruby/Rails and various other technologies), resulting in my being a tad bit rusty. I'm doing a little personal project just to brush up and make sure I still understand PHP's newest features and its SPL. So, a question I have is, what would be the best SPL interface to use in order to create a "deck of cards"? The deck will consist, basically, of an array of "Card" objects. I want to be able to "deal" cards off the top of the deck in a loop (like array_shift), shuffle it, count() it, So something like:

Code: Select all

$deck = new Cards\Deck;
$deck->shuffle();
$players = Game\Hearts\Factory::buildPlayers(); // I haven't actually created any game/player code yet. this is pseudo-code.
// Deal out 13 cards to each player...
while ($deck->hasCards()) {
    foreach ($players as $player) {
        $card = $deck->deal();
        $player->getHand()->addCard($card);
    }
}
I also need to be able to put cards back on the bottom of the deck (like array_push)

Code: Select all

$deck = new Cards\Deck;

// .. snip

$deck->burn(); // takes a card off the top and places it on the bottom
$flop = $deck->deal(3);

// .. or ..
$turn = $deck->deal();
$deck->accept($players[3]->getHand()); // player 3 folds, so his cards go back on bottom

// .. or ..
$deck->accept($discard); // deck gets a player's discard and puts it on bottom
I want to be able to count and treat the deck as an array

Code: Select all

if (count($deck) != 52) {
    throw new Cards\Exception\InvalidDeck('Deck is short of cards');
}

$lastcard = $deck[51];
I want to be able to cut the deck too (at a specific position)

Code: Select all

$deck = new Cards\Deck;
$deck->shuffle();
$deck->cut(15); // Cuts the deck in half at the 15th card, and places the top half under the bottom half
I also want to be able to simply loop through the deck without "dealing" any cards

Code: Select all

foreach ($deck as $card) {
    // do something with $card but dont take it outta the deck
}
So... basically I need the deck to behave similar to an array, but there are all these SPL interfaces and classes like ArrayObject, Countable, and SeekableIterator and I'm not sure which one(s) are most appropriate for my class. What do y'all think?

Re: Been a while away from PHP, what SPL interface?

Posted: Thu Nov 08, 2012 2:17 pm
by requinix
SplQueue is pretty close but I'm not sure it'll support cutting or shuffling the deck.

Since you have to write your own class anyways, I'd recommend just sticking with an array. array_push/pop/shift/unshift() let you add and remove from both ends, and you can easily shuffle() it. Countable for count() which just wraps a count() on the inner array, while ArrayAccess probably isn't appropriate since you shouldn't be reaching into the middle of the deck. IteratorAggregate gives you the functionality of foreach but you only have to implement one method, getIterator(), which can just return an ArrayIterator on the underlying array (versus Iterator with five methods you have to write from scratch).

Re: Been a while away from PHP, what SPL interface?

Posted: Thu Nov 08, 2012 2:26 pm
by Luke
You make a good point about ArrayAccess. I can't really think of any reason why I'd need to be able to access some mid-deck card. You know, I think what I'll do is move on to other code for now, and as I have need of certain features in the deck, I'll consider which of the above functionality I actually need. The only time I can think of where one would need to grab a card mid-deck is if they were doing a card trick (pick a card, any card), and LOL I don't think I'll be doing many magic tricks with this particular deck.

Re: Been a while away from PHP, what SPL interface?

Posted: Thu Nov 08, 2012 2:32 pm
by Luke
I should mention, however, that I'll probably be creating a class called "Hand" which will need to have much of the same functionality as "Deck". It will need to be able to have cards added, removed, and I WILL need to be able to access its cards individually for sure. But I think I'll need to be able to do something like $hand['clubs5'] or something. I'm not sure yet. I'm definitely going to need to build the code that uses these classes first so I know how they are to be used...

Re: Been a while away from PHP, what SPL interface?

Posted: Fri Nov 09, 2012 3:04 pm
by Christopher
Hey Luke good to see you back.

I think ArrayObject is probably what you want. It includes all the array stuff in a single class (i.e., IteratorAggregate, Traversable, ArrayAccess, Serializable, Countable). That will give you a clean OO base for your deck if you don't just want to use an internal $cards property and do the array stuff directly yourself plus Iterator.

Re: Been a while away from PHP, what SPL interface?

Posted: Wed Dec 18, 2013 2:27 pm
by Weirdan
lampdev112 wrote: It seems, that when you are implementing the interface Iterator, yout method key() has to return a string or integer.
This is fixed in php 5.5.0:
php changelog wrote: Added support for non-scalar Iterator keys in foreach