improve grid generator

This commit is contained in:
Adrien MALINGREY 2020-10-09 01:09:02 +02:00
parent 7195d84a55
commit 7621d0c8a5
4 changed files with 39 additions and 19 deletions

View File

@ -50,7 +50,7 @@
echo " <button type='button' onclick='showValue(this.textContent)'>$value</button>\n"; echo " <button type='button' onclick='showValue(this.textContent)'>$value</button>\n";
} }
?> ?>
<label for="colorPicjer">✏️</label> <label for="colorPicjer">🎨</label>
<input id='colorPicker' type="color" value='#00008b'/> <input id='colorPicker' type="color" value='#00008b'/>
</div> </div>
<div> <div>

View File

@ -66,7 +66,9 @@
if ($box != $neighbour && !in_array($neighbour, $box->neighbourhood)) if ($box != $neighbour && !in_array($neighbour, $box->neighbourhood))
$box->neighbourhood[] = $neighbour; $box->neighbourhood[] = $neighbour;
} }
}
function generate() {
// Init with a shuffle row // Init with a shuffle row
$values = array("1", "2", "3", "4", "5", "6", "7", "8", "9"); $values = array("1", "2", "3", "4", "5", "6", "7", "8", "9");
shuffle($values); shuffle($values);
@ -80,16 +82,15 @@
$this->findSolutions(true, 1, 4)->current(); $this->findSolutions(true, 1, 4)->current();
// Remove clues while there is still a unique solution // Remove clues while there is still a unique solution
$untestedBoxes = $this->boxes; shuffle($this->boxes);
shuffle($untestedBoxes); $nbClues = count($this->boxes);
$nbClues = count($untestedBoxes); foreach($this->boxes as $testBox) {
while(count($untestedBoxes)) { $testBoxes = array($testBox);
$testBoxes = array(array_pop($untestedBoxes));
if ($nbClues >=30) if ($nbClues >=30)
$testBoxes[] = $this->rows[8-$testBoxes[0]->rowId][8-$testBoxes[0]->columnId]; $testBoxes[] = $this->rows[8-$testBox->rowId][8-$testBox->columnId];
if ($nbClues >=61) { if ($nbClues >=61) {
$testBoxes[] = $this->rows[8-$testBoxes[0]->rowId][$testBoxes[0]->columnId]; $testBoxes[] = $this->rows[8-$testBox->rowId][$testBox->columnId];
$testBoxes[] = $this->rows[$testBoxes[0]->rowId][8-$testBoxes[0]->columnId]; $testBoxes[] = $this->rows[$testBox->rowId][8-$testBox->columnId];
} }
$erasedValues = array(); $erasedValues = array();
forEach($testBoxes as $testBox) { forEach($testBoxes as $testBox) {
@ -98,9 +99,8 @@
forEach($testBox->neighbourhood as $neighbour) forEach($testBox->neighbourhood as $neighbour)
$neighbour->searchAllowedValues(); $neighbour->searchAllowedValues();
} }
if (count(iterator_to_array($this->findSolutions(false, 2, 4), true)) == 1) { if ($this->isValid()) {
$nbClues -= count($testBoxes); $nbClues -= count($testBoxes);
forEach($testBoxes as $testBox) array_unset_value($testBox, $untestedBoxes);
} else { } else {
forEach($testBoxes as $i => $box) { forEach($testBoxes as $i => $box) {
$box->value = $erasedValues[$i]; $box->value = $erasedValues[$i];
@ -110,15 +110,28 @@
} }
} }
function findSolutions($randomized=false, $maxSolutions=1, $maxTries=4) { function isValid() {
$solutionsFinder = $this->findSolutions(false);
$solutionsFound = array();
foreach($solutionsFinder as $solution) {
$solutionsFound[$solution] = true;
if (count($solutionsFound) > 1) {
$solutionsFinder->send(true);
break;
}
}
return count($solutionsFound) == 1;
}
function findSolutions($randomized=false) {
$emptyBoxes = array_filter($this->boxes, "isUnknown"); $emptyBoxes = array_filter($this->boxes, "isUnknown");
if (count($emptyBoxes)) { if (count($emptyBoxes)) {
if ($randomized) shuffle($emptyBoxes); if ($randomized) shuffle($emptyBoxes);
usort($emptyBoxes, "easyFirst"); usort($emptyBoxes, "easyFirst");
$testBox = $emptyBoxes[0]; $testBox = $emptyBoxes[0];
$nbSolutionsFound = 0;
$nbTries = 0; $nbTries = 0;
if ($randomized) shuffle($testBox->allowedValues); if ($randomized) shuffle($testBox->allowedValues);
$stop = null;
foreach($testBox->allowedValues as $testBox->value) { foreach($testBox->allowedValues as $testBox->value) {
foreach($testBox->neighbourhood as $neighbour) foreach($testBox->neighbourhood as $neighbour)
$neighbour->testValueWasAllowed[] = array_unset_value($testBox->value, $neighbour->allowedValues); $neighbour->testValueWasAllowed[] = array_unset_value($testBox->value, $neighbour->allowedValues);
@ -127,16 +140,20 @@
if (count($neighbour->allowedValues) == 0) $correctGrid = false; if (count($neighbour->allowedValues) == 0) $correctGrid = false;
} }
if ($correctGrid) { if ($correctGrid) {
foreach($this->findSolutions($randomized, $maxSolutions-$nbSolutionsFound, $maxTries) as $solution) { $solutionsFinder = $this->findSolutions($randomized);
yield $solution; foreach($solutionsFinder as $solution) {
$nbSolutionsFound++; $stop = (yield $solution);
if ($stop) {
$solutionsFinder->send($stop);
break;
}
} }
} }
forEach($testBox->neighbourhood as $neighbour) forEach($testBox->neighbourhood as $neighbour)
if (array_pop($neighbour->testValueWasAllowed)) if (array_pop($neighbour->testValueWasAllowed))
$neighbour->allowedValues[] = $testBox->value; $neighbour->allowedValues[] = $testBox->value;
if (($maxSolutions && $nbSolutionsFound >= $maxSolutions) || ++$nbTries >= $maxTries) break; if ($stop) break;
} }
$testBox->value = "?"; $testBox->value = "?";
} else { } else {
@ -156,6 +173,7 @@
} }
$grid = new Grid(); $grid = new Grid();
$grid->generate();
header("Location: " . $_SERVER["REQUEST_SCHEME"] . "://" . $_SERVER["HTTP_HOST"] . dirname($_SERVER["DOCUMENT_URI"]) . "/" . $grid->toString()); header("Location: " . $_SERVER["REQUEST_SCHEME"] . "://" . $_SERVER["HTTP_HOST"] . dirname($_SERVER["DOCUMENT_URI"]) . "/" . $grid->toString());
exit(); exit();
?> ?>

View File

@ -12,6 +12,7 @@ div {
margin: 1em auto; margin: 1em auto;
justify-content: center; justify-content: center;
text-align: center; text-align: center;
align-items: center;
} }
table { table {
@ -125,6 +126,7 @@ input::placeholder {
} }
.buttons { .buttons {
flex-wrap: wrap;
column-gap: 0.2em; column-gap: 0.2em;
margin: 0; margin: 0;
} }

View File

@ -186,9 +186,9 @@ function shuffle(iterable) {
easyFirst = (box1, box2) => box1.allowedValues.size - box2.allowedValues.size easyFirst = (box1, box2) => box1.allowedValues.size - box2.allowedValues.size
function showSuggestion() { function showSuggestion() {
const emptyBoxes = boxes.filter(box => box.value == "") const emptyBoxes = boxes.filter(box => box.value == "" && box.allowedValues.size == 1)
if (emptyBoxes.length) { if (emptyBoxes.length) {
shuffle(emptyBoxes).sort(easyFirst)[0].placeholder = "!" shuffle(emptyBoxes).placeholder = "!"
} else { } else {
clearTimeout(suggestionTimer) clearTimeout(suggestionTimer)
suggestionTimer = null suggestionTimer = null