alternate stylesheet
							
								
								
									
										22
									
								
								400.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,22 @@ | ||||
| <?php http_response_code(400); ?> | ||||
| <!DOCTYPE html> | ||||
| <html lang='fr'> | ||||
|     <head> | ||||
|         <?php require("head.php"); ?> | ||||
|         <title>Requête incorrecte</title> | ||||
|     </head> | ||||
|     <body> | ||||
|         <header> | ||||
|             <h1>Requête incorrecte</h1> | ||||
|         </header> | ||||
|         L'adresse URL doit être de la forme :<br/> | ||||
|         <?=$dirUrl?>/?<em>grille</em><br/> | ||||
|         <em>grille</em> étant une suite de 81 caractères représentant la grille de gauche à droite puis de haut en bas, soit : | ||||
|         <ul> | ||||
|             <li>un chiffre entre 1 et 9 pour les cases connues</li> | ||||
|             <li>un point pour les case vides</li> | ||||
|         </ul> | ||||
|         Exemple :<br/> | ||||
|         <a href='<?=$newGridUrl?>'><?=$newGridUrl?></a> | ||||
|     </body> | ||||
| </html> | ||||
							
								
								
									
										54
									
								
								404.php
									
									
									
									
									
								
							
							
						
						| @ -1,54 +0,0 @@ | ||||
| <?php | ||||
|     require("classes.php"); | ||||
|     $grid = new Grid(); | ||||
|     $grid->generate(); | ||||
|  | ||||
|     header("HTTP/1.0 404 Not Found", true, 404); | ||||
|  | ||||
|     $urlDir = $_SERVER["REQUEST_SCHEME"] . "://" . $_SERVER["HTTP_HOST"] . dirname($_SERVER["DOCUMENT_URI"]); | ||||
|     $urlExample = $urlDir . "/" . $grid->toString(); | ||||
| ?> | ||||
| <!DOCTYPE html> | ||||
| <html lang='fr'> | ||||
|     <head> | ||||
|         <meta charset='utf-8' /> | ||||
|         <meta name='viewport' content='width=device-width' /> | ||||
|         <title>Sudoku non trouvé</title> | ||||
|         <link rel='stylesheet' type='text/css' href='style.css' /> | ||||
|         <link rel="apple-touch-icon" href="thumbnail.php?size=57"  sizes="57x57"> | ||||
|         <link rel="apple-touch-icon" href="thumbnail.php?size=114" sizes="114x114"> | ||||
|         <link rel="apple-touch-icon" href="thumbnail.php?size=72"  sizes="72x72"> | ||||
|         <link rel="apple-touch-icon" href="thumbnail.php?size=144" sizes="144x144"> | ||||
|         <link rel="apple-touch-icon" href="thumbnail.php?size=60"  sizes="60x60"> | ||||
|         <link rel="apple-touch-icon" href="thumbnail.php?size=120" sizes="120x120"> | ||||
|         <link rel="apple-touch-icon" href="thumbnail.php?size=76"  sizes="76x76"> | ||||
|         <link rel="apple-touch-icon" href="thumbnail.php?size=152" sizes="152x152"> | ||||
|         <link rel="icon" type="image/png" href="thumbnail.php?size=196" sizes="196x196"> | ||||
|         <link rel="icon" type="image/png" href="thumbnail.php?size=160" sizes="160x160"> | ||||
|         <link rel="icon" type="image/png" href="thumbnail.php?size=96"  sizes="96x96"> | ||||
|         <link rel="icon" type="image/png" href="thumbnail.php?size=16"  sizes="16x16"> | ||||
|         <link rel="icon" type="image/png" href="thumbnail.php?size=32"  sizes="32x32"> | ||||
|         <link rel="manifest" href="manifest.php"> | ||||
|         <meta property="og:title" content="Sudoku"/> | ||||
|         <meta property="og:type" content="website"/> | ||||
|         <meta property="og:url" content="<?=$_SERVER["REQUEST_SCHEME"]."://".$_SERVER["HTTP_HOST"].$_SERVER["DOCUMENT_URI"]?>"/> | ||||
|         <meta property="og:image" content="<?=$_SERVER["REQUEST_SCHEME"]."://".$_SERVER["HTTP_HOST"].dirname($_SERVER["DOCUMENT_URI"])?>/thumbnail.php?size=200"/> | ||||
|         <meta property="og:image:width" content="200"/> | ||||
|         <meta property="og:image:height" content="200"/> | ||||
|         <meta property="og:description" content="Remplissez la grille de sorte que chaque ligne, colonne et région (carré de 3×3 cases) contienne tous les chiffres de 1 à 9."/> | ||||
|         <meta property="og:locale" content="fr_FR"/> | ||||
| 		<meta property="og:site_name" content="<?=$_SERVER["HTTP_HOST"]?>"/> | ||||
|     </head> | ||||
|     <body> | ||||
|         <header> | ||||
|             <h1>#404</h1> | ||||
|         </header> | ||||
|         L'adresse URL doit être de la forme : <?=$urlDir?>/<em>grille</em>,<br/> | ||||
|         <em>grille</em> étant une suite de 81 caractères représentant la grille de gauche à droite puis de haut en bas, soit : | ||||
|         <ul> | ||||
|             <li>un chiffre entre 1 et 9 pour les cases connues</li> | ||||
|             <li>un point pour les case vides</li> | ||||
|         </ul> | ||||
|         Exemple : <a href='<?=$urlExample?>'><?=$urlExample?></a><br/> | ||||
|     </body> | ||||
| </html> | ||||
							
								
								
									
										
											BIN
										
									
								
								css/handmadepaper.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 6.3 KiB | 
							
								
								
									
										103
									
								
								css/v1.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,103 @@ | ||||
| body { | ||||
|     /* Background pattern from Toptal Subtle Patterns */ | ||||
|     background: url("handmadepaper.png"); | ||||
|     text-align: center; | ||||
| } | ||||
|  | ||||
| h1 { | ||||
|     text-align: center; | ||||
|     text-shadow: 1px 1px grey; | ||||
|     text-decoration: underline; | ||||
| } | ||||
|  | ||||
| table { | ||||
|     border-spacing: 0; | ||||
|     border-collapse: collapse; | ||||
|     margin: auto; | ||||
| } | ||||
|  | ||||
| div { | ||||
|     display: flex; | ||||
|     column-gap: 0.5em; | ||||
|     row-gap: 0.5em; | ||||
|     margin: 1em auto; | ||||
|     justify-content: center; | ||||
| } | ||||
|  | ||||
| input[type="radio"] { | ||||
|     margin-top: -1px; | ||||
|     vertical-align: middle; | ||||
| } | ||||
|  | ||||
| label.disabled { | ||||
|     color: #aaa; | ||||
| } | ||||
|  | ||||
| .grid td { | ||||
|     border: 2px solid black; | ||||
|     padding: 0; | ||||
| } | ||||
|  | ||||
| .region td { | ||||
|     border: 1px solid grey; | ||||
| } | ||||
|  | ||||
| .grid input { | ||||
|     width: 1.6em; | ||||
|     height: 1.6em; | ||||
|     font-size: 1.5em; | ||||
|     border: 0; | ||||
|     padding: 0; | ||||
|     text-align: center; | ||||
| } | ||||
|  | ||||
| .grid input:enabled { | ||||
|     font-family: cursive; | ||||
|     color: darkblue; | ||||
| } | ||||
|  | ||||
| .grid input:disabled { | ||||
|     color: black; | ||||
|     font-weight: bold; | ||||
| } | ||||
|  | ||||
| .grid input::placeholder { | ||||
|     color: #888; | ||||
| } | ||||
|  | ||||
| .unhighlighted:enabled { | ||||
|     background: transparent; | ||||
| } | ||||
|  | ||||
| .highlighted { | ||||
|     background: yellow; | ||||
| } | ||||
|  | ||||
| #shareDiv { | ||||
|     display: block; | ||||
|     line-height: 80%; | ||||
| } | ||||
|  | ||||
| #shareA { | ||||
|     text-decoration: none; | ||||
|     font-size: 0.8em; | ||||
|     letter-spacing: 0.5em; | ||||
| } | ||||
|  | ||||
| #highlightRadiosDiv { | ||||
|     column-gap: 0; | ||||
| } | ||||
|  | ||||
| input[type="number"] { | ||||
|     -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; | ||||
| } | ||||
| @ -9,7 +9,9 @@ h1 { | ||||
|     margin: 1rem; | ||||
| } | ||||
| 
 | ||||
