Playing cards: Difference between revisions
Content added Content deleted
m (→{{header|PHP}}: Removed redundant Deck::__toString() and added convenience method CardCollection::toString()) |
(→{{header|PHP}}: Refactored, implemented Iterator interface and a sort method for CardCollection, and various compare methods for Card) |
||
Line 2,091: | Line 2,091: | ||
=={{header|PHP}}== |
=={{header|PHP}}== |
||
{{works with|PHP|5.3+}} |
|||
Implementation: |
Implementation: |
||
<lang php>class Card |
<lang php>class Card |
||
Line 2,100: | Line 2,101: | ||
protected $suit; |
protected $suit; |
||
protected $suitOrder; |
|||
protected $pip; |
protected $pip; |
||
protected $pipOrder; |
|||
protected $order; |
|||
public function __construct( $suit, $pip ) |
public function __construct( $suit, $pip ) |
||
Line 2,126: | Line 2,133: | ||
{ |
{ |
||
return $this->pip; |
return $this->pip; |
||
} |
|||
public function getSuitOrder() |
|||
{ |
|||
// lazy evaluate suit order |
|||
if( !isset( $this->suitOrder ) ) |
|||
{ |
|||
// cache suit order |
|||
$this->suitOrder = array_search( $this->suit, self::$suits ); |
|||
} |
|||
return $this->suitOrder; |
|||
} |
|||
public function getPipOrder() |
|||
{ |
|||
// lazy evaluate pip order |
|||
if( !isset( $this->pipOrder ) ) |
|||
{ |
|||
// cache pip order |
|||
$this->pipOrder = array_search( $this->pip, self::$pips ); |
|||
} |
|||
return $this->pipOrder; |
|||
} |
|||
public function getOrder() |
|||
{ |
|||
// lazy evaluate order |
|||
if( !isset( $this->order ) ) |
|||
{ |
|||
$suitOrder = $this->getSuitOrder(); |
|||
$pipOrder = $this->getPipOrder(); |
|||
// cache order |
|||
$this->order = $pipOrder * count( self::$suits ) + $suitOrder; |
|||
} |
|||
return $this->order; |
|||
} |
|||
public function compareSuit( Card $other ) |
|||
{ |
|||
return $this->getSuitOrder() - $other->getSuitOrder(); |
|||
} |
|||
public function comparePip( Card $other ) |
|||
{ |
|||
return $this->getPipOrder() - $other->getPipOrder(); |
|||
} |
|||
public function compare( Card $other ) |
|||
{ |
|||
return $this->getOrder() - $other->getOrder(); |
|||
} |
} |
||
Line 2,145: | Line 2,205: | ||
class CardCollection |
class CardCollection |
||
implements Countable |
implements Countable, Iterator |
||
{ |
{ |
||
protected $cards = array(); |
protected $cards = array(); |
||
Line 2,157: | Line 2,217: | ||
} |
} |
||
/** |
|||
* Countable::count() implementation |
|||
*/ |
|||
public function count() |
public function count() |
||
{ |
{ |
||
Line 2,162: | Line 2,225: | ||
} |
} |
||
/** |
|||
// use this method to iterate cards |
|||
* Iterator::key() implementation |
|||
public function toArray() |
|||
*/ |
|||
public function key() |
|||
{ |
{ |
||
return $this->cards; |
return key( $this->cards ); |
||
} |
|||
/** |
|||
* Iterator::valid() implementation |
|||
*/ |
|||
public function valid() |
|||
{ |
|||
return null !== $this->key(); |
|||
} |
|||
/** |
|||
* Iterator::next() implementation |
|||
*/ |
|||
public function next() |
|||
{ |
|||
next( $this->cards ); |
|||
} |
|||
/** |
|||
* Iterator::current() implementation |
|||
*/ |
|||
public function current() |
|||
{ |
|||
return current( $this->cards ); |
|||
} |
|||
/** |
|||
* Iterator::rewind() implementation |
|||
*/ |
|||
public function rewind() |
|||
{ |
|||
reset( $this->cards ); |
|||
} |
|||
public function sort( $comparer = null ) |
|||
{ |
|||
$comparer = $comparer ?: function( $a, $b ) { |
|||
return $a->compare( $b ); |
|||
}; |
|||
if( !is_callable( $comparer ) ) |
|||
{ |
|||
throw new InvalidArgumentException( 'Invalid comparer; comparer should be callable' ); |
|||
} |
|||
usort( $this->cards, $comparer ); |
|||
return $this; |
|||
} |
} |
||
Line 2,180: | Line 2,292: | ||
protected function addCard( Card $card ) |
protected function addCard( Card $card ) |
||
{ |
{ |
||
if( in_array( $card, $this->cards ) ) |
|||
{ |
|||
throw new DomainException( 'Card is already present in this collection' ); |
|||
} |
|||
$this->cards[] = $card; |
$this->cards[] = $card; |
||
} |
} |
||
Line 2,192: | Line 2,309: | ||
{ |
{ |
||
foreach( Card::getPips() as $pip ) |
foreach( Card::getPips() as $pip ) |
||
{ |
{ |
||
$this->addCard( new Card( $suit, $pip ) ); |
$this->addCard( new Card( $suit, $pip ) ); |
||
} |
} |
||
Line 2,205: | Line 2,322: | ||
public function deal( $amount = 1 ) |
public function deal( $amount = 1 ) |
||
{ |
{ |
||
$ |
if( !is_int( $amount ) || $amount < 1 ) |
||
if( !is_int( $amount ) || $amount < 1 || $cardCount == 0 || $amount > $cardCount ) |
|||
{ |
{ |
||
throw new InvalidArgumentException( 'Invalid amount; amount should be an integer, larger than 0' ); |
|||
return false; |
|||
} |
|||
if( $amount > count( $this->cards ) ) |
|||
{ |
|||
throw new RangeException( 'Invalid amount; requested amount is larger than the amount of available cards' ); |
|||
} |
} |
||
Line 2,229: | Line 2,350: | ||
// show the cards in the new deck |
// show the cards in the new deck |
||
echo count( $deck ) . ' cards in the new deck: ' . PHP_EOL . $deck . PHP_EOL; |
echo count( $deck ) . ' cards in the new deck: ' . PHP_EOL . $deck . PHP_EOL; |
||
// sort the deck, default sort |
|||
$deck->sort(); |
|||
// show the cards in the sorted deck |
|||
echo PHP_EOL . count( $deck ) . ' cards in the new deck, default sort: ' . PHP_EOL . $deck . PHP_EOL; |
|||
// sort the deck, custom sort |
|||
$deck->sort( function( $a, $b ) { |
|||
return $a->compareSuit( $b ) ?: $a->comparePip( $b ); |
|||
} ); |
|||
// show the cards in the sorted deck |
|||
echo PHP_EOL . count( $deck ) . ' cards in the new deck, custom sort: ' . PHP_EOL . $deck . PHP_EOL; |
|||
// shuffle the deck |
// shuffle the deck |
||
Line 2,239: | Line 2,374: | ||
for( $p = 1; $p <= 4; $p++ ) |
for( $p = 1; $p <= 4; $p++ ) |
||
{ |
{ |
||
// deal player cards |
// deal player cards, and sort them, using default sort |
||
$playerCards = $deck->deal( 4 ); |
$playerCards = $deck->deal( 4 )->sort(); |
||
// show player cards |
// show player cards |
||
echo 'Player ' . $p . ' got dealt the following ' . count( $playerCards ) . ' cards: ' . $playerCards . PHP_EOL; |
echo 'Player ' . $p . ' got dealt the following ' . count( $playerCards ) . ' cards: ' . $playerCards . PHP_EOL; |
||
Line 2,250: | Line 2,385: | ||
This will output something like: |
This will output something like: |
||
<pre>52 cards in the new deck: |
<pre>52 cards in the new deck: |
||
♠2 ♠3 ♠4 ♠5 ♠6 ♠7 ♠8 ♠9 ♠T ♠J ♠Q ♠K ♠A ♥2 ♥3 ♥4 ♥5 ♥6 ♥7 ♥8 ♥9 ♥T ♥J ♥Q ♥K ♥A ♦2 ♦3 ♦4 ♦5 ♦6 ♦7 ♦8 ♦9 ♦T ♦J ♦Q ♦K ♦A ♣2 ♣3 ♣4 ♣5 ♣6 ♣7 ♣8 ♣9 ♣T ♣J ♣Q ♣K ♣A |
|||
52 cards in the new deck, default sort: |
|||
♠2 ♥2 ♦2 ♣2 ♠3 ♥3 ♦3 ♣3 ♠4 ♥4 ♦4 ♣4 ♠5 ♥5 ♦5 ♣5 ♠6 ♥6 ♦6 ♣6 ♠7 ♥7 ♦7 ♣7 ♠8 ♥8 ♦8 ♣8 ♠9 ♥9 ♦9 ♣9 ♠T ♥T ♦T ♣T ♠J ♥J ♦J ♣J ♠Q ♥Q ♦Q ♣Q ♠K ♥K ♦K ♣K ♠A ♥A ♦A ♣A |
|||
52 cards in the new deck, custom sort: |
|||
♠2 ♠3 ♠4 ♠5 ♠6 ♠7 ♠8 ♠9 ♠T ♠J ♠Q ♠K ♠A ♥2 ♥3 ♥4 ♥5 ♥6 ♥7 ♥8 ♥9 ♥T ♥J ♥Q ♥K ♥A ♦2 ♦3 ♦4 ♦5 ♦6 ♦7 ♦8 ♦9 ♦T ♦J ♦Q ♦K ♦A ♣2 ♣3 ♣4 ♣5 ♣6 ♣7 ♣8 ♣9 ♣T ♣J ♣Q ♣K ♣A |
♠2 ♠3 ♠4 ♠5 ♠6 ♠7 ♠8 ♠9 ♠T ♠J ♠Q ♠K ♠A ♥2 ♥3 ♥4 ♥5 ♥6 ♥7 ♥8 ♥9 ♥T ♥J ♥Q ♥K ♥A ♦2 ♦3 ♦4 ♦5 ♦6 ♦7 ♦8 ♦9 ♦T ♦J ♦Q ♦K ♦A ♣2 ♣3 ♣4 ♣5 ♣6 ♣7 ♣8 ♣9 ♣T ♣J ♣Q ♣K ♣A |
||
52 cards in the new deck, shuffled: |
52 cards in the new deck, shuffled: |
||
♥3 ♣2 ♥6 ♦A ♠J ♦K ♥T ♦3 ♦6 ♠6 ♥J ♥5 ♣J ♥4 ♥K ♠4 ♦T ♠5 ♠8 ♠T ♠3 ♣6 ♣9 ♦5 ♣T ♣3 ♠K ♦8 ♣K ♣5 ♠2 ♥A ♥2 ♥7 ♥Q ♥8 ♠7 ♣7 ♠Q ♠9 ♦J ♣Q ♠A ♦Q ♦9 ♣4 ♦2 ♣8 ♥9 ♣A ♦4 ♦7 |
|||
Player 1 got dealt the following 4 cards: |
Player 1 got dealt the following 4 cards: ♣2 ♥3 ♥6 ♦A |
||
Player 2 got dealt the following 4 cards: |
Player 2 got dealt the following 4 cards: ♦3 ♥T ♠J ♦K |
||
Player 3 got dealt the following 4 cards: |
Player 3 got dealt the following 4 cards: ♥5 ♠6 ♦6 ♥J |
||
Player 4 got dealt the following 4 cards: |
Player 4 got dealt the following 4 cards: ♠4 ♥4 ♣J ♥K |
||
36 cards remaining in the deck: |
36 cards remaining in the deck: |
||
♦T ♠5 ♠8 ♠T ♠3 ♣6 ♣9 ♦5 ♣T ♣3 ♠K ♦8 ♣K ♣5 ♠2 ♥A ♥2 ♥7 ♥Q ♥8 ♠7 ♣7 ♠Q ♠9 ♦J ♣Q ♠A ♦Q ♦9 ♣4 ♦2 ♣8 ♥9 ♣A ♦4 ♦7</pre> |
|||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |