Your First PHP Game

Now it’s time to program your first game in PHP! You will start off with a simple game of tic-tac-toe. This game will use all the aspects that you have learned in all the previous chapters. It contains session variables, arrays, functions, and PHP working together with HTML.

The first step you need to take to set up a new game is to create a directory for it inside your Web server. For IIS the directory would be C:Inetpubwwwroot, and if you are using an Apache Web server the directory would be /usr/web. If you are on Windows the Apache directory would look something like C:Apache depending on where you installed Apache. You can name the directory whatever you like. I am going to name it tictactoe.

Now that you have a directory set up you can create a new PHP file. I recommend fol-lowing a regular naming scheme. The default page in a directory should be named index.php or default.php. You can use whichever you like. Since the game will only be in one file I will just name it index.php.

The next step you need to take is to define all of your constants and globals, and include the common functions file that you use in all of your games. The first set of constants that you need is four game states. The first of the four states is to tell you when the game is starting, the second lets you know when the game is in play, the third tells you if someone has won the game, and the fourth and final state tells you if someone has lost the game.

// Includes
include(“common.php”);
// Game States
define(“GAME_START”, 0);
define(“GAME_PLAY”, 1);
define(“GAME_WIN”, 2);
define(“GAME_OVER”, 3);

For tic-tac-toe, the only other two defines needed are one for the “X” image and one for the “O” image.

// Images
define(“X_IMAGE”, “images/X.gif”);
define(“O_IMAGE”, “images/O.gif”);

The only reason you define these is because it makes it easy if you want to change the images later, plus it saves you some typing when you create the render function to display your board to the browser. You will also need three global variables for all of your functions to use. The first stores what state the game is in, the second stores the state of the board, and the third stores the difficulty level of the computer A.I.

// Globals
global $gGameState;
global $gBoard;
global $gDifficulty;

Now that the global information for the game is defined, you will set up the HTML framework for the game. The HTML framework is the form you will use to get user input for your game. The following is all the HTML you will need for the game:

<!doctype html public “-//W3C//DTD HTML 4.0 //EN”>
<html>   
<head>
        <title>Tic-Tac-Toe</title>
        <link rel=“stylesheet” href=“style.css” type=“text/css”>
</head>
<body>
 
<form action=“index.php” method=“post”>
<input type=“hidden” name=“turn” value=“<? printf($turn) ?>”>
    <?php WriteTableHeader(); ?>
        <div align=“center”>
        <input type=“submit” name=“btnNewGame” value=“New Game”>&nbsp;&nbsp;&nbsp;
            <b>Difficulty Level</b>
            <select name=“dlDifficulty“>
                <option value=“1”>Easy</option>
                <option value=“2” SELECTED>Normal</option>
                <option value=“3”>Not-Likely</option>
            </select><br><br>
        <?php
            // Render the game
            Render();
        ?>
    </div>
    <?php WriteTableFooter(); ?>
</form>
 

</body>
</html>

NOTE

Remember that all of this code is provided for you on the CD.

The framework for the game is very simple; the form is redirecting back to itself. Then the header for the cool table layout is written. After that, some form elements are created. One allows the user to start a new game, and the drop-down box is used to choose the difficulty level of the computer A.I. After all that, the render function is called. Because you don’t yet have a render function, you’ll need to create one now.

The render function needs to determine what state the game is in by using the global game state variable that was declared earlier. If the state of the game is starting, then the render function needs to start a new game and change the state to playing. If the state of the game is playing then the render function needs to take the user input, process it, calculate the move for the computer, and update the board. If one of the players has won the game, the render function needs to tell the user that he either has won or lost the game.

As you can see, the render function needs to do a ton of work. To accomplish all these tasks the render function will need some helper functions. You will need a function to start a new game, a function to draw the board, a function to check for a win, a function to check to see if the board is full, and, finally, a function to end the game and free your session. Let’s start off with the render function itself and then continue on to the child functions that render() will call.

function Render()
{
    global $gGameState;
    global $gBoard;
    global $gDifficulty;

    switch($gGameState)
    {
        case GAME_PLAY:
        {
            // Get the move if the user made one
            if($_POST[‘btnMove’] != “”)
            {
                 $gBoard[$_POST[‘btnMove’]] = “x”;
                 $_SESSION[‘gBoard’] = $gBoard;
            }

            // Check for a win
            if(CheckWin() == “X”)
            {
                 $gGameState = GAME_WIN;
                 Render();
                 return;
            }

            // Check to see if the board is full
            if(CheckFull() == 1)
            {
                 $gGameState = GAME_OVER;
                 Render();
                 return; 
            }
            // Compute the computer’s move if we can still move
            if($gGameState == GAME_PLAY && $_POST[‘btnMove’] != “”)
            {
                if($gDifficulty == 1)
                {
                    ComputerRandomMove();
                }
                elseif($gDifficulty == 2)
                {
                    $computerMove = ComputerMove();
                    if($computerMove == “”)
                    {
                        ComputerRandomMove();
                    }
                    else
                    {
                        $gBoard[$computerMove] = “o”;
                        $_SESSION[‘gBoard’] = $gBoard;
                    }
                }
                elseif($gDifficulty == 3)
                {
                    $computerMove = ComputerMove();
                        if ($computerMove == ‘’)
                        {
                            if($gBoard[4] == ‘’)
                                $computerMove = 4;
                                    elseif($gBoard[0] == ‘’)
                                        $computerMove = 0;
                                    elseif($gBoard[2] == ‘’)
                                        $computerMove = 2;
                                    elseif($gBoard[6] == ‘’)
                                        $computerMove = 6;
                                    elseif($gBoard[8] == ‘’)
                                        $computerMove = 8;
 
                                    if($computerMove == ‘’)
                            ComputerRandomMove();
                            }
                }   
            }
 
            // Check for a win
            if(CheckWin() == “O”)
            {
                $gGameState = GAME_OVER;
                Render();
                return;
            }
 
            // Check to see if the board is full
            if(CheckFull() == 1)
            {
                $gGameState = GAME_OVER;
                Render();
                return;
            }
 
            // Draw the board
            DrawBoard();
            break;
        }
        case GAME_WIN:
        {
            EndGame();
            printf(“<br><br><br><img src=“images/youWin.jpg“
                border=”0”>”);
            break;
        }
        case GAME_OVER:
        {
            EndGame();
            printf(“<br><br><br><img src=“images/gameOver.jpg“
                border=”0”>”);
            break;
        }
    }
    // Update our game state
    $_SESSION[‘gGameState’] = $gGameState;
}   
if($_POST[‘dlDifficulty’] != “”)
{
    $gDifficulty = $_POST[‘dlDifficulty’];

    EndGame();

    $gGameState = GAME_START;
    StartGame();
}

if($gGameState == GAME_START)
{
    StartGame();
}

// Check to see if the user is starting a new game
if($_POST[‘btnNewGame’] != “”)
{
    EndGame();

    $gGameState = GAME_START;
    StartGame();
}

As you can see, a switch statement is used to determine the state of the game. You also may have noticed that there is not a state for the game starting; this is because all of the game start events take place outside of the render function. The game checks to see if the New Game button has been clicked or if the difficulty level has been changed every time the page is loaded. That is what the three if statements that live outside of the render function are used for.

Here is a complete list of the functions that still need to be created.

  • StartGame()

  • EndGame()

  • DrawBoard()

  • CheckWin()

  • CheckFull()

  • ComputerRandomMove()

  • ComputerMove()

The StartGame() and EndGame() functions control the session variables. The StartGame() function creates all the variables that will be stored in the session and changes the game state to play. The EndGame() function simply unsets all the variables and destroys the active session.

function StartGame()
{
    global $gGameState;
    global $gBoard;

    if($gGameState == GAME_START)
    {
        $gGameState = GAME_PLAY;
    }

    // use $_SESSION instead of session_register due to security issues
    session_start();
    $turn = $_SESSION[‘turn’];
    if(!isset($turn))
    {
        $turn = 1;
        $gBoard = array(“”,“”,“”,“”,“”,“”,“”,“”,“”);
        $_SESSION[‘gGameState’] = $gGameState;
        $_SESSION[‘gBoard’] = $gBoard;
        $_SESSION[‘gDifficulty’] = $gDifficulty;
        $_SESSION[‘turn’] = $turn;
    }

    // Retrieve the board state
    $gBoard = $_SESSION[‘gBoard’];

    // Get the difficulty level
    $gDifficulty = $_SESSION[‘gDifficulty’];
}

function EndGame()
{
    global $gGameState;
    global $gBoard;

    $gGameState = GAME_OVER;

    unset($gBoard);
    unset($gGameState);
    unset($turn);
    session_destroy();
}

The first lines of the StartGame() function tell it that the function will use global variables. Then the function changes the game state and starts the session. Starting the session creates a new file in the directory where the sessions are stored, which is specified in the php.ini file. After the session is started it checks to see if the $turn variable has been set. If it has, then it doesn’t bother to create new session variables, but if it hasn’t been set then the function creates the array for the board, a session variable to store the game state, a session variable to store the state of the board, and a session variable to store the difficulty level; finally, it sets the variable $turn.

The first lines of the EndGame() function also tell it what global variables it should use. Then the function changes the game state to game over. After the game state has been changed, it unsets all of the variables and destroys the session.

DrawBoard() simply draws the board. Fantastic, isn’t it? It uses HTML and PHP together to write out the appropriate board to the browser.

function DrawBoard()
{
    global $gBoard;

    // Start the table
    printf(“<table border=0 cellpadding=0 cellspacing=0>”);

    $iLoop = 0;
    for($iRow = 0; $iRow < 5; $iRow++)
    {
        printf(“<tr>
”);
        for($iCol = 0; $iCol < 5; $iCol++)
        {
            if($iRow == 1 || $iRow == 3)
            {
                printf(“<td width=“12” height=“5”
                    align=“center” valign=“middle”
                bgcolor=“#000000”>&nbsp;</td>
”);
            }
            else
            {
                if($iCol == 1 || $iCol == 3)
                {   
                printf(“<td width=“12” height=“115” align=“center”
                    valign=“middle” bgcolor=“#000000”>&nbsp;</td>
”);
                }
                else
                {
                    printf(“<td width=“115” height=“115”
                        align=“center” valign=“middle”>”);

                    if($gBoard[$iLoop] == “x”)
                    {
                        printf(“<img src=““ . X_IMAGE . ””>”);
                    }
                    elseif($gBoard[$iLoop] == “o”)
                    {
                        printf(“<img src=““ . O_IMAGE . ””>”);
                    }
                    else
                    {
                        printf(“<input type=“submit” name=“btnMove”  value=““ .
                        $iLoop . ””>”);
                    }
                    printf(“</td>
”);
                    $iLoop++;
                }
            }

        }
        printf(“</tr>
”);
    }

    // End the table
    printf(“</table>”);
}

The DrawBoard() function uses only one global—the board itself. It has two nested loops; the first loop is the number of rows in the table that should be rendered, and the second loop is the number of columns in each row that should be rendered. If the count of $iCol is 1 or 3, then it draws the divider between the squares; otherwise it checks to see if there is a piece on the board in that particular row and that particular column. If there is a piece it renders it to the browser; otherwise it puts in a button.

The next two functions, CheckFull() and CheckWin(),check to see if the board is full or if someone has won the game.

function CheckFull()
{
    global $gGameState;
    global $gBoard;

    $gGameState = GAME_OVER;
    for($iLoop = 0; $iLoop < count($gBoard); $iLoop++)
    {
        if($gBoard[$iLoop] == “”)
        {
            $gGameState = GAME_PLAY;
            return 0;
        }
    }

    return 1;
}
function CheckWin()
{
    global $gGameState;
    global $gBoard;

    $player = 1;
    while($player <= 2)
    {
        if ($player == 1)
            $tile = “o”;
        else
            $tile = “x”;
        if (
        # horizontal
        ($gBoard[0] == $tile && $gBoard[1] == $tile &&
            $gBoard[2] == $tile) ||($gBoard[3] == $tile && $gBoard[4] == $tile &&
            $gBoard[5] == $tile) ||
        ($gBoard[6] == $tile && $gBoard[7] == $tile &&
            $gBoard[8] == $tile) ||
        # vertical
        ($gBoard[0] == $tile && $gBoard[3] == $tile &&
            $gBoard[6] == $tile) ||
        ($gBoard[1] == $tile && $gBoard[4] == $tile &&
            $gBoard[7] == $tile) ||
        ($gBoard[2] == $tile && $gBoard[5] == $tile &&
            $gBoard[8] == $tile) || 
        # diagonal
        ($gBoard[0] == $tile && $gBoard[4] == $tile &&
            $gBoard[8] == $tile) ||
        ($gBoard[2] == $tile && $gBoard[4] == $tile &&
            $gBoard[6] == $tile))
        {
            return strtoupper($tile);
        }
        $player++;
    }
}

The CheckFull() function starts off assuming that the game is finished. It then loops through each square on the board checking to see if there is a blank square. If the CheckFull() function finds a blank square it sets the game state back to play.

The CheckWin() function checks three tiles in a row for each player. It first checks to see if there are three horizontal tiles in a row with the same marker in them. It does the same exact procedures for three vertical tiles in a row and for three diagonal tiles in a row. If any of these tests evaluate to true, then the winning tile is returned to the render function.

The final two functions deal with the computer A.I. ComputerRandomMove() and ComputerMove() both calculate where the computer should place its piece. ComputerRandom- Move() is used for the easiest difficulty level and ComputerMove() is used for the normal and impossible difficulty levels.

function ComputerRandomMove()
{
    global $gBoard;
    $computerMove = “”;

    srand((double) microtime() * 1000000);
    while($computerMove == “”)
    {
        $test = rand(0, 8);
        if($gBoard[$test] == “”)
        {
            $computerMove = $test;
            $gBoard[$computerMove] = “o”;
            $_SESSION[‘gBoard’] = $gBoard;
        }
    }
}
function ComputerMove()
{
    global $gBoard;
      $computerMove = “”;

      for($player = 0; $player <= 1; $player++)
      {
          if($player == 0)
          {
              $tile = “o”;
          }
          else
          {
              $tile = “x”;
          }

          if ($gBoard[0] == $tile && $gBoard[1] == $tile &&
                  $gBoard[2] == ‘’)
              $computerMove = 2;
          if ($gBoard[0] == $tile && $gBoard[1] == ‘’ && $gBoard[2] == $tile)
              $computerMove = 1;
          if($gBoard[0] == ‘’ && $gBoard[1] == $tile &&
                  $gBoard[2] == $tile)
              $computerMove = 0;
          if($gBoard[3] == $tile && $gBoard[4] == $tile &&
                  $gBoard[5] == ‘’)
              $computerMove = 5;
          if($gBoard[3] == $tile && $gBoard[4] == ‘’ &&
                  $gBoard[5] == $tile)
              $computerMove = 4;
          if($gBoard[3] == ‘’ && $gBoard[4] == $tile &&
                  $gBoard[5] == $tile)
              $computerMove = 3;

          if($gBoard[6] == $tile && $gBoard[7] == $tile &&
                  $gBoard[8] == ‘’)
              $computerMove = 8;
          if($gBoard[6] == $tile && $gBoard[7] == ‘’ &&
                  $gBoard[8] == $tile)
              $computerMove = 7;
          if($gBoard[6] == ‘’ && $gBoard[7] == $tile &&
                  $gBoard[8] == $tile)
              $computerMove = 6;   
          if($gBoard[0] == $tile && $gBoard[3] == $tile &&
                  $gBoard[6] == ‘’)
              $computerMove = 6;
          if($gBoard[0] == $tile && $gBoard[3] == ‘’ &&
                  $gBoard[6] == $tile)
              $computerMove = 3;
          if($gBoard[0] == ‘’ && $gBoard[3] == $tile &&
                  $gBoard[6] == $tile)
              $computerMove = 0;

          if($gBoard[1] == $tile && $gBoard[4] == $tile &&
                  $gBoard[7] == ‘’)
              $computerMove = 7;
          if($gBoard[1] == $tile && $gBoard[4] == ‘’ &&
                  $gBoard[7] == $tile)
              $computerMove = 4;
          if($gBoard[1] == ‘’ && $gBoard[4] == $tile &&
                  $gBoard[7] == $tile)
              $computerMove = 1;
          if($gBoard[2] == $tile && $gBoard[5] == $tile &&
                  $gBoard[8] == ‘’)
              $computerMove = 8;
          if($gBoard[2] == $tile && $gBoard[5] == ‘’ &&
                  $gBoard[8] == $tile)
              $computerMove = 5;
          if($gBoard[2] == ‘’ && $gBoard[5] == $tile &&
                  $gBoard[8] == $tile)
              $computerMove = 2;

          if($gBoard[0] == $tile && $gBoard[4] == $tile &&
                  $gBoard[8] == ‘’)
              $computerMove = 8;
          if($gBoard[0] == $tile && $gBoard[4] == ‘’ &&
                  $gBoard[8] == $tile)
              $computerMove = 4;
          if($gBoard[0] == ‘’ && $gBoard[4] == $tile &&
                  $gBoard[8] == $tile)
              $computerMove = 0;

          if($gBoard[2] == $tile && $gBoard[4] == $tile &&
                  $gBoard[6] == ‘’)
              $computerMove = 6;   
          if($gBoard[2] == $tile && $gBoard[4] == ‘’ &&
                  $gBoard[6] == $tile)
              $computerMove = 4;
          if($gBoard[2] == ‘’ && $gBoard[4] == $tile &&
                  $gBoard[6] == $tile)
              $computerMove = 2;

          if($computerMove <> ‘’)
              break;
    }

    return $computerMove;
}

ComputerRandomMove() simply calculates a random number from the server’s timer. Once it gets this random number it tests to see if that square is blank. If the tested square is blank, then the computer puts its piece in that square. If the square tested is not blank, ComputerRandomMove() is run again until an empty square is found.

ComputerMove() looks at every single square on the board. If there are two tiles in a row with the opposing tile in them, the computer will place its tile on the third open square, thus blocking the opponent. This level of difficulty is increased in the render function with the following lines:

$computerMove = ComputerMove();
if ($computerMove == ‘’)
{
if($gBoard[4] == ‘’)
$computerMove = 4;
elseif($gBoard[0] == ‘’)
    $computerMove = 0;
elseif($gBoard[2] == ‘’)
            $computerMove = 2;
elseif($gBoard[6] == ‘’)
$computerMove = 6;
elseif($gBoard[8] == ‘’)
$computerMove = 8;
if($computerMove == ‘’)
ComputerRandomMove();
}

First it calculates the computer’s move. If the computer’s move is blank it tries to pick the first available square. If it doesn’t find an available square it randomly calculates the move. With these three methods of calculating moves, it is nearly impossible to win. It makes for a great challenge.

Congratulations! You have successfully completed your very first PHP game. The results of your efforts should look like Figure 6.10.

Figure 6.10. Your first PHP game!


NOTE

At this point you will want to go into your php.ini file and turn display_errors to off. The reason for this is because you only want to display errors when debugging; otherwise you will have warning notices all over the place that really don’t affect the gameplay.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset