Afficher le codeMasquer le code
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Génération de zone maspero.blue</title>
<style>
table{
padding: 2em;
border-spacing: 0;
background: lightgrey;
}
#espace:checked ~ table{
border-spacing: 1px;
}
tr:last-child, tr:first-child, td:first-child, td:last-child{
visibility: hidden;
}
#regle:checked ~ label ~ table tr:last-child,
#regle:checked ~ label ~ table tr:first-child,
#regle:checked ~ label ~ table td:first-child,
#regle:checked ~ label ~ table td:last-child{
visibility: visible;
}
td{
width: 1em;
height: 1em;
line-height: 0;
font-size: 1em;
background: green;
}
td.zone{
background-color: brown;
}
td.rivage{
background-color: sandybrown;
}
label{
display: block;
}
pre{
position: relative;
padding: 1em 2em;
}
code{
width: 100%;
height: 50em;
display: none;
border: 1px solid black;
overflow: auto;
margin: 2em 0;
}
code:target{
display: block;
}
pre a{
position: absolute;
left: 4em;
}
a[href="#top"] {
display: none;
}
pre:target > code {
display: block;
}
pre:target > a:nth-child(1) {
display: none;
}
pre:target > a:nth-child(2) {
display: inherit;
}
</style>
</head>
<body id="top">
<?php
$taille = isset($_GET['taille']) ? $_GET['taille'] : 200;
$densite = isset($_GET['densite']) ? $_GET['densite'] : 2;
$pixel = isset($_GET['pixel']) ? $_GET['pixel'] == 'on' : false;
$regle = isset($_GET['regle']) ? $_GET['regle'] == 'on' : false;
?>
<form action="" method="GET">
<fieldset>
<legend>Paramètrages</legend>
<label>Taille de la zone <input name="taille" type="number" value="<?= $taille ?>" /></label>
<label>Densité
<select name="densite">
<?php
foreach (['Forte - tout se touche)', 'Moins Forte', 'Faible', 'Tres Faible - grande carte'] as $key => $val ){
$key++;
echo '<option value="' . $key . '" ' . ($key == $densite ? 'selected="selected"' : '') .">$val</option>";
}
?>
</select>
</label>
<button type="submit" name="submit">Générer la zone</button>
</fieldset>
<?php
// Si on a pas GETé le formulaire, on ne calcul rien
if(isset($_GET['submit'])){;
function calculerZone(&$res, &$lat, &$lon, $taille, $densite){
$valDens = rand(1, 4 * $densite);
$pasDens = ceil($valDens / 4);
switch($valDens % 4){
case 0: $lat -= $pasDens; break;
case 1: $lon -= $pasDens; break;
case 2: $lat += $pasDens; break;
case 3: $lon += $pasDens; break;
}
$point = "$lat:$lon";
if(!in_array($point, $res)){ // Existe pas encore, on a un nouveau point
$res[] = $point;
} else {
// Pour debug
$point;
}
// Si on est en densité, on essaye quand même de trouver une zone proche
if(count($res)<$taille){
$ret = true;
if($densite % 2 == 0){
$ret = calculerZone($res, $lat, $lon, $taille, $densite - 1);
}
return $ret;
}
return false;
}
$res=[];
// On ne fait pas du recursif au cas ou on depasse le maximum d'imrication, si on demande un "gros" nombre
$continue = true;
$lat = 0;
$lon = 0;
$antiLoop = 0;
do{
if($continue = calculerZone($res, $lat, $lon, $taille, $densite)){
$antiLoop = 0;
}
}
while( ++$antiLoop < 1000 && $continue );
if($antiLoop > 1000){
echo "<h1>Impossible de calculer la totalité de la zone</h1>";
}
//$res = unserialize('a:50:{i:5;s:5:"-1:-2";i:14;s:4:"-1:1";i:15;s:4:"-1:2";i:16;s:4:"-1:3";i:22;s:4:"-1:5";i:18;s:4:"-2:2";i:19;s:4:"-2:3";i:20;s:4:"-2:4";i:21;s:4:"-2:5";i:2;s:4:"0:-1";i:4;s:4:"0:-2";i:13;s:3:"0:1";i:17;s:3:"0:3";i:24;s:3:"0:4";i:23;s:3:"0:5";i:1;s:4:"1:-1";i:3;s:4:"1:-2";i:45;s:4:"1:-3";i:0;s:3:"1:0";i:12;s:3:"1:1";i:25;s:3:"1:3";i:7;s:4:"2:-1";i:6;s:4:"2:-2";i:43;s:4:"2:-3";i:44;s:4:"2:-4";i:10;s:3:"2:0";i:11;s:3:"2:1";i:39;s:3:"2:2";i:26;s:3:"2:3";i:27;s:3:"2:4";i:8;s:4:"3:-1";i:9;s:3:"3:0";i:41;s:3:"3:1";i:40;s:3:"3:2";i:30;s:3:"3:3";i:28;s:3:"3:4";i:47;s:4:"4:-1";i:46;s:3:"4:0";i:42;s:3:"4:1";i:32;s:3:"4:2";i:31;s:3:"4:3";i:29;s:3:"4:4";i:33;s:3:"4:5";i:34;s:3:"4:6";i:48;s:3:"5:0";i:49;s:3:"5:1";i:38;s:3:"5:2";i:37;s:3:"5:3";i:35;s:3:"5:4";i:36;s:3:"5:5";}');
// On affiche la "montage"
// On doit calculer le min-max des deux directions
$tailleLon = [9999, 0];
$tailleLat = [9999, 0];
foreach($res as $direction){
$direction = explode(':', $direction);
$tailleLat[0] = min($tailleLat[0], $direction[0]);
$tailleLat[1] = max($tailleLat[1], $direction[0]);
$tailleLon[0] = min($tailleLon[0], $direction[1]);
$tailleLon[1] = max($tailleLon[1], $direction[1]);
}
// On recupère les valeurs de notre tableau de resultat
$zones = array_values($res); // On extrait les valeurs
natsort($zones); // Pas necessaire mais bien pour le debug, un tri alpha
// On s'occupe de déterminer les rivages, est un rivage une zone qui a au moins un voisin inconnu, simple et juste à chaque fois
$rivages=[];
foreach($zones as $zone){
$coords = explode(':', $zone);
$j = $coords[0];
$i = $coords[1];
$point = "$j:$i";
$voisins['o'] = sprintf("%d:%d", $j-1,$i);
$voisins['e'] = sprintf("%d:%d", $j+1,$i);
$voisins['n'] = sprintf("%d:%d", $j,$i-1);
$voisins['s'] = sprintf("%d:%d", $j,$i+1);
foreach($voisins as $voisin){
// Notre point n'est pas dans nos zones connues, c'est un rivage
if(!in_array($voisin, $zones)){
$rivages[] = $zone;
break;
}
}
}
// On dessine la zone dans un tableau, on ajoute volontairement une serie pour les bordures
$tailleLon[0]-=2; $tailleLon[1]+=2;
$tailleLat[0]-=2; $tailleLat[1]+=2;
//echo '<textarea>' . serialize($zones) . '</textarea>';
$o = ['<table>'];
$o[] = "<caption>Notre zone s'étend sur $taille zones</caption>";
for($i=$tailleLon[0];$i<=$tailleLon[1];$i++){
$o[] ='<tr>';
for($j=$tailleLat[0];$j<=$tailleLat[1];$j++){
$point = "$j:$i";
$content = " ";
if($j == $tailleLat[0] || $j == $tailleLat[1]) $content = $i;
if($i == $tailleLon[0] || $i == $tailleLon[1]) $content = $j;
$className = [];
// Le point existe dans nos résultats
if(in_array($point, $zones)){
$className[] = 'zone';
}
// Gestion des rivages
if(in_array($point, $rivages)){
$className[] = 'rivage';
}
$o[] ='<td title="Coordonnées: ' . $point . '" class="' . implode(' ', $className) . '">' . $content . '</td>';
}
$o[] ='</tr>';
}
$o[] ='</table>';
echo '<label for="regle">Afficher les règles</label><input id="regle" name="regle" type="checkbox" ' . ($regle ? 'checked="checked"':'') .' />';
echo '<label for="espace">Espacer les cellules</label><input id="espace" name="pixel" type="checkbox" ' . ($pixel ? 'checked="checked"':'') .' />';
echo implode('', $o);
}
?>
</form>
<pre id="showCode">
<a href="#showCode">Afficher le code</a><a href="#top">Masquer le code</a>
<code><?php echo htmlentities(file_get_contents(__FILE__)); ?></code>
</pre>
</body>
</html>