Created
January 17, 2017 13:11
-
-
Save hevertonfreitas/7d6161e0e843ae7221dda17f88d443b4 to your computer and use it in GitHub Desktop.
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 | |
/** | |
* Convert Hex Color to RGB | |
* | |
* @param string $h | |
* @return array | |
*/ | |
function hexrgb(&$h) | |
{ | |
return (array(hexdec($h[0] . $h[1]), hexdec($h[2] . $h[3]), hexdec($h[4] . $h[5]))); | |
} | |
/** | |
* Allocate a color for an image from RGB | |
* | |
* @param resource $i | |
* @param array $c | |
* @return int | |
*/ | |
function rgbc(&$i, &$c) | |
{ | |
return (imagecolorallocate($i, $c[0], $c[1], $c[2])); | |
} | |
class Maze | |
{ | |
/** | |
* @var array horizontal walls | |
*/ | |
private $H; | |
/** | |
* @var array vertical walls | |
*/ | |
private $V; | |
/** | |
* @var int number of rows | |
*/ | |
private $x; | |
/** | |
* @var int numbers of cols | |
*/ | |
private $y; | |
/** | |
* @var bool resolve the maze | |
*/ | |
private $r; | |
/** | |
* @var int walls thickness | |
*/ | |
private $b; | |
/** | |
* @var int cell size | |
*/ | |
private $c; | |
/** | |
* @var array background color | |
*/ | |
private $f; | |
/** | |
* @var array walls color | |
*/ | |
private $m; | |
/** | |
* @var array entrance color | |
*/ | |
private $e; | |
/** | |
* @var array exit color | |
*/ | |
private $s; | |
/** | |
* @var resource gd image identifier | |
*/ | |
private $i; | |
/** | |
* Initialize Maze class | |
* | |
* @param int $x number of rows | |
* @param int $y numbers of cols | |
* @param bool $r resolve the maze | |
* @param int $b walls thickness | |
* @param int $c cell size | |
* @param string $f background color | |
* @param string $m walls color | |
* @param string $e entrance color | |
* @param string $s exit color | |
*/ | |
public function __construct($x, $y, $r, $b, $c, $f, $m, $e, $s) | |
{ | |
$this->x = $x; | |
$this->y = $y; | |
$this->r = $r; | |
$this->b = $b; | |
$this->c = $c; | |
$this->f = hexrgb($f); | |
$this->m = hexrgb($m); | |
$this->e = hexrgb($e); | |
$this->s = hexrgb($s); | |
} | |
/** | |
* Checks if cell is a closed room | |
* | |
* @param int $x | |
* @param int $y | |
* @return bool | |
*/ | |
private function isroom($x, $y) | |
{ | |
return ((empty($this->H[$x][$y]) | |
&& empty($this->V[$x][$y]) | |
&& empty($this->H[$x][$y + 1]) | |
&& empty($this->V[$x + 1][$y])) ? true : false); | |
} | |
/** | |
* Save the stack as solution path | |
* | |
* @param int $x | |
* @param int $y | |
* @param int $m | |
*/ | |
private function save(&$x, &$y, &$m) | |
{ | |
if ($this->r == 1 && $x == $this->x - 1 && $y == $this->y - 1) { | |
$this->r = $m; | |
array_push($this->r, array($x, $y)); | |
} | |
} | |
/** | |
* Dig the maze | |
*/ | |
private function dig() | |
{ | |
$x = 0; | |
$y = 0; | |
$cc = $this->x * $this->y; | |
$v = 1; | |
$m = array(); | |
while ($v < $cc) { | |
$c = ''; | |
if ($y > 0 && $this->isroom($x, $y - 1)) | |
$c .= 'N'; | |
if ($y < $this->y - 1 && $this->isroom($x, $y + 1)) | |
$c .= 'S'; | |
if ($x < $this->x - 1 && $this->isroom($x + 1, $y)) | |
$c .= 'E'; | |
if ($x > 0 && $this->isroom($x - 1, $y)) | |
$c .= 'W'; | |
if ($c) { | |
$v++; | |
array_push($m, array($x, $y)); | |
$d = $c[rand(0, strlen($c) - 1)]; | |
if ($d == 'N') | |
$this->H[$x][$y--] = true; | |
if ($d == 'S') | |
$this->H[$x][$y++ + 1] = true; | |
if ($d == 'E') | |
$this->V[$x++ + 1][$y] = true; | |
if ($d == 'W') | |
$this->V[$x--][$y] = true; | |
} else | |
list($x, $y) = array_pop($m); | |
$this->save($x, $y, $m); | |
} | |
$this->save($x, $y, $m); | |
$this->V[0][0] = 1; | |
$this->V[$this->x][$this->y - 1] = 1; | |
} | |
/** | |
* Draw the maze full grid | |
* | |
* @param int $m | |
*/ | |
private function grid(&$m) | |
{ | |
for ($y = 0; $y <= $this->y; ++$y) { | |
imagefilledrectangle($this->i, 0, $y * ($this->c + $this->b), | |
$this->b + $this->x * ($this->c + $this->b) - 1, | |
$this->b + $y * ($this->c + $this->b) - 1, | |
$m); | |
} | |
for ($x = 0; $x <= $this->x; ++$x) { | |
imagefilledrectangle($this->i, $x * ($this->c + $this->b), 0, | |
$this->b + $x * ($this->c + $this->b) - 1, | |
$this->b + $this->y * ($this->c + $this->b) - 1, | |
$m); | |
} | |
} | |
/** | |
* Breaks the horizontal walls | |
* | |
* @param int $x | |
* @param int $y | |
* @param int $f | |
*/ | |
private function line($x, $y, &$f) | |
{ | |
imagefilledrectangle($this->i, | |
$x * ($this->c + $this->b) + $this->b, | |
$y * ($this->c + $this->b), | |
$x * ($this->c + $this->b) + $this->b + $this->c - 1, | |
$y * ($this->c + $this->b) + $this->b, | |
$f); | |
} | |
/** | |
* Breaks the vertical walls | |
* | |
* @param int $x | |
* @param int $y | |
* @param int $f | |
*/ | |
private function col($x, $y, &$f) | |
{ | |
imagefilledrectangle($this->i, | |
$x * ($this->c + $this->b), | |
$y * ($this->c + $this->b) + $this->b, | |
$x * ($this->c + $this->b) + $this->b, | |
$y * ($this->c + $this->b) + $this->b + $this->c - 1, | |
$f); | |
} | |
/** | |
* Breaks the walls | |
* | |
* @param int $f | |
*/ | |
private function dot(&$f) | |
{ | |
for ($x = 0; $x <= $this->x; ++$x) { | |
for ($y = 0; $y <= $this->y; ++$y) { | |
if (isset($this->H[$x][$y])) | |
$this->line($x, $y, $f); | |
if (isset($this->V[$x][$y])) | |
$this->col($x, $y, $f); | |
} | |
} | |
} | |
/** | |
* Fill color cell | |
* | |
* @param int $x | |
* @param int $y | |
* @param int $c | |
*/ | |
private function cellfill(&$x, &$y, &$c) | |
{ | |
imagefilledrectangle($this->i, | |
$x * ($this->c + $this->b) + $this->b, | |
$y * ($this->c + $this->b) + $this->b, | |
$x * ($this->c + $this->b) + $this->b + $this->c - 1, | |
$y * ($this->c + $this->b) + $this->b + $this->c - 1, | |
$c); | |
} | |
/** | |
* Draw solution | |
*/ | |
private function path() | |
{ | |
$l = count($this->r); | |
for ($i = 0; $i < $l; ++$i) { | |
list($x, $y) = $this->r[$i]; | |
$r = ($this->e[0] * ($l - $i) + $this->s[0] * $i) / $l; | |
$g = ($this->e[1] * ($l - $i) + $this->s[1] * $i) / $l; | |
$b = ($this->e[2] * ($l - $i) + $this->s[2] * $i) / $l; | |
if (!isset($c[$r][$g][$b])) | |
$c[$r][$g][$b] = imagecolorallocate($this->i, $r, $g, $b); | |
$this->cellfill($x, $y, $c[$r][$g][$b]); | |
if (isset($ox, $oy)) { | |
if ($ox - $x == -1) | |
$this->col($x, $y, $c[$r][$g][$b]); | |
if ($oy - $y == -1) | |
$this->line($x, $y, $c[$r][$g][$b]); | |
if ($ox - $x == 1) | |
$this->col($ox, $oy, $c[$r][$g][$b]); | |
if ($oy - $y == 1) | |
$this->line($ox, $oy, $c[$r][$g][$b]); | |
} | |
if ($i == 0) | |
$this->col(0, 0, $c[$r][$g][$b]); | |
if ($i == $l - 1) | |
$this->col($x + 1, $y, $c[$r][$g][$b]); | |
$ox = $x; | |
$oy = $y; | |
} | |
} | |
/** | |
* Call digger and make rendering | |
*/ | |
public function __destruct() | |
{ | |
$this->dig(); | |
$this->i = imagecreatetruecolor( | |
$this->b + $this->x * ($this->c + $this->b), | |
$this->b + $this->y * ($this->c + $this->b)); | |
$f = rgbc($this->i, $this->f); | |
$m = rgbc($this->i, $this->m); | |
unset($this->f, $this->m); | |
imagefill($this->i, 0, 0, $f); | |
$this->grid($m); | |
$this->dot($f); | |
unset($f, $m, $this->H, $this->V); | |
if ($this->r) | |
$this->path(); | |
unset($this->r, $this->e, $this->s); | |
header('content-disposition:inline;filename="maze.png"'); | |
header('cache-control:no-store,no-cache,must-revalidate'); | |
header('content-type:image/png'); | |
imagepng($this->i, NULL, 9, PNG_ALL_FILTERS); | |
imagedestroy($this->i); | |
} | |
} | |
$x = 30; | |
$y = 30; | |
$r = true; | |
$b = 1; | |
$c = 10; | |
$f = 'FFFFFF'; | |
$m = '000000'; | |
$e = 'F3F3F3'; | |
$s = 'F3F3F3'; | |
$maze = new Maze($x, $y, $r, $b, $c, $f, $m, $e, $s); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment