sudoku/gnieark.php
2015-11-18 21:48:00 +01:00

229 lines
6.0 KiB
PHP

<?php
//separer les map
$grids=explode("\n",str_replace(array("+-----------------+\n","|"),"",file_get_contents("easy.txt")));
$grid=array();
foreach($grids as $gridLine){
$lineArray=array();
for($i=0;$i<strlen($gridLine);$i=$i+2){
$lineArray[]=$gridLine[$i];
}
$grid[]=$lineArray;
if(count($grid)==9){
viewGrid(resolveSudoku($grid));
$grid=array();
}
}
function resolveSudokuByBruteforce($grille){
$possib=array();
//se placer sur la première case non remplie
for ($y=0;$y<9;$y++){
for($x=0;$x<9;$x++){
if($grille[$y][$x]==" "){
//$possib[$x."-".$y]=array();
//enregistrer toutes les possibilités sur cette case
$canPlay=false;
for($k=1;$k<10;$k++){
if(canBePlaced($k,$x,$y,$grille)){
//$possib[$x."-".$y][]=$k;
$canPlay=true;
$grilleTemp=$grille;
$grilleTemp[$y][$x]=$k;
if($gr=resolveSudokuByBruteforce($grilleTemp)){
return $gr;
}else{
//en fait, non , on ne peut pas jouer là
$canPlay=false;
}
}
}
if(!$canPlay){
return false;
}
}
}
}
/*
if(count($possib==1)){
//y a qu'une case à jouer
list($x,$y)=explode("-",array_keys($possib)[0]);
$grilleTemp[$y][$x]=$possib[$x."-".$y][0];
return $grilleTemp;
}
*/
}
function resolveSudoku($grille){
//compter les cases libres
$numberOfFreeCases=0;
for ($y=0;$y<9;$y++){
for($x=0;$x<9;$x++){
if($grille[$y][$x]==" "){
$numberOfFreeCases++;
}
}
}
while( $numberOfFreeCases>0){
if(isset($lastNumberOfFreeCases)){
if($lastNumberOfFreeCases == $numberOfFreeCases){
//semble bloqué
if($grid=resolveSudokuByBruteforce($grille)){
return $grid;
}else{
return $grille;
}
}
}
$lastNumberOfFreeCases = $numberOfFreeCases;
// echo $numberOfFreeCases."\n";
//toutes les cases
for ($y=0;$y<9;$y++){
for($x=0;$x<9;$x++){
//si la case est vide
if($grille[$y][$x]==" "){
$numbersAvailable=array();
for($k=1;$k<10;$k++){
if (canBePlaced($k,$x,$y,$grille)){
$numbersAvailable[]=$k;
}
}
if(count($numbersAvailable)==1){
//only 1 number can be placed there
$grille[$y][$x]=$numbersAvailable[0];
$numberOfFreeCases--;
}else{
//tester si une des valeurs doit etre là dans le sens où elle ne peut pas etre
// placée ailleurs dans son petit carré, sa ligne ou sa colonne
$listsOfFreeCasesSame=listFreeCasesNearMe($x,$y,$grille);
foreach ($listsOfFreeCasesSame as $freeCasesSame){
foreach ($numbersAvailable as $number){
$cantPlace=true;
foreach($freeCasesSame as $case){
if(canBePlaced($number,$case['x'],$case['y'],$grille)){
$cantPlace=false;
break;
}
}
if($cantPlace){
//on va le placer ici
$grille[$y][$x]= $number;
$numberOfFreeCases--;
break 2;
}
}
}
}
}
}
}
}
return $grille;
}
function listFreeCasesNearMe($x,$y,$grid){
//ligne
$freeOnSameLine=array();
for($i=0;$i<9;$i++){
if(($grid[$y][$i]==" ") && ($x<>$i)){
$freeOnSameLine[]=array('x'=>$i,'y'=>$y);
}
}
//colonne
$freeOnSameColumn=array();
for($i=0;$i<9;$i++){
if(($grid[$i][$x]==" ") && ($y<>$i)){
$freeOnSameColumn[]=array('x'=>$x,'y'=>$i);
}
}
//carré 3X3
if($x<3){
$xMin=0;
}elseif(($x>2) && ($x<6)){
$xMin=3;
}else{
//x>=6
$xMin=6;
}
if($y<3){
$yMin=0;
}elseif(($y>2) && ($y<6)){
$yMin=3;
}else{
//y>=6
$yMin=6;
}
for($k=$yMin;$k<$yMin + 3;$k++){
for($l=$xMin;$l<$xMin + 3;$l++){
if($grid[$k][$l]==" "){
$freeOnSameCarre[]=array('x'=>$l,'y'=>$k);
}
}
}
return array($freeOnSameLine,$freeOnSameColumn,$freeOnSameCarre);
}
function canBePlaced($number,$x,$y,$grid){
//vis à vis des valeurs sur la ligne
if(in_array($number,$grid[$y])){
return false;
}
// vis à vis des valeurs libres sur la colonne
$col=array();
$valeursPossiblesEnColonnes=array();
for($k=0;$k<9;$k++){
if($number==$grid[$k][$x]){
return false;
}
}
//valeurs libres petit carré
if($x<3){
$xMin=0;
}elseif(($x>2) && ($x<6)){
$xMin=3;
}else{
//x>=6
$xMin=6;
}
if($y<3){
$yMin=0;
}elseif(($y>2) && ($y<6)){
$yMin=3;
}else{
//y>=6
$yMin=6;
}
$valeursPossiblesPetitCarre=array();
$carre=array();
for($k=$yMin;$k<$yMin + 3;$k++){
for($l=$xMin;$l<$xMin + 3;$l++){
if($number==$grid[$k][$l]){
return false;
}
}
}
return true;
}
function viewGrid($grid){
echo "+-----------------+\n";
foreach($grid as $line){
echo "|";
echo implode(" ",$line);
echo "|\n";
}
echo "+-----------------+\n";
}