Heim > Web-Frontend > CSS-Tutorial > Erzeugen (und Lösung!) Sudokus in CSS

Erzeugen (und Lösung!) Sudokus in CSS

尊渡假赌尊渡假赌尊渡假赌
Freigeben: 2025-03-25 09:49:16
Original
263 Leute haben es durchsucht

Erzeugen (und Lösung!) Sudokus in CSS

Ich liebe es, CSS zu machen, was es nicht tun sollte. Es ist die Art von Problemlösungs-Gehirntraining, die Sie in Minecraft einen Taschenrechner erstellen würden, außer dass Sie wahrscheinlich keine Arbeit mit Minecraft Redstone bekommen, egal wie gut Sie darauf gelangen, während CSS-Fähigkeiten tatsächlich Geld wert sind und viele Generalistenprogrammierer vor CSS ängstlich sind. Wenn Sie das Unmögliche mit CSS erledigt haben, scheinen alle normalen CSS -Aufgaben einfach zu sein.

Ich habe interessante Diskussionen im Web gelesen, ob CSS eine vollständige Sprache ist und ob CSS und HTML als Programmiersprachen gilt. Ich habe mich nicht entschieden, aber ich kann sagen, dass einige der neueren CSS auf der Suche nach allgemeinen UI -Mustern auf standardmäßige Weise die Grenze zwischen Styling und Funktionalität verwischen.

Wenn wir uns herausfordern, logische Probleme mit nur CSS und HTML zu lösen, können wir uns dazu zwingen, Zeit mit einigen der neuesten, programmierungsähnlichen Funktionen von CSS wie benutzerdefinierten Eigenschaften und logischen Funktionen zu verbringen. Es war immer noch nicht klar, wie diese verwendet werden konnten, um einen Sudoku-Solver mit nur CSS zu erstellen, aber so verrückt die Idee auch klang, schien die Einschränkungslogik von Sudoku so zu sein, dass sie mit der deklarativen Natur von CSS kompatibel sein könnte, daher war ich nicht schockiert, jemanden zu finden, der behauptete, ein „CSS3-Sudoku-Lösungs-Solver“ aufgebaut zu haben. Wie sich herausstellte, war dies eher ein Sudoku -Validator in CSS als ein Löser. Es wurde auch ein kleines Stück JavaScript verwendet, um mit Textboxen zu arbeiten.

Nach Tagen, in denen ich versuchte, einen vollständigen Sudoku -Solver und eine Generator -App in reinem CSS zu erstellen, lernte ich drei Dinge.

  1. Sie können Einheitstests -Sass -Funktionen und Mixins, was fantastisch ist. Wenn Sie diese SASS-Funktionen stark verwenden und wiederverwenden, für die sie bestimmt sind, werden sie so missionskritisch und beängstigend, sich zu ändern wie ein anderer Teil Ihrer Codebasis. Sie verdienen Tests um sie herum.
  2. Chrome Devtools zeigt einen unendlichen Spinner des Todes, wenn Sie 50 MB Sass-generierte CSS darauf werfen.
  3. Vielleicht ist es unmöglich, so etwas wie dieses Python -Skript in reine CSS zu übersetzen. Vielleicht.

Wir können jedoch eine Sudoku Solver und Generator App für 16 Quadratmeter Sudoku erreichen, mit der Sie unten spielen können. Dann werden wir die Funktionsweise der Funktionen aufschlüsseln. Wo ist dein Gott jetzt, einfaches Puzzle für kleine Kinder?

Der Wertwählte

Da wir mit CSS experimentieren, sind wir vertraglich verpflichtet, etwas visuell Interessantes aufzunehmen, obwohl nichts zu übertrieben als Sudoku-Spieler eine Benutzeroberfläche zu schätzen scheinen, die aus dem Weg bleibt. Meiner Meinung nach könnte die Art und Weise, wie Sie Zahlen in einigen der Sudoku -Apps auswählen, intuitiver sein. Daher habe ich beschlossen, das UI -Muster des radialen Menüs anzuwenden, das bis zu den Tagen des Schwarz -Weiß -Macintosh ausgeht und in modernen Videospielen immer noch beliebt ist. Jemand hat tatsächlich eine schöne reine CSS -Bibliothek für Radialmenüs gebaut, aber ich habe mich in React Planet verknallt, da ich die Art und Weise, wie er sowohl einen Gegenstand mit dem Kreis um ihn herum ausgewählt hat als auch die Art und Weise, wie er die verfügbaren Aktionen attraktiv zeigt, erfasst. Ich wollte sehen, ob ich einen ähnlichen Effekt mit nur CSS aufbauen könnte.

