Been a while away from PHP, what SPL interface?

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Post Reply
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Been a while away from PHP, what SPL interface?

Post 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?
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

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

Post 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).
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

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

Post 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.
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

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

Post 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...
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

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

Post 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.
(#10850)
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

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

Post 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
Post Reply