Skip to content

Instantly share code, notes, and snippets.

@goatslacker
Created April 15, 2011 06:17
Show Gist options
  • Save goatslacker/921230 to your computer and use it in GitHub Desktop.
Save goatslacker/921230 to your computer and use it in GitHub Desktop.
A tiles test
<?php
$tiles1 = array(
"11", // 1
"23",
"",
"44", // 2
"11",
"",
"16", // 3
"36",
"",
"51", // 4
"71",
"",
"46", // 5
"26",
"",
"14", // 6
"68",
0);
$tiles2 = array(
"12", // 1
"34",
"",
"36", // 2
"15",
"",
"56", // 3
"78",
"",
"78", // 4
"90",
"",
"46", // 5
"26",
"",
"88", // 6
"01",
"",
"93", // 7
"54",
0);
$tiles3 = array(
"11", // 1
"12",
"",
"12", // 2
"93",
"",
"93", // 3
"99",
"",
"39", // 4
"98",
"",
"95", // 5
"86",
"",
"57", // 6
"66",
"",
"77", // 7
"57",
"",
"13", // 8
"24",
"",
"45", // 9
"47",
"",
"24", // 10
"39",
0);
function link_tiles (array $tile_list) {
// the virtual grid
$grid = new Tiles();
// split the array into tiles
$tiles = array_chunk($tile_list, 3);
// the no of tiles
$tileNo = 1;
foreach ($tiles as $tile) {
echo "link " . $tileNo;
echo "\n";
// drop the last element
$tile = new Tile($tile);
// Hack -- need to use a better way to detect if two quadrants match
// should've looked at example3 better!
$match = false;
// if the virtual grid is empty, add the item and move on
if ($grid->isEmpty()) {
// add the tile to the virtual grid
$grid->add($tile, array(0, 0));
$match = true;
// we need to check the grid to find any possible matches
} else {
// first we get all available corners we're going to look through.
// Josh's definition of a corner is any item that's "hanging out there" the top, left, right or bottom must have 2 empty spots
// those 2 empty spots will be filled with my tile! (if it fits of course)
// we loop through each corner until we find a match
// we WILL find a match, they promised me we will!
for ($i = 0; $i < 360; $i = $i + 90) {
foreach ($grid->getCorners() as $xy) {
if ($grid->checkCorners(array($xy[0], $xy[1]), $tile) === false) {
continue;
}
$match = $xy;
}
if ($match) {
$grid->add($tile, array($match[0], $match[1]));
break;
}
$tile->rotate90();
}
}
// add the link ct
$tileNo = $tileNo + 1;
// echo out the current progess
$grid->toString();
// add a line break because it's pretty
echo "\n";
// reset
$match = false;
}
}
class Tiles {
private $grid = array();
public function getGrid () {
return $this->grid;
}
public function add (Tile $tile, $where) {
$top = $tile->getTop();
$bottom = $tile->getBottom();
$this->grid[$where[0]][$where[1]] = $top[0];
$this->grid[$where[0]][$where[1] + 1] = $top[1];
$this->grid[$where[0] + 1][$where[1]] = $bottom[0];
$this->grid[$where[0] + 1][$where[1] + 1] = $bottom[1];
//ksort($this->grid);
}
public function toString () {
$xy = $this->getSquareBlock();
for ($x = $xy[0]; $x <= $xy[1]; $x = $x + 1) {
if (array_key_exists($x, $this->grid)) {
for ($y = $xy[0]; $y <= $xy[1]; $y = $y + 1) {
if (array_key_exists($y, $this->grid[$x])) {
echo $this->grid[$x][$y];
} else {
echo " ";
}
}
} else {
echo " ";
}
echo "\n";
}
}
public function checkCorners (array $point, Tile $tile) {
//tlXY stands for Top-Left XY - it's the top-left of the square's XY coordinates
// a tlXY of -2, 0 means that we'll have to check -3, 0;
$TLX = $point[0];
$TLY = $point[1];
$matches = 0;
// do topLeft
// top
if (array_key_exists($TLX - 1, $this->grid)) {
if (array_key_exists($TLY, $this->grid[$TLX - 1])) {
if ($tile->topLeftIsEqualTo($this->grid[$TLX - 1][$TLY])) {
$matches = $matches + 1;
} else {
return false;
}
}
}
if (array_key_exists($TLX, $this->grid)) {
if (array_key_exists($TLY - 1, $this->grid[$TLX])) {
// left
if ($tile->topLeftIsEqualTo($this->grid[$TLX][$TLY - 1])) {
$matches = $matches + 1;
} else {
return false;
}
}
}
// do topRight
if (array_key_exists($TLX - 1, $this->grid)) {
if (array_key_exists($TLY + 1, $this->grid[$TLX - 1])) {
// top
if ($tile->topRightIsEqualTo($this->grid[$TLX - 1][$TLY + 1])) {
$matches = $matches + 1;
} else {
return false;
}
}
}
if (array_key_exists($TLX, $this->grid)) {
if (array_key_exists($TLY + 2, $this->grid[$TLX])) {
// right
if ($tile->topRightIsEqualTo($this->grid[$TLX][$TLY + 2])) {
$matches = $matches + 1;
} else {
return false;
}
}
}
// do bottomLeft
if (array_key_exists($TLX + 2, $this->grid)) {
if (array_key_exists($TLY, $this->grid[$TLX + 2])) {
// bottom
if ($tile->bottomLeftIsEqualTo($this->grid[$TLX + 2][$TLY])) {
$matches = $matches + 1;
} else {
return false;
}
}
}
if (array_key_exists($TLX + 1, $this->grid)) {
if (array_key_exists($TLY - 1, $this->grid[$TLX + 1])) {
// left
if ($tile->bottomLeftIsEqualTo($this->grid[$TLX + 1][$TLY - 1])) {
$matches = $matches + 1;
} else {
return false;
}
}
}
// do bottomRight
if (array_key_exists($TLX + 2, $this->grid)) {
if (array_key_exists($TLY + 1, $this->grid[$TLX + 2])) {
// bottom
if ($tile->bottomRightIsEqualTo($this->grid[$TLX + 2][$TLY + 1])) {
$matches = $matches + 1;
} else {
return false;
}
}
}
if (array_key_exists($TLX + 1, $this->grid)) {
if (array_key_exists($TLY + 2, $this->grid[$TLX + 1])) {
// right
if ($tile->bottomRightIsEqualTo($this->grid[$TLX + 1][$TLY + 2])) {
$matches = $matches + 1;
} else {
return false;
}
}
}
// if two match, we're golden...
return ($matches >= 2);
}
public function isEmpty () {
return (count($this->grid) === 0);
}
public function getSquareBlock () {
$top = $this->getTopMost();
$left = $this->getLeftMost();
$right = $this->getRightMost();
$bottom = $this->getBottomMost();
return array(($top < $left) ? $top : $left, ($right > $bottom) ? $right : $bottom);
}
private function getLeftMost () {
$tmp = $this->grid;
ksort($tmp);
$min = 0;
foreach ($tmp as $grid) {
ksort($grid);
$minChallenger = array_shift(array_keys($grid));
$min = ($min > $minChallenger) ? $minChallenger : $min;
}
return $min;
}
private function getTopMost () {
$tmp = $this->grid;
ksort($tmp);
return array_shift(array_keys($tmp));
}
private function getRightMost () {
$tmp = $this->grid;
ksort($tmp);
$min = 0;
foreach ($tmp as $grid) {
ksort($grid);
$minChallenger = array_pop(array_keys($grid));
$min = ($min < $minChallenger) ? $minChallenger : $min;
}
return $min;
}
private function getBottomMost () {
$tmp = $this->grid;
ksort($tmp);
return array_pop(array_keys($tmp));
}
public function getCorners () {
$xy = $this->getSquareBlock();
$corners = array();
for ($x = $xy[0]; $x <= $xy[1]; $x = $x + 1) {
if (array_key_exists($x, $this->grid)) {
for ($y = $xy[0]; $y <= $xy[1]; $y = $y + 1) {
// skip the ones that don't have any values
if (!array_key_exists($x, $this->grid) || !array_key_exists($y, $this->grid[$x])) {
continue;
}
// if top 2 are empty
if (array_key_exists($y + 1, $this->grid[$x])) {
if (!array_key_exists($x - 1, $this->grid) ||
(!array_key_exists($y, $this->grid[$x - 1]) && !array_key_exists($y + 1, $this->grid[$x - 1]))
) {
array_push($corners, array($x - 2, $y));
}
}
// if left 2 are empty
if (array_key_exists($x + 1, $this->grid)) {
if (!array_key_exists($y - 1, $this->grid[$x]) && !array_key_exists($y - 1, $this->grid[$x + 1])) {
array_push($corners, array($x, $y - 2));
}
}
// if bottom 2 are empty
if (array_key_exists($y + 1, $this->grid[$x])) {
if (!array_key_exists($x + 1, $this->grid) ||
(!array_key_exists($y, $this->grid[$x + 1]) && !array_key_exists($y + 1, $this->grid[$x + 1]))
) {
array_push($corners, array($x + 1, $y));
}
}
// if right 2 are empty
if (array_key_exists($x + 1, $this->grid)) {
if (!array_key_exists($y + 1, $this->grid[$x]) && !array_key_exists($y + 1, $this->grid[$x + 1])) {
array_push($corners, array($x, $y + 1));
}
}
} // end Y loop
} // endIf
} // end X for
return $corners;
}
}
class Tile {
private $tile;
public function __construct ($tile) {
if (count($tile) > 2) {
$tile = array_slice($tile, 0, 2);
}
$this->tile = array(
array(
substr($tile[0], 0, 1),
substr($tile[0], 1, 1)
),
array(
substr($tile[1], 0, 1),
substr($tile[1], 1, 1)
)
);
}
public function getTile () {
return $this->tile;
}
public function getTop () {
return array($this->tile[0][0], $this->tile[0][1]);
}
public function getRight () {
return array($this->tile[0][1], $this->tile[1][1]);
}
public function getBottom () {
return array($this->tile[1][0], $this->tile[1][1]);
}
public function getLeft () {
return array($this->tile[0][0], $this->tile[1][0]);
}
public function rotate90 () {
$this->tile = array(
array(
$this->tile[1][0],
$this->tile[0][0]
),
array(
$this->tile[1][1],
$this->tile[0][1]
)
);
return $this;
}
public function rotate180 () {
$this->tile = array(
array(
$this->tile[1][1],
$this->tile[1][0]
),
array(
$this->tile[0][1],
$this->tile[0][0]
)
);
return $this;
}
public function rotate270 () {
$this->tile = array(
array(
$this->tile[0][1],
$this->tile[1][1]
),
array(
$this->tile[0][0],
$this->tile[1][0]
)
);
return $this;
}
public function topLeftIsEqualTo ($grid) {
$topLeft = $this->getTop();
return ($topLeft[0] === $grid);
}
public function topRightIsEqualTo ($grid) {
$topRight = $this->getTop();
return ($topRight[1] === $grid);
}
public function bottomLeftIsEqualTo ($grid) {
$bottomLeft = $this->getBottom();
return ($bottomLeft[0] === $grid);
}
public function bottomRightIsEqualTo ($grid) {
$bottomRight = $this->getBottom();
return ($bottomRight[1] === $grid);
}
public function topIsEqualTo ($grid) {
return ($this->assertEquals($this->getTop(), $grid));
}
public function leftIsEqualTo ($grid) {
return ($this->assertEquals($this->getLeft(), $grid));
}
public function bottomIsEqualTo ($grid) {
return ($this->assertEquals($this->getBottom(), $grid));
}
public function rightIsEqualTo ($grid) {
return ($this->assertEquals($this->getRight(), $grid));
}
private function assertEquals ($grid1, $grid2) {
return ($grid1[0] === $grid2[0] && $grid1[1] === $grid2[1]);
}
}
link_tiles($tiles1);
echo "\n";
link_tiles($tiles2);
echo "\n";
link_tiles($tiles3);
echo "\n";
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment