V2.8
This commit is contained in:
		
							
								
								
									
										77
									
								
								classes.php
									
									
									
									
									
								
							
							
						
						
									
										77
									
								
								classes.php
									
									
									
									
									
								
							| @ -1,6 +1,8 @@ | ||||
| <?php | ||||
|     const UNKNOWN = "."; | ||||
|  | ||||
|     $validGrids = array(); | ||||
|  | ||||
|     function isKnown($box) { | ||||
|         return $box->value != UNKNOWN; | ||||
|     } | ||||
| @ -84,7 +86,7 @@ | ||||
|             } | ||||
|         } | ||||
|              | ||||
|         function generate() { | ||||
|         function generate_() { | ||||
|             // Init with a shuffle row | ||||
|             $values = array("1", "2", "3", "4", "5", "6", "7", "8", "9"); | ||||
|             shuffle($values); | ||||
| @ -101,9 +103,9 @@ | ||||
|             $nbClues = count($this->boxes); | ||||
|             foreach($this->boxes as $testBox) { | ||||
|                 $testBoxes = array($testBox); | ||||
|                 if ($nbClues >=30) | ||||
|                 if ($nbClues >= 30) | ||||
|                     $testBoxes[] = $this->rows[8-$testBox->rowId][8-$testBox->columnId]; | ||||
|                 if ($nbClues >=61) { | ||||
|                 if ($nbClues >= 61) { | ||||
|                     $testBoxes[] = $this->rows[8-$testBox->rowId][$testBox->columnId]; | ||||
|                     $testBoxes[] = $this->rows[$testBox->rowId][8-$testBox->columnId]; | ||||
|                 } | ||||
| @ -124,6 +126,60 @@ | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             $validGrids[] = $this->toString(); | ||||
|         } | ||||
|  | ||||
|         function generate() { | ||||
|             // Init with a shuffle row | ||||
|             $values = array("1", "2", "3", "4", "5", "6", "7", "8", "9"); | ||||
|             shuffle($values); | ||||
|             forEach($this->rows[0] as $columnId => $box) { | ||||
|                 $box->value = $values[$columnId]; | ||||
|                 forEach($box->neighbourhood as $neighbour) | ||||
|                     array_unset_value($box->value, $neighbour->candidates); | ||||
|             } | ||||
|             // Fill grid | ||||
|             $this->solutionsGenerator(true)->current(); | ||||
|              | ||||
|             // Group boxes with their groupedSymetricals | ||||
|             $groupedSymetricals = array(array($this->rows[4][4])); | ||||
|             for ($rowId = 0; $rowId <= 3; $rowId++) { | ||||
|                 for ($columnId = 0; $columnId <= 3; $columnId++) { | ||||
|                     $groupedSymetricals[] = array( | ||||
|                         $this->rows[$rowId][$columnId], | ||||
|                         $this->rows[8-$rowId][8-$columnId], | ||||
|                         $this->rows[8-$rowId][$columnId], | ||||
|                         $this->rows[$rowId][8-$columnId] | ||||
|                     ); | ||||
|                 } | ||||
|                 $groupedSymetricals[] = array( | ||||
|                     $this->rows[$rowId][4], | ||||
|                     $this->rows[8-$rowId][4] | ||||
|                 ); | ||||
|             } | ||||
|             for ($columnId = 0; $columnId <= 3; $columnId++) { | ||||
|                 $groupedSymetricals[] = array( | ||||
|                     $this->rows[4][$columnId], | ||||
|                     $this->rows[4][8-$columnId] | ||||
|                 ); | ||||
|             } | ||||
|  | ||||
|             // Remove clues randomly and their groupedSymetricals while there is still a unique solution | ||||
|             shuffle($groupedSymetricals); | ||||
|             foreach($groupedSymetricals as $symetricals) { | ||||
|                 shuffle($symetricals); | ||||
|                 foreach ($symetricals as $testBox) { | ||||
|                     $erasedValue = $testBox->value; | ||||
|                     $testBox->value = UNKNOWN; | ||||
|                     forEach($testBox->neighbourhood as $neighbour) | ||||
|                         $neighbour->searchCandidates(); | ||||
|                     if (!$this->isValid()) { | ||||
|                         $testBox->value = $erasedValue; | ||||
|                         forEach($testBox->neighbourhood as $neighbour) array_unset_value($testBox->value, $neighbour->candidates); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             $validGrids[] = $this->toString(); | ||||
|         } | ||||
|  | ||||
|         function containsDuplicates() { | ||||
| @ -139,17 +195,19 @@ | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|          | ||||
|  | ||||
|         function countSolutions($max=2) { | ||||
|             $solutions = $this->solutionsGenerator(false); | ||||
|             $solutionsWithoutDuplicates = array(); | ||||
|             $nbSolutions = 0; | ||||
|             foreach($solutions as $solution) { | ||||
|                 $solutionsWithoutDuplicates[$solution] = true; | ||||
|                 $nbSolutions = count($solutionsWithoutDuplicates); | ||||
|                 if ($nbSolutions >= $max) { | ||||
|                     $solutions->send(true); | ||||
|                     break; | ||||
|                 if (!in_array($solution, $solutionsWithoutDuplicates)) { | ||||
|                     $solutionsWithoutDuplicates[] = $solution; | ||||
|                     $nbSolutions ++; | ||||
|                     if ($nbSolutions >= $max) { | ||||
|                         $solutions->send(true); | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             return $nbSolutions; | ||||
| @ -165,7 +223,6 @@ | ||||
|                 if ($randomized) shuffle($emptyBoxes); | ||||
|                 usort($emptyBoxes, "easyFirst"); | ||||
|                 $testBox = $emptyBoxes[0]; | ||||
|                 $nbTries = 0; | ||||
|                 if ($randomized) shuffle($testBox->candidates); | ||||
|                 $stop = null; | ||||
|                 foreach($testBox->candidates as $testBox->value) { | ||||
|  | ||||
							
								
								
									
										1
									
								
								img/light-bulb.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								img/light-bulb.svg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| <svg id="Capa_1" enable-background="new 0 0 497 497" height="24" viewBox="0 0 497 497" width="24" xmlns="http://www.w3.org/2000/svg"><g><g><path d="m282.159 497h-67.319c-5.014 0-9.331-3.539-10.314-8.456l-9.529-47.643h107.004l-9.529 47.643c-.982 4.917-5.299 8.456-10.313 8.456z" fill="#b1abb4"/></g><g><path d="m272.002 440.901-9.529 47.643c-.983 4.917-5.3 8.456-10.314 8.456h30c5.014 0 9.331-3.539 10.314-8.456l9.529-47.643z" fill="#a29aa5"/></g><path d="m302.997 418.462c12.392 0 22.438-10.047 22.438-22.44s-10.046-22.439-22.439-22.439l-54.496-20-54.496 20c-12.393 0-22.439 10.046-22.439 22.439s10.046 22.439 22.438 22.44c-12.392.001-22.438 10.047-22.438 22.439 0 12.393 10.047 22.439 22.44 22.439h108.992c12.393 0 22.439-10.047 22.439-22.439-.001-12.392-10.046-22.439-22.439-22.439z" fill="#f6f6f6"/><path d="m302.996 418.462c12.393 0 22.439-10.047 22.439-22.44s-10.046-22.439-22.439-22.439l-13.031-10-16.969 10c12.393 0 22.439 10.046 22.439 22.439s-10.046 22.44-22.439 22.44c12.393 0 22.439 10.047 22.439 22.439 0 12.393-10.046 22.439-22.439 22.439h30c12.393 0 22.439-10.047 22.439-22.439 0-12.393-10.046-22.439-22.439-22.439z" fill="#eaeaea"/><g><path d="m405.577 157.077c0-87.128-70.938-157.688-158.209-157.073-85.121.6-154.794 69.813-155.93 154.929-.489 36.674 11.595 70.504 32.213 97.463 23.117 30.226 35.092 67.512 35.092 105.565v1.372c0 7.87 6.38 14.25 14.25 14.25h151.017c7.87 0 14.25-6.38 14.25-14.25 0-38.726 12.155-76.653 35.537-107.523 19.945-26.334 31.78-59.15 31.78-94.733z" fill="#f7e365"/></g><g><path d="m247.367.004c-4.64.033-9.23.281-13.769.713 79.668 7.598 141.978 74.702 141.978 156.359 0 35.583-11.835 68.4-31.781 94.734-23.382 30.87-35.537 68.797-35.537 107.523 0 7.87-6.38 14.25-14.25 14.25h30c7.87 0 14.25-6.38 14.25-14.25 0-38.726 12.155-76.653 35.537-107.523 19.946-26.334 31.781-59.15 31.781-94.734.001-87.128-70.938-157.687-158.209-157.072z" fill="#f0d944"/></g><path d="m326.359 109.713c-3.749-1.763-8.216-.154-9.979 3.594l-10.465 22.244c-.075-.049-.145-.103-.222-.149-35.277-21.166-79.107-21.166-114.385 0-.077.046-.147.1-.222.149l-10.465-22.244c-1.764-3.748-6.231-5.357-9.98-3.594-3.748 1.764-5.357 6.231-3.594 9.979l39.048 82.998c6.613 14.056 10.108 29.696 10.108 45.229v11.246 2.333 112.083h15v-106.914h34.594v106.916h15v-112.083-2.333-11.247c0-15.533 3.496-31.173 10.108-45.229l39.048-82.998c1.763-3.748.154-8.216-3.594-9.98zm-49.027 86.592c-7.546 16.041-11.535 33.889-11.535 51.615v3.746h-34.594v-3.746c0-17.726-3.989-35.574-11.535-51.615l-22.263-47.321c.555-.174 1.099-.408 1.62-.72 30.517-18.311 68.433-18.311 98.949 0 .521.313 1.067.541 1.623.715z" fill="#dbb72b"/></g></svg> | ||||
| After Width: | Height: | Size: 2.6 KiB | 
							
								
								
									
										235
									
								
								style.css
									
									
									
									
									
								
							
							
						
						
									
										235
									
								
								style.css
									
									
									
									
									
								
							| @ -1,12 +1,78 @@ | ||||
| :root { | ||||
|     --body-bc: #e8ffff; | ||||
|     --body-fc: black; | ||||
|     --shadow: lightgray; | ||||
|  | ||||
|     --border-color: #555b6e; | ||||
|  | ||||
|     --box-bc: #F7FFF7; | ||||
|     --box-fc: black; | ||||
|     --forbidden-box-bc: #FFEE99; | ||||
|     --same-value-box-bc: #ffbc25; | ||||
|     --placeholder-fc: var(--grid-color); | ||||
|  | ||||
|     --clue-bc: #60D2CB; | ||||
|     --forbidden-clue-bc: var(--clue-bc); | ||||
|     --same-value-clue-bc: #24737F; | ||||
|     --clue-fc: var(--box-bc); | ||||
|     --forbidden-clue-fc: var(--forbidden-box-bc); | ||||
|     --same-value-clue-fc: var(--forbidden-box-bc); | ||||
|  | ||||
|     --tool-fc: var(--clue-fc); | ||||
|     --tool-bc: var(--clue-bc); | ||||
|     --selected-tool-bc: var(--same-value-clue-bc); | ||||
|     --selected-tool-fc: var(--same-value-clue-fc); | ||||
|     --tool-hover-bc: #80DBD5; | ||||
|     --selected-tool-hover-bc: #319EAF; | ||||
| } | ||||
|  | ||||
| @media (prefers-color-scheme: dark) { | ||||
|     :root { | ||||
|         --body-bc: #1c1c1e; | ||||
|         --body-fc: #fefefe; | ||||
|         --shadow: darkgray; | ||||
|  | ||||
|         --border-color: #292929; | ||||
|  | ||||
|         --box-bc: #0C151D; | ||||
|         --box-fc: #bfcbce; | ||||
|         --forbidden-box-bc: #004E52; | ||||
|         --same-value-box-bc: #09BC8A; | ||||
|         --placeholder-fc: var(--grid-color); | ||||
|  | ||||
|         --clue-bc: #508991; | ||||
|         --forbidden-clue-bc: var(--clue-bc); | ||||
|         --same-value-clue-bc: #75DDDD; | ||||
|         --clue-fc: var(--box-bc); | ||||
|         --forbidden-clue-fc: var(--forbidden-box-bc); | ||||
|         --same-value-clue-fc: var(--forbidden-box-bc); | ||||
|  | ||||
|         --tool-fc: var(--clue-fc); | ||||
|         --tool-bc: var(--clue-bc); | ||||
|         --selected-tool-bc: var(--same-value-clue-bc); | ||||
|         --selected-tool-fc: var(--same-value-clue-fc); | ||||
|         --tool-hover-bc: #61A0A8; | ||||
|         --selected-tool-hover-bc: #9DE7E7; | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| body { | ||||
|     font-family: sans-serif; | ||||
|     width: min-content; | ||||
|     margin: auto; | ||||
|     background: var(--body-bc); | ||||
|     color: var(--body-fc) | ||||
| } | ||||
|  | ||||
| h1 { | ||||
|     text-align: center; | ||||
|     margin: 1rem; | ||||
|     font-weight: 50; | ||||
|     margin: 2rem; | ||||
|     text-transform: uppercase; | ||||
|     letter-spacing: 1rem; | ||||
|     text-indent: 1rem; | ||||
|     text-shadow: .1rem .1rem var(--shadow); | ||||
| } | ||||
|  | ||||
| section, div, footer { | ||||
| @ -14,7 +80,7 @@ section, div, footer { | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|     text-align: center; | ||||
|     margin: 0.8rem 0; | ||||
|     margin: 1rem 0; | ||||
| } | ||||
|  | ||||
| div { | ||||
| @ -28,79 +94,45 @@ div { | ||||
|  | ||||
| .grid { | ||||
|     border-spacing: 0; | ||||
|     border: 1px solid black; | ||||
|     border-radius: 6px; | ||||
|     margin: auto; | ||||
|     cursor: url(img/ink-pen.svg) 2 22, text; | ||||
|     border-collapse: collapse; | ||||
| } | ||||
|  | ||||
| .grid td, tr { | ||||
|     padding: 0; | ||||
| } | ||||
|  | ||||
| .grid tr:first-child td:first-child { | ||||
|     border-top-left-radius: 5px; | ||||
| } | ||||
|  | ||||
| .grid tr:first-child td:first-child input { | ||||
|     border-top-left-radius: 4px; | ||||
| } | ||||
|  | ||||
| .grid tr:first-child td:last-child { | ||||
|     border-top-right-radius: 5px; | ||||
| } | ||||
|  | ||||
| .grid tr:first-child td:last-child input { | ||||
|     border-top-right-radius: 4px; | ||||
| } | ||||
|  | ||||
| .grid tr:last-child td:first-child { | ||||
|     border-bottom-left-radius: 5px; | ||||
| } | ||||
|  | ||||
| .grid tr:last-child td:first-child > input { | ||||
|     border-bottom-left-radius: 4px; | ||||
| } | ||||
|  | ||||
| .grid tr:last-child td:last-child { | ||||
|     border-bottom-right-radius: 5px; | ||||
| } | ||||
|  | ||||
| .grid tr:last-child td:last-child input { | ||||
|     border-bottom-right-radius: 4px; | ||||
| } | ||||
|  | ||||
| .grid tr:nth-child(3n+1) td { | ||||
|     border-top: 1px solid black; | ||||
|     border-top: 2px solid var(--border-color); | ||||
| } | ||||
|  | ||||
| .grid tr:nth-child(3n+2) td { | ||||
|     border-top: 1px solid grey; | ||||
|     border-bottom: 1px solid grey; | ||||
|     border-top: 1px solid var(--border-color); | ||||
|     border-bottom: 1px solid var(--border-color); | ||||
| } | ||||
|  | ||||
| .grid tr:nth-child(3n) td { | ||||
|     border-bottom: 1px solid black; | ||||
|     border-bottom: 2px solid var(--border-color); | ||||
| } | ||||
|  | ||||
| .grid td:nth-child(3n+1) { | ||||
|     border-left: 1px solid black; | ||||
|     border-left: 2px solid var(--border-color); | ||||
| } | ||||
|  | ||||
| .grid td:nth-child(3n+2) { | ||||
|     border-left: 1px solid grey; | ||||
|     border-right: 1px solid grey; | ||||
|     border-left: 1px solid var(--border-color); | ||||
|     border-right: 1px solid var(--border-color); | ||||
| } | ||||
|  | ||||
| .grid td:nth-child(3n+3) { | ||||
|     border-right: 1px solid black; | ||||
|     border-right: 2px solid var(--border-color); | ||||
| } | ||||
|  | ||||
|  | ||||
| .grid input { | ||||
|     width: 2.5rem; | ||||
|     height: 2.5rem; | ||||
|     font-size: 1.5rem; | ||||
|     border: 0; | ||||
|     border-radius: 0; | ||||
|     padding: 0; | ||||
| @ -120,8 +152,9 @@ input[type="number"]::-webkit-calendar-picker-indicator { | ||||
| } | ||||
|  | ||||
| .grid input:enabled { | ||||
|     background: white; | ||||
|     color: darkblue; | ||||
|     font-size: 1.4rem; | ||||
|     color: var(--box-fc); | ||||
|     background: var(--box-bc); | ||||
|     cursor: inherit; | ||||
| } | ||||
|  | ||||
| @ -132,49 +165,52 @@ input[type="number"]::-webkit-calendar-picker-indicator { | ||||
| } | ||||
|  | ||||
| .grid input:disabled { | ||||
|     color: white !important; | ||||
|     background: #6666ff !important; | ||||
|     cursor: not-allowed !important; | ||||
|     font-size: 1.3rem; | ||||
|     font-weight: bold; | ||||
|     color: var(--clue-fc); | ||||
|     background: var(--clue-bc); | ||||
|     cursor: default; | ||||
| } | ||||
|  | ||||
| .grid input.forbidden:enabled { | ||||
|     background: #ffffaa !important; | ||||
|     background: var(--forbidden-box-bc); | ||||
|     cursor: not-allowed; | ||||
| } | ||||
|  | ||||
| .grid input.same-value:enabled { | ||||
|     background: #ffff33; | ||||
|     background: var(--same-value-box-bc); | ||||
|     cursor: not-allowed !important; | ||||
| } | ||||
|  | ||||
| .grid input.forbidden:disabled { | ||||
|     color: #ffffaa; | ||||
|     background: #6666ff; | ||||
|     color: var(--forbidden-clue-fc); | ||||
|     background: var(--forbidden-clue-bc) !important; | ||||
|     cursor: not-allowed; | ||||
| } | ||||
|  | ||||
| .grid input.same-value:disabled, | ||||
| .tools button.same-value:enabled, | ||||
| .tools input:enabled:checked + label { | ||||
|     color: #ffffaa !important; | ||||
|     background: #00b359 !important; | ||||
| .grid input.same-value:disabled { | ||||
|     color: var(--same-value-clue-fc) !important; | ||||
|     background: var(--same-value-clue-bc) !important; | ||||
| } | ||||
|  | ||||
| .grid input.one-candidate { | ||||
|     cursor: help !important; | ||||
| } | ||||
|  | ||||
| .tools div { | ||||
|     justify-content: space-between; | ||||
| } | ||||
|  | ||||
| .tools button, | ||||
| .tools input + label { | ||||
|     color: white; | ||||
|     text-shadow: -1px -1px #5b6c9e; | ||||
|     background: #8ca6f2; | ||||
|     border: 2px outset #8ca6f2; | ||||
|     border-radius: 4px; | ||||
|     color: var(--tool-fc); | ||||
|     background: var(--clue-bc); | ||||
|     border: 1px outset var(--clue-bc); | ||||
|     font-size: 1.3rem; | ||||
|     font-weight: bold; | ||||
|     min-width:20px; | ||||
|     padding: 4px 5px 5px 5px; | ||||
|     margin:  0px 1px 1px 1px; | ||||
|     padding: 6px; | ||||
|     margin: .1rem; | ||||
|     cursor: pointer; | ||||
| } | ||||
|  | ||||
| @ -191,51 +227,44 @@ input[type="number"]::-webkit-calendar-picker-indicator { | ||||
|     pointer-events: none; | ||||
| } | ||||
|  | ||||
| .tools button:enabled:hover, | ||||
| .tools button:enabled:focus, | ||||
| .tools input:enabled:hover + label, | ||||
| .tools input:enabled:focus + label { | ||||
|     border-width: 1px; | ||||
|     border-style: outset; | ||||
|     padding: 5px 5px 5px 6px; | ||||
|     margin:  1px 1px 1px 2px; | ||||
| } | ||||
|  | ||||
| .tools input:enabled:checked:hover + label, | ||||
| .tools input:enabled:checked:focus + label { | ||||
|     border-width: 3px; | ||||
|     border-style: inset; | ||||
|     padding: 4px 2px 2px 5px; | ||||
|     margin:  1px 1px 1px 2px; | ||||
| } | ||||
|  | ||||
| .tools button:enabled:checked, | ||||
| .tools input:enabled:checked + label { | ||||
|     text-shadow: -1px -1px #005f2f; | ||||
|     border: 2px inset #00b359; | ||||
|     background: #00b359; | ||||
|     padding: 4px 4px 4px 5px; | ||||
|     margin:  1px 1px 0px 2px; | ||||
|     border-style: inset; | ||||
| } | ||||
|  | ||||
| .tools button:enabled:active, | ||||
| .tools input:enabled:active + label { | ||||
|     border-width: 4px !important; | ||||
|     border-style: inset !important; | ||||
|     padding: 4px 0px 0px 5px !important; | ||||
|     margin:  0px 1px 0px 2px !important; | ||||
| .tools button.same-value:enabled, | ||||
| .tools input:enabled:checked + label { | ||||
|     background: var(--selected-tool-bc); | ||||
|     color: var(--selected-tool-fc); | ||||
|     border-color: var(--selected-tool-bc); | ||||
| } | ||||
|  | ||||
| .tools button:enabled:hover, | ||||
| .tools input:enabled:hover + label { | ||||
|     background: var(--tool-hover-bc); | ||||
|     border-color: var(--tool-hover-bc); | ||||
| } | ||||
|  | ||||
| .tools button:enabled:checked:hover, | ||||
| .tools input:enabled:checked:hover + label { | ||||
|     background: var(--selected-tool-hover-bc); | ||||
|     border-color: var(--selected-tool-hover-bc); | ||||
| } | ||||
|  | ||||
| .tools button:disabled, | ||||
| .tools input:disabled + label { | ||||
|     text-shadow: -1px -1px #555; | ||||
|     color: #ccc; | ||||
|     background: darkgrey; | ||||
|     border: 1px outset darkgrey; | ||||
|     padding: 5px 6px 6px 6px; | ||||
|     margin:  0px 1px 1px 1px; | ||||
|     border-style: outset; | ||||
|     border-color: darkgrey; | ||||
|     cursor: not-allowed; | ||||
| } | ||||
|  | ||||
| .tools button:disabled * { | ||||
|     filter: grayscale(100%); | ||||
|     opacity: 0.7; | ||||
| } | ||||
|  | ||||
| .tools button.warning:hover { | ||||
|     background: #ff5050; | ||||
|     border-color: #ff5050; | ||||
| @ -282,11 +311,15 @@ input[type="number"]::-webkit-calendar-picker-indicator { | ||||
|  | ||||
| a { | ||||
|     text-decoration: none; | ||||
|     color: var(--forbidden-clue-bc); | ||||
| } | ||||
|  | ||||
| a:visited { | ||||
|     color: var(--same-value-clue-bc); | ||||
| } | ||||
|  | ||||
|  | ||||
| .credits { | ||||
|     font-size: 0.8rem; | ||||
|     margin: 0; | ||||
| } | ||||
|  | ||||
| } | ||||
| @ -134,11 +134,11 @@ input[type="number"]::-webkit-calendar-picker-indicator { | ||||
| .grid input:disabled { | ||||
|     color: white !important; | ||||
|     background: #6666ff !important; | ||||
|     cursor: not-allowed !important; | ||||
|     cursor: default; | ||||
| } | ||||
| 
 | ||||
| .grid input.forbidden:enabled { | ||||
|     background: #ffffaa !important; | ||||
|     background: #f9f99f; | ||||
|     cursor: not-allowed; | ||||
| } | ||||
| 
 | ||||
| @ -148,14 +148,15 @@ input[type="number"]::-webkit-calendar-picker-indicator { | ||||
| } | ||||
| 
 | ||||
| .grid input.forbidden:disabled { | ||||
|     color: #ffffaa; | ||||
|     color: #f9f99f; | ||||
|     background: #6666ff; | ||||
|     cursor: not-allowed; | ||||
| } | ||||
| 
 | ||||
| .grid input.same-value:disabled, | ||||
| .tools button.same-value:enabled, | ||||
| .tools input:enabled:checked + label { | ||||
|     color: #ffffaa !important; | ||||
|     color: #f9f99f !important; | ||||
|     background: #00b359 !important; | ||||
| } | ||||
| 
 | ||||
| @ -236,7 +237,12 @@ input[type="number"]::-webkit-calendar-picker-indicator { | ||||
|     cursor: not-allowed; | ||||
| } | ||||
| 
 | ||||
| .tools button.warning { | ||||
| .tools button:disabled * { | ||||
|     filter: grayscale(100%); | ||||
|     opacity: 0.7; | ||||
| } | ||||
| 
 | ||||
| .tools button.warning:hover { | ||||
|     background: #ff5050; | ||||
|     border-color: #ff5050; | ||||
| } | ||||
| @ -290,3 +296,13 @@ a { | ||||
|     margin: 0; | ||||
| } | ||||
| 
 | ||||
| @media (prefers-color-scheme: dark) { | ||||
|     body { | ||||
|       color: #eee; | ||||
|       background: #121212; | ||||
|     } | ||||
|    | ||||
|     body a { | ||||
|       color: #809fff; | ||||
|     } | ||||
|   } | ||||
							
								
								
									
										328
									
								
								style.css.bak2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										328
									
								
								style.css.bak2
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,328 @@ | ||||
| :root { | ||||
|     --body-bc: #e8ffff; | ||||
|     --body-fc: black; | ||||
|     --shadow: lightgray; | ||||
|  | ||||
|     --border-color: #555b6e; | ||||
|  | ||||
|     --box-bc: #F7FFF7; | ||||
|     --box-fc: black; | ||||
|     --forbidden-box-bc: #FFEE99; | ||||
|     --same-value-box-bc: #ffbc25; | ||||
|     --placeholder-fc: var(--grid-color); | ||||
|  | ||||
|     --clue-bc: #60D2CB; | ||||
|     --forbidden-clue-bc: var(--clue-bc); | ||||
|     --same-value-clue-bc: #24737F; | ||||
|     --clue-fc: var(--box-bc); | ||||
|     --forbidden-clue-fc: var(--forbidden-box-bc); | ||||
|     --same-value-clue-fc: var(--forbidden-box-bc); | ||||
|  | ||||
|     --tool-fc: var(--clue-fc); | ||||
|     --tool-bc: var(--clue-bc); | ||||
|     --selected-tool-bc: var(--same-value-clue-bc); | ||||
|     --selected-tool-fc: var(--same-value-clue-fc); | ||||
|     --tool-hover-bc: #80DBD5; | ||||
|     --selected-tool-hover-bc: #319EAF; | ||||
| } | ||||
|  | ||||
| @media (prefers-color-scheme: dark) { | ||||
|     :root { | ||||
|         --body-bc: #1c1c1e; | ||||
|         --body-fc: #fefefe; | ||||
|         --shadow: darkgray; | ||||
|  | ||||
|         --border-color: #292929; | ||||
|  | ||||
|         --box-bc: #0C151D; | ||||
|         --box-fc: #bfcbce; | ||||
|         --forbidden-box-bc: #004E52; | ||||
|         --same-value-box-bc: #09BC8A; | ||||
|         --placeholder-fc: var(--grid-color); | ||||
|  | ||||
|         --clue-bc: #508991; | ||||
|         --forbidden-clue-bc: var(--clue-bc); | ||||
|         --same-value-clue-bc: #75DDDD; | ||||
|         --clue-fc: var(--box-bc); | ||||
|         --forbidden-clue-fc: var(--forbidden-box-bc); | ||||
|         --same-value-clue-fc: var(--forbidden-box-bc); | ||||
|  | ||||
|         --tool-fc: var(--clue-fc); | ||||
|         --tool-bc: var(--clue-bc); | ||||
|         --selected-tool-bc: var(--same-value-clue-bc); | ||||
|         --selected-tool-fc: var(--same-value-clue-fc); | ||||
|         --tool-hover-bc: #61A0A8; | ||||
|         --selected-tool-hover-bc: #9DE7E7; | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| body { | ||||
|     font-family: sans-serif; | ||||
|     width: min-content; | ||||
|     margin: auto; | ||||
|     background: var(--body-bc); | ||||
|     color: var(--body-fc) | ||||
| } | ||||
|  | ||||
| h1 { | ||||
|     text-align: center; | ||||
|     font-weight: 50; | ||||
|     margin: 2rem; | ||||
|     text-transform: uppercase; | ||||
|     letter-spacing: 1rem; | ||||
|     text-indent: 1rem; | ||||
|     text-shadow: .1rem .1rem var(--shadow); | ||||
| } | ||||
|  | ||||
| section, | ||||
| div, | ||||
| footer { | ||||
|     align-items: center; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|     text-align: center; | ||||
|     margin: 1rem 0; | ||||
| } | ||||
|  | ||||
| div { | ||||
|     display: flex; | ||||
|     flex-wrap: wrap; | ||||
|     row-gap: 0.5rem; | ||||
|     column-gap: 0.3rem; | ||||
|     margin: 0.5rem auto; | ||||
| } | ||||
|  | ||||
|  | ||||
| .grid { | ||||
|     border-spacing: 0; | ||||
|     margin: auto; | ||||
|     cursor: url(img/ink-pen.svg) 2 22, text; | ||||
|     border-collapse: collapse; | ||||
| } | ||||
|  | ||||
| .grid td, | ||||
| tr { | ||||
|     padding: 0; | ||||
| } | ||||
|  | ||||
| .grid tr:nth-child(3n+1) td { | ||||
|     border-top: 2px solid var(--border-color); | ||||
| } | ||||
|  | ||||
| .grid tr:nth-child(3n+2) td { | ||||
|     border-top: 1px solid var(--border-color); | ||||
|     border-bottom: 1px solid var(--border-color); | ||||
| } | ||||
|  | ||||
| .grid tr:nth-child(3n) td { | ||||
|     border-bottom: 2px solid var(--border-color); | ||||
| } | ||||
|  | ||||
| .grid td:nth-child(3n+1) { | ||||
|     border-left: 2px solid var(--border-color); | ||||
| } | ||||
|  | ||||
| .grid td:nth-child(3n+2) { | ||||
|     border-left: 1px solid var(--border-color); | ||||
|     border-right: 1px solid var(--border-color); | ||||
| } | ||||
|  | ||||
| .grid td:nth-child(3n+3) { | ||||
|     border-right: 2px solid var(--border-color); | ||||
| } | ||||
|  | ||||
|  | ||||
| .grid input { | ||||
|     width: 2.5rem; | ||||
|     height: 2.5rem; | ||||
|     border: 0; | ||||
|     border-radius: 0; | ||||
|     padding: 0; | ||||
|     text-align: center; | ||||
|     transition: background 0.5s; | ||||
|     -moz-appearance: textfield; | ||||
| } | ||||
|  | ||||
| input[type="number"]::-webkit-outer-spin-button, | ||||
| input::-webkit-inner-spin-button { | ||||
|     -webkit-appearance: none; | ||||
|     margin: 0; | ||||
| } | ||||
|  | ||||
| input[type="number"]::-webkit-calendar-picker-indicator { | ||||
|     display: none; | ||||
| } | ||||
|  | ||||
| .grid input:enabled { | ||||
|     font-size: 1.4rem; | ||||
|     color: var(--box-fc); | ||||
|     background: var(--box-bc); | ||||
|     cursor: inherit; | ||||
| } | ||||
|  | ||||
| .grid input.pencil, | ||||
| .grid input::placeholder { | ||||
|     color: #666 !important; | ||||
|     font-size: 0.9rem !important; | ||||
| } | ||||
|  | ||||
| .grid input:disabled { | ||||
|     font-size: 1.3rem; | ||||
|     font-weight: bold; | ||||
|     color: var(--clue-fc); | ||||
|     background: var(--clue-bc); | ||||
|     cursor: default; | ||||
| } | ||||
|  | ||||
| .grid input.forbidden:enabled { | ||||
|     background: var(--forbidden-box-bc); | ||||
|     cursor: not-allowed; | ||||
| } | ||||
|  | ||||
| .grid input.same-value:enabled { | ||||
|     background: var(--same-value-box-bc); | ||||
|     cursor: not-allowed !important; | ||||
| } | ||||
|  | ||||
| .grid input.forbidden:disabled { | ||||
|     color: var(--forbidden-clue-fc); | ||||
|     background: var(--forbidden-clue-bc) !important; | ||||
|     cursor: not-allowed; | ||||
| } | ||||
|  | ||||
| .grid input.same-value:disabled { | ||||
|     color: var(--same-value-clue-fc) !important; | ||||
|     background: var(--same-value-clue-bc) !important; | ||||
| } | ||||
|  | ||||
| .grid input.one-candidate { | ||||
|     cursor: help !important; | ||||
| } | ||||
|  | ||||
| .tools div { | ||||
|     justify-content: space-between; | ||||
| } | ||||
|  | ||||
| .tools button, | ||||
| .tools input+label { | ||||
|     color: var(--tool-fc); | ||||
|     background: var(--clue-bc); | ||||
|     border: 1px outset var(--clue-bc); | ||||
|     font-size: 1.3rem; | ||||
|     font-weight: bold; | ||||
|     min-width: 20px; | ||||
|     padding: 6px; | ||||
|     margin: .1rem; | ||||
|     cursor: pointer; | ||||
| } | ||||
|  | ||||
| .tools img { | ||||
|     display: block; | ||||
|     width: 24px; | ||||
|     height: 24px; | ||||
| } | ||||
|  | ||||
| .tools input { | ||||
|     position: fixed; | ||||
|     opacity: 0; | ||||
|     width: 0; | ||||
|     pointer-events: none; | ||||
| } | ||||
|  | ||||
| .tools button:enabled:checked, | ||||
| .tools input:enabled:checked+label { | ||||
|     border-style: inset; | ||||
| } | ||||
|  | ||||
| .tools button.same-value:enabled, | ||||
| .tools input:enabled:checked+label { | ||||
|     background: var(--selected-tool-bc); | ||||
|     color: var(--selected-tool-fc); | ||||
|     border-color: var(--selected-tool-bc); | ||||
| } | ||||
|  | ||||
| .tools button:enabled:hover, | ||||
| .tools input:enabled:hover+label { | ||||
|     background: var(--tool-hover-bc); | ||||
|     border-color: var(--tool-hover-bc); | ||||
| } | ||||
|  | ||||
| .tools button:enabled:checked:hover, | ||||
| .tools input:enabled:checked:hover+label { | ||||
|     background: var(--selected-tool-hover-bc); | ||||
|     border-color: var(--selected-tool-hover-bc); | ||||
| } | ||||
|  | ||||
| .tools button:disabled, | ||||
| .tools input:disabled+label { | ||||
|     color: #ccc; | ||||
|     background: darkgrey; | ||||
|     border-style: outset; | ||||
|     border-color: darkgrey; | ||||
|     cursor: not-allowed; | ||||
| } | ||||
|  | ||||
| .tools button:disabled * { | ||||
|     filter: grayscale(100%); | ||||
|     opacity: 0.7; | ||||
| } | ||||
|  | ||||
| .tools button.warning:hover { | ||||
|     background: #ff5050; | ||||
|     border-color: #ff5050; | ||||
| } | ||||
|  | ||||
|  | ||||
| .context-menu { | ||||
|     display: none; | ||||
|     z-index: 1000; | ||||
|     position: absolute; | ||||
|     overflow: hidden; | ||||
|     border: 1px solid #CCC; | ||||
|     white-space: nowrap; | ||||
|     font-family: sans-serif; | ||||
|     background: #EEE; | ||||
|     color: #333; | ||||
|     border-top-right-radius: 3px; | ||||
|     border-bottom-left-radius: 3px; | ||||
|     border-bottom-right-radius: 3px; | ||||
|     padding: 0; | ||||
|     margin: 0; | ||||
| } | ||||
|  | ||||
| .context-menu li { | ||||
|     padding: 6px 10px; | ||||
|     cursor: default; | ||||
|     list-style-type: none; | ||||
|     transition: all .3s ease; | ||||
|     font-size: 1rem; | ||||
| } | ||||
|  | ||||
| .context-menu li:hover { | ||||
|     background-color: #DEF; | ||||
| } | ||||
|  | ||||
| .context-menu li.error { | ||||
|     color: #888 | ||||
| } | ||||
|  | ||||
| .context-menu li.error:hover { | ||||
|     background-color: #EEE; | ||||
| } | ||||
|  | ||||
|  | ||||
| a { | ||||
|     text-decoration: none; | ||||
|     color: var(--forbidden-clue-bc); | ||||
| } | ||||
|  | ||||
| a:visited { | ||||
|     color: var(--same-value-clue-bc); | ||||
| } | ||||
|  | ||||
|  | ||||
| .credits { | ||||
|     font-size: 0.8rem; | ||||
|     margin: 0; | ||||
| } | ||||
							
								
								
									
										147
									
								
								sudoku.js
									
									
									
									
									
								
							
							
						
						
									
										147
									
								
								sudoku.js
									
									
									
									
									
								
							| @ -10,7 +10,7 @@ let suggestionTimer = null | ||||
| let valueToInsert = "" | ||||
| let history = [] | ||||
| let accessKeyModifiers = "AccessKey+" | ||||
| let changesToSave = false | ||||
| let easyBoxes = [] | ||||
|  | ||||
| function shuffle(iterable) { | ||||
|     array = Array.from(iterable) | ||||
| @ -103,7 +103,7 @@ function searchCandidatesOf(box) { | ||||
|                 box.title = "Aucune possibilité !" | ||||
|                 break | ||||
|             case 1: | ||||
|                 box.title = "1 possibilité [Clic-droit]" | ||||
|                 box.title = "Une seule possibilité [Clic-droit]" | ||||
|                 break | ||||
|             default: | ||||
|                 box.title = box.candidates.size + " possibilités [Clic-droit]" | ||||
| @ -113,6 +113,7 @@ function searchCandidatesOf(box) { | ||||
|  | ||||
| function onfocus() { | ||||
|     if (pencilRadio.checked) { | ||||
|         //this.type = "text" | ||||
|         this.value = this.placeholder | ||||
|         this.classList.add("pencil") | ||||
|     } else { | ||||
| @ -130,9 +131,10 @@ function onclick() { | ||||
|             this.select() | ||||
|         } | ||||
|     } else if (pencilRadio.checked) { | ||||
|         if (valueToInsert) | ||||
|             this.value += valueToInsert | ||||
|         if (valueToInsert) { | ||||
|             this.value = Array.from(new Set(this.value + valueToInsert)).join("") | ||||
|             this.oninput() | ||||
|         } | ||||
|     } else if (eraserRadio.checked) { | ||||
|         this.value = "" | ||||
|         this.placeholder = "" | ||||
| @ -143,9 +145,8 @@ function onclick() { | ||||
| function oninput() { | ||||
|     history.push({ box: this, value: this.previousValue, placeholder: this.previousPlaceholder }) | ||||
|     undoButton.disabled = false | ||||
|     changesToSave = true | ||||
|     saveButton.disabled = false | ||||
|     if (pencilRadio.checked) { | ||||
|         this.value = Array.from(new Set(this.value)).sort().join("") | ||||
|         this.previousValue = "" | ||||
|         this.previousPlaceholder = this.value | ||||
|     } else { | ||||
| @ -153,9 +154,6 @@ function oninput() { | ||||
|         this.previousPlaceholder = this.placeholder | ||||
|         refreshBox(this) | ||||
|     } | ||||
|  | ||||
|     if (suggestionTimer) clearTimeout(suggestionTimer) | ||||
|     suggestionTimer = setTimeout(showSuggestion, SUGESTION_DELAY) | ||||
| } | ||||
|  | ||||
| function refreshBox(box) { | ||||
| @ -165,33 +163,32 @@ function refreshBox(box) { | ||||
|  | ||||
| function checkBox(box) { | ||||
|     box.neighbourhood.concat([box]).forEach(neighbour => { | ||||
|         searchCandidatesOf(neighbour) | ||||
|         neighbour.setCustomValidity("") | ||||
|         searchCandidatesOf(neighbour) | ||||
|         if (neighbour.candidates.size == 0) { | ||||
|             neighbour.setCustomValidity("Aucun chiffre possible !") | ||||
|         } | ||||
|     }) | ||||
|  | ||||
|     for (neighbour1 of box.neighbourhood) { | ||||
|         if (neighbour1.value) { | ||||
|             for (area of [ | ||||
|                 { name: "région", neighbours: regions[neighbour1.regionId] }, | ||||
|                 { name: "ligne", neighbours: rows[neighbour1.rowId] }, | ||||
|                 { name: "colonne", neighbours: columns[neighbour1.columnId] }, | ||||
|             ]) | ||||
|                 for (neighbour2 of area.neighbours) | ||||
|                     if (neighbour2 != neighbour1 && neighbour2.value == neighbour1.value) { | ||||
|                         for (neighbour of [neighbour1, neighbour2]) { | ||||
|                             neighbour.setCustomValidity(`Il y a un autre ${neighbour.value} dans cette ${area.name}.`) | ||||
|                         } | ||||
|                     } | ||||
|         } else { | ||||
|             if (neighbour1.candidates.size == 0) { | ||||
|                 neighbour1.setCustomValidity("Aucun chiffre possible !") | ||||
|     if (box.value) { | ||||
|         for (area of [ | ||||
|             { name: "région", neighbours: regions[box.regionId] }, | ||||
|             { name: "ligne", neighbours: rows[box.rowId] }, | ||||
|             { name: "colonne", neighbours: columns[box.columnId] }, | ||||
|         ]) | ||||
|         for (neighbour of area.neighbours) | ||||
|             if (box != neighbour && box.value == neighbour.value) { | ||||
|                 for (neighbour of [box, neighbour]) { | ||||
|                     neighbour.setCustomValidity(`Il y a un autre ${box.value} dans cette ${area.name}.`) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (box.form.checkValidity()) { // Correct grid | ||||
|         if (boxes.filter(box => box.value == "").length == 0) | ||||
|         if (boxes.filter(box => box.value == "").length == 0) { | ||||
|             setTimeout(() => alert(`Bravo ! Vous avez résolu la grille.`), 500) | ||||
|             saveButton.disabled = true | ||||
|         } | ||||
|     } else { // Errors on grid | ||||
|         box.form.reportValidity() | ||||
|     } | ||||
| @ -200,7 +197,6 @@ function checkBox(box) { | ||||
| function refreshUI() { | ||||
|     enableRadio() | ||||
|     highlight() | ||||
|     showEasyBoxes() | ||||
| } | ||||
|  | ||||
| function enableRadio() { | ||||
| @ -211,62 +207,42 @@ function enableRadio() { | ||||
|         } else { | ||||
|             radio.disabled = true | ||||
|             radio.label.title = `Tous les ${radio.value} sont posés.` | ||||
|             if (valueToInsert == radio.value) { | ||||
|                 let nextRadio = document.querySelector(".insertRadioGroup :checked ~ input:enabled") || document.querySelector(".insertRadioGroup :enabled") | ||||
|                 if (nextRadio) { | ||||
|                     nextRadio.click() | ||||
|                     nextRadio.onfocus() | ||||
|                 } else { | ||||
|                     valueToInsert = "" | ||||
|                 } | ||||
|             } | ||||
|             if (valueToInsert == radio.value) | ||||
|                 valueToInsert = "" | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| function highlight() { | ||||
|     hintButton.disabled = true | ||||
|     easyBoxes = [] | ||||
|     boxes.forEach(box => { | ||||
|         if (valueToInsert && box.value == valueToInsert) { | ||||
|             box.classList.add("same-value") | ||||
|             box.tabIndex = -1 | ||||
|         } else { | ||||
|             box.classList.remove("same-value") | ||||
|             if (box.disabled) { | ||||
|             if (valueToInsert && highlighterCheckbox.checked && !box.candidates.has(valueToInsert)) { | ||||
|                 box.classList.add("forbidden") | ||||
|                 box.tabIndex = -1 | ||||
|             } else { | ||||
|                 if (valueToInsert && highlighterCheckbox.checked && !box.candidates.has(valueToInsert)) { | ||||
|                     box.classList.add("forbidden") | ||||
|                     box.tabIndex = -1 | ||||
|                 } else { | ||||
|                     box.classList.remove("forbidden") | ||||
|                     box.tabIndex = 0 | ||||
|                 } | ||||
|                 box.classList.remove("forbidden") | ||||
|                 box.tabIndex = 0 | ||||
|             } | ||||
|         } | ||||
|         if (!box.value && box.candidates.size == 1) { | ||||
|             hintButton.disabled = false | ||||
|             easyBoxes.push(box) | ||||
|         } | ||||
|     }) | ||||
|     highlighterCheckbox.label.title = "Surligner les lignes, colonnes et régions contenant déjà " + (valueToInsert? "un " + valueToInsert: "le chiffre sélectionné") | ||||
| } | ||||
|  | ||||
| function showEasyBoxes() { | ||||
|     boxes.filter(box => !box.disabled).forEach(box => { | ||||
|         if (!box.value && box.candidates.size == 1) { | ||||
|             box.classList.add("one-candidate") | ||||
|             box.onclick = function() { | ||||
|                 valueToInsert = this.candidates.values().next().value | ||||
|                 document.getElementById("insertRadio" + valueToInsert).checked = true | ||||
|                 onclick.apply(box) | ||||
|             } | ||||
|         } else { | ||||
|             box.classList.remove("one-candidate") | ||||
|             box.onclick = onclick | ||||
|         } | ||||
|     }) | ||||
| } | ||||
|  | ||||
| function onblur() { | ||||
|     if (this.classList.contains("pencil")) { | ||||
|         this.placeholder = this.value | ||||
|         this.value = "" | ||||
|         //this.type = "number" | ||||
|         this.classList.remove("pencil") | ||||
|     } | ||||
| } | ||||
| @ -292,7 +268,10 @@ function undo() { | ||||
|         previousState.box.value = previousState.value | ||||
|         previousState.box.placeholder = previousState.placeholder | ||||
|         refreshBox(previousState.box) | ||||
|         if (history.length < 1) undoButton.disabled = true | ||||
|         if (history.length < 1) { | ||||
|             undoButton.disabled = true | ||||
|             saveButton.disabled = true | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -316,26 +295,30 @@ function save() { | ||||
|     let saveGame = boxes.map(box => box.value || UNKNOWN).join("") | ||||
|     localStorage[location.pathname] = saveGame | ||||
|     fixGridLink.href = saveGame | ||||
|     changesToSave = false | ||||
|     saveButton.disabled = true | ||||
|     alert("Partie sauvegardée") | ||||
| } | ||||
|  | ||||
| window.onbeforeunload = function(event) { | ||||
|     if (changesToSave) { | ||||
|     if (!saveButton.disabled) { | ||||
|         event.preventDefault() | ||||
|         event.returnValue = "" | ||||
|         event.returnValue = "La partie n'est pas sauvegardée. Quitter quand même ?" | ||||
|     } | ||||
| } | ||||
|  | ||||
| function showSuggestion() { | ||||
|     const easyBoxes = boxes.filter(box => box.value == "" && box.candidates.size == 1) | ||||
| function showHint() { | ||||
|     if (easyBoxes.length) { | ||||
|         let randomEasyBox = shuffle(easyBoxes)[0] | ||||
|         randomEasyBox.placeholder = "💡" | ||||
|         randomEasyBox.focus() | ||||
|     } else { | ||||
|         clearTimeout(suggestionTimer) | ||||
|         suggestionTimer = null | ||||
|         shuffle(easyBoxes) | ||||
|         let box = easyBoxes.pop() | ||||
|         box.placeholder = "💡" | ||||
|         box.focus() | ||||
|         /*value = Array.from(box.candidates)[0] | ||||
|         radio = document.getElementById("insertRadio" + value) | ||||
|         radio.checked = true | ||||
|         insert(radio)*/ | ||||
|         return box | ||||
|     } | ||||
|     hintButton.disabled = true | ||||
| } | ||||
|  | ||||
| function oncontextmenu(event) { | ||||
| @ -348,10 +331,9 @@ function oncontextmenu(event) { | ||||
|             li.innerText = candidate | ||||
|             li.onclick = function (event) { | ||||
|                 contextMenu.style.display = "none" | ||||
|                 box.onfocus() | ||||
|                 box.value = event.target.innerText | ||||
|                 box.oninput() | ||||
|                 box.onblur() | ||||
|                 valueToInsert = event.target.innerText | ||||
|                 document.getElementById("insertRadio" + valueToInsert).checked = true | ||||
|                 box.onclick() | ||||
|             } | ||||
|             contextMenu.appendChild(li) | ||||
|         }) | ||||
| @ -363,14 +345,13 @@ function oncontextmenu(event) { | ||||
|     } | ||||
|     contextMenu.style.left = `${event.pageX}px` | ||||
|     contextMenu.style.top = `${event.pageY}px` | ||||
|     console.log(event.target) | ||||
|     contextMenu.style.display = "block" | ||||
|     return false | ||||
| } | ||||
|  | ||||
| document.onclick = function (event) { | ||||
|     if (contextMenu.style.display == "block") | ||||
|     document.onclick = function (event) { | ||||
|         contextMenu.style.display = "none" | ||||
|         document.onclick = null | ||||
|     } | ||||
|     return false | ||||
| } | ||||
|  | ||||
| document.onkeydown = function(event) { | ||||
|  | ||||
							
								
								
									
										26
									
								
								sudoku.php
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								sudoku.php
									
									
									
									
									
								
							| @ -4,7 +4,7 @@ | ||||
|     $currentGrid = strip_tags($_GET['grid']); | ||||
|     $_SESSION["currentGrid"] = $currentGrid; | ||||
|  | ||||
|     if (!isset($_SESSION[$currentGrid])) { | ||||
|     if (!in_array($currentGrid, $validGrids)) { | ||||
|         $grid = new Grid(); | ||||
|         $grid->import($currentGrid); | ||||
|         if ($grid->containsDuplicates()) { | ||||
| @ -15,6 +15,7 @@ | ||||
|                     $warning = "Cette grille n'a pas de solution."; | ||||
|                     break; | ||||
|                 case 1: | ||||
|                     $validGrids[] = $currentGrid; | ||||
|                     break; | ||||
|                 default: | ||||
|                     $warning = "Cette grille a plusieurs solutions."; | ||||
| @ -58,6 +59,18 @@ | ||||
|         <header> | ||||
|             <h1>Sudoku</h1> | ||||
|         </header> | ||||
|         <section class="tools"> | ||||
|             <div> | ||||
|                 <input id='highlighterCheckbox' type="checkbox" onclick='highlight()'/><label for='highlighterCheckbox' title='Surligner les lignes, colonnes et régions contenant déjà le chiffre sélectionné'><img src='img/highlighter.svg' alt='Surligneur'></label> | ||||
|                 <input type='radio' id='inkPenRadio' name='tool' onclick='grid.style.cursor = "url(img/ink-pen.svg) 2 22, auto"' checked/><label for='inkPenRadio' title='Écrire un chiffre'><img src='img/ink-pen.svg' alt='Stylo indélébile'/></label> | ||||
|                 <input type='radio' id='pencilRadio' name='tool' onclick='grid.style.cursor = "url(img/pencil.svg) 2 22, auto"'/><label for='pencilRadio' title='Prendre des notes'><img src='img/pencil.svg' alt='Crayon'/></label> | ||||
|                 <input type='radio' id='eraserRadio' name='tool' onclick='grid.style.cursor = "url(img/eraser.svg) 2 22, auto"'/><label for='eraserRadio' title='Effacer une case'><img src='img/eraser.svg' alt='Gomme'/></label> | ||||
|                 <button type='button' class='warning' onclick='restart()' title='Recommencer'><img src='img/restart.svg' alt='Recommencer'/></button> | ||||
|                 <button id='undoButton' type='button' onclick='undo()' disabled title='Annuler' accesskey='z'><img src='img/undo.svg' alt='Annuler'/></button> | ||||
|                 <button id="hintButton" type="button" onclick="showHint()" title="Afficher un indice" accesskey="h" disabled=""><img src='img/light-bulb.svg' alt='Ampoule'/></button> | ||||
|                 <button id='saveButton' type='button' onclick='save()' disabled title='Sauvegarder' accesskey='s'><img src='img/save.svg' alt='Disquette'/></button> | ||||
|             </div> | ||||
|         </section> | ||||
|         <form id='sudokuForm'> | ||||
|             <table id='grid' class='grid'> | ||||
|                 <tbody> | ||||
| @ -94,15 +107,6 @@ | ||||
|         } | ||||
| ?> | ||||
|             </div> | ||||
|             <div> | ||||
|                 <input id='highlighterCheckbox' type="checkbox" onclick='highlight()'/><label for='highlighterCheckbox' title='Surligner les lignes, colonnes et régions contenant déjà le chiffre sélectionné'><img src='img/highlighter.svg' alt='Surligneur'></label> | ||||
|                 <input type='radio' id='inkPenRadio' name='tool' onclick='grid.style.cursor = "url(img/ink-pen.svg) 2 22, auto"' checked/><label for='inkPenRadio' title='Écrire un chiffre'><img src='img/ink-pen.svg' alt='Stylo indélébile'/></label> | ||||
|                 <input type='radio' id='pencilRadio' name='tool' onclick='grid.style.cursor = "url(img/pencil.svg) 2 22, auto"'/><label for='pencilRadio' title='Prendre des notes'><img src='img/pencil.svg' alt='Crayon'/></label> | ||||
|                 <input type='radio' id='eraserRadio' name='tool' onclick='grid.style.cursor = "url(img/eraser.svg) 2 22, auto"'/><label for='eraserRadio' title='Effacer une case'><img src='img/eraser.svg' alt='Gomme'/></label> | ||||
|                 <button type='button' class='warning' onclick='restart()' title='Recommencer'><img src='img/restart.svg' alt='Recommencer'/></button> | ||||
|                 <button id='undoButton' type='button' onclick='undo()' disabled title='Annuler' accesskey='z'><img src='img/undo.svg' alt='Annuler'/></button> | ||||
|                 <button id='undoButton' type='button' onclick='save()' title='Sauvegarder' accesskey='s'><img src='img/save.svg' alt='Disquette'/></button> | ||||
|             </div> | ||||
|         </section> | ||||
|         <section> | ||||
| <?php | ||||
| @ -122,7 +126,7 @@ | ||||
|                  | ||||
|             </div> | ||||
|             <div class='credits'> | ||||
|                 Icônes par <a href='https://www.flaticon.com/authors/freepik' title='Freepik'>Freepik</a> chez <a href='https://www.flaticon.com/' title='Flaticon'>www.flaticon.com</a> | ||||
|                 Icônes par <a href='https://www.flaticon.com/authors/freepik' title='Freepik' target="_blank">Freepik</a> chez <a href='https://www.flaticon.com/' title='Flaticon' target="_blank">www.flaticon.com</a> | ||||
|             </div> | ||||
|         </footer> | ||||
|     </body> | ||||
|  | ||||
| @ -14,10 +14,10 @@ | ||||
|     $thumbnail = imagecreate($size, $size); | ||||
|     $transparent = imagecolorallocate($thumbnail, 1, 1, 1); | ||||
|     imagecolortransparent($thumbnail, $transparent); | ||||
|     $black = imagecolorallocate($thumbnail, 0, 0, 0); | ||||
|     $grey = imagecolorallocate($thumbnail, 128, 128, 128); | ||||
|     $blue = imagecolorallocate($thumbnail, 102, 102, 255); | ||||
|     $white = imagecolorallocate($thumbnail, 255, 255, 255); | ||||
|     $black = imagecolorallocate($thumbnail, 85, 91, 110); | ||||
|     $grey = imagecolorallocate($thumbnail, 85, 91, 110); | ||||
|     $blue = imagecolorallocate($thumbnail, 96, 210, 203); | ||||
|     $white = imagecolorallocate($thumbnail, 247, 255, 247); | ||||
|      | ||||
|     if ($size <= 36) { | ||||
|         $boxSize = floor(($size-4) / 9); | ||||
|  | ||||
		Reference in New Issue
	
	Block a user