Created
October 23, 2012 20:23
-
-
Save ringmaster/3941295 to your computer and use it in GitHub Desktop.
Tic Tac Toe
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
function checkwin($board, $pos, $who) { | |
$set = ''; | |
foreach($pos as $pt) { | |
$set .= $board[$pt[1]][$pt[0]]; | |
} | |
if($set == str_repeat($who, 3)) return true; | |
return false; | |
} | |
function boardpos() { | |
$pos = array(array(0,0), array(0,1), array(0,2), array(1,0), array(1,1), array(1,2), array(2,0), array(2,1), array(2,2)); | |
shuffle($pos); | |
return $pos; | |
} | |
function winboard($board, $who) { | |
$win = checkwin($board, array(array(0,0), array(0,1), array(0,2)), $who) | |
|| checkwin($board, array(array(1,0), array(1,1), array(1,2)), $who) | |
|| checkwin($board, array(array(2,0), array(2,1), array(2,2)), $who) | |
|| checkwin($board, array(array(0,0), array(1,1), array(2,2)), $who) | |
|| checkwin($board, array(array(2,0), array(1,1), array(0,2)), $who) | |
|| checkwin($board, array(array(0,0), array(1,0), array(2,0)), $who) | |
|| checkwin($board, array(array(0,1), array(1,1), array(2,1)), $who) | |
|| checkwin($board, array(array(0,2), array(1,2), array(2,2)), $who); | |
return $win; | |
} | |
function willwin($board, $who) { | |
$pos = boardpos(); | |
foreach($pos as $pt) { | |
$newboard = $board; | |
if($newboard[$pt[1]][$pt[0]] == '_') { | |
$newboard[$pt[1]][$pt[0]] = $who; | |
if(winboard($newboard, $who)) { | |
return $pt; | |
} | |
} | |
} | |
return false; | |
} | |
function winscore($board, $who) { | |
$pos = boardpos(); | |
$point = false; | |
$max = 0; | |
foreach($pos as $pt) { | |
$score = 0; | |
$board2 = $board; | |
if($board2[$pt[1]][$pt[0]] == '_') { | |
$board2[$pt[1]][$pt[0]] = $who; | |
foreach($pos as $pt2) { | |
$board3 = $board2; | |
if($board3[$pt2[1]][$pt2[0]] == '_') { | |
$board3[$pt2[1]][$pt2[0]] = $who; | |
if(winboard($board3, $who)) { | |
$score++; | |
} | |
} | |
} | |
if($score > $max) { | |
$max = $score; | |
$point = $pt; | |
} | |
} | |
} | |
return $point; | |
} | |
function sidehas($a, $b, $who) { | |
$c = $a . $b; | |
if(strpos($c, $who) !== false) { | |
if(strpos($c, notplayer($who)) === false) { | |
return true; | |
} | |
} | |
return false; | |
} | |
function cornerblock($board, $who) { | |
$opp = notplayer($who); | |
if($board[0][1] == '_' && $board[0][0] == $opp && sidehas($board[2][1], $board[2][2], $opp)) { | |
return array(1,0); | |
} | |
if($board[0][1] == '_' && $board[2][0] == $opp && sidehas($board[0][1], $board[0][2], $opp)) { | |
return array(1,0); | |
} | |
if($board[2][1] == '_' && $board[0][2] == $opp && sidehas($board[2][0], $board[2][1], $opp)) { | |
return array(1,2); | |
} | |
if($board[2][1] == '_' && $board[2][2] == $opp && sidehas($board[0][0], $board[0][1], $opp)) { | |
return array(1,2); | |
} | |
if($board[1][0] == '_' && $board[0][0] == $opp && sidehas($board[1][2], $board[2][2], $opp)) { | |
return array(0,1); | |
} | |
if($board[1][0] == '_' && $board[0][2] == $opp && sidehas($board[1][0], $board[2][0], $opp)) { | |
die("b\n"); | |
return array(0,1); | |
} | |
if($board[1][2] == '_' && $board[2][0] == $opp && sidehas($board[0][2], $board[1][2], $opp)) { | |
return array(2,1); | |
} | |
if($board[1][2] == '_' && $board[2][2] == $opp && sidehas($board[0][0], $board[1][0], $opp)) { | |
return array(2,1); | |
} | |
if($board[0][0] == '_' && sidehas($board[0][1], $board[0][2], $opp) && sidehas($board[1][0], $board[2][0], $opp)) { | |
return array(0,0); | |
} | |
if($board[2][0] == '_' && sidehas($board[0][0], $board[1][0], $opp) && sidehas($board[2][1], $board[2][2], $opp)) { | |
return array(0,2); | |
} | |
if($board[2][2] == '_' && sidehas($board[0][2], $board[1][2], $opp) && sidehas($board[2][0], $board[2][1], $opp)) { | |
return array(2,2); | |
} | |
if($board[0][2] == '_' && sidehas($board[1][2], $board[2][2], $opp) && sidehas($board[0][0], $board[0][1], $opp)) { | |
return array(2,0); | |
} | |
return false; | |
} | |
function allowwin($board, $player) { | |
$pos = boardpos(); | |
foreach($pos as $pt) { | |
if($board[$pt[1]][$pt[0]] != '_') continue; | |
$newboard = $board; | |
$newboard[$pt[1]][$pt[0]] = $player; | |
if(willwin($newboard, $player)) { | |
return $pt; | |
} | |
} | |
return false; | |
} | |
function notplayer($player) { | |
return ($player == 'X') ? 'O' : 'X'; | |
} | |
function displayboard($board, $move = false, $player = '') { | |
if($move) { | |
$board[$move[1]][$move[0]] = $player; | |
} | |
foreach($board as $row) { | |
echo "$row\n"; | |
} | |
} | |
/* Complete the function below to print 2 integers separated by a single space which will be your next move | |
*/ | |
function getnextMove($player, $board){ | |
$move = false; | |
$strategy = 'board full'; | |
// If a move will win, take it | |
if($move = willwin($board, $player)) { | |
$strategy = 'to win'; | |
} | |
// If avoiding a move would incure a loss, take it | |
else if($move = willwin($board, notplayer($player))) { | |
$strategy = 'to block'; | |
} | |
// If there isn't a move in the center square, take it | |
elseif($board[1][1] == '_') { | |
$strategy = 'to center'; | |
$move = array(1,1); | |
} | |
// If a move can block a force, take it | |
elseif($move = cornerblock($board, $player)) { | |
$strategy = 'to block force'; | |
} | |
// If a move can eventually produce a win, take it | |
elseif($move = winscore($board, $player)) { | |
$strategy = 'to setup win'; | |
} | |
if($move == false || $board[$move[1]][$move[0]] != '_') { | |
// If all else fails, take an empty space | |
$moves = array(array(1,1)); | |
$corners = array(array(0,0),array(2,2),array(0,2),array(2,0)); | |
shuffle($corners); | |
while(count($corners)) { | |
$moves[] = array_shift($corners); | |
} | |
$sides = array(array(1,0),array(0,1),array(1,2),array(2,1)); | |
shuffle($sides); | |
while(count($sides)) { | |
$moves[] = array_shift($sides); | |
} | |
foreach($moves as $pos) { | |
if($board[$pos[1]][$pos[0]] == '_') { | |
$move = $pos; | |
$strategy = 'prefered random'; | |
break; | |
} | |
} | |
} | |
$move[] = $strategy; | |
return $move; | |
} | |
function playGame($player, $board) { | |
$player = ($player == 'C') ? 'X' : 'O'; | |
$moves = 0; | |
displayboard($board); | |
while(!winboard($board, 'X') && !winboard($board, 'O') && $moves < 9 && strpos(implode('', $board), '_') !== false) { | |
$moves++; | |
$move = getnextMove($player, $board); | |
if(!$move) {die("'no move'\n");} | |
echo "Move $moves, Player $player: " . implode(' ', $move) . "\n"; | |
$board[$move[1]][$move[0]] = $player; | |
displayboard($board); | |
$player = notplayer($player); | |
} | |
if(winboard($board, 'X')) { | |
echo "Player X Wins.\n"; | |
return 'X'; | |
} | |
elseif(winboard($board, 'Y')) { | |
echo "Player Y Wins.\n"; | |
return 'Y'; | |
} | |
else { | |
echo "Draw.\n"; | |
return 'D'; | |
} | |
} | |
/* Complete the function below to print 2 integers separated by a single space which will be your next move | |
*/ | |
function nextMove($player, $board){ | |
if($player == 'C' || $player == 'P') { | |
playGame($player, $board); | |
} | |
elseif($player == 'T') { | |
for($z = 1; $z < 1000; $z++) { | |
ob_start(); | |
$outcome = playGame($player, $board); | |
$games = ob_get_clean(); | |
if($outcome != 'D') { | |
echo $games; | |
die(); | |
} | |
} | |
echo "All Draws.\n"; | |
} | |
else { | |
$move = array_reverse(array_slice(getnextMove($player, $board), 0, 2)); | |
echo implode(' ', $move) . "\n"; | |
} | |
} | |
$fp = fopen("php://stdin", "r"); | |
//If player is X, I'm the first player. | |
//If player is O, I'm the second player. | |
fscanf($fp, "%s", $player); | |
//Read the board now. The board is a 3x3 array filled with X, O or _. | |
$board = array(); | |
for ($i=0; $i<3; $i++) { | |
fscanf($fp, "%s", $board[$i]); | |
} | |
//$player = 'C'; | |
//$board = ['O_X', '_X_', 'O__']; | |
nextMove($player,$board); | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment