Skip to content

Instantly share code, notes, and snippets.

@ringmaster
Created October 23, 2012 20:23
Show Gist options
  • Save ringmaster/3941295 to your computer and use it in GitHub Desktop.
Save ringmaster/3941295 to your computer and use it in GitHub Desktop.
Tic Tac Toe
<?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