Created
November 16, 2013 12:42
-
-
Save mgldev/7499736 to your computer and use it in GitHub Desktop.
So I was told about the Lizard and Spock extension to Rock, Paper Scissors and I wanted to see how the current OOP approach would extend to the introduction of the new winning methods and roles.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class DrawException extends DomainException {} | |
abstract class Hand { | |
public function beats(Hand $hand) { | |
$this->rejectDraw($hand); | |
return $this->assess($hand); | |
} | |
protected abstract function assess(Hand $hand); | |
public function __toString() { | |
return get_class($this); | |
} | |
public function rejectDraw(Hand $hand) { | |
if ($hand === $this) { | |
throw new DrawException('No player wins, round is a draw'); | |
} | |
} | |
} | |
interface Wrappable {} | |
interface Cuttable {} | |
interface Bluntable {} | |
interface Beheadable {} | |
interface Vapourisable {} | |
interface Crushable {} | |
interface Poisonable {} | |
interface Edible {} | |
interface Disprovable {} | |
interface Smashable {} | |
class Rock extends Hand implements Wrappable { | |
protected function assess(Hand $hand) { | |
$retval = ['result' => false, 'method' => null]; | |
switch (true) { | |
case $hand instanceof Bluntable: | |
$retval['result'] = true; | |
$retval['method'] = 'Blunted'; | |
break; | |
case $hand instanceof Crushable: | |
$retval['result'] = true; | |
$retval['method'] = 'Crushed'; | |
break; | |
} | |
return $retval; | |
} | |
} | |
class Paper extends Hand implements Cuttable, Edible { | |
protected function assess(Hand $hand) { | |
$retval = ['result' => false, 'method' => null]; | |
switch (true) { | |
case $hand instanceof Wrappable: | |
$retval['result'] = true; | |
$retval['method'] = 'Wrapped'; | |
break; | |
case $hand instanceof Disprovable: | |
$retval['result'] = true; | |
$retval['method'] = 'Disproven'; | |
break; | |
} | |
return $retval; | |
} | |
} | |
class Scissors extends Hand implements Bluntable, Crushable { | |
protected function assess(Hand $hand) { | |
$retval = ['result' => false, 'method' => null]; | |
switch (true) { | |
case $hand instanceof Cuttable: | |
$retval['result'] = true; | |
$retval['method'] = 'Cut to death'; | |
break; | |
case $hand instanceof Beheadable: | |
$retval['result'] = true; | |
$retval['method'] = 'Beheaded'; | |
break; | |
} | |
return $retval; | |
} | |
} | |
class Lizard extends Hand implements Beheadable, Crushable { | |
public function assess(Hand $hand) { | |
$retval = ['result' => false, 'method' => null]; | |
switch (true) { | |
case $hand instanceof Poisonable: | |
$retval['result'] = true; | |
$retval['method'] = 'Poisoned'; | |
break; | |
case $hand instanceof Edible: | |
$retval['result'] = true; | |
$retval['method'] = 'Eaten'; | |
break; | |
} | |
return $retval; | |
} | |
} | |
class Spock extends Hand implements Disprovable, Poisonable { | |
public function assess(Hand $hand) { | |
$retval = ['result' => false, 'method' => null]; | |
switch (true) { | |
case $hand instanceof Smashable: | |
$retval['result'] = true; | |
$retval['method'] = 'Smashed'; | |
break; | |
case $hand instanceof Vapourisable: | |
$retval['result'] = true; | |
$retval['method'] = 'Vapourised'; | |
break; | |
} | |
return $retval; | |
} | |
} | |
$hands = [ | |
'r' => new Rock, | |
'p' => new Paper, | |
'sc' => new Scissors, | |
'l' => new Lizard, | |
'sp' => new Spock | |
]; | |
while (true) { | |
echo "\n\nChoose hand [r (rock), p (paper), sc (scissors), l (lizard), sp (spock)]: "; | |
$choices = [ | |
'computer' => array_keys($hands)[rand(0, count($hands) - 1)], | |
'player' => strtolower(trim(fgets(STDIN))) | |
]; | |
$computerHand = $hands[$choices['computer']]; | |
$playerHand = $hands[$choices['player']]; | |
echo "Player chose $playerHand\n"; | |
echo "Computer chose $computerHand\n"; | |
try { | |
$result = $playerHand->beats($computerHand); | |
if ($result['result']) { | |
echo sprintf("Player wins, %s beats %s by being %s\n", $playerHand, $computerHand, $result['method']); | |
} else { | |
echo sprintf("Computer wins, %s beats %s but I don't know by which method\n", $computerHand, $playerHand); | |
} | |
} catch (DrawException $ex) { | |
echo $ex->getMessage() . "\n"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment