$TempsMax = 5; // 5 secondes semblent suffire
$Temps = time();
// Propose un carré pour compléter la ligne
function complete_h($c1,$c2) {
$t = range(1,9);
$r1 = array($c1[0],$c1[1],$c1[2],$c2[0],$c2[1],$c2[2]);
$r2 = array($c1[3],$c1[4],$c1[5],$c2[3],$c2[4],$c2[5]);
$r3 = array($c1[6],$c1[7],$c1[8],$c2[6],$c2[7],$c2[8]);
$v1 = array_diff($t,$r1); shuffle($v1);
$v2 = array_diff($t,$r2); shuffle($v2);
$v3 = array_diff($t,$r3); shuffle($v3);
return array_merge($v1,$v2,$v3);
}
// Propose un carré pour compléter la colonne
function complete_v($c1,$c2) {
$t = range(1,9);
$r1 = array($c1[0],$c1[3],$c1[6],$c2[0],$c2[3],$c2[6]);
$r2 = array($c1[1],$c1[4],$c1[7],$c2[1],$c2[4],$c2[7]);
$r3 = array($c1[2],$c1[5],$c1[8],$c2[2],$c2[5],$c2[8]);
$v1 = array_diff($t,$r1); shuffle($v1);
$v2 = array_diff($t,$r2); shuffle($v2);
$v3 = array_diff($t,$r3); shuffle($v3);
return array($v1[0],$v2[0],$v3[0],$v1[1],$v2[1],$v3[1],$v1[2],$v2[2],$v3[2]);
}
// Détermine le n° du carré et le rang de la case d'après les coordonnées
function ij2nr($i,$j) { // coords i-j => coords carré
$n = 3*floor($i/3)+floor($j/3);
$r = 3*($i%3)+$j%3;
return array($n,$r);
}
// Teste si la ligne ou la colonne est conforme
function test(&$c,$colflag) {
$s = sizeof($c); // nombre de carrés
// limite le nombre de lignes/colonnes à tester
if($colflag) { // Test sur les colonnes
$nc=3; if($s==2) $nc=6; elseif($s>2) $nc = 9;
} else // Test sur les lignes
$nc = (floor(($s-1)/3)+1)*3;
// On teste
for($i=0;$i<$nc;$i++) {
for($j=0;$j<9;$j++) {
$t = ($colflag) ? ij2nr($j,$i) : ij2nr($i,$j);
if($t[0]>=$s) continue;
$row[$i][] = $c[$t[0]][$t[1]];
}
if(array_unique($row[$i])!=$row[$i]) return false;
}
return true;
}
// Tente de générer une grille dans le temps imparti
function genere() { global $Temps,$TempsMax;
// Liste des 9 valeurs possibles
$liste = range(1,9);
// carré haut-gauche
shuffle($liste); // Mélange la liste
$carre[0] = $liste; $result = $carre; $nbcarre = 1;
// Pour les autres carrés
while($nbcarre<9) {
// Soit c'est une fin de ligne => on complète
if(($nbcarre==2)||($nbcarre==5)||($nbcarre==8))
$l = complete_h($carre[$nbcarre-2],$carre[$nbcarre-1]);
// Soit c'est une fin de colonne => on complète
elseif(($nbcarre==6)||($nbcarre==7))
$l = complete_v($carre[$nbcarre-6],$carre[$nbcarre-3]);
// Sinon => tirage random
else {
shuffle($liste); $l = $liste;
}
// On teste
$carre[$nbcarre] = $l;
if($test = (test($carre,0)&&test($carre,1)) ) {
// OK, mémorise et passe au carré suivant
$result[$nbcarre] = $l; $nbcarre++;
// echo (time()-$Temps)." - ";
}
// Le temps de recherche est dépassé ?
if(time()-$Temps>$TempsMax) break;
}
return $result;
}
if($search=@$_GET["search"]) {
echo "Recherche".str_repeat(".",@$_GET["n"]+1);
if(@$_GET["n"]) $sudoku = genere();
}
$tmp = @file("sudoku.txt"); $s=0; if($tmp) $s = sizeof($tmp);
// On a trouvé une nouvelle grille => on la sauve
if($search&&@$sudoku[8]) {
$search = 0; // Fin de la recherche
$t = serialize($sudoku)."\n";
if($tmp) {
if(!in_array($t,$tmp)) {
$f=fopen("sudoku.txt","a");
fputs($f,$t);
fclose($f);
$s++;
} else $search=1; // déjà trouvée...
} else {
$f=fopen("sudoku.txt","w");
fputs($f,$t);
fclose($f);
$s++;
}
if(!$search) { ?>
}
}
?>
} else { ?>
grille disponible
Créer une nouvelle grille
} ?>