| section, div, footer { | ||||
| section, | ||||
| div, | ||||
| footer { | ||||
|     align-items: center; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
| @ -25,7 +27,6 @@ div { | ||||
|     margin: 0.5rem auto; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| .grid { | ||||
|     border-spacing: 0; | ||||
|     border: 1px solid black; | ||||
| @ -34,7 +35,8 @@ div { | ||||
|     cursor: url(img/ink-pen.svg) 2 22, text; | ||||
| } | ||||
| 
 | ||||
| .grid td, tr { | ||||
| .grid td, | ||||
| tr { | ||||
|     padding: 0; | ||||
| } | ||||
| 
 | ||||
| @ -58,7 +60,7 @@ div { | ||||
|     border-bottom-left-radius: 5px; | ||||
| } | ||||
| 
 | ||||
| .grid tr:last-child td:first-child > input { | ||||
| .grid tr:last-child td:first-child>input { | ||||
|     border-bottom-left-radius: 4px; | ||||
| } | ||||
| 
 | ||||
| @ -96,7 +98,6 @@ div { | ||||
|     border-right: 1px solid black; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| .grid input { | ||||
|     width: 2.5rem; | ||||
|     height: 2.5rem; | ||||
| @ -155,7 +156,7 @@ input[type="number"]::-webkit-calendar-picker-indicator { | ||||
| 
 | ||||
| .grid input.same-value:disabled, | ||||
| .tools button.same-value:enabled, | ||||
| .tools input:enabled:checked + label { | ||||
| .tools input:enabled:checked+label { | ||||
|     color: #f9f99f !important; | ||||
|     background: #00b359 !important; | ||||
| } | ||||
| @ -164,18 +165,17 @@ input[type="number"]::-webkit-calendar-picker-indicator { | ||||
|     cursor: help !important; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| .tools button, | ||||
| .tools input + label { | ||||
| .tools input+label { | ||||
|     color: white; | ||||
|     text-shadow: -1px -1px #5b6c9e; | ||||
|     background: #8ca6f2; | ||||
|     border: 2px outset #8ca6f2; | ||||
|     border-radius: 4px; | ||||
|     font-size: 1.3rem; | ||||
|     min-width:20px; | ||||
|     min-width: 20px; | ||||
|     padding: 4px 5px 5px 5px; | ||||
|     margin:  0px 1px 1px 1px; | ||||
|     margin: 0px 1px 1px 1px; | ||||
|     cursor: pointer; | ||||
| } | ||||
| 
 | ||||
| @ -194,46 +194,46 @@ input[type="number"]::-webkit-calendar-picker-indicator { | ||||
| 
 | ||||
| .tools button:enabled:hover, | ||||
| .tools button:enabled:focus, | ||||
| .tools input:enabled:hover + label, | ||||
| .tools input:enabled:focus + label { | ||||
| .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; | ||||
|     margin: 1px 1px 1px 2px; | ||||
| } | ||||
| 
 | ||||
| .tools input:enabled:checked:hover + label, | ||||
| .tools input:enabled:checked:focus + label { | ||||
| .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; | ||||
|     margin: 1px 1px 1px 2px; | ||||
| } | ||||
| 
 | ||||
| .tools input:enabled:checked + label { | ||||
| .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; | ||||
|     margin: 1px 1px 0px 2px; | ||||
| } | ||||
| 
 | ||||
| .tools button:enabled:active, | ||||
| .tools input:enabled:active + label { | ||||
| .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; | ||||
|     margin: 0px 1px 0px 2px !important; | ||||
| } | ||||
| 
 | ||||
| .tools button:disabled, | ||||
| .tools input:disabled + label { | ||||
| .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; | ||||
|     margin: 0px 1px 1px 1px; | ||||
|     cursor: not-allowed; | ||||
| } | ||||
| 
 | ||||
| @ -247,7 +247,6 @@ input[type="number"]::-webkit-calendar-picker-indicator { | ||||
|     border-color: #ff5050; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| .context-menu { | ||||
|     display: none; | ||||
|     z-index: 1000; | ||||
| @ -285,12 +284,10 @@ input[type="number"]::-webkit-calendar-picker-indicator { | ||||
|     background-color: #EEE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| a { | ||||
|     text-decoration: none; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| .credits { | ||||
|     font-size: 0.8rem; | ||||
|     margin: 0; | ||||
| @ -298,11 +295,10 @@ a { | ||||
| 
 | ||||
| @media (prefers-color-scheme: dark) { | ||||
|     body { | ||||
|       color: #eee; | ||||
|       background: #121212; | ||||
|         color: #eee; | ||||
|         background: #121212; | ||||
|     } | ||||
|    | ||||
|     body a { | ||||
|       color: #809fff; | ||||
|         color: #809fff; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -2,22 +2,18 @@ | ||||
|     --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); | ||||
| @ -27,26 +23,22 @@ | ||||
| } | ||||
| 
 | ||||
| @media (prefers-color-scheme: dark) { | ||||
|     :root { | ||||
|      :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); | ||||
| @ -56,7 +48,6 @@ | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| body { | ||||
|     font-family: sans-serif; | ||||
|     width: min-content; | ||||
| @ -93,7 +84,6 @@ div { | ||||
|     margin: 0.5rem auto; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| .grid { | ||||
|     border-spacing: 0; | ||||
|     margin: auto; | ||||
| @ -132,7 +122,6 @@ tr { | ||||
|     border-right: 2px solid var(--border-color); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| .grid input { | ||||
|     width: 2.5rem; | ||||
|     height: 2.5rem; | ||||
| @ -273,7 +262,6 @@ input[type="number"]::-webkit-calendar-picker-indicator { | ||||
|     border-color: #ff5050; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| .context-menu { | ||||
|     display: none; | ||||
|     z-index: 1000; | ||||
| @ -311,7 +299,6 @@ input[type="number"]::-webkit-calendar-picker-indicator { | ||||
|     background-color: #EEE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| a { | ||||
|     text-decoration: none; | ||||
|     color: var(--forbidden-clue-bc); | ||||
| @ -321,7 +308,6 @@ a:visited { | ||||
|     color: var(--same-value-clue-bc); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| .credits { | ||||
|     font-size: 0.8rem; | ||||
|     margin: 0; | ||||
							
								
								
									
										387
									
								
								css/v4.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,387 @@ | ||||
| * { | ||||
|     font-family: "Roboto", "Calibri", "Arial", sans-serif; | ||||
| } | ||||
|  | ||||
| body { | ||||
|     width: min-content; | ||||
|     margin: auto; | ||||
|     font-weight: 300; | ||||
| } | ||||
|  | ||||
| h1 { | ||||
|     text-align: center; | ||||
|     margin: 1rem; | ||||
|     font-weight: 300; | ||||
|     font-size: 2rem; | ||||
| } | ||||
|  | ||||
| div { | ||||
|     display: flex; | ||||
|     flex-wrap: wrap; | ||||
|     row-gap: 0.5rem; | ||||
|     column-gap: 0.2rem; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|     text-align: center; | ||||
|     margin: 0.5rem 0; | ||||
| } | ||||
|  | ||||
| button, | ||||
| label { | ||||
|     font-weight: 400; | ||||
|     transition: all 200ms cubic-bezier(0.25, 0.46, 0.45, 0.94); | ||||
|     border: 1px solid; | ||||
|     border-radius: 3px; | ||||
|     padding: 3px 0px; | ||||
|     margin: 0; | ||||
|     background-clip: border-box; | ||||
|     font-size: 1.1rem; | ||||
|     cursor: pointer; | ||||
|     min-width: 2.5rem; | ||||
| } | ||||
|  | ||||
| button:disabled, | ||||
| :disabled+label { | ||||
|     cursor: not-allowed !important; | ||||
| } | ||||
|  | ||||
| i { | ||||
|     height: 18px; | ||||
|     width: 18px; | ||||
|     font-size: 1.1rem; | ||||
| } | ||||
|  | ||||
| input[type="checkbox"], | ||||
| input[type="radio"] { | ||||
|     position: fixed; | ||||
|     opacity: 0; | ||||
|     width: 0; | ||||
|     pointer-events: none; | ||||
| } | ||||
|  | ||||
| .radioGroup { | ||||
|     column-gap: 0px; | ||||
| } | ||||
|  | ||||
| input[type="radio"]+label { | ||||
|     margin: 0; | ||||
|     border-radius: 0; | ||||
| } | ||||
|  | ||||
| input[type="radio"]:first-child+label { | ||||
|     border-top-left-radius: 3px; | ||||
|     border-bottom-left-radius: 3px; | ||||
| } | ||||
|  | ||||
| .radioGroup label:last-child { | ||||
|     border-right-width: 1px; | ||||
|     border-top-right-radius: 3px; | ||||
|     border-bottom-right-radius: 3px; | ||||
| } | ||||
|  | ||||
| form { | ||||
|     border: 3px solid; | ||||
|     border-radius: 6px; | ||||
|     box-shadow: 0 2px 5px 0 rgb(0 0 0 / 16%), 0 2px 10px 0 rgb(0 0 0 / 12%); | ||||
| } | ||||
|  | ||||
| table { | ||||
|     border-spacing: 0; | ||||
|     margin: auto; | ||||
|     cursor: text; | ||||
|     border-collapse: collapse; | ||||
| } | ||||
|  | ||||
| td { | ||||
|     padding: 0; | ||||
|     border: 1px solid; | ||||
| } | ||||
|  | ||||
| table input { | ||||
|     width: 2.4rem; | ||||
|     height: 2.4rem; | ||||
|     font-size: 1.4rem; | ||||
|     border: 1px solid transparent; | ||||
|     padding: 0; | ||||
|     transition: background 0.5s; | ||||
|     text-align: center; | ||||
|     -moz-appearance: textfield; | ||||
| } | ||||
|  | ||||
| tr:nth-child(3n+1) td { | ||||
|     border-top-width: 3px; | ||||
| } | ||||
|  | ||||
| tr:nth-child(3n) td { | ||||
|     border-bottom-width: 3px; | ||||
| } | ||||
|  | ||||
| td:nth-child(3n+1) { | ||||
|     border-left-width: 3px; | ||||
| } | ||||
|  | ||||
| td:nth-child(3n) { | ||||
|     border-right-width: 3px; | ||||
| } | ||||
|  | ||||
| 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; | ||||
| } | ||||
|  | ||||
| table input:enabled { | ||||
|     cursor: inherit; | ||||
| } | ||||
|  | ||||
| .forbidden { | ||||
|     cursor: not-allowed !important; | ||||
| } | ||||
|  | ||||
| .pencil, | ||||
| ::placeholder { | ||||
|     font-size: 0.9rem !important; | ||||
| } | ||||
|  | ||||
| #links { | ||||
|     flex-direction: column; | ||||
|     row-gap: .2rem; | ||||
| } | ||||
|  | ||||
| a { | ||||
|     text-decoration: none; | ||||
| } | ||||
|  | ||||
| .context-menu { | ||||
|     display: none; | ||||
|     z-index: 1000; | ||||
|     position: absolute; | ||||
|     overflow: hidden; | ||||
|     border: 1px solid; | ||||
|     white-space: nowrap; | ||||
|     font-family: sans-serif; | ||||
|     box-shadow: 0 2px 5px 0 rgb(0 0 0 / 16%), 0 2px 10px 0 rgb(0 0 0 / 12%); | ||||
|     padding: 0; | ||||
|     margin: 0; | ||||
|     border-radius: 3px; | ||||
| } | ||||
|  | ||||
| .context-menu li { | ||||
|     padding: 6px 10px; | ||||
|     cursor: default; | ||||
|     list-style-type: none; | ||||
|     transition: all .3s ease; | ||||
|     font-size: 1rem; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Colors */ | ||||
|  | ||||
| body { | ||||
|     color: #273134; | ||||
|     background-color: #f7f7f7; | ||||
| } | ||||
|  | ||||
| form, | ||||
| td { | ||||
|     border-color: #d3e1e8; | ||||
| } | ||||
|  | ||||
| table input { | ||||
|     color: #303d41; | ||||
|     background-color: #ffffff; | ||||
| } | ||||
|  | ||||
| table input:enabled:hover { | ||||
|     color: #273134; | ||||
| } | ||||
|  | ||||
| :focus { | ||||
|     border-color: rgba(46, 179, 152, 0.5); | ||||
| } | ||||
|  | ||||
| :checked+label, | ||||
| .context-menu li:hover { | ||||
|     color: #ffffff; | ||||
|     background-color: #2eb398; | ||||
| } | ||||
|  | ||||
| :checked+label img { | ||||
|     filter: invert(); | ||||
|     opacity: 100%; | ||||
| } | ||||
|  | ||||
| :disabled, | ||||
| :disabled+label, | ||||
| .context-menu li.error { | ||||
|     color: rgba(39, 49, 52, 0.55); | ||||
| } | ||||
|  | ||||
| :disabled img, | ||||
| :disabled+label img { | ||||
|     opacity: 25%; | ||||
| } | ||||
|  | ||||
| button, | ||||
| input+label, | ||||
| .context-menu { | ||||
|     color: #273134; | ||||
|     border-color: rgba(0, 0, 0, 0.15); | ||||
|     background-color: #fcfcfc; | ||||
| } | ||||
|  | ||||
| img { | ||||
|     opacity: 70%; | ||||
| } | ||||
|  | ||||
| :focus, | ||||
| :focus+label { | ||||
|     border-color: rgba(46, 179, 152, 0.5); | ||||
| } | ||||
|  | ||||
| button:enabled:hover, | ||||
| input:enabled:hover+label { | ||||
|     color: #060808; | ||||
|     background-color: white; | ||||
| } | ||||
|  | ||||
| input:enabled:checked:hover+label { | ||||
|     background-color: #59d4bc; | ||||
| } | ||||
|  | ||||
| button:enabled:hover img, | ||||
| input:enabled:hover+label img { | ||||
|     opacity: 85%; | ||||
| } | ||||
|  | ||||
| a { | ||||
|     color: #248a76; | ||||
| } | ||||
|  | ||||
| a:visited { | ||||
|     color: #252f32; | ||||
| } | ||||
|  | ||||
| a:hover { | ||||
|     color: #2eb398; | ||||
| } | ||||
|  | ||||
| a:active { | ||||
|     color: #248a76; | ||||
| } | ||||
|  | ||||
| .forbidden { | ||||
|     background-color: #ebebeb; | ||||
| } | ||||
|  | ||||
| .same-value { | ||||
|     background-color: #ebebeb; | ||||
|     color: #2eb398; | ||||
| } | ||||
|  | ||||
| h1 { | ||||
|     color: #2eb398; | ||||
| } | ||||
|  | ||||
| @media (prefers-color-scheme: dark) { | ||||
|     body { | ||||
|         color: #abb9b6; | ||||
|         background-color: #1b2224; | ||||
|     } | ||||
|  | ||||
|     form, | ||||
|     td { | ||||
|         border-color: #3f5055; | ||||
|     } | ||||
|  | ||||
|     img { | ||||
|         filter: invert(); | ||||
|     } | ||||
|  | ||||
|     table input { | ||||
|         color: #abb9b6; | ||||
|         background-color: #222b2e; | ||||
|     } | ||||
|  | ||||
|     table input:enabled:hover { | ||||
|         color: #ccd7d4; | ||||
|     } | ||||
|  | ||||
|     :focus { | ||||
|         border-color: rgba(46, 179, 152, 0.7); | ||||
|     } | ||||
|  | ||||
|     :checked+label, | ||||
|     .context-menu li:hover { | ||||
|         color: #ffffff; | ||||
|         background-color: #2eb398; | ||||
|     } | ||||
|  | ||||
|     :checked+label img { | ||||
|         filter: invert(); | ||||
|     } | ||||
|  | ||||
|     :disabled, | ||||
|     :disabled+label, | ||||
|     .context-menu li.error { | ||||
|         color: rgba(204, 215, 212, 0.45); | ||||
|     } | ||||
|  | ||||
|     button, | ||||
|     input+label, | ||||
|     .context-menu { | ||||
|         color: #ccd7d4; | ||||
|         border-color: rgba(0, 0, 0, 0.25); | ||||
|         background-color: #263034; | ||||
|     } | ||||
|  | ||||
|     img { | ||||
|         opacity: 70%; | ||||
|     } | ||||
|  | ||||
|     :focus, | ||||
|     :focus+label { | ||||
|         border-color: rgba(46, 179, 152, 0.7); | ||||
|         ; | ||||
|     } | ||||
|  | ||||
|     button:enabled:hover, | ||||
|     input:enabled:hover+label { | ||||
|         color: #a1b5b0; | ||||
|         border-color: rgba(0, 0, 0, 0.25); | ||||
|         background-color: #38464b; | ||||
|     } | ||||
|  | ||||
|     :enabled:hover+label img { | ||||
|         opacity: 85%; | ||||
|     } | ||||
|  | ||||
|     a { | ||||
|         color: #6ddac4; | ||||
|     } | ||||
|  | ||||
|     a:visited { | ||||
|         color: #c7d0ce; | ||||
|     } | ||||
|  | ||||
|     a:hover { | ||||
|         color: #96e4d4; | ||||
|     } | ||||
|  | ||||
|     a:active { | ||||
|         color: #6ddac4; | ||||
|     } | ||||
|  | ||||
|     .forbidden { | ||||
|         background-color: #2d383b; | ||||
|     } | ||||
|  | ||||
|     .same-value { | ||||
|         color: #2eb398; | ||||
|         background-color: #2d383b; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										0
									
								
								fonts/.keep
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										0
									
								
								fonts/.keep 3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										2317
									
								
								fonts/remixicon.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								fonts/remixicon.eot
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								fonts/remixicon.glyph.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										2319
									
								
								fonts/remixicon.less
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										6835
									
								
								fonts/remixicon.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.1 MiB | 
							
								
								
									
										11356
									
								
								fonts/remixicon.symbol.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 877 KiB | 
							
								
								
									
										
											BIN
										
									
								
								fonts/remixicon.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								fonts/remixicon.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								fonts/remixicon.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										35
									
								
								head.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,35 @@ | ||||
| <meta charset="utf-8" /> | ||||
| <title>Sudoku</title> | ||||
| <meta name="viewport" content="width=device-width" /> | ||||
| <link rel="stylesheet" type="text/css" href="css/v4.css" title="Par défaut" /> | ||||
| <link href="css/v1.css" rel="alternate stylesheet" type="text/css" title="v1"> | ||||
| <link href="css/v2.css" rel="alternate stylesheet" type="text/css" title="v2"> | ||||
| <link href="css/v3.css" rel="alternate stylesheet" type="text/css" title="v3"> | ||||
| <link rel="stylesheet" type="text/css" href="fonts/remixicon.css"> | ||||
| <link rel="apple-touch-icon" href="thumbnail.php?size=57" sizes="57x57"> | ||||
| <link rel="apple-touch-icon" href="thumbnail.php?size=114" sizes="114x114"> | ||||
| <link rel="apple-touch-icon" href="thumbnail.php?size=72" sizes="72x72"> | ||||
| <link rel="apple-touch-icon" href="thumbnail.php?size=144" sizes="144x144"> | ||||
| <link rel="apple-touch-icon" href="thumbnail.php?size=60" sizes="60x60"> | ||||
| <link rel="apple-touch-icon" href="thumbnail.php?size=120" sizes="120x120"> | ||||
| <link rel="apple-touch-icon" href="thumbnail.php?size=76" sizes="76x76"> | ||||
| <link rel="apple-touch-icon" href="thumbnail.php?size=152" sizes="152x152"> | ||||
| <link rel="icon" type="image/png" href="thumbnail.php?size=196" sizes="196x196"> | ||||
| <link rel="icon" type="image/png" href="thumbnail.php?size=160" sizes="160x160"> | ||||
| <link rel="icon" type="image/png" href="thumbnail.php?size=96" sizes="96x96"> | ||||
| <link rel="icon" type="image/png" href="thumbnail.php?size=16" sizes="16x16"> | ||||
| <link rel="icon" type="image/png" href="thumbnail.php?size=32" sizes="32x32"> | ||||
| <link rel="manifest" href="manifest.php"> | ||||
| <meta property="og:title" content="Sudoku" /> | ||||
| <meta property="og:type" content="website" /> | ||||
| <meta property="og:url" | ||||
|     content="<?=$_SERVER["REQUEST_SCHEME"]."://".$_SERVER["HTTP_HOST"].$_SERVER["DOCUMENT_URI"]?>" /> | ||||
| <meta property="og:image" | ||||
|     content="<?=$_SERVER["REQUEST_SCHEME"]."://".$_SERVER["HTTP_HOST"].dirname($_SERVER["DOCUMENT_URI"])?>/thumbnail.php?size=200" /> | ||||
| <meta property="og:image:width" content="200" /> | ||||
| <meta property="og:image:height" content="200" /> | ||||
| <meta property="og:description" | ||||
|     content="Remplissez la grille de sorte que chaque ligne, colonne et région (carré de 3×3 cases) contienne tous les chiffres de 1 à 9." /> | ||||
| <meta property="og:locale" content="fr_FR" /> | ||||
| <meta property="og:site_name" content="<?=$_SERVER["HTTP_HOST"]?>" /> | ||||
| <script src='sudoku.js'></script> | ||||
| @ -1 +0,0 @@ | ||||
| <svg id="Capa_1" enable-background="new 0 0 512 512" height="24" viewBox="0 0 512 512" width="24" xmlns="http://www.w3.org/2000/svg"><g><path d="m214.28 498.762c4.098 0 8.029-1.628 10.927-4.526l278.144-278.144c11.398-11.398 11.398-29.879 0-41.277l-152.928-152.928c-11.398-11.398-29.878-11.398-41.277 0l-300.597 300.598c-11.398 11.398-11.398 29.878 0 41.277l130.474 130.474c2.898 2.898 6.828 4.526 10.927 4.526z" fill="#d3e1f5"/><path d="m275.208 386.418-78.91 78.91c-2.898 2.898-6.828 4.526-10.927 4.526h-64.331c-4.098 0-8.029-1.628-10.927-4.526l28.909 28.909c2.898 2.898 6.829 4.526 10.927 4.526h64.331c4.098 0 8.029-1.628 10.927-4.526l78.91-78.91z" fill="#c0d6f2"/><path d="m505.059 176.523-156.344-156.344c-10.455-10.455-28.935-8.925-41.277 3.417l-228.75 228.75 194.205 194.204 228.75-228.75c12.341-12.342 13.871-30.822 3.416-41.277z" fill="#0473ce"/><path d="m187.955 245.061 134.545-134.545c4.023-4.023 10.546-4.023 14.569 0l77.653 77.653c4.023 4.023 4.023 10.546 0 14.569l-134.545 134.545c-4.023 4.023-10.546 4.023-14.569 0l-77.653-77.653c-4.023-4.023-4.023-10.546 0-14.569z" fill="#0055a3"/><path d="m505.059 176.523-28.908-28.909c10.455 10.455 8.925 28.935-3.417 41.277l-228.75 228.75 28.909 28.909 228.75-228.75c12.341-12.342 13.871-30.822 3.416-41.277z" fill="#0067c5"/></g></svg> | ||||
| Before Width: | Height: | Size: 1.3 KiB | 
| @ -1,44 +0,0 @@ | ||||
| <?xml version="1.0" encoding="iso-8859-1"?> | ||||
| <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve"> | ||||
| <polygon style="fill:#FFCC75;" points="47.202,417.53 94.404,464.732 47.202,511.945 0,464.743 "/> | ||||
| <polygon style="fill:#082947;" points="236.149,414.811 212.545,438.4 111.564,368.892 166.634,313.823 "/> | ||||
| <polygon style="fill:#274B6D;" points="182.37,329.559 127.301,384.628 73.529,299.384 97.126,275.788 "/> | ||||
| <polygon style="fill:#FF9D49;" points="512,118.078 452.926,59.003 294.044,186.413 166.634,345.296 251.886,430.548 "/> | ||||
| <path style="fill:#274B6D;" d="M143.037,368.892l69.508,69.508c0,0-61.136,0.802-102.397,42.063l-39.35-39.333l20.383-51.855 | ||||
| 	L143.037,368.892z"/> | ||||
| <polygon style="fill:#FFCC75;" points="393.977,0.055 81.39,260.051 166.634,345.296 452.926,59.003 "/> | ||||
| <path style="fill:#185F8D;" d="M73.529,299.384l69.508,69.508l-72.239,72.239L31.458,401.79 | ||||
| 	C72.719,360.529,73.529,299.384,73.529,299.384z"/> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| </svg> | ||||
| Before Width: | Height: | Size: 1.3 KiB | 
| @ -1,48 +0,0 @@ | ||||
| <?xml version="1.0" encoding="iso-8859-1"?> | ||||
| <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 viewBox="0 0 511.989 511.989" style="enable-background:new 0 0 511.989 511.989;" xml:space="preserve"  width="24" height="24"> | ||||
| <rect x="408.399" y="26.854" transform="matrix(-0.7071 0.7071 -0.7071 -0.7071 819.7593 -231.0359)" style="fill:#9EC8E8;" width="98.659" height="54.811"/> | ||||
| <polygon style="fill:#082947;" points="430.604,174.402 186.029,418.976 124.017,372.468 376.343,120.141 "/> | ||||
| <polygon style="fill:#274B6D;" points="384.094,127.892 131.769,380.219 93.012,325.958 337.586,81.384 "/> | ||||
| <polygon style="fill:#4284B2;" points="477.112,127.892 430.604,174.402 376.343,120.141 430.604,81.384 "/> | ||||
| <rect x="20.377" y="439.543" transform="matrix(-0.7071 -0.7071 0.7071 -0.7071 -273.1405 837.2019)" style="fill:#082947;" width="32.886" height="71.254"/> | ||||
| <polygon style="fill:#4284B2;" points="186.029,418.976 69.757,488.74 46.502,465.484 77.509,403.473 139.52,372.468 "/> | ||||
| <g> | ||||
| 	<polygon style="fill:#6DA8D6;" points="139.52,372.468 46.502,465.484 23.248,442.23 93.012,325.958 	"/> | ||||
| 	 | ||||
| 		<rect x="351.209" y="48.511" transform="matrix(-0.7071 0.7071 -0.7071 -0.7071 713.2485 -132.6418)" style="fill:#6DA8D6;" width="65.773" height="65.773"/> | ||||
| </g> | ||||
| <polygon style="fill:#9EC8E8;" points="178.681,193.781 155.426,170.527 302.704,23.249 442.229,162.774 418.975,186.028  | ||||
| 	302.704,69.757 "/> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| </svg> | ||||
| Before Width: | Height: | Size: 1.7 KiB | 
| @ -1 +0,0 @@ | ||||
| <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> | ||||
| Before Width: | Height: | Size: 2.6 KiB | 
| @ -1,45 +0,0 @@ | ||||
| <?xml version="1.0" encoding="iso-8859-1"?> | ||||
| <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve"  width="24" height="24"> | ||||
| <polygon style="fill:#FF9D49;" points="393.29,213.665 142.441,464.524 87.044,424.954 345.817,150.364 "/> | ||||
| <polygon style="fill:#FFCC75;" points="353.73,158.277 87.044,424.954 47.473,369.557 298.333,118.708 "/> | ||||
| <polygon style="fill:#BD1515;" points="512,94.965 440.78,166.185 377.475,118.708 464.522,47.486 "/> | ||||
| <polygon style="fill:#F2484B;" points="464.516,47.482 385.382,126.615 345.817,71.224 417.038,0.002 "/> | ||||
| <g> | ||||
| 	 | ||||
| 		<rect x="335.974" y="75.292" transform="matrix(-0.7071 0.7071 -0.7071 -0.7071 731.5841 -18.1559)" style="fill:#082947;" width="67.157" height="134.292"/> | ||||
| 	<polygon style="fill:#082947;" points="71.22,488.261 0,511.998 23.736,440.776 63.305,448.692 	"/> | ||||
| </g> | ||||
| <polygon style="fill:#F2EBD9;" points="47.473,369.557 23.736,440.776 71.22,488.261 142.441,464.524 "/> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| </svg> | ||||
| Before Width: | Height: | Size: 1.3 KiB | 
| @ -1,55 +0,0 @@ | ||||
| <?xml version="1.0" encoding="iso-8859-1"?> | ||||
| <!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||
| <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 width="574.859px" height="574.86px" viewBox="0 0 574.859 574.86" style="enable-background:new 0 0 574.859 574.86;" | ||||
| 	 xml:space="preserve"> | ||||
| <g> | ||||
| 	<path d="M181.688,521.185V353.841H19.125v167.344c0,10.566,13.34,23.906,23.906,23.906h124.312 | ||||
| 		C177.91,545.091,181.688,531.751,181.688,521.185z M66.938,502.06c0,2.64-2.142,4.781-4.781,4.781s-4.781-2.142-4.781-4.781 | ||||
| 		V377.748c0-2.64,2.142-4.781,4.781-4.781s4.781,2.142,4.781,4.781V502.06z M105.188,502.06c0,2.64-2.142,4.781-4.781,4.781 | ||||
| 		s-4.781-2.142-4.781-4.781V377.748c0-2.64,2.142-4.781,4.781-4.781s4.781,2.142,4.781,4.781V502.06z M143.438,502.06 | ||||
| 		c0,2.64-2.142,4.781-4.781,4.781s-4.781-2.142-4.781-4.781V377.748c0-2.64,2.142-4.781,4.781-4.781s4.781,2.142,4.781,4.781V502.06 | ||||
| 		z"/> | ||||
| 	<path d="M19.125,334.716h162.562v-19.125h19.125v-19.125h-57.375c0-10.566-6.828-19.125-15.243-19.125H77.399 | ||||
| 		c-8.415,0-15.243,8.559-15.243,19.125H0v19.125h19.125V334.716z"/> | ||||
| 	<path d="M357.007,191.556C370.968,329.811,243.892,542.08,243.892,542.08c145.235-78.212,169.189-207.363,169.189-207.363 | ||||
| 		c42.333,66.479,44.475,228.305,44.475,228.305c80.995-194.109,0-377.049,0-377.049l117.304,48.874 | ||||
| 		c-19.546-74.014-141.047-125.68-141.047-125.68c-110.322,50.27-249.974,44.686-249.974,44.686 | ||||
| 		C259.249,226.469,357.007,191.556,357.007,191.556z"/> | ||||
| 	<circle cx="369.782" cy="55.128" r="43.29"/> | ||||
| 	<path d="M94.43,229.529c5.977-2.391,27.492-13.148,28.764,0c1.271,13.148,11.876,9.562,19.048,0s3.586-25.102,11.953-23.906 | ||||
| 		s15.539-10.758,17.93-21.735c2.391-10.978-22.711-18.905-33.469-21.458s-20.32,13.321-27.492,13.321s-17.93-20.33-25.102-10.768 | ||||
| 		s-11.953,40.641-11.953,40.641c-10.758-5.977-21.516,7.172-25.102,16.734S88.453,231.919,94.43,229.529z"/> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| </svg> | ||||
| Before Width: | Height: | Size: 2.2 KiB | 
							
								
								
									
										43
									
								
								img/save.svg
									
									
									
									
									
								
							
							
						
						| @ -1,43 +0,0 @@ | ||||
| <?xml version="1.0" encoding="iso-8859-1"?> | ||||
| <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve"> | ||||
| <path style="fill:#DCF4FF;" d="M512,492H0V20h403.213L512,128.787V492z"/> | ||||
| <polygon style="fill:#CCEFFF;" points="403.213,20 256,20 256,492 512,492 512,128.787 "/> | ||||
| <path style="fill:#0A4EAF;" d="M403.213,20H396v175H116V20H0v472h116V315c0-16.568,13.431-30,30-30h220c16.569,0,30,13.432,30,30 | ||||
| 	v177h116V128.787L403.213,20z"/> | ||||
| <g> | ||||
| 	<rect x="296" y="20" style="fill:#063E8B;" width="40" height="115"/> | ||||
| 	<path style="fill:#063E8B;" d="M403.213,20H396v175H256v90h110c16.569,0,30,13.432,30,30v177h116V128.787L403.213,20z"/> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| </svg> | ||||
| Before Width: | Height: | Size: 1.0 KiB | 
							
								
								
									
										46
									
								
								img/undo.svg
									
									
									
									
									
								
							
							
						
						| @ -1,46 +0,0 @@ | ||||
| <?xml version="1.0" encoding="iso-8859-1"?> | ||||
| <!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||
| <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 width="299.021px" height="299.021px" viewBox="0 0 299.021 299.021" style="enable-background:new 0 0 299.021 299.021;" | ||||
| 	 xml:space="preserve"> | ||||
| <g> | ||||
| 	<g> | ||||
| 		<path d="M292.866,254.432c-2.288,0-4.443-1.285-5.5-3.399c-0.354-0.684-28.541-52.949-146.169-54.727v51.977 | ||||
| 			c0,2.342-1.333,4.48-3.432,5.513c-2.096,1.033-4.594,0.793-6.461-0.63L2.417,154.392C0.898,153.227,0,151.425,0,149.516 | ||||
| 			c0-1.919,0.898-3.72,2.417-4.888l128.893-98.77c1.87-1.426,4.365-1.667,6.461-0.639c2.099,1.026,3.432,3.173,3.432,5.509v54.776 | ||||
| 			c3.111-0.198,7.164-0.37,11.947-0.37c43.861,0,145.871,13.952,145.871,143.136c0,2.858-1.964,5.344-4.75,5.993 | ||||
| 			C293.802,254.384,293.34,254.432,292.866,254.432z"/> | ||||
| 	</g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| <g> | ||||
| </g> | ||||
| </svg> | ||||
| Before Width: | Height: | Size: 1.2 KiB | 
							
								
								
									
										46
									
								
								index.php
									
									
									
									
									
								
							
							
						
						| @ -1,10 +1,40 @@ | ||||
| <?php | ||||
| <?php  | ||||
|     require("classes.php"); | ||||
|     session_start(); | ||||
|     $grid = new Grid(); | ||||
|     $grid->generate(); | ||||
|     $currentGrid = $grid->toString(); | ||||
|     $_SESSION[$currentGrid] = "checked"; | ||||
|     header("Location: ".$_SERVER["REQUEST_SCHEME"]."://".$_SERVER["HTTP_HOST"].dirname($_SERVER["DOCUMENT_URI"])."/".$currentGrid); | ||||
|     exit(); | ||||
| ?> | ||||
|     $fullUrl = $_SERVER["REQUEST_SCHEME"]."://".$_SERVER["HTTP_HOST"].$_SERVER["DOCUMENT_URI"]; | ||||
|     $dirUrl = dirname($fullUrl); | ||||
|     $currentGrid = strip_tags($_SERVER['QUERY_STRING']); | ||||
|  | ||||
|     if (preg_match("/^[1-9.]{81}$/", $currentGrid)) { | ||||
|         if (!isset($_SESSION[$currentGrid]) || $_SESSION[$currentGrid] != "checked") { | ||||
|             $grid = new Grid(); | ||||
|             $grid->import($currentGrid); | ||||
|             if ($grid->containsDuplicates()) { | ||||
|                 $warning = "Cette grille contient des doublons."; | ||||
|             } else { | ||||
|                 switch($grid->countSolutions(2)) { | ||||
|                     case 0: | ||||
|                         $warning = "Cette grille n'a pas de solution."; | ||||
|                         break; | ||||
|                     case 1: | ||||
|                         $validGrids[] = $currentGrid; | ||||
|                         break; | ||||
|                     default: | ||||
|                         $warning = "Cette grille a plusieurs solutions."; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         require("sudoku.php"); | ||||
|     } else { | ||||
|         $grid = new Grid(); | ||||
|         $grid->generate(); | ||||
|         $gridAsString = $grid->toString(); | ||||
|         $newGridUrl = "$dirUrl/?$gridAsString"; | ||||
|         $_SESSION[$gridAsString] = "checked"; | ||||
|         if (!$currentGrid) { | ||||
|             header("Location: $newGridUrl"); | ||||
|         } else { | ||||
|             require("400.php"); | ||||
|         } | ||||
|     } | ||||
| ?> | ||||
| @ -1,29 +0,0 @@ | ||||
| location /sudoku/ { | ||||
|         alias /var/www/sudoku/; | ||||
|  | ||||
|         if ($scheme = http) { | ||||
|                 rewrite ^ https://$server_name$request_uri? permanent; | ||||
|         } | ||||
|  | ||||
|         try_files $uri $uri/; | ||||
|         | ||||
|         location ~ [^/]\.php(/|$) { | ||||
|                 try_files $uri =404; | ||||
|                 fastcgi_split_path_info ^(.+?\.php)(/.*)$; | ||||
|                 fastcgi_pass unix:/var/run/php/php7.3-fpm-sudoku.sock; | ||||
|                 fastcgi_index index.php; | ||||
|                 include fastcgi_params; | ||||
|                 fastcgi_param REMOTE_USER $remote_user; | ||||
|                 fastcgi_param PATH_INFO $fastcgi_path_info; | ||||
|                 fastcgi_param SCRIPT_FILENAME $request_filename; | ||||
|         } | ||||
|  | ||||
|         error_page 404 /sudoku/404.php; | ||||
|         location  /sudoku/404.php { | ||||
|                 internal; | ||||
|         } | ||||
| } | ||||
|  | ||||
| location ~ "^/sudoku/([1-9.]{81})$" { | ||||
|         rewrite "^/sudoku/([1-9.]{81})\??(.*)?(#.*)?$" /sudoku/sudoku.php?grid=$1&$2$3 last; | ||||
| } | ||||
							
								
								
									
										325
									
								
								style.css
									
									
									
									
									
								
							
							
						
						| @ -1,325 +0,0 @@ | ||||
| :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; | ||||
| } | ||||
							
								
								
									
										70
									
								
								sudoku.js
									
									
									
									
									
								
							
							
						
						| @ -26,7 +26,7 @@ function shuffle(iterable) { | ||||
|     return array | ||||
| } | ||||
|  | ||||
| window.onload = function () { | ||||
| window.onload = function() { | ||||
|     let rowId = 0 | ||||
|     for (let row of grid.getElementsByTagName('tr')) { | ||||
|         let columnId = 0 | ||||
| @ -82,7 +82,7 @@ window.onload = function () { | ||||
| } | ||||
|  | ||||
| function loadSavedGame() { | ||||
|     const savedGame = localStorage[location.pathname] | ||||
|     const savedGame = localStorage[location.search] | ||||
|     if (savedGame) { | ||||
|         boxes.forEach((box, i) => { | ||||
|             if (!box.disabled && savedGame[i] != UNKNOWN) { | ||||
| @ -90,7 +90,7 @@ function loadSavedGame() { | ||||
|                 box.previousValue = savedGame[i] | ||||
|             } | ||||
|         }) | ||||
|         fixGridLink.href = savedGame | ||||
|         fixGridLink.href = "?" + savedGame | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -119,7 +119,7 @@ function onfocus() { | ||||
|     } else { | ||||
|         this.select() | ||||
|     } | ||||
|     this.style.caretColor = valueToInsert? "transparent": "auto" | ||||
|     this.style.caretColor = valueToInsert ? "transparent" : "auto" | ||||
| } | ||||
|  | ||||
| function onclick() { | ||||
| @ -143,9 +143,14 @@ function onclick() { | ||||
| } | ||||
|  | ||||
| function oninput() { | ||||
|     history.push({ box: this, value: this.previousValue, placeholder: this.previousPlaceholder }) | ||||
|     history.push({ | ||||
|         box: this, | ||||
|         value: this.previousValue, | ||||
|         placeholder: this.previousPlaceholder | ||||
|     }) | ||||
|     undoButton.disabled = false | ||||
|     saveButton.disabled = false | ||||
|     restartButton.disabled = false | ||||
|     if (pencilRadio.checked) { | ||||
|         this.previousValue = "" | ||||
|         this.previousPlaceholder = this.value | ||||
| @ -171,17 +176,22 @@ function checkBox(box) { | ||||
|     }) | ||||
|  | ||||
|     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}.`) | ||||
|         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 | ||||
| @ -235,14 +245,14 @@ function highlight() { | ||||
|             easyBoxes.push(box) | ||||
|         } | ||||
|     }) | ||||
|     highlighterCheckbox.label.title = "Surligner les lignes, colonnes et régions contenant déjà " + (valueToInsert? "un " + valueToInsert: "le chiffre sélectionné") | ||||
|     highlighterCheckbox.label.title = "Surligner les lignes, colonnes et régions contenant déjà " + (valueToInsert ? "un " + valueToInsert : "le chiffre sélectionné") | ||||
| } | ||||
|  | ||||
| function onblur() { | ||||
|     if (this.classList.contains("pencil")) { | ||||
|         this.placeholder = this.value | ||||
|         this.value = "" | ||||
|         //this.type = "number" | ||||
|             //this.type = "number" | ||||
|         this.classList.remove("pencil") | ||||
|     } | ||||
| } | ||||
| @ -254,11 +264,7 @@ function insert(radio) { | ||||
|     } else { | ||||
|         valueToInsert = radio.value | ||||
|     } | ||||
|     if (inkPenRadio.checked) customCursor = "url(img/ink-pen.svg) 2 22" | ||||
|     if (pencilRadio.checked) customCursor = "url(img/pencil.svg) 2 22" | ||||
|     if (eraserRadio.checked) customCursor = "url(img/eraser.svg) 2 22" | ||||
|     fallbackCursor = valueToInsert? "copy": "text" | ||||
|     grid.style.cursor = `${customCursor}, ${fallbackCursor}` | ||||
|     grid.style.cursor = valueToInsert ? "copy" : "text" | ||||
|     highlight() | ||||
| } | ||||
|  | ||||
| @ -286,6 +292,7 @@ function restart() { | ||||
|         }) | ||||
|         let history = [] | ||||
|         undoButton.disabled = true | ||||
|         restartButton.disabled = true | ||||
|         boxes.forEach(searchCandidatesOf) | ||||
|         refreshUI() | ||||
|     } | ||||
| @ -293,8 +300,8 @@ function restart() { | ||||
|  | ||||
| function save() { | ||||
|     let saveGame = boxes.map(box => box.value || UNKNOWN).join("") | ||||
|     localStorage[location.pathname] = saveGame | ||||
|     fixGridLink.href = saveGame | ||||
|     localStorage[location.search] = saveGame | ||||
|     fixGridLink.href = "?" + saveGame | ||||
|     saveButton.disabled = true | ||||
|     alert("Partie sauvegardée") | ||||
| } | ||||
| @ -312,10 +319,10 @@ function showHint() { | ||||
|         let box = easyBoxes.pop() | ||||
|         box.placeholder = "💡" | ||||
|         box.focus() | ||||
|         /*value = Array.from(box.candidates)[0] | ||||
|         radio = document.getElementById("insertRadio" + value) | ||||
|         radio.checked = true | ||||
|         insert(radio)*/ | ||||
|             /*value = Array.from(box.candidates)[0] | ||||
|             radio = document.getElementById("insertRadio" + value) | ||||
|             radio.checked = true | ||||
|             insert(radio)*/ | ||||
|         return box | ||||
|     } | ||||
|     hintButton.disabled = true | ||||
| @ -329,9 +336,10 @@ function oncontextmenu(event) { | ||||
|         Array.from(box.candidates).sort().forEach(candidate => { | ||||
|             li = document.createElement("li") | ||||
|             li.innerText = candidate | ||||
|             li.onclick = function (event) { | ||||
|             li.onclick = function(event) { | ||||
|                 contextMenu.style.display = "none" | ||||
|                 valueToInsert = event.target.innerText | ||||
|                 grid.style.cursor = "copy" | ||||
|                 document.getElementById("insertRadio" + valueToInsert).checked = true | ||||
|                 box.onclick() | ||||
|             } | ||||
| @ -347,7 +355,7 @@ function oncontextmenu(event) { | ||||
|     contextMenu.style.top = `${event.pageY}px` | ||||
|     contextMenu.style.display = "block" | ||||
|  | ||||
|     document.onclick = function (event) { | ||||
|     document.onclick = function(event) { | ||||
|         contextMenu.style.display = "none" | ||||
|         document.onclick = null | ||||
|     } | ||||
| @ -359,4 +367,4 @@ document.onkeydown = function(event) { | ||||
|         event.preventDefault() | ||||
|         contextMenu.style.display = "none" | ||||
|     } | ||||
| } | ||||
| } | ||||
							
								
								
									
										136
									
								
								sudoku.php
									
									
									
									
									
								
							
							
						
						| @ -1,133 +1,91 @@ | ||||
| <?php | ||||
|     require("classes.php"); | ||||
|     session_start(); | ||||
|     $currentGrid = strip_tags($_GET['grid']); | ||||
|     $_SESSION["currentGrid"] = $currentGrid; | ||||
|  | ||||
|     if (!in_array($currentGrid, $validGrids)) { | ||||
|         $grid = new Grid(); | ||||
|         $grid->import($currentGrid); | ||||
|         if ($grid->containsDuplicates()) { | ||||
|             $warning = "Cette grille contient des doublons."; | ||||
|         } else { | ||||
|             switch($grid->countSolutions(2)) { | ||||
|                 case 0: | ||||
|                     $warning = "Cette grille n'a pas de solution."; | ||||
|                     break; | ||||
|                 case 1: | ||||
|                     $validGrids[] = $currentGrid; | ||||
|                     break; | ||||
|                 default: | ||||
|                     $warning = "Cette grille a plusieurs solutions."; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| ?> | ||||
| <!DOCTYPE html> | ||||
| <html lang='fr' prefix="og: https://ogp.me/ns#"> | ||||
|  | ||||
|     <head> | ||||
|         <meta charset='utf-8' /> | ||||
|         <meta name='viewport' content='width=device-width' /> | ||||
|         <title>Sudoku</title> | ||||
|         <link rel='stylesheet' type='text/css' href='style.css' /> | ||||
|         <script src='sudoku.js'></script> | ||||
|         <link rel="apple-touch-icon" href="thumbnail.php?size=57"  sizes="57x57"> | ||||
|         <link rel="apple-touch-icon" href="thumbnail.php?size=114" sizes="114x114"> | ||||
|         <link rel="apple-touch-icon" href="thumbnail.php?size=72"  sizes="72x72"> | ||||
|         <link rel="apple-touch-icon" href="thumbnail.php?size=144" sizes="144x144"> | ||||
|         <link rel="apple-touch-icon" href="thumbnail.php?size=60"  sizes="60x60"> | ||||
|         <link rel="apple-touch-icon" href="thumbnail.php?size=120" sizes="120x120"> | ||||
|         <link rel="apple-touch-icon" href="thumbnail.php?size=76"  sizes="76x76"> | ||||
|         <link rel="apple-touch-icon" href="thumbnail.php?size=152" sizes="152x152"> | ||||
|         <link rel="icon" type="image/png" href="thumbnail.php?size=196" sizes="196x196"> | ||||
|         <link rel="icon" type="image/png" href="thumbnail.php?size=160" sizes="160x160"> | ||||
|         <link rel="icon" type="image/png" href="thumbnail.php?size=96"  sizes="96x96"> | ||||
|         <link rel="icon" type="image/png" href="thumbnail.php?size=16"  sizes="16x16"> | ||||
|         <link rel="icon" type="image/png" href="thumbnail.php?size=32"  sizes="32x32"> | ||||
|         <link rel="manifest" href="manifest.php"> | ||||
|         <meta property="og:title" content="Sudoku"/> | ||||
|         <meta property="og:type" content="website"/> | ||||
|         <meta property="og:url" content="<?=$_SERVER["REQUEST_SCHEME"]."://".$_SERVER["HTTP_HOST"].$_SERVER["DOCUMENT_URI"]?>"/> | ||||
|         <meta property="og:image" content="<?=$_SERVER["REQUEST_SCHEME"]."://".$_SERVER["HTTP_HOST"].dirname($_SERVER["DOCUMENT_URI"])?>/thumbnail.php?size=200"/> | ||||
|         <meta property="og:image:width" content="200"/> | ||||
|         <meta property="og:image:height" content="200"/> | ||||
|         <meta property="og:description" content="Remplissez la grille de sorte que chaque ligne, colonne et région (carré de 3×3 cases) contienne tous les chiffres de 1 à 9."/> | ||||
|         <meta property="og:locale" content="fr_FR"/> | ||||
| 		<meta property="og:site_name" content="<?=$_SERVER["HTTP_HOST"]?>"/> | ||||
|         <?php require_once("head.php") ?> | ||||
|     </head> | ||||
|  | ||||
|     <body> | ||||
|         <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 class='toolBar'> | ||||
|             <div class='radioGroup'> | ||||
|                 <input type='radio' id='inkPenRadio' name='tool' checked /><label for='inkPenRadio' | ||||
|                     title='Écrire un chiffre'><i class="ri-ball-pen-fill"></i></label> | ||||
|                 <input type='radio' id='pencilRadio' name='tool' /><label for='pencilRadio' title='Prendre des notes'><i | ||||
|                         class="ri-pencil-fill"></i></label> | ||||
|                 <input type='radio' id='eraserRadio' name='tool' '/><label for='eraserRadio' | ||||
|                     title='Effacer une case'><i class="ri-eraser-fill"></i></label> | ||||
|             </div> | ||||
|         </section> | ||||
|             <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é'><i | ||||
|                     class="ri-mark-pen-fill"></i></label> | ||||
|             <button id="hintButton" type="button" onclick="showHint()" title="Afficher un indice" accesskey="H" | ||||
|                 disabled=""><i class="ri-lightbulb-flash-fill"></i></button> | ||||
|             <button id='restartButton' type='button' class='warning' onclick='restart()' disabled title='Recommencer'><i | ||||
|                     class="ri-restart-fill"></i></button> | ||||
|             <button id='undoButton' type='button' onclick='undo()' disabled title='Annuler' accesskey='Z'><i | ||||
|                     class="ri-arrow-go-back-fill"></i></button> | ||||
|             <button id='saveButton' type='button' onclick='save()' disabled title='Sauvegarder' accesskey='S'><i | ||||
|                     class="ri-save-3-fill"></i></button> | ||||
|         </div> | ||||
|         <form id='sudokuForm'> | ||||
|             <table id='grid' class='grid'> | ||||
|                 <tbody> | ||||
| <?php | ||||
|         for ($row = 0; $row < 9; $row++) { | ||||
|                     <?php | ||||
|         for ($row = 0; $row < 81; $row += 9) { | ||||
| ?> | ||||
|                     <tr> | ||||
| <?php | ||||
|                         <?php | ||||
|         for ($column = 0; $column < 9; $column++) { | ||||
|             $value = $currentGrid[9*$row+$column]; | ||||
|             $value = $currentGrid[$row+$column]; | ||||
|             if ($value == UNKNOWN) { | ||||
| ?> | ||||
|                         <td><input type='number' min='1' max='9' step='1' value='' title='Valeurs possibles [Clic-droit]'/></td> | ||||
| <?php | ||||
|                         <td><input type='number' min='1' max='9' step='1' value='' | ||||
|                                 title='Valeurs possibles [Clic-droit]' /></td> | ||||
|                         <?php | ||||
|                 } else { | ||||
| ?> | ||||
|                         <td><input type='number' min='1' max='9' step='1' value='<?=$value?>' disabled/></td> | ||||
| <?php | ||||
|                         <td><input type='number' min='1' max='9' step='1' value='<?=$value?>' disabled /></td> | ||||
|                         <?php | ||||
|             }                                                             | ||||
|         } | ||||
| ?> | ||||
|                     </tr> | ||||
| <?php | ||||
|                     <?php | ||||
|    } | ||||
| ?> | ||||
|                 </tbody> | ||||
|             </table> | ||||
|         </form> | ||||
|         <section class='tools'> | ||||
|             <div id='insertRadioGroup' class='insertRadioGroup'> | ||||
| <?php | ||||
|         <div class='toolBar'> | ||||
|             <div id='insertRadioGroup' class='radioGroup'> | ||||
|                 <?php | ||||
|         for($value=1; $value<=9; $value++) { | ||||
|             echo "                <input type='radio' id='insertRadio$value' value='$value' name='insertRadioGroup' onclick='insert(this)' accesskey='$value'/><label for='insertRadio$value' title='Insérer un $value'>$value</label>\n"; | ||||
|         } | ||||
| ?> | ||||
|             </div> | ||||
|         </section> | ||||
|         <section> | ||||
| <?php | ||||
|         </div> | ||||
|         <div> | ||||
|             <?php | ||||
|     if (isset($warning)) | ||||
|         echo("            <strong>⚠️ $warning ⚠️</strong><br/>\n"); | ||||
|     else | ||||
|         echo("            Remplissez la grille de sorte que chaque ligne, colonne et région (carré de 3×3 cases) contienne tous les chiffres de 1 à 9.\n") | ||||
| ?> | ||||
|         </section> | ||||
|         </div> | ||||
|         <ul id='contextMenu' class='context-menu'></ul> | ||||
|         <footer> | ||||
|             <div id='links'> | ||||
|                 <a href=''>Lien vers cette grille</a><br/> | ||||
|                 <a href='.'>Nouvelle grille</a><br/> | ||||
|                 <a href='.................................................................................'>Grille vierge</a><br/> | ||||
|                 <a href='' id='fixGridLink'>Figer cette grille</a> | ||||
|                  | ||||
|             </div> | ||||
|             <div class='credits'> | ||||
|                 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> | ||||
|                 <a href='.'>Nouvelle grille</a> | ||||
|                 <a href=''>Lien vers cette grille</a> | ||||
|                 <a href='?.................................................................................'>Grille | ||||
|                     vierge</a> | ||||
|                 <a href='' id='fixGridLink'>Figer la grille enregistrée</a> | ||||
|             </div> | ||||
|         </footer> | ||||
|     </body> | ||||
| </html> | ||||
|  | ||||
| </html> | ||||
| @ -14,10 +14,11 @@ | ||||
|     $thumbnail = imagecreate($size, $size); | ||||
|     $transparent = imagecolorallocate($thumbnail, 1, 1, 1); | ||||
|     imagecolortransparent($thumbnail, $transparent); | ||||
|     $black = imagecolorallocate($thumbnail, 85, 91, 110); | ||||
|     $grey = imagecolorallocate($thumbnail, 85, 91, 110); | ||||
|     $blue = imagecolorallocate($thumbnail, 96, 210, 203); | ||||
|     $white = imagecolorallocate($thumbnail, 247, 255, 247); | ||||
|     $darkerBorder = imagecolorallocate($thumbnail, 150, 155, 160); | ||||
|     $lighterBorder = imagecolorallocate($thumbnail, 210, 225, 230); | ||||
|     $emptyBoxBC = imagecolorallocate($thumbnail, 255, 255, 255); | ||||
|     $clueBC = imagecolorallocate($thumbnail, 255, 255, 255); | ||||
|     $clueFC = imagecolorallocate($thumbnail, 150, 155, 160); | ||||
|      | ||||
|     if ($size <= 36) { | ||||
|         $boxSize = floor(($size-4) / 9); | ||||
| @ -27,8 +28,8 @@ | ||||
|         $lineStart = $start + 1; | ||||
|         $lineEnd = $end - 2; | ||||
|         for ($i = $start; $i < $end; $i += 3*$boxSize + 1) { | ||||
|             ImageLine($thumbnail,  $lineStart,  $i, $lineEnd,  $i, $black); | ||||
|             ImageLine($thumbnail,  $i,  $lineStart,  $i, $lineEnd, $black); | ||||
|             ImageLine($thumbnail,  $lineStart,  $i, $lineEnd,  $i, $darkerBorder); | ||||
|             ImageLine($thumbnail,  $i,  $lineStart,  $i, $lineEnd, $darkerBorder); | ||||
|         } | ||||
|         $x = $start; | ||||
|         $y = $start; | ||||
| @ -37,9 +38,9 @@ | ||||
|             if ($i % 3 == 0) $x++; | ||||
|             if ($i % 27 == 0) $y++; | ||||
|             if ($value == UNKNOWN) { | ||||
|                 $bgColor = $white; | ||||
|                 $bgColor = $emptyBoxBC; | ||||
|             } else { | ||||
|                 $bgColor = $blue; | ||||
|                 $bgColor = $clueFC; | ||||
|             } | ||||
|             imagefilledrectangle($thumbnail, $x, $y, $x+$boxSizeMinusOne, $y+$boxSizeMinusOne, $bgColor); | ||||
|             $x += $boxSize; | ||||
| @ -56,21 +57,21 @@ | ||||
|         $lineStart = $start + 1; | ||||
|         $lineEnd = $end - 2; | ||||
|         for ($i = $start + $boxSize; $i < $end - $boxSize; $i += $boxSize) { | ||||
|             ImageLine($thumbnail,  $lineStart,  $i, $lineEnd,  $i, $grey); | ||||
|             ImageLine($thumbnail,  $i,  $lineStart,  $i, $lineEnd, $grey); | ||||
|             ImageLine($thumbnail,  $lineStart,  $i, $lineEnd,  $i, $lighterBorder); | ||||
|             ImageLine($thumbnail,  $i,  $lineStart,  $i, $lineEnd, $lighterBorder); | ||||
|         } | ||||
|         for ($i = $start; $i < $end; $i += 3*$boxSize) { | ||||
|             ImageLine($thumbnail,  $lineStart,  $i, $lineEnd,  $i, $black); | ||||
|             ImageLine($thumbnail,  $i,  $lineStart,  $i, $lineEnd, $black); | ||||
|             ImageLine($thumbnail,  $lineStart,  $i, $lineEnd,  $i, $darkerBorder); | ||||
|             ImageLine($thumbnail,  $i,  $lineStart,  $i, $lineEnd, $darkerBorder); | ||||
|         } | ||||
|         $x = $start + 1; | ||||
|         $y = $start + 1; | ||||
|         $boxSizeMinusTwo = $boxSize - 2; | ||||
|         foreach(str_split($currentGrid) as $i => $value) { | ||||
|             if ($value == UNKNOWN) { | ||||
|                 $bgColor = $white; | ||||
|                 $bgColor = $emptyBoxBC; | ||||
|             } else { | ||||
|                 $bgColor = $blue; | ||||
|                 $bgColor = $clueFC; | ||||
|             } | ||||
|             imagefilledrectangle($thumbnail, $x, $y, $x+$boxSizeMinusTwo, $y+$boxSizeMinusTwo, $bgColor); | ||||
|             $x += $boxSize; | ||||
| @ -89,26 +90,26 @@ | ||||
|         $fontSize = floor($boxSize/2) - 4; | ||||
|         $fdx = floor(($boxSize - imagefontwidth($fontSize)) / 2); | ||||
|         $fdy = ceil(($boxSize - imagefontheight($fontSize)) / 2) - 1; | ||||
|         $fontColor = $white; | ||||
|         $fontColor = $emptyBoxBC; | ||||
|         for ($i = $start + $boxSize; $i < $end - $boxSize; $i += $boxSize) { | ||||
|             ImageLine($thumbnail,  $lineStart,  $i, $lineEnd,  $i, $grey); | ||||
|             ImageLine($thumbnail,  $i,  $lineStart,  $i, $lineEnd, $grey); | ||||
|             ImageLine($thumbnail,  $lineStart,  $i, $lineEnd,  $i, $lighterBorder); | ||||
|             ImageLine($thumbnail,  $i,  $lineStart,  $i, $lineEnd, $lighterBorder); | ||||
|         } | ||||
|         for ($i = $start; $i < $end; $i += 3*$boxSize) { | ||||
|             ImageLine($thumbnail,  $lineStart,  $i, $lineEnd,  $i, $black); | ||||
|             ImageLine($thumbnail,  $i,  $lineStart,  $i, $lineEnd, $black); | ||||
|             ImageLine($thumbnail,  $lineStart,  $i, $lineEnd,  $i, $darkerBorder); | ||||
|             ImageLine($thumbnail,  $i,  $lineStart,  $i, $lineEnd, $darkerBorder); | ||||
|         } | ||||
|         $x = $start + 1; | ||||
|         $y = $start + 1; | ||||
|         $boxSizeMinusTwo = $boxSize - 2; | ||||
|         foreach(str_split($currentGrid) as $i => $value) { | ||||
|             if ($value == UNKNOWN) { | ||||
|                 $bgColor = $white; | ||||
|                 $bgColor = $emptyBoxBC; | ||||
|             } else { | ||||
|                 $bgColor = $blue; | ||||
|                 $bgColor = $clueBC; | ||||
|             } | ||||
|             imagefilledrectangle($thumbnail, $x, $y, $x+$boxSizeMinusTwo, $y+$boxSizeMinusTwo, $bgColor); | ||||
|             if ($value != UNKNOWN) imagestring($thumbnail, $fontSize, $x + $fdx, $y + $fdy, $value, $fontColor); | ||||
|             if ($value != UNKNOWN) imagestring($thumbnail, $fontSize, $x + $fdx, $y + $fdy, $value, $clueFC); | ||||
|             $x += $boxSize; | ||||
|             if ($i % 9 == 8) { | ||||
|                 $y += $boxSize; | ||||
|  | ||||