Zum Rätsel springen
Neulich kam mir eine Erinnerung an ein kleines Puzzlespielzeug aus meiner Kindheit in den Sinn, ein Schiebepuzzle, bei dem 15 quadratische Kacheln in einem Rahmen in einer 4 x 4-Anordnung von Zellen angeordnet sind, so dass ein freier Raum bleibt. Eine Reihe von Rippen und Rillen an den Kanten jeder Fliese und des Rahmens ermöglichen, dass die Fliesen aneinander vorbeigleiten und gleichzeitig die Fliesen im Rahmen halten. Zu jedem beliebigen Zeitpunkt kann jedes an das freie Feld angrenzende Plättchen in dieses Feld verschoben werden, andernfalls wird die Bewegung der Plättchen verhindert. Durch das Verschieben eines Plättchens in das freie Feld entsteht dort, wo das Plättchen herkam, ein neues freies Feld, und ein anderes Plättchen kann dann in dieses neue Feld verschoben werden. Die Idee besteht darin, durch wiederholtes Verschieben der Kacheln auf diese Weise die Kacheln in einer vorgegebenen Reihenfolge anzuordnen.
Anscheinend nennt man das „15-Puzzle“ und es gibt es schon seit den 1870er Jahren. Beim Durchsuchen des Webs werden eine Reihe von Nachbildungen gefunden, die in verschiedenen Programmiersprachen geschrieben wurden, und tatsächlich gibt es hier auf dev.to mehrere Artikel, darunter https://dev.to/artydev/let-us-code-a-sliding-puzzle-9n , https://dev.to/xzanderzone/making-a-slider-puzzle-in-java-script-83m und https://dev.to/claurcia/slide-puzzle-5c55, alle in JavaScript und https:/ /dev.to/mfbmina/building-a-sliding-puzzle-with-go-3bnj in Go. Es stellt auch eine gute Einstiegsherausforderung für diejenigen dar, die JavaScript lernen.
Was mein Interesse jedoch geweckt hat, war die Idee, dass es im Web ganz ohne Programmiersprache nachbildbar sein sollte! Das heißt, eine Implementierung, die nur reines HTML und CSS verwendet. Deshalb stelle ich es unten vor. Der einzige Kompromiss, den ich eingehen musste, war, dass die 10 bereitgestellten Spiele feste, vorab gemischte Startpositionen haben.
Hierfür ist die vorgegebene Reihenfolge, ein fertiges Bild anzuzeigen.
Das Grundprinzip dieser Implementierung besteht darin, dass jede Kachel einen Zustandsdatensatz darüber behält, wo sie sich innerhalb des Rahmens befindet. Es gibt nicht viele Möglichkeiten, den Status in HTML und CSS zu ändern und beizubehalten, aber die häufigste ist der „Checkbox-Hack“, und diese Implementierung nutzt ihn intensiv. Für alle, die mit dem Checkbox-Hack nicht vertraut sind: Wenn auf ein
Jede Kachel verfügt also über ein Paar Optionsfeldgruppen mit jeweils vier Optionsfeldern. Eine dieser Gruppen behält die Position der Kachel auf der X-Achse und die andere ihre Position auf der Y-Achse. (Oder horizontale bzw. vertikale Position, wenn Sie es vorziehen.) Den fünfzehn Kacheln wird zunächst über ihre Optionsfelder jeweils eine andere Kombination aus X- und Y-Koordinaten zugewiesen, sodass jede Kachel eine andere Zelle im Rahmen einnimmt.
Die Kacheln werden zunächst in der oberen, linken Zelle des Rahmens platziert und dann innerhalb des Rahmens verschoben, indem CSS den Zustand der Optionsfelder misst, indem eine Übersetzungstransformation auf sie angewendet wird:
/* "X" refers to the X-axis cell positions, "Y" to the Y-axis cell positions. * 0, 1, 2, 3 refers to the position on that axis, * 0 = left and top, 3 = right and bottom respectively. */ .tile:has(.X0:checked~.Y0:checked) { transform: translate(0%, 0%); } .tile:has(.X0:checked~.Y1:checked) { transform: translate(0%, 100%); } .tile:has(.X0:checked~.Y2:checked) { transform: translate(0%, 200%); } .tile:has(.X0:checked~.Y3:checked) { transform: translate(0%, 300%); } .tile:has(.X1:checked~.Y0:checked) { transform: translate(100%, 0%); } /* and so on for the remainder of the sixteen combinations */
Die Kachel enthält dann auch acht Beschriftungselemente, entsprechend den acht Optionsfeldern. Jedes Etikett liegt absolut übereinander und füllt die Kachel vollständig aus. Die Beschriftungen sind transparent und zunächst so eingerichtet, dass sie nicht auf Klicks und Tippen reagieren, indem für alle von ihnen pointer-events:none festgelegt wird.
Der nächste Schritt besteht darin, dass die CSS-Selektoren identifizieren, wo sich die leere Zelle befindet. Dies erfolgt durch Eliminierung. Es handelt sich um die Zelle, deren X- und Y-Koordinaten nicht durch das Optionsfeldgruppenpaar einer der fünfzehn Kacheln dargestellt werden.
Wenn dies beispielsweise übereinstimmt:
.frame:not(:has(.tile .X0:checked~.Y0:checked)) { .... }
Dann muss sich die leere Zelle derzeit in der oberen linken Eckzelle befinden. Wiederholen Sie dies für jede der sechzehn Zellen und genau eine davon wird übereinstimmen.
Sobald dies erledigt ist, können die Zellen neben der leeren Zelle identifiziert werden. Befindet sich die leere Zelle in einer Ecke, können genau zwei Kacheln in diese Zelle verschoben werden. Wenn sich die leere Zelle andernfalls an einer der Seiten des Rahmens befindet, können drei Kacheln in die Zelle verschoben werden, andernfalls die leere Die Zelle muss eine der vier mittleren Zellen sein und es gibt vier Kacheln, die dorthin verschoben werden können. Für jede dieser Kacheln aktiviert genau eine der acht Beschriftungen der Kacheln das richtige Optionsfeld, das zum Verschieben der Kachel in die leere Zelle erforderlich ist. Diese Bezeichnung wird aktiviert, indem der Wert von itspointer-events wieder auf auto gesetzt wird. Also als Beispiele:
/* Top, left corner */ .frame:not(:has(.tile .X0:checked ~ .Y0:checked)) { :is( .tile:has(.X0:checked ~ .Y1:checked) label.Y0, .tile:has(.X1:checked ~ .Y0:checked) label.X0 ) { pointer-events: auto; } } /* right most cell of row two */ .frame:not(:has(.tile .X1:checked ~ .Y3:checked)) { :is( .tile:has(.X1:checked ~ .Y2:checked) label.Y3, .tile:has(.X0:checked ~ .Y3:checked) label.X1, .tile:has(.X2:checked ~ .Y3:checked) label.X1 ) { pointer-events: auto; } } /* second cell from left on row three */ .frame:not(:has(.tile .X2:checked ~ .Y1:checked)) { :is( .tile:has(.X2:checked ~ .Y0:checked) label.Y1, .tile:has(.X2:checked ~ .Y2:checked) label.Y1, .tile:has(.X1:checked ~ .Y1:checked) label.X2, .tile:has(.X3:checked ~ .Y1:checked) label.X2 ) { pointer-events: auto; } }
Der letzte Schritt des Spiels besteht darin, festzustellen, wann das Rätsel gelöst ist. Dabei geht es lediglich darum, zu überprüfen, ob bei allen 15 Kacheln die erwarteten Optionsfelder für die X- und Y-Achse auf die „gelöste“ Position eingestellt sind.
/* Each tile is assigned a letter "a" to "o". * The puzzle is solved when the tiles are in alphabetical order * reading left to right and top to bottom */ .frame:has(.a .X0:checked ~ .Y0:checked):has(.b .X1:checked ~ .Y0:checked):has( .c .X2:checked ~ .Y0:checked ):has(.d .X3:checked ~ .Y0:checked):has(.e .X0:checked ~ .Y1:checked):has( .f .X1:checked ~ .Y1:checked ):has(.g .X2:checked ~ .Y1:checked):has(.h .X3:checked ~ .Y1:checked):has( .i .X0:checked ~ .Y2:checked ):has(.j .X1:checked ~ .Y2:checked):has(.k .X2:checked ~ .Y2:checked):has( .l .X3:checked ~ .Y2:checked ):has(.m .X0:checked ~ .Y3:checked):has(.n .X1:checked ~ .Y3:checked):has( .o .X2:checked ~ .Y3:checked ) ~ .options .success { display: block; }
Der Rest ist kosmetischer Natur. Das Gleiten erfolgt mit einem einfachen Übergang der oben beschriebenen Transformation
.tile { transition: 0.5s transform; @media (prefers-reduced-motion) { transition: none; } }
und jede Kachel zeigt einen Teil des Spielbildes unter Verwendung von Hintergrundgröße und Hintergrundposition
.tile { background-size: 400%; } #board1 .tile { background-image: url("https://alohci.net/image/dev.to/slidergame/mullermarc-k7bQqdUf954-unsplash.webp"); } .a { background-position: 0% 0%; } .b { background-position: 33.333% 0%; } .c { background-position: 66.667% 0%; } .d { background-position: 100% 0%; } .e { background-position: 0% 33.333%; } /* and so on for the remaining tiles */
Und es gibt einen einzigen Satz Optionsfelder, mit denen Sie auswählen können, welches der zehn Spiele gespielt werden soll.
Um das Spiel zu spielen, klicken oder tippen Sie einfach auf die Kachel, die Sie in die leere Zelle verschieben möchten.
Ich habe auch einen „Barebones“-Modus bereitgestellt, um die Kachelbuchstaben und Optionsfelder anzuzeigen, die zum Verständnis der Funktionsweise von HTML und CSS beitragen könnten.
Hier ist also das fertige Puzzlespiel. Bitte teilen Sie mir Ihr Feedback mit.
Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.
Copyright© 2022 湘ICP备2022001581号-3