13-10-2011, 03:55 PM
(desole pour les accent, clavier qwerty :/)
L'algo que j'ai fait part d'une position aleatoire dans la map (par defaut le centre) et s'arrete a une position donne (par defaut un coin de la carte (depend de la direction de la spirale: droite, bas, gauche, haut))
C'est un complement des 2 autres ^^
(30-09-2011, 09:11 AM)niahoo a écrit : Pourquoi vous tenez absolument à ne pas utiliser la récursivité, alors que ça semble très indiqué dans ce cas précis ?Je pense qu'il vaut mieux le faire a coup d'iterateur, c'est plus fun a utiliser
L'algo que j'ai fait part d'une position aleatoire dans la map (par defaut le centre) et s'arrete a une position donne (par defaut un coin de la carte (depend de la direction de la spirale: droite, bas, gauche, haut))
C'est un complement des 2 autres ^^
<?php
class Rect
{
private $width, $height;
function __construct($width, $height = null){
$this->width = $width;
$this->height = $height ?: $width;
}
function width(){
return $this->width;
}
function height(){
return $this->height;
}
function size(){
return $this->height * $this->width;
}
function origin(){
return floor($this->height / 2) * $this->width + floor($this->width / 2);
}
function index($x,$y){
return $x + $y * $this->width;
}
function coord($index){
return array($index % $this->width, $index / $this->width);
}
}
class Nexter
{
private $add;
function __construct($add = 1){
$this->add = $add;
}
function per(&$n){
$n += $this->add;
}
}
class SpiralSquareIterator implements Iterator
{
const TO_RIGHT = 0;
const TO_DOWN = 1;
const TO_LEFT = 2;
const TO_UP = 3;
private $begin, $it, $end, $circular, $step, $to, $m, $odd, $inner, $nexter;
function __construct($shape, $begin = null, $end = null, $to = SpiralSquareIterator::TO_RIGHT){
$this->begin = $begin === null ? $shape->origin() : $begin;
$this->end = $end ?: self::getEndIndex($to, $shape);
$h = $shape->height();
//SplFixedArray ?
$this->circular = new InfiniteIterator(new ArrayIterator(array(
new Nexter(1),
new Nexter($h),
new Nexter(-1),
new Nexter(-$h),
)));
$this->to = $to;
}
static function getEndIndex($to, $shape){
return $to === SpiralSquareIterator::TO_RIGHT ? $shape->width() - 1 : (
$to === SpiralSquareIterator::TO_DOWN ? $shape->size() - 1 : (
$to === SpiralSquareIterator::TO_LEFT ? $shape->height() * ($shape->width() - 1) :
0));
}
function rewind(){
$this->it = $this->begin;
$this->circular->rewind();
for ($n = $this->to; $n--; $this->circular->next());
$this->m = 1;
$this->step = 0;
$this->odd = false;
$this->inner = false;
$this->nexter = $this->circular->current();
}
function valid(){
if ($this->inner)
return false;
if ($this->it == $this->end)
$this->inner = true;
return true;
}
function current(){
return $this->it;
}
/**
* Retourne l'indice du bord du carré (↑:0, →:1, ↓:2, ←: 3)
* @attention la clef étant 0,1,2 ou 3 celle-ci n'est pas unique
*/
function key(){
$r = $this->circular->key();
return $r === $this->to && !$this->m
? ($this->to + 1 === 4 ? 0 : $this->to + 1) : $r;
}
function next(){
if (!$this->m--){
$this->m = ($this->odd = !$this->odd) ? $this->step : ++$this->step;
$this->circular->next();
$this->nexter = $this->circular->current();
}
$this->nexter->per($this->it);
}
/**
* @param bool $get_pair = false : si true la valeur est une pair avec comme premier
* indice la clef de l'itérateur
* @param bool $calculate_distance = true : si true l'itérateur sert de clef et la valeur
* et la distance par rapport au centre de la spiral
*
* $get_pair = false & $calculate_distance = false : $r[] = $this->current()
* $get_pair = true & $calculate_distance = false : $r[] = array($this->key(), $this->current())
* $get_pair = false & $calculate_distance = true : $r[$this->current()] = $n++
* $get_pair = true & $calculate_distance = true: $r[$this->current()] = array($this->key(), $n++)
*/
function toArray($get_pair = false, $calculate_distance = true){
$r = array();
$this->rewind();
if ($calculate_distance) {
$n = 0;
if ($get_pair){
while ($this->it != $this->end){
$r[$this->it] = array($this->key(), $n++);
$this->next();
}
$r[$this->it] = array($this->key(), $n++);
} else {
while ($this->it != $this->end){
$r[$this->it] = $n++;
$this->next();
}
$r[$this->it] = $n++;
}
}
else if ($get_pair){
while ($this->it != $this->end){
$r[] = array($this->key(), $this->it);
$this->next();
}
$r[] = array($this->key(), $this->it);
} else {
while ($this->it != $this->end){
$r[] = $this->it;
$this->next();
}
$r[] = $this->it;
}
return $r;
}
}
function spiral_square($shape, $begin = null, $end = null, $to = SpiralSquareIterator::TO_RIGHT,
$get_pair = false, $calculate_distance = true)
{
$it = new SpiralSquareIterator($shape, $begin, $end, $to);
return $it->toArray($get_pair, $calculate_distance);
}
$square = new Rect(17);
$indices = spiral_square($square, null, null, SpiralSquareIterator::TO_RIGHT, true);
/*$indices = array();
$n = 0;
foreach(new SpiralSquareIterator($square) as $border => $i){
$indices[$i] = array($border, $n++);
}*/
//var_dump(iterator_to_array(new SpiralSquareIterator($square), false));
//var_dump($indices);
$c = array('#00D', '#000', '#D00', '#0D0');
echo '<table border=1>';
for ($i = 0, $end = $square->size(); $i != $end; )
{
echo '<tr>';
for ($endx = $i + $square->width(); $i != $endx; ++$i)
{
echo isset($indices[$i])
? '<td style="color:'.$c[$indices[$i][0]].'">'.$indices[$i][1].'</td>'
: '<td style="color:darkorange">'.$i.'</td>';
}
echo '</tr>';
}
echo '</table>';