PX : code

Concentration by Eric Hanson
Download this code


<?php
/*******************************************************************
Concentration by Eric Hanson
By Eric Hanson, eric@cornado.com, http://www.cornado.com/
May 2, 1999

- Requires PHPlib Sessions.  PHPlib is available from
  http://phplib.shonline.de/.
- Refers to images as
  pics/pic1.jpg
  pics/pic2.jpg
  ...
  Place your images in the "pics" directory use the same naming convention.


This code can be used for anything you'd like.

Example available at 
http://www.cornado.com/fun/memory/

Music of choice while programming:
  Pedro the Lion, Ben Folds Five, Propellerheads
********************************************************************/ 

/****************************************************************************
class concentration (x_size, y_size)
*****************************************************************************/

/* defines */
$MATCHED 1;
$SELECTED 2;
$UNMATCHED 0;

/* config */
$image_width 60;
$image_height 100;

class 
concentration {
  var 
$board;                     ## 2d array of card pairs
  
var $match;                     ## 2d bool array that keeps track of which
                                  ## cards have been matched
  
var $x;                         ## the width of the playing board
  
var $y;                         ## the height of the playing board
  
  
var $state;                     ## internal state machine
  
var $choice1_x = -1;            ## history keepers
  
var $choice1_y = -1;
  var 
$choice2_x = -1;
  var 
$choice2_y = -1;
  
  var 
$move_count;                ## total moves
  
  
var $classname="concentration"## phplib serialization helper
  
var $persistent_slots = array
  (
"board","match","x","y","state","choice1_x","choice1_y","move_count",
   
"choice2_x","choice2_y");

  function 
init ($x$y) {
    
$this->$x;
    
$this->$y;
    
$this->initGameBoard ();
    
$this->initMatchArray ();
    
$this->move_count 0;
    
    
$this->state 1;
  }
  
/****************************************************************************
function initGameBoard ()
generates an x by y array of randomized pairs numbered from 0 to ((x*y)/2)-1.
*****************************************************************************/

  
function initGameBoard () {
    
$cards = array ();
 
/* fill in the array with unshuffled values, as pairs of 2 */
    
$cards $this->getPairsArray ($this->$this->y);

/* shuffle the array */
    
$cardsRand $this->betterRandomizeArray ($cards,4);
  
/* get the 2d array from the shuffled 1d array */
    
$board $this->get2dArray ($cardsRand,$this->x,$this->y);
  
    
$this->board $board;
  }
  
  function 
initMatchArray () {
    global 
$UNMATCHED;
    
$this->match = array ();
    for (
$i=0;$i<$this->x;$i++) {
      
$this->match[$i] = array ();
      for (
$j=0;$j<$this->y;$j++) {
        
$this->match[$i][$j] = $UNMATCHED;
      }
    }
  }
  
/****************************************************************************
function makeMove (x,y)
makes a move at x y
*****************************************************************************/

  
function gameOver () {
    global 
$MATCHED;
    for (
$j=0;$j<$this->y;$j++) {
      for (
$i=0;$i<$this->x;$i++) {
        if (
$this->match[$i][$j] != $MATCHED) {
##            print "False on i=$i, j=$j";
            
return false;
          }
      }
    }
    return 
true;
  }
  
/****************************************************************************
function makeMove (x,y)
makes a move at x y
*****************************************************************************/

  
function makeMove ($x$y) {
    global 
$MATCHED$SELECTED$UNMATCHED;
    
$this->move_count += .5;
    
    switch (
$this->state) {
    
/* if this is the client's first choice of card for this turn */    
      
case 1:
/* if the client's choice is an unmatched card */
        
if ($this->match[$x][$y] == $UNMATCHED) {
/* mark the card as selected */
          
$this->match [$x][$y] = $SELECTED;
/* advance to state 2 */
          
$this->state 2;
/* save this choice for comparison with next choice (in state 2) */
          
$this->choice1_x $x;
          
$this->choice1_y $y;
          
$this->choice2_x = -1;
          
$this->choice2_y = -1;
          return 
true;
        }
/* the client picked a card that was already flipped or matched */
        
else {
          return 
false;
        }
      break;
       
       
/* if this is the client's second choice this turn, trying to match an
      already flipped card witht this choice */
      
case 2:
      
/* if the client's choice is an unmatched card */
        
if ($this->match[$x][$y] == $UNMATCHED) {
/* set up the history vars */
            
$this->choice2_x $x;
            
$this->choice2_y $y;
  
          if (
$this->board[$x][$y] ==
           
$this->board[$this->choice1_x][$this->choice1_y]) {
              
$this->match[$x][$y] = $MATCHED;
              
$this->match[$this->choice1_x][$this->choice1_y] = $MATCHED;
            }
            else {
              
$this->match[$this->choice1_x][$this->choice1_y] = $UNMATCHED;
            }
  
         
$this->state 1;
            return 
true;
        }
        else {
          return 
false;
        }
      break;
      
/* unrecognized state */
      
default: 
        print 
"Internal error: unrecognized state ".$this->state;
        return 
false;
      break;

    }
  }

/****************************************************************************
function printPlayBoard ()
prints the playboard
*****************************************************************************/

  
function printPlayBoard () {
    global 
$SELECTED$UNMATCHED$MATCHED$image_width$image_height;
##    print "<p>State = ".$this->state;
    
    
$table_width $this->$image_width;
    
    print 
"<table width=\""$table_width ."\" border=0 cellspacing=5>\n";
    for (
$j 0$j $this->y$j ++) {
      print 
"  <tr>\n";
      for (
$i 0$i $this->x$i ++) {
        print 
"    <td height=$image_height width=$image_width>\n";
          if ((
$this->match[$i][$j]) ||
            (
$i == $this->choice1_x && $j == $this->choice1_y) ||
            (
$i == $this->choice2_x && $j == $this->choice2_y)
             ){
          print 
"
            <img width=$image_width border=0 height=$image_height 
             src=\"pics/pic"
.( $this->board[$i][$j] + 1).".jpg\"><br>";
        }
        else {
          if (
$this->match[$i][$j] == $UNMATCHED) {
            print 
"
              <a 
               href=\"?move=yes&x_move="
.$i."&y_move=".$j."\"
              ><img 
               width=$image_width 
               height=$image_height 
               border=0 
               src=\"pics/1/cardback.gif\"
              ></a><br>\n"
;
            }
            else {
              print 
"<br>";
            }
        }
        print 
"</td>\n";
      }
      print 
"  </tr>\n";
    }
    print 
"</table>\n";
    return 
1;
  }  

/* generate an array of numeric pairs of size $size */
  
function getPairsArray ($size) {
    
$a = array ();
    for (
$i=0;$i $size$i ++) {
      
$a[$i] = floor($i/2);
    }  
    return 
$a;
  }
  
/* push a 1d array into a 2d array */
  
function get2dArray ($a,$x,$y) {
    for (
$j 0$j $y$j ++) {
      for (
$i 0$i $x$i ++) {
        
$b[$i][$j] = $a[($x)*($j)+$i];
      }
    }
    return 
$b;
  }  
    
/* miserable array randomizer */
  
function betterRandomizeArray ($array$iterations 1) {
    
$size sizeof($array);
    for (
$count 0$count $iterations$count ++) {
      for (
$i=0;$i<$size-1;$i++) {
/* swap element $i with another element in a random position */
        
$swap_pos rand () % $size;
        
$temp $array[$i];
        
$array[$i] = $array[$swap_pos];
        
$array[$swap_pos] = $temp;
      }
    }
    return 
$array;
  }
}


/****************************************************************************
example usage
*****************************************************************************/

/* phplib function */
page_open (array ("sess" => "Poe_Session"));

/* the dimensions of the game board */
$x 5;
$y 4;

if (!
$concentration_game) {
  
$concentration_game = new concentration;
  
$concentration_game->init($x,$y);
/* phplib function */
  
$sess->register ("concentration_game");
}

if (
$move) {
  
$concentration_game->makeMove ($x_move$y_move);
}

if (
$concentration_game->gameOver ()) {
  
$sess->delete();
  
$game_over true;
}

require 
"cornado.inc";
print 
"<h3>So...how's your short-term memory?</h3>\n";

$concentration_game->printPlayBoard ();

print 
"<p><b>".$concentration_game->move_count." total moves</b>\n";

if (
$game_over) {
  print 
"<h3><a href=\"\">New game?</a></h3>\n";
}

page_close ();
?>

Comments or questions?
PX is running PHP 5.2.17
Thanks to Miranda Productions for hosting and bandwidth.
Use of any code from PX is at your own risk.