Ich nahm einen Teil des gestrichelten Kreiscode aus diesem Stift und machte die Zahlen mit dem alten Border-Radius: 50% Trick aus Etiketten. Dann habe ich die absolute Positionierung verwendet, um die Zahlen „kleben“ auf den richtigen Punkt auf dem gestrichelten Kreis zu machen, selbst wenn die Animation die Größe änderte.

 .Context .number.top {
  Hintergrund: grün;
  Rand-Links: Auto;
  Margin-Right: Auto;
  links: 0;
  Rechts: 0;
  Oben: -12,5px;
}

.Context .number.left {
  Hintergrund: Orange;
  Rand: Auto;
  Randboden: Auto;
  Top: 0;
  unten: 0;
  links: -12,5px;
}
Nach dem Login kopieren

Die Animation verblasst den Zahlen-Picker, während sie seinen Z-Index höher macht, damit er anklickbar wird. Wir animieren auch die obere und linke Marge von 50% auf Null, sodass sich der Kreis aus der Mitte ausdehnt, um den verfügbaren Speicherplatz zu füllen.

 @KeyFrames springen aus {
  0% {
    Z -Index: -1;
    Breite: 35%;
    Höhe: 35%;
    Margin-Links: 50%;
    Marge-Top: 50%;
    Deckkraft: 0;
  }
  100% {
    Z-Index: 2;
    Deckkraft: 1;
    Breite: var (-Kreisradius);
    Höhe: var (-Kreisradius);
  }
}
Nach dem Login kopieren

Um die Bouncy Physics ähnlich wie React Planet zu simulieren, verwende ich eine Kubik-Bezier () -Funktion auf der Animation. Die Website sacessings.net war eine große Hilfe, um die Lockerungsfunktionen einfach zu machen.

 .Context {
  Animation: Bounce-out Cubic-Bezier (.68, -0,6, .32, 2,5) .5s Forwards;        
}
Nach dem Login kopieren

Sowohl die Auswahl der Werte als auch das Verhalten des Öffnens des Wertschiffes für das ausgewählte Quadrat, der mit Optionsknopf -Hacks arbeitet, um sich zu beachten, welche Werte ausgewählt wurden, und gegenseitige Exklusivität zu erreichen. CSS-Tricks verfügt über einen hervorragenden Artikel über Kontrollkästchen und Optionsknopf-Hacks. Daher werde ich diese Informationen hier nicht wiederholen, aber ich werde zeigen, wie wir CSS-Variablen auf der Ebene des Sudoku CSS-Gitters basierend auf Kontrollkästchen festlegen, da es für die Art und Weise, wie dieses Experiment funktioniert, von zentraler Bedeutung ist.

Da wir Variablen verwenden, können wir das gleiche Verhalten erhalten, wenn ein Wert festgelegt wird, unabhängig davon, ob es sich bei dem Benutzer um ein Feld handelt, um einen Wert anzugeben, oder der Puzzlegenerator für das Quadrat denselben Wert. Es gibt viele Kombinationen von Quadraten und Werten, daher verwenden wir SASS, anstatt alle Kombinationen von Hand zu schreiben. Wir erstellen auch separate Bitwerte für jede Wertquadrat-Kombination und eine andere benutzerdefinierte Eigenschaft, um uns mitzuteilen, ob das Quadrat ungelöst ist. Das liegt daran, dass CSS uns eingeschränkt in der Lage ist, einen Wert mit einem anderen zu vergleichen (es ist möglich, aber schwierig sein kann). Wir definieren diese Werte auf eine Weise, die zuerst etwas seltsam aussieht, aber es wird uns das Leben leichter machen, wenn es darum geht, zu validieren, ob ein Satz von Sudoku -Quadratwerten lösbar ist oder nicht.

 @Für $ i von 1 bis 16 {
  @Für $ j von 1 bis 4 {
    #Select-#{$ J} -Value-Quadrat-#{$ I}: Checked ~ .sudoku {
       -Square-#{$ i} -Nsolved: 0; 
       -Square-#{$ i} -äquals-#{$ j}: 1;
    }
  }
}
Nach dem Login kopieren

Validierung des Netzes

Doktor Google sagt uns, dass es auch mit nur 16 Quadraten vier Milliarden mögliche Kombinationen von vier Zahlen gibt. Ein Programm, das alle diese Kombinationen erzwingen und diejenigen ausgeben, die gemäß den Regeln von Sudoku gültig sind, zeigt, dass es in 4 × 4 Sudoku nur 288 gültige Lösungen gibt. Dies ist ein großer Unterschied zu der Anzahl der möglichen gültigen Lösungen in einem 9 × 9 -Gitter. Mit nur 288 möglichen Lösungen kann Sass wirklich für sich selbst kommen. Ich bin mir immer noch nicht sicher, ob CSS eine vollständige Sprache ist, aber Sass ist es, und es gibt uns einige geeignete Datenstrukturen, wie z. B. Listen. Mit ein bisschen Regex-Magie können wir die Liste der gültigen 4 × 4-Rätsel in eine zweidimensionale Liste mit Sass-betrieben verwandeln!

 $solutions: ((1,2,3,4,3,4,1,2,2,1,4,3,4,3,2,1),(3,1,2,4,2,4,1,3,1,3,4,2,4,2,3,1),(1,2,3,4,3,4,1,2,2,3,4,1,4,1,2,3),/*...many lines Später ...*/(2,4,3,1,3,1,4,2,4,2,1,3,1,3,2,4), (4,3,2,1,2,1,4,3,3,4,4,2,1,2,3,4));
Nach dem Login kopieren

Süß! Wenn unser CSS-Hack eine mehrstufige Anwendung wäre, wäre dies unsere Datenbank. Die Validierung hätte den gleichen Ansatz für die Überprüfung von Zeilen- und Spaltenwerten wie den 9 × 9 -Validator verwenden können, den wir in der Einführung gesehen haben, aber da wir die Antwort wissen, sollten wir uns nicht die Mühe machen, Blöcke und Spalten und Zeilen zu überprüfen. Stattdessen können wir überprüfen, ob die eingegebenen Nummern noch ein gültiges Rätsel sein könnten oder nicht. In Pseudocode könnte dies so aussehen wie:

 foreach (s in Quadraten) 
{
  if (Solutionscontains (s.value, S.Intex) oder S.Isunsalved ())
  {
    showValidationError ();
  } 
}
Nach dem Login kopieren

Denken Sie daran, dass wir diese seltsamen Variablen erstellt haben, wenn ein quadratischer Wert ausgewählt wird?

 -Square-#{$ i} -Nsolved: 0;        
-Square-#{$ i} -äquals-#{$ j}: 1;
Nach dem Login kopieren

Jetzt haben wir also Antworten auf beide Fragen in der Bedingung in Zeile 3 des Pseudocode oben, aber wie können wir einen logischen oder Operator in CSS durchführen? Es gibt einen großartigen Artikel über CSS-Tricks über die Verwendung von Calc (), um Logikoperatoren in CSS zu simulieren, und ich bin mir nicht sicher, ob ich ohne sie an einen Teil des Code in meinem Sudoku-Solver gedacht hätte, aber einige der in diesem Artikel erklärten Formeln werden etwas unhandlich, insbesondere wenn Sie sich verhindern möchten, und und ORS mit mehr als zwei Operanden. Zum Beispiel brauchen wir das CSS -Äquivalent dieses Pseudocode:

 if (SquareOneEqualsone und Squaretwoequalstwo /*...*/ und SquaresIXteenequalsone) oder (SquareOneEqualsone und SquaretwoequalsThree /*...*/ und SquaresixteenQualsone)))
  {
    sudokuisvalid ();
  } 
}
Nach dem Login kopieren

Nun, dieser Artikel, der zeigt, wie man mit Calc () Logik macht, wurde 2019 geschrieben. Heutzutage haben wir zusätzlich zu Calc () die gut unterstützten Min () und Max () Mathematikfunktionen, die unseren Bedürfnissen noch besser entsprechen. Wenn Sie "CSS min, max und klemmen" (der letzte davon nur bequemer Zucker für eine Kombination von min () und max ()) sind, dass viele Beispiele zeigen, wie sie verwendet werden können, um die Fluid -Typografie zu vereinfachen. Das ist ein überzeugender Anwendungsfall, aber Sie können diese Mathematikfunktionen überall überall verwenden, wo Sie eine Nummer verwenden würden, die CSS viel Kraft verleiht. Wenn Sie beispielsweise Bit -Flag -Variablen an CSS min () übergeben, entspricht dies und. Wenn Sie dieselben Flags an CSS max () übergeben, entspricht dies oder. Wir können dies mit den folgenden Wahrheitstabellen beweisen.

Wir können damit ziemlich raffiniert werden, insbesondere wenn Sie die hilfreiche Tatsache hinzufügen, dass wir alles tun dürfen, was Calc () innerhalb von min () und max () tun kann. CSS trat nur einen Schritt näher daran, seine eigene seltsame Skriptsprache zu sein. Jetzt können wir die Bedingung in unserem Validierungs -Pseudocode oben in CSS implementieren. (In der Praxis generieren wir dies von SASS, da es sich sehr wiederholt.)

 .sudoku { 
  -Square-1-Matches-Puzle-1: max (var (-quadratisch-1-ungelöst), var (-Quadrat-1-Equals-1, 0));
  -Square-2-Matches-Puzle-1: max (var (-Quadrat-2-ungelöstes), var (-Quadrat-2-Equals-2, 0));
  /*...*/
  -Square-16-Matches-Puzle-1: max (var (-quadratisch-16-ungelöstes), var (-Quadrat-16-Equals-1, 0));
  -Puzzle-1-Fund: min (var (-Square-1-Matches-Puzle-1), 
  /*...*/ 
  var (-Square-16-Matches-Puzzle-1));
  -Fundig: max (var (-Puzzle-1-Fund), /*...*/ var (-Puzzle-288-Fundern));
}
Nach dem Login kopieren

Durch Überprüfen, ob jedes Quadrat entweder ungelöst ist oder einen Wert aufweist, der in einer unserer vorbereiteten Lösungen aus der SASS 2D-Liste in einer unserer vorbereiteten Lösungen vorhanden ist, können wir eine Variable erstellen, die uns mitteilt, ob die aktuell definierten Quadrate in einem gültigen 4 × 4-Sudoku-Puzzle existieren. Solange wir jetzt etwas Numerisches finden können, das ein Verhalten in CSS vorantreibt, können wir das CSS-Verhalten stützen-Lösung. Damit unser Gitter beispielsweise rot wird, wenn es ungültig ist, können wir dies auf jedem Quadrat einfügen:

 .Quadrat {
  Farbe: RGB (Calc (255 * (1-var (-Lösung)), 0, 0);
}
Nach dem Login kopieren

Nicht jede CSS-Eigenschaft kann von einer Zahl angetrieben werden, aber viele können, und sowohl Z-Index als auch Opazität sind besonders vielseitige CSS-Eigenschaften für diese Verwendung. Andere Verhaltensweisen können schwieriger sein, aber oft erreichbar. Zum Beispiel war ich ein bisschen festgefahren darüber, wie man die Shake -Animation für ein ungültiges Raster mit nur einer numerischen Bit -Flag -Eigenschaft auslöst, damit das Netz jederzeit erschüttert, aber dies ist ein großartiges Beispiel dafür, wie das Hacken von CSS Sie dazu zwingt, die Spezifikationen zu lesen und die Kantenfälle für jede Eigenschaft zu verstehen. Ich habe meine Lösung auf dieser Seite über die Animationsdauer gefunden.

Ein Wert von 0s, der den Standardwert ist, zeigt an, dass keine Animation auftreten sollte.

Daher können wir die Animationsdauer der Shake-Animation auf-die Lösung der Animation bei jedem Klicken einer Nummer mit der aktiven Pseudoklasse basieren und entfernen, um die Animationsreplay jederzeit zu machen, wenn die Lösung ungültig wird, und sonst nichts tun.

 #select-#{$ j} -Value-Quadrat-#{$ I}: Active { 
  Animation: Keine;
}

 #Select-#{$ J} -Value-Quadrat-#{$ I}: Checked ~ .sudoku {
  Animation: Shake Cubic-Bezier (.36, .07, .19, .97) Calc ((Klemme (0, 1-var (-Lösung), 1)) * 1s) Vorwärts;
}
Nach dem Login kopieren

Eine reine CSS -Sudoku -App wäre wahrscheinlich unmöglich, wenn wir keine CSS -benutzerdefinierten Eigenschaften hätten, und sie sind mächtiger, als sie auf den ersten Blick erscheinen mögen. Die Art und Weise, wie sie neu bewertet werden, und die Benutzeroberfläche aktualisieren, wenn eine Eigenschaft, von der sie sich von Änderungen abhängen, wie eine einfachere Version der Reaktivität, die Sie von einem ausgefallenen JavaScript -Framework wie Vue erhalten, erhalten. Es ist fair zu sagen, dass Reaktivität in Form von CSS -Variablen direkt in den Browser eingebaut wird!

Nachdem wir diesen Ansatz für die Validierung haben und unser Stylesheet die Lösung in ihrem Unterbewusstsein kennt, wenn wir gültige Werte in unserem Sudoku festlegen, stehen wir kurz vor der Implementierung des Lösers!

Alle 4 × 4 Sudoku lösen

Erinnerst du dich, als wir diese Zwischenvariablen eingeführt haben?

 .sudoku { 
  -Puzzle-1-Fund: min (var (-Square-1-Matches-Puzle-1), 
  /*...*/ 
  var (-Square-16-Matches-Puzzle-1));
}
Nach dem Login kopieren

Das war nicht nur, um den Validierungscode einfacher zu schreiben und zu verstehen. Wenn wir wissen, welche der 288 möglichen Rätsel (en) übereinstimmt, können wir den Löser schreiben!

 #No-Lösung {
  Z-Index: 1;
  Farbe: Rot;
}
@for $ lösungs-Index von 1 bis 288 {
Label [für = Lösung-#{$ lösungs-Index}] {
  Cursor: Zeiger;
  Z-Index: Calc (var (-Puzzle- #{$ lösungs-Index} -Found) * #{$ lösungs-Index});
}

#Solution-#{$ lösungs-Index}: geprüft ~ .sudoku {
  @Für $ Square von 1 bis 16 {
    -Square-#{$ Square} -Solution: "#{nth (nth ($ lösungen, $ lösungs-Index), $ Square)}";
    -Square-#{$ Square} -Color: Gray;
    --auto-#{$ Square}: 1;
  }
Nach dem Login kopieren

Ich habe den optionalen Plural in das Wort „Puzzle (s)“ oben eingebaut, da der Benutzer, wenn nicht viele Quadrate ausgefüllt wurde, es möglich ist, dass es mehrere gültige Lösungen gibt. Ich grabe Solver wie dieses JavaScript -One, das schnell eine Lösung erzeugen kann, auch wenn Sie nicht genügend Werte für einen Menschen angegeben haben, um sie ohne Erraten zu lösen.

Der Trick in meinem CSS -Solver ist, dass die Schaltfläche „Lösen“ zwar wie ein einzelner Taste aussieht, aber tatsächlich 288 Optionsknopflabels übereinander gestapelt sind - aber alle sehen gleich aus. Stellen Sie sich einen Kartenstapel vor: Sie alle haben das gleiche Design auf der Rückseite, aber unterschiedliche Werte auf der Vorderseite. Die Löserlogik setzt die Karte mit der Lösung oben auf dem Stapel mit Z-Index. Wenn Sie sie also abholen und die andere Seite lesen, haben Sie immer die richtige Lösung. Es funktioniert immer noch, wenn es mehrere korrekte Lösungen gibt, da die Lösung, die später in unserer Liste gültiger Antworten erfolgt, oben platziert wird, da wir den Z-Index durch Multiplizieren des Flags mit $ lösungs-Index berechnen. Wenn keine Lösungen übereinstimmen, ist der Z-Index aller Lösungsschaltflächen Null und da die deaktivierte Version der Taste mit der Nachricht "Ungültiges Puzzle" Z-Index von einem enthält, wird sie oben angezeigt. Wenn Puzzle Nummer eins die Lösung ist, werden wir immer noch die Rätsel -Taste sehen, da die ungültige Taste früher in der HTML erfolgt.

Das Stapeln von Kontext kann sich unerwartet verhalten, wenn Sie sich nicht darüber informiert haben. Dies ist ein schönes Beispiel für eines der nicht offensichtlichen Stapelverhalten.

Rätsel erzeugen

Wir können uns die erzeugenden Rätsel als eine andere Version des Lösers mit zusätzlichen Anforderungen vorstellen.

  1. Einige zufällige Quadrate müssen ungelöst bleiben, wenn der Puzzlegenerator -Taste gedrückt wird.
  2. Die Kombination aus zufällig ungelösten Quadraten und einer korrekten Lösung sollte bei jedem Drücken der Generatortaste unterschiedlich sein.
  3. Durch Drücken der Lösungs -Taste sollte die vollständige Lösung angezeigt werden.
  4. Wenn der Benutzer das erzeugte Puzzle manuell löst, möchten wir sie mit einem Siegbildschirm belohnen, der Feedback darüber gibt, wie schnell er es gelöst hat.

CSS hat keine zufällige () -Funktion (obwohl SASS dies tut), sodass es möglicherweise nicht offensichtlich ist, wie wir jedes Mal, wenn wir denselben Knopf drücken, ein anderes Verhalten erhalten können. Die obige Erklärung der Löser war jedoch ein bisschen Spoiler, da er bereits etwas Ähnliches mit einer Taste macht, die wie ein einzelnes Element aussieht, aber je nach aktueller gültiger Lösung tatsächlich unterschiedlich ist.

Die Frage mit der Schaltfläche „Generieren“ ist, wie wir jedes Mal, wenn wir klicken, ein unvorhersehbares Ergebnis erzielen können. Vollständige Kredit an Alvaro Montoro für seinen Artikel über CSS-Tricks darüber, wie man scheinbar zufällige Werte mit nur CSS generiert. Die Kombination von Optionsknopf -Hacks und der Animation der Stapelreihenfolge scheint gut zu funktionieren. Ich habe mich bemüht zu sehen, ob ich es ohne zusätzliches Markup tun könnte, aber ich kam zu dem Schluss, dass dieser Ansatz der beste und einfachste ist. Um das Kartenspiel der Kartenanalogie aus der Erklärung des Solvers wiederzuverwenden, ist es, als ob das Deck der Puzzle -Karten die ganze Zeit unsichtbar mischt, so dass Sie, wenn Sie eine Karte nehmen, ein anderes Gesicht hat.

Wir können diese Pseudo -Zufälligkeit mit der tatsächlichen Zufälligkeit der Sass Random () -Funktion kombinieren, um unserem Sudoku -Spiel -Wiederholungswert zu geben.

 @Für $ j von 0 bis 287 {
  Label [für = generieren#{$ j}] { 
    Animation-Delay: #{$ j * .35s}; 
  }
  Label [für = generieren#{$ j}]: aktiv: After {{
    Z-Index: 300;
    Breite: 100%;
  }
  #Generate#{$ j}: geprüft ~ .sudoku { 
    $ blockCounts: (1: 2, 2: 2, 3: 3, 4: 2);
    $ shufflesquares: (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);

     @Für $ Square von 1 bis 16 {
       $ index1: random (16);
       $ index2: random (16);

       $ temp: nth ($ shufflesquares, $ index1);
       $ shufflesquares: set-nth ($ shufflesquares, $ index1, n-ten ($ shufflesquares, $ index2));
       $ shufflesquares: set-nth ($ shufflesquares, $ index2, $ temp);
     }

     @each $ Square in $ shufflesquares {
       $ Row: Ceil ($ Square/4);
      $ Spalte: 1 ($ Square - 1) % 4;

       $ block: if ($ row & lt; 3, 1, 3) if ($ spalte  0) {
         $ blockCounts: map -merge ($ blockCounts, ($ block: $ count - 1));
        -Square-#{$ Square} -Nsolved: 0; 
        -Square-#{$ Square} -äquals-#{$ val}: 1;

        @Für $ other-value von 1 bis 4 {
          @if ($ other-value! = $ val) {
            -Square-#{$ Square} -äquals-#{$ other-value}: 0;   
          }
        }

        -Square-#{$ Square} -Color: Gray;
        --auto-#{$ Square}: 1;
      }
    } 
  }
}
Nach dem Login kopieren

Für jeden „Block“ (das ist Sudoku-Speak für diese 4 × 4-Abschnitte des Sudoku-Netzes mit dem dicken Rand um sie herum) verwenden wir SASS, um zufällig zwei von vier Quadraten zu lösen, mit Ausnahme eines „Gimmen“, das nur ein ungelöstes Quadrat hat. Da die Validierungslogik und die Solver -Logik die Variablen verwendet, anstatt direkt auf der Basis der Werte mit dem Wertschöpfungs -Selektor überprüft zu werden, verhalten sich die Validierung und Lösung der Logik beide genauso. Das bedeutet, dass generierte Werte genauso behandelt werden, als hätte der Benutzer jeden Wert einzeln ausgewählt.

Der Lösungs -Timer

Hier ist der Timer, der in den ersten elf Sekunden tickt.

Wir werden in einem Moment in die CSS für den Lösungs -Timer eintauchen, aber zeigen wir zunächst, wie eine der Ziffern ohne CSS -Überlauf aussieht, und mit einem grünen Rand um das Element, um den Teil zu zeigen, der bei jedem Schritt der Animation für den Benutzer sichtbar wäre.

Wir verwenden eine unendlich wiederholende Keyframes -Animation, um die Liste der möglichen Ziffern ein Zeichen in einem gewünschten Intervall nach links zu verschieben (wir verwenden eine monospaced -Schriftart, damit wir sicher sein können, dass jedes Charakter die gleiche genaue Breite besetzt). Die Sekunden -Ziffer wird von null auf neun steigen, und die nächste Ziffer sollte nur bis zu fünf steigen und steigen pro zehn Sekunden, bevor beide Ziffern der Sekunden auf Null zurückgesetzt werden müssen.

Jede Ziffer animiert mit derselben Technik, mit der Sie ein Spritscher in CSS animieren können, außer dass wir ein Pseudo -Element mit den möglichen Ziffern enthält, die einen Animationsingenieurwechsel wechseln, um einen Bildhintergrund zu erzielen, um einen Animationseffekt zu erzielen.

Wie bei vielen Aufgaben in CSS gibt es mehr als eine Möglichkeit, in CSS einen animierten Zähler zu erstellen. Aber einige arbeiten nicht mit dem Querbrowser und fordern wirklich einen Präprozessor, um den Code kurz zu halten. Ich mag meinen Ansatz, weil er ziemlich kurz ist. CSS macht das schwere Heben, um herauszufinden, wann und wie man zur nächsten Ziffer wechselt. Alles, was er tun muss, ist, einen Platzhalter zu erstellen, in dem jede Ziffer führt, und gibt uns einige Freiheit, wie wir unseren Timer präsentieren.

Hier ist das Markup:

 <div>  
  <div> </div>
  <div>: </div>
  <div> </div>
  <div> </div>
</div>
Nach dem Login kopieren

… Und das CSS:

 .Stopwatch {
  Text-Align: Mitte;
  Schriftfamilie: Monospace;
  Randboden: 10px;
}

.symbol {
  Breite: 1ch;
  Überlauf: versteckt;
  Anzeige: Inline-Flex;
  Schriftgröße: 5Ch;
}

.Symbol: n-te Kind (1) :: After {{
  Animation: Ten 3600S -Schritte (6, Ende) unendlich;
  Inhalt: '012345';
}

.Symbol: n-te Kind (2) :: nach {{
  Animation: Einheiten 600S -Schritte (10, Ende) unendlich;
  Inhalt: '0123456789';
}

.Symbol: n-te Kind (4) :: After {{
  Animation: Zehns 60er Schritte (6, Ende) unendlich;
  Inhalt: '012345';
}

.Symbol: n-te Kind (5) :: After {{
  Animation: Einheiten 10S Schritte (10, Ende) unendlich;
  Inhalt: '0123456789';
}

@keyframes Einheiten {
  Zu {
    Transformation: Translatex (-10Ch);
  }
}

@Keyframes Tens {
  Zu {
    Transformation: Translatex (-6Ch);
  }
}
Nach dem Login kopieren

Sie werden vielleicht feststellen, dass der Schalter von Anfang an nach einer Stunde wieder beginnt. Das liegt daran, dass alle Iterationszahlen unendlich eingestellt sind. Wir könnten es beheben, aber ich denke, wenn jemand eine Stunde damit verbringt, eines davon zu lösen, haben sie größere Probleme als das Sudoku -Rätsel für Kinder. ?

Was jedoch unfair wäre, ist, wenn wir denselben Timer erlauben, auch dann weiter zu ticken, selbst wenn der Benutzer ein frisches Rätsel generiert. Können wir es zurücksetzen lassen? Es stellt sich heraus, dass wir dieses Problem bereits im ersten Schritt in diesem Artikel gelöst haben, in dem wir die Animation für unseren Zahlenwählten unter Verwendung der aktiven Pseudoklasse entfernt haben und konditionell neu angepasst haben. Diesmal ist es tatsächlich einfacher, denn jedes Mal, wenn wir auf die Taste „Erzeugen“ klicken, möchten wir die Animation auf allen Ziffern entfernen, um sie wieder auf Null zu bringen. Dann beginnt die Animation erneut, wenn das Optionsfeld nicht mehr aktiv ist. Es ist also nur eine CSS -Zeile, die wir jedes Mal, wenn wir generieren, den Timer zurücksetzen lassen!

 input [name = generate]: aktiv ~ .stopwatch .symbol :: After {{{
  Animation: Keine;
}
Nach dem Login kopieren

Sudokumeter ™ euen

Selbst wenn das Puzzle gelöst ist, möchte ich den Wiederholungswert anbieten, indem ich dem Spieler visuelles Feedback zu ihrer Zeitleistung geben und sie herausfordern, um Rätsel schneller zu lösen. Ich möchte Sie auch dafür belohnen, dass Sie es so weit durch den Artikel geschafft haben, indem Sie Ihnen eine minimalistische Kreisstrahlung geben, die Sie in Ihren eigenen Projekten wiederverwenden können. Hier ist ein eigenständiger Stift mit dem kreisförmigen Messgerät, mit dem Sie experimentieren können:

Wir wenden die gleichen Prinzipien an, die aus dem Spiel aus dem Spiel verwendet werden, außer in diesem Stift wird die angezeigte Bewertung mit Optionsknopf -Hacks gesteuert, während es im Spiel durch Animation gesteuert wird, die sich im Laufe der Zeit langsam zu einer geringeren Bewertung bewegt. Die Anzeige im Spiel wird mit Null -Depazität versteckt und wird nur angezeigt (und inne), wenn wir feststellen, dass das Puzzle manuell gelöst wurde.

Lassen Sie uns erklären, wie wir die Illusion eines Halbkreises erzeugen, der durch Farbe in zwei Seiten unterteilt ist. Es ist eigentlich ein vollständiger CSS -Kreis mit der unteren Hälfte mit Überlauf: versteckt.

Wir wenden die beiden Farben mit einem Pseudoelement an, das die Hälfte der

füllt.

Dann schneiden wir ein Loch in der Mitte, um einen Donut zu erstellen, indem wir einen anderen Kreis mit der Hintergrundfarbe des Spiels verwenden, und die Mitte des größeren Kreises mit Flexbox.

Verstecken Sie als nächstes die Hälfte davon, indem Sie die Größe des Behälters halb so hoch wie der volle Kreis und erneut über Überlauf: versteckt.

Wenn wir jetzt unseren Donut drehen, sieht es so aus, als würde sich die Messdose mit grün füllen oder grün verlieren, je nachdem, ob wir unseren Donut um negative oder positive Grad drehen!

Wir möchten Etiketten an beiden Enden der Anzeige und eine Beschreibung dazwischen legen, und es stellt sich heraus, dass Flexbox eine elegante Lösung ist:

 #rate {
  Schriftgröße: 30px;
  Anzeige: Flex;
  Breite: 300px;
  Rechtfertigungsbekämpfung: Weltraum zwischen;
}
Nach dem Login kopieren

Hier ist das Markup:

 <div>
  <div>? </div>
  <div> </div>
  <div>? </div>
</div>
Nach dem Login kopieren

Das ist alles, was wir brauchen, um unsere Etiketten zu positionieren. Wenn die Bewertung

die Breite des Durchmessers unseres Kreises ist, positioniert Flexbox die Emoji -Etiketten an den Enden und die Beschreibung in der Mitte des Kreises!

Um die Beschreibung zu kontrollieren, ähnelt sie dem Trick, den wir für unseren Timer verwendet haben, außer dass wir diesmal eher vertikal als horizontal tun, da die Rückkopplungsbeschreibungen von variabler Länge sind. Aber sie sind immer die gleiche Größe.

Abschluss

Ich habe diesen Artikel mit Fragen geöffnet, ob CSS eine Programmiersprache ist. Es ist schwer zu argumentieren, dass die Logik, die wir mit nur CSS nicht implementieren konnten, nicht programmiert, aber ein Teil davon ist eine ungewöhnliche Verwendung von CSS, um es gelinde auszudrücken. Wie bei vielen Dingen in der Tech -Welt scheint die Antwort „es abhängig“ zu sein, und so sehr wir durch dieses Experiment über CSS gelernt haben, haben wir auch veranschaulicht, dass die Programmierung genauso viel um die Einstellung wie die Technologie geht.

Kein CSS -Hacking -Artikel ist ohne den Haftungsausschluss vollständig, dass wir zwar gezeigt haben können, dass wir eine ausgefeilte Logik in CSS implementieren und dabei viel lernen können. Die meiste Zeit sollten wir dies in der Produktion wahrscheinlich nicht tun, da Wartbarkeit, Zugänglichkeit und andere Wörter mit „Isilität“ enden.

Wir haben aber auch gesehen, dass einige Dinge-wie das, was ich als die eingebaute Reaktivität betrachte, in CSS mit CSS-Variablen ziemlich bequem sind, aber möglicherweise verlangen, dass wir Reifen in JavaScript durchgehen und wahrscheinlich ein Framework verwenden. Indem wir die Grenzen von CSS überschreiten, haben wir am Ende eine kreisförmige Messstoffe geschaffen, von der ich glaube, dass sie vernünftigerweise in einer Produktions -App verwendet werden könnte, und könnte sogar das Richtige sein, verglichen mit einem JavaScript -Widget, das möglicherweise schwer ist und mehr tut, als wir wirklich brauchen.

Auf meiner Wunschliste für die CSS Sudoku App befindet sich eine Reset -Taste. Wenn Sie ein neues Sudoku -Spiel starten möchten, müssen Sie die Seite aktuell aktualisieren. Das ist eine inhärente Einschränkung von Optionsknopf -Hacks, die CSS -Hacking von der herkömmlichen Programmierung unterscheidet. In einer Phase glaubte ich, eine Lösung zu finden, als ich dachte, Animationen könnten zum Festlegen von CSS-Variablen verwendet werden-es stellt sich jedoch heraus, dass dies Teil von CSS Houdini ist und nur in Browsern auf Chrombasis unterstützt wird. Wenn und wenn das überall unterstützt wird, wird es eine Hacksschachtel einer Pandora öffnen und viel Spaß machen. In einem zukünftigen Artikel kann ich sogar untersuchen, warum dieses harmlose Feature, das wir in Chrome haben, ein Spielveränderer für CSS -Hacking ist.

Die Jury ist immer noch verabschiedet, ob in CSS ein voller 81 Quadratmeter mögliches Sudoku-Solver möglich ist. Wenn Sie jedoch neugierig sind, hinterlassen Sie Ihr Feedback in den Kommentaren. Wenn genügend Menschen es wollen, können wir dieses Kaninchenloch zusammen durchgehen und sehen, welche dunklen Ecken von CSS wir dabei beleuchten können.

Das obige ist der detaillierte Inhalt vonErzeugen (und Lösung!) Sudokus in CSS. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage