<?php
// Hangman game example ported from WACT hangman example and refactored to
// follow MVC pattern.
require 'config.php';
require dirname(__FILE__) . '/../../A/Locator.php';
#include_once 'A/Http/Request.php';
#include_once 'A/Http/Response.php';
#include_once 'A/Template/Strreplace.php';
#include_once 'A/Rule/Abstract.php';
#include_once 'A/Rule/Notnull.php';
#include_once 'A/Filter/Regexp.php';
#include_once 'A/Controller/Input.php';
#include_once 'A/Controller/App.php';
// create Registry/Loader and initialize autoloading
$Locator = new A_Locator();
$Locator->autoload();
//-----------------------------------------------------------------------------
class HangmanGame {
public $word;
public $level;
public $levels;
public $guesses = '';
public $misses = 0;
public $feedback = '';
public $availableLetters;
function HangmanGame() {
$this->levels = $this->getLevels();
}
function getLevels() {
return array('easy' => 10, 'medium' => 5, 'hard' => 3);
}
function pickRandomWord() {
$words = preg_split("/[\s,]+/", file_get_contents('constitution.txt'));
do {
$i = rand(0, count($words)-1);
$word = $words[$i];
} while(strlen($word) < 5 || !preg_match('/^[a-z]*$/i', $word));
$this->word = strtoupper($word);
}
function guess($letter) {
if ($letter) {
$this->guesses .= $letter;
if (!is_integer(strpos($this->word, $letter))) {
$this->misses++;
}
}
$this->feedback = '';
for ($i = 0; $i < strlen($this->word); $i++) {
if (is_integer(strpos($this->guesses, $this->word{$i}))) {
$this->feedback .= $this->word{$i};
} else {
$this->feedback .= '_';
}
}
$this->availableLetters = array();
for ($ch=65; $ch<=90; ++$ch) {
$this->availableLetters[] = array(
'letter' => chr($ch),
'available' => (boolean) !is_integer(strpos($this->guesses, chr($ch))));
}
}
function hasLost() {
return ($this->misses >= $this->level);
}
function hasWon() {
for ($i = 0; $i < strlen($this->word); $i++) {
if (!is_integer(strpos($this->guesses, $this->word{$i}))) {
return FALSE;
}
}
return TRUE;
}
}
class StartView {
function render($locator) {
$response = $locator->get('Response');
$game = $locator->get('Game');
$game->pickRandomWord();
$template = new A_Template_Strreplace('templates/start.html');
$template->set('game_levels_easy', $game->levels['easy']);
$template->set('game_levels_medium', $game->levels['medium']);
$template->set('game_levels_hard', $game->levels['hard']);
$template->set('misses', '0');
$template->set('guesses', '');
$template->set('word', $game->word);
$response->set('Content', $template->render());
}
}
class GameView {
function render($locator) {
$request = $locator->get('Request');
$response = $locator->get('Response');
$game = $locator->get('Game');
foreach ($game->availableLetters as $letter) {
$ch = $letter['letter'];
if ($letter['available']) {
$list[] = "<a href=\"?misses={$game->misses}&guesses={$game->guesses}&word={$game->word}&level={$game->level}&letter=$ch\">$ch</a>";
} else {
$list[] = $ch;
}
}
$template = new A_Template_Strreplace('templates/game.html');
$template->set('word', $game->word);
$template->set('guesses', $game->guesses);
$template->set('misses', $game->misses);
$template->set('level', $game->level);
$template->set('feedback', $game->feedback);
$template->set('list', implode(' ', $list));
$response->set('Content', $template->render());
}
}
class WinView {
function render($locator) {
$request = $locator->get('Request');
$response = $locator->get('Response');
$game = $locator->get('Game');
$template = new A_Template_Strreplace('templates/win.html');
$template->set('word', $request->get('word'));
$response->set('Content', $template->render());
}
}
class LoseView {
function render($locator) {
$request = $locator->get('Request');
$response = $locator->get('Response');
$game = $locator->get('Game');
$template = new A_Template_Strreplace('templates/lose.html');
$template->set('word', $request->get('word'));
$response->set('Content', $template->render());
}
}
class WinRule extends A_Rule_Base {
function WinRule($game) {
$this->game = $game;
}
function validate() {
return $this->game->hasWon();
}
}
class LoseRule extends A_Rule_Base {
function LoseRule($game) {
$this->game = $game;
}
function validate() {
return $this->game->hasLost();
}
}
class Guess extends A_Rule_Base {
function validate() {
$value = $this->getValue('level');
return in_array($value, HangmanGame::getLevels());
}
}
class Hangman extends A_Controller_App {
function run($locator) {
$request = $locator->get('Request');
$response = $locator->get('Response');
$response->setRenderer(new A_Template_Strreplace('templates/layout.html'));
$number_rule = new A_Filter_Regexp('/[^0-9]/');
$letter_rule = new A_Filter_Regexp('/[^A-Z]/');
$param = new A_Controller_Input_Field('level');
$param->addFilter($number_rule);
$this->addField($param);
$param = new A_Controller_Input_Field('word');
$param->addFilter($letter_rule);
$this->addField($param);
$param = new A_Controller_Input_Field('guesses');
$param->addFilter($letter_rule);
$this->addField($param);
$param = new A_Controller_Input_Field('misses');
$param->addFilter($number_rule);
$this->addField($param);
$letter = new A_Controller_Input_Field('letter');
$letter->addFilter($letter_rule);
$this->addField($letter);
$this->processRequest($request);
$game = new HangmanGame();
$locator->set('Game', $game);
$game->word = $request->get('word');
$game->guesses = $request->get('guesses');
$game->misses = $request->get('misses');
$game->level = $request->get('level');
$game->guess($letter->value);
$this->addState(new A_Controller_App_State('start', array(new StartView(), 'render')));
$this->addState(new A_Controller_App_State('game', array(new GameView(), 'render')));
$this->addState(new A_Controller_App_State('win', array(new WinView(), 'render')));
$this->addState(new A_Controller_App_State('lose', array(new LoseView(), 'render')));
$this->addTransition(new A_Controller_App_Transition('start', 'game', new A_Rule_Notnull('level', '')));
$this->addTransition(new A_Controller_App_Transition('start', 'lose', new A_Rule_Notnull('giveup', '')));
$this->addTransition(new A_Controller_App_Transition('game', 'lose', new LoseRule($game)));
$this->addTransition(new A_Controller_App_Transition('game', 'win', new WinRule($game)));
parent::run($locator);
}
}
//-----------------------------------------------------------------------------
$Request = new A_Http_Request();
$Response = new A_Http_Response($Locator);
$Locator->set('Request', $Request);
$Locator->set('Response', $Response);
$controller = new Hangman($Locator, 'start');
$controller->run($Locator);
echo $Response->render();
|