Tic Tac Toe Design Code in PHP

TicTacToe is an old interesting game played in schools and when people are free. This is a web-based Tic Tac Toe game written in PHP where a user can compete against computer.

I’ve been doing a simple Tic-Tac-Toe with PHP, generating only HTML code. I thought to write Tic Tac Toe ion PHP for providing site users to play it on my site (but found it a bit more difficult than anticipated). And I thought I could figure out on how to do it, but it took some time to figure various aspects.

Following Tic Tac Tac game works great and it can be played in 2 modes easy and hard (or hard is not that hard but moderate level). Though, one would find that there are some code snippets that could be rewritten in much better way but for providing a logic and a working Tic Tac Toe game this one is good.

One of the difficult task was to check if someone has won after every move and then there was another tough portion where does Computer picks a position after a user has chosen taken his chance. It is pretty hard to make a computer player, and make the computer actually smart enough for the game to be a challenge. I would just make the computer randomly move to different spaces. I could come up with  the solution using arrays etc. to decide on winner check and computer move. So, here is this PHP Tic Tac Toe Game code which can be played between user and computer in 2 modes easy and hard. In easy mode, it is just a random move by computer where it does tries to stop user to win but in hard mode it tries to win too.

Output is HTML and there are links to be clicked to make a next move. First chance is that of a user and after that computer automatically decides a move depending on easy or hard move. There are 4 files (just the numbers are more but the code is simple). index.php, function.php, logic.php, play.php. Place function.php, play.php and logic.php ina sub-directory named as tictactoe.

index.php

[php]

<?php
include "tictactoe/function.php";
?>
<?php
$err_msg=array();
$crr_msg=array();
?>
<?php
if(isset($_GET[‘tw_subkey’]))
{
$tw_subkey=$_GET[‘tw_subkey’];
if($tw_subkey!=”)
{
$sts_tw_subkey=1;
}
else
{
$sts_tw_subkey=0;
}
}
else
{
$tw_subkey="";
$sts_tw_subkey=0;
}

if($sts_tw_subkey==’0′)
{

if($sts_tw_msg==0 && $search_qry==”)
{
$crr_msg[]="Welcome to TicTacToe<br>";
$crr_msg[]= "<a href=’$path$app_file_path?tw_subkey=play&game_mode=0′>Easy Mode</a>";
$crr_msg[]= "<a href=’$path$app_file_path?tw_subkey=play&game_mode=1′>Hard Mode</a>";
}
else
{
include "tictactoe/play.php";
}
}
else
{
if($tw_subkey==’play’)
{
include "tictactoe/play.php";
}
elseif($tw_subkey==’easy’)
{
$ttt_game_mode=0;
include "tictactoe/play.php";
}
elseif($tw_subkey==’hard’)
{
$ttt_game_mode=1;
include "tictactoe/play.php";
}
else
{
$out_content="This is a Sub keyword.<br>Oops! it doesn’t exist yet.";
}
}
?>
<?php
$out_header = "<html><head></head><body>";
$out_footer= "</body></html>";
$out_content.=implode("<br>",$err_msg);
$out_content.=implode("<br>",$crr_msg);
$out_body=$out_content;
$out_message=$out_header.$out_body.$out_footer;
echo $out_message;
?>[/php]

function.php

[php]<?php

function game_mode_name($game_mode_code)
{
if($game_mode_code==0)
{
$game_mode_name="Easy";
}
else
{
$game_mode_name="Hard";
}

return($game_mode_name);
}

function cue_type_name($cue_code)
{
if($cue_code==1)
{
$cue_type_name="x";
}
elseif($cue_code==2)
{
$cue_type_name="o";
}
else
{
$cue_type_name="-";
}

return($cue_type_name);
}

function print_game($ttt_moves)
{
global $base_path, $cells_rows, $cells_cols, $ttt_play_sts, $path, $app_file_path, $ttt_game_mode;
$ttt_moves_arr = str_split($ttt_moves);

$loop_count=0;
$print_game_msg="";
for($i=0; $i<$cells_rows;$i++)
{

for($j=0; $j<$cells_cols;$j++)
{
$loop_count_next=$loop_count+1;
if($ttt_moves_arr[$loop_count]==1)
{
$cue_type_name=cue_type_name(1);
$print_game_msg.=$cue_type_name;
}
elseif($ttt_moves_arr[$loop_count]==2)
{
$cue_type_name=cue_type_name(2);
$print_game_msg.=$cue_type_name;
}
else
{
$ttt_move_link= substr_replace($ttt_moves, "1", $loop_count,1);
if($ttt_play_sts==0)
{
//$print_game_msg.="<a href=’$base_path?move_next=$ttt_move_link’>$loop_count_next</a>";
$print_game_msg.="<a href=’$path$app_file_path?tw_subkey=play&move_next=$ttt_move_link&game_mode=$ttt_game_mode’>&nbsp;</a>";
}
else
{
$cue_type_name=cue_type_name(0);
$print_game_msg.=$cue_type_name;
}
}

$print_game_msg.="&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
$loop_count++;
}
$print_game_msg.="<br>";
}

return($print_game_msg);
}

function cells_free($ttt_moves)
{
$cells_free=substr_count($ttt_moves, ‘0’);

return($cells_free);
}

function cells_used($cells_free)
{
global $cells_total;
$cells_used=$cells_total-$cells_free;

return($cells_used);
}

function cells_pos_free($ttt_moves)
{
$cell_pos_free=array();
$ttt_moves_arr = str_split($ttt_moves);
foreach($ttt_moves_arr AS $ttt_moves_arr_val)
{
if($ttt_moves_arr_val==0)
{
$cell_pos_free[]=$ttt_moves_arr_val+1;
}
}

return($cell_pos_free);
}

function pattern_cells_used($ttt_moves,$pattern_id)
{
$winning_patterns=game_winning_patterns();
$pattern_current=$winning_patterns[$pattern_id];

$ttt_moves_arr = str_split($ttt_moves);
$pattern_cells_used_count=0;

foreach($pattern_current AS $pattern_current_val)
{
$pattern_current_val_temp=$pattern_current_val-1;
if($ttt_moves_arr[$pattern_current_val_temp]!=0)
{
$pattern_cells_used_count++;
}
}
return($pattern_cells_used_count);
}

function pattern_free_pos($ttt_moves,$pattern_id)
{
//echo "$ttt_moves,$pattern_id<br>";
$winning_patterns=game_winning_patterns();
$pattern_current=$winning_patterns[$pattern_id];

$ttt_moves_arr = str_split($ttt_moves);

$pattern_current_free_pos=array();
foreach($pattern_current AS $pattern_current_val)
{
$pattern_current_val_temp=$pattern_current_val-1;
if($ttt_moves_arr[$pattern_current_val_temp]==0)
{
$pattern_current_free_pos[]=$pattern_current_val;
}
}
shuffle($pattern_current_free_pos);
return($pattern_current_free_pos[0]);
}

function game_free_pos($ttt_moves)
{
$ttt_moves_arr = str_split($ttt_moves);

$game_free_pos=array();
foreach($ttt_moves_arr AS $ttt_moves_arr_val)
{
if($ttt_moves_arr_val==0)
{
$game_free_pos[]=$ttt_moves_arr_val;
}
}
return($game_free_pos);
}

function game_winning_patterns()
{
$win_patterns[1]=array(1,2,3);
$win_patterns[2]=array(4,5,6);
$win_patterns[3]=array(7,8,9);
$win_patterns[4]=array(1,4,7);
$win_patterns[5]=array(2,5,8);
$win_patterns[6]=array(3,6,9);
$win_patterns[7]=array(1,5,9);
$win_patterns[8]=array(3,5,7);

return($win_patterns);
}

function cue_patterns($cue_pos)
{
$cue_patterns[1]=array(1,4,7);
$cue_patterns[2]=array(1,5);
$cue_patterns[3]=array(1,6,8);
$cue_patterns[4]=array(2,4);
$cue_patterns[5]=array(2,5,7,8);
$cue_patterns[6]=array(2,6);
$cue_patterns[7]=array(3,4,8);
$cue_patterns[8]=array(3,5,7);
$cue_patterns[9]=array(3,6,7);

return($cue_patterns[$cue_pos]);
}

function patterns_all()
{
global $patterns_total;

$patterns_all=array();
for($i=1;$i<=$patterns_total;$i++)
{
$patterns_all[]=$i;
}

return($patterns_all);
}

function game_result_status($ttt_moves,$usr=1)
{
global $game_win_cues_count;

$winning_patterns=game_winning_patterns();
//echo "<pre>";
//    print_r($winning_patterns);
//echo "</pre>";
//echo $ttt_moves."hi1<br>";
$ttt_moves_arr = str_split($ttt_moves);

$cue_pos=0;
$win_pattern_chk=array();
$pattern_used_cues_count=array();
foreach($ttt_moves_arr AS $ttt_moves_arr_value)
{
$cue_pos++;
if($ttt_moves_arr_value==$usr)
{
$cue_pattern=cue_patterns($cue_pos);
//echo "$cue_pos<br>";
foreach($cue_pattern AS $cue_pattern_key=>$cue_pattern_val)
{
if(in_array($cue_pattern_val, $win_pattern_chk))
{
}
else
{
$win_pattern_pos=$winning_patterns[$cue_pattern_val];//123 positions for cue at pos 1
foreach($win_pattern_pos AS $win_pattern_pos_key=>$win_pattern_pos_val)
{
$win_pattern_pos_val_temp=$win_pattern_pos_val-1;
if($ttt_moves_arr[$win_pattern_pos_val_temp]==$usr)
{
$pattern_used_cues_count[$cue_pattern_val]++;
}
}

$win_pattern_chk[]=$cue_pattern_val;
}
}
}
}
rsort($pattern_used_cues_count);
//echo "Pattern".count($pattern_used_cues_count)."<br>";
if($pattern_used_cues_count[0]==$game_win_cues_count)
{
return(1);
}
else
{
return(0);
}
}

function move_computer($ttt_moves)
{
global $game_win_cues_count,$ttt_game_mode;
$move_for=1;

$winning_patterns=game_winning_patterns();

$ttt_moves_arr = str_split($ttt_moves);

$cue_pos=0;
$win_pattern_chk=array();
$pattern_used_cues_count=array();
$patterns_priority=array();
$patterns_available=array();
$patterns_unavailable=array();
$pattern_choosen=0;
$move_computer_next_pos=0;

foreach($ttt_moves_arr AS $ttt_moves_arr_value)
{
$cue_pos++;
if($ttt_moves_arr_value==$move_for)
{
$cue_pattern=cue_patterns($cue_pos);
foreach($cue_pattern AS $cue_pattern_key=>$cue_pattern_val)
{
if(in_array($cue_pattern_val, $win_pattern_chk))
{
}
else
{
$win_pattern_pos=$winning_patterns[$cue_pattern_val];//123 positions for cue at pos 1 i.e. pattern 1
foreach($win_pattern_pos AS $win_pattern_pos_key=>$win_pattern_pos_val)
{
$win_pattern_pos_val_temp=$win_pattern_pos_val-1;
if($ttt_moves_arr[$win_pattern_pos_val_temp]==$move_for)
{
$pattern_used_cues_count[$cue_pattern_val]++;
}
if($ttt_moves_arr[$win_pattern_pos_val_temp]==1 || $ttt_moves_arr[$win_pattern_pos_val_temp]==2)
{
$pattern_used_cues_total_count[$cue_pattern_val]++;
}
}

$win_pattern_chk[]=$cue_pattern_val;
}
}
}
}
arsort($pattern_used_cues_count);

foreach($pattern_used_cues_count AS $pattern_used_cues_count_key=>$pattern_used_cues_count_val)
{
$pattern_cells_used_count=pattern_cells_used($ttt_moves,$pattern_used_cues_count_key);
//echo "$pattern_used_cues_count_key:$pattern_used_cues_count_val:$pattern_cells_used_count<br>";
if($pattern_cells_used_count==$game_win_cues_count)
{
$patterns_unavailable[]=$pattern_used_cues_count_key;
}
elseif($pattern_cells_used_count==2)
{
if($pattern_cells_used_count==$pattern_used_cues_count_val)
{
$patterns_priority[]=$pattern_used_cues_count_key;
}
else
{
$patterns_available[]=$pattern_used_cues_count_key;
}
}
else
{
$patterns_available[]=$pattern_used_cues_count_key;
}
}

if($ttt_game_mode==1)
{
$pattern_choosen_importance=move_computer_medium($ttt_moves);
if($pattern_choosen_importance[0]==1)
{
$pattern_choosen=$pattern_choosen_importance[1];
}
}

if($pattern_choosen==0)
{
if(count($patterns_priority)>0)
{
shuffle($patterns_priority);
$pattern_choosen=$patterns_priority[0];
}
else
{
if($ttt_game_mode==0)
{
$patterns_all=patterns_all();
$patterns_available = array_diff($patterns_all, $patterns_unavailable);
shuffle($patterns_available);
$pattern_choosen=$patterns_available[0];
}
else
{
$pattern_choosen=$pattern_choosen_importance[1];
}
}
}

if($pattern_choosen!=0)
{
$pattern_free_pos=pattern_free_pos($ttt_moves,$pattern_choosen);
if($pattern_free_pos!=0)
{
$move_computer_next_pos=$pattern_free_pos;
}
}

if($move_computer_next_pos==0)
{
//get free positions
//select one of free positions
$game_free_positions=game_free_pos($ttt_moves);
shuffle($game_free_positions);

$move_computer_next_pos=$game_free_positions[0];
}

return($move_computer_next_pos);
//cells_pos_free($ttt_moves)
}

function move_computer_medium($ttt_moves)
{
global $game_win_cues_count;

$move_for=2;

$winning_patterns=game_winning_patterns();

$ttt_moves_arr = str_split($ttt_moves);

$cue_pos=0;
$win_pattern_chk=array();
$pattern_used_cues_count=array();
$patterns_priority=array();
$patterns_available=array();
$patterns_unavailable=array();
$pattern_choosen=0;
$move_computer_next_pos=0;
$pattern_choosen_importance=array();

foreach($ttt_moves_arr AS $ttt_moves_arr_value)
{
$cue_pos++;
if($ttt_moves_arr_value==2)
{

$cue_pattern=cue_patterns($cue_pos);
foreach($cue_pattern AS $cue_pattern_key=>$cue_pattern_val)
{
if(in_array($cue_pattern_val, $win_pattern_chk))
{

}
else
{
$win_pattern_pos=$winning_patterns[$cue_pattern_val];//123 positions for cue at pos 1 i.e. pattern 1
foreach($win_pattern_pos AS $win_pattern_pos_key=>$win_pattern_pos_val)
{
$win_pattern_pos_val_temp=$win_pattern_pos_val-1;
if($ttt_moves_arr[$win_pattern_pos_val_temp]==$move_for)
{
$pattern_used_cues_count[$cue_pattern_val]++;
}
}

$win_pattern_chk[]=$cue_pattern_val;
}
}
}
}
arsort($pattern_used_cues_count);

foreach($pattern_used_cues_count AS $pattern_used_cues_count_key=>$pattern_used_cues_count_val)
{
$pattern_cells_used_count=pattern_cells_used($ttt_moves,$pattern_used_cues_count_key);
//echo "$pattern_used_cues_count_key:$pattern_used_cues_count_val:$pattern_cells_used_count<br>";
if($pattern_cells_used_count==$game_win_cues_count)
{
$patterns_unavailable[]=$pattern_used_cues_count_key;
}
elseif($pattern_cells_used_count==2)
{
if($pattern_cells_used_count==$pattern_used_cues_count_val)
{
$patterns_priority[]=$pattern_used_cues_count_key;
}
else
{
$patterns_available[]=$pattern_used_cues_count_key;
}
}
else
{
$patterns_available[]=$pattern_used_cues_count_key;
}
}

if(count($patterns_priority)>0)
{
shuffle($patterns_priority);
$pattern_choosen_importance[0]=1;
$pattern_choosen_importance[1]=$patterns_priority[0];
}
elseif(count($patterns_available)>0)
{
shuffle($patterns_available);
$pattern_choosen_importance[0]=0;
$pattern_choosen_importance[1]=$patterns_available[0];
}
else
{
$patterns_all=patterns_all();
$patterns_available = array_diff($patterns_all, $patterns_unavailable);
shuffle($patterns_available);
$pattern_choosen_importance[0]=0;
$pattern_choosen_importance[1]=$patterns_available[0];
}

return($pattern_choosen_importance);
//cells_pos_free($ttt_moves)
}

function ttt_move_next_new($ttt_moves,$ttt_move_new)
{
$ttt_moves_arr = str_split($ttt_moves);
$ttt_move_new_temp=$ttt_move_new-1;
$ttt_moves_arr[$ttt_move_new_temp]=2;
$ttt_moves_arr=implode("",$ttt_moves_arr);
return($ttt_moves_arr);
}

?>[/php]

play.php

[php]<?php
$err_sts=0;
$crr_sts=0;
$err_msg=array();
$crr_msg=array();

$crr_msg[]= "TicTacToe";
$crr_msg[]= "—– –";
$crr_msg[]= "<a href=’index.php’>Start New Game</a>";
$crr_msg[]= "– –";

//initialize
//blank=0; user=1; compauter=2;
$ttt_move="000000000";
$ttt_play_sts=0;
$ttt_win_sts=0;

$cells_rows=3;
$cells_cols=3;
$cells_total=$cells_rows*$cells_cols;
$patterns_total=8;
$game_win_cues_count=3;

$move_by_first=1;
$move_by_now=$move_by_first;
$cue_type_usr=cue_type_name(1);

if(isset($_GET[‘move_next’]))
{
$ttt_move_next=$_GET[‘move_next’];
if(strlen($ttt_move_next)!=9)
{
$err_sts=1;
$err_msg[]="Next move not correctly formatted.";
}
}
else
{
$ttt_move_next=$ttt_move;
}

if(isset($_GET[‘game_mode’]))
{
$ttt_game_mode=$_GET[‘game_mode’];
if($ttt_game_mode==”)
{
$ttt_game_mode=0;
}
elseif($ttt_game_mode>1)
{
$ttt_game_mode=0;
}
}
else
{
if($ttt_game_mode!=0)
{
if($ttt_game_mode>1)
{
$ttt_game_mode=0;
}
}
}

if($err_sts==0)
{
include "tictactoe/logic.php";
$print_game=print_game($ttt_move_next);
$crr_msg[]=$print_game;
$crr_msg[]="Your Cue: $cue_type_usr";
$crr_msg[]="Mode: ". game_mode_name($ttt_game_mode)."<br>";
}
?>[/php]

logic.php

[php]<?php

//$ttt_move_next
$cells_free=cells_free($ttt_move_next);
$cells_used=cells_used($cells_free);
$cells_used_win_min=$cells_rows+$cells_cols-1;

if($cells_used>=$cells_used_win_min)
{
$ttt_win_sts=game_result_status($ttt_move_next,1);
}

if($ttt_win_sts==1)
{
$ttt_play_sts=1;
$crr_msg[]="Game Won by You";
}
else
{
if($cells_free==$cells_total)
{
$crr_msg[]="It’s your Chance Now";
}
elseif($cells_total==$cells_used)
{
$ttt_play_sts=1;

$crr_msg[]="Game Over";
$crr_msg[]="Match Drawn";

}
else
{
//Computer Chance
$ttt_move_next_computer=move_computer($ttt_move_next);
$ttt_move_next=ttt_move_next_new($ttt_move_next,$ttt_move_next_computer);

$ttt_win_sts=game_result_status($ttt_move_next,2);

if($ttt_win_sts==1)
{
$ttt_play_sts=1;
$crr_msg[]="Game Won by Computer";
}
else
{
$crr_msg[]="It’s your Chance Now";
}
}
}

?>[/php]

Leave a Comment