PHP Tutorial: 2 Player Tic-Tac-Toe Game (no database required)
In the first part of my games tutorial series we created a PHP Hangman game and then in the second installment we converted Hangman to use AJAX. Now it’s time to follow the same approach, only with Tic Tac Toe.
The Beauty of Classes
One of the things I like about classes is how easy it is to use and reuse them without writing a lot of code to go with it. So to start our Tic Tac Toe game we’re going to copy all the files from our original PHP Hangman game. We won’t need to change anything in the game class but we will need to make some modifications to the other class. First we’ll remove all references to letters, then we’ll remove any functions we don’t need anymore. Finally we change the main functions to display a Tic Tac Toe board instead of our hangman pictures, and finish it off by changing the logic behind how you win a game and how you make a move in the game.
Our new Tic Tac Toe game will need a player (or turn) variable so we know whose turn it is to place an X or an O. Then we’re going to add another variable to keep track of how many guesses have been made — that makes it easier to figure out if there’s a tie game instead of looping through the whole array each time someone guesses. We’ll also need a new array called Board to store all of the X and O’s placed on our game board.
The Index File
We’re going to keep things as short and easy as possible. The only changes we have to make to our index file is to load a tic tac toe game instead of a hangman game. Then we change the page title and we’re nearly done!
Tic Tac Toe
The Updated Class File
Here’s the class file with our updated game logic. Can you see how similar it is to our hangman class file? What’s changed and what looks the same?
start(); //reset the player $this->player = "X"; $this->totalMoves = 0; //clear out the board $this->board = array(); } /** * Purpose: run the game until it's tied or someone has won * Preconditions: all $_POST content * Postconditions: game is in play **/ function playGame($_POST) { if (!$this->isOver() && $_POST['move']) $this->move($_POST); //player pressed the button to start a new game if ($_POST['newgame']) $this->newGame(); //display the game $this->displayGame(); } /** * Purpose: display the game interface * Preconditions: none * Postconditions: start a game or keep playing the current game **/ function displayGame() { //while the game isn't over if (!$this->isOver()) { echo ""; for ($x = 0; $x < 3; $x++) { for ($y = 0; $y < 3; $y++) { echo ""; } else { //someone won the game or there was a tie if ($this->isOver() != "Tie") echo successMsg("Congratulations player " . $this->isOver() . ", you've won the game!"); else if ($this->isOver() == "Tie") echo errorMsg("Whoops! Looks like you've had a tie game. Want to try again?"); session_destroy(); echo ""; } } /** * Purpose: trying to place an X or O on the board * Preconditions: the position they want to make their move * Postconditions: the game data is updated **/ function move($_POST) { if ($this->isOver()) return; //remove duplicate entries on the board $_POST = array_unique($_POST); foreach ($_POST as $key => $value) { if ($value == $this->player) { //update the board in that position with the player's X or O $coords = explode("_", $key); $this->board[$coords[0]][$coords[1]] = $this->player; //change the turn to the next player if ($this->player == "X") $this->player = "O"; else $this->player = "X"; $this->totalMoves++; } } if ($this->isOver()) return; } /** * Purpose: check for a winner * Preconditions: none * Postconditions: return the winner if found **/ function isOver() { //top row if ($this->board[0][0] && $this->board[0][0] == $this->board[0][1] && $this->board[0][1] == $this->board[0][2]) return $this->board[0][0]; //middle row if ($this->board[1][0] && $this->board[1][0] == $this->board[1][1] && $this->board[1][1] == $this->board[1][2]) return $this->board[1][0]; //bottom row if ($this->board[2][0] && $this->board[2][0] == $this->board[2][1] && $this->board[2][1] == $this->board[2][2]) return $this->board[2][0]; //first column if ($this->board[0][0] && $this->board[0][0] == $this->board[1][0] && $this->board[1][0] == $this->board[2][0]) return $this->board[0][0]; //second column if ($this->board[0][1] && $this->board[0][1] == $this->board[1][1] && $this->board[1][1] == $this->board[2][1]) return $this->board[0][1]; //third column if ($this->board[0][2] && $this->board[0][2] == $this->board[1][2] && $this->board[1][2] == $this->board[2][2]) return $this->board[0][2]; //diagonal 1 if ($this->board[0][0] && $this->board[0][0] == $this->board[1][1] && $this->board[1][1] == $this->board[2][2]) return $this->board[0][0]; //diagonal 2 if ($this->board[0][2] && $this->board[0][2] == $this->board[1][1] && $this->board[1][1] == $this->board[2][0]) return $this->board[0][2]; if ($this->totalMoves >= 9) return "Tie"; } }"; //check to see if that position is already filled if ($this->board[$x][$y]) echo ""; else { //let them choose to put an x or o there echo ""; } echo ""; } echo ""; } echo "
It's player {$this->player}'s turn.
I tried your code and it returns an error message saying undefined offset error on most of the lines from /** Check for winner **/ i have a feeling that $board is not set to anything.
Did you use the code from the .zip files or from the post directly? Can you copy/paste the entire error.
@desire:hey,you just try isset on each of the checking of $board and error will be gone..
i just download code and it gives me 500 Internal Server Error. its in class tictactoe
You need to turn off safe error messages in IE or use a different browser to see what error you’re getting.