
CSS memungkinkan Anda membuat tata letak dan antarmuka dinamis di Internet, tetapi sebagai bahasa markup, ia statis - Anda tidak dapat mengubahnya setelah menetapkan nilainya. Gagasan tentang kesempatan tidak dibahas. Pembuatan angka acak Runtime adalah wilayah JavaScript, bukan CSS.
Atau tidak? Jika kami mengizinkan sedikit interaksi pengguna, kami sebenarnya dapat menghasilkan beberapa tingkat keacakan dalam CSS. Mari lihat!
Keacakan dalam bahasa lain
Ada beberapa cara untuk mendapatkan "pengacakan dinamis" menggunakan variabel CSS, seperti yang dijelaskan Robin Rendle dalam artikel
tentang trik CSS . Tetapi solusi ini bukan 100% CSS, karena mereka membutuhkan JavaScript untuk memperbarui variabel CSS dengan nilai acak baru.
Kita dapat menggunakan preprocessor seperti Sass atau Less untuk menghasilkan nilai acak, tetapi begitu kode CSS dikompilasi dan diekspor, nilainya tetap dan keacakan hilang.
Mengapa saya khawatir tentang nilai acak dalam CSS?
Di masa lalu, saya mengembangkan aplikasi sederhana CSS saja seperti
Kuis , permainan
CS Simon, dan
Trik Sulap , tetapi saya ingin melakukan sesuatu yang lebih kompleks.
* Saya akan meninggalkan diskusi tentang validitas, kegunaan, atau kepraktisan membuat cuplikan ini di CSS hanya di lain waktu.
Berdasarkan fakta bahwa beberapa board game dapat direpresentasikan sebagai mesin negara (FSM), maka mereka dapat direpresentasikan menggunakan HTML dan CSS.
Oleh karena itu, saya mulai mengembangkan game
"Leela" (juga "Snakes and Ladders").
Ini adalah permainan sederhana. Singkatnya, tujuan permainan ini adalah untuk memajukan chip dari awal hingga akhir papan, menghindari ular dan mencoba menaiki tangga.
Proyek itu tampak layak, tetapi saya melewatkan sesuatu, ya tentu - dadu!
Melempar dadu (di gim lain, melempar koin) adalah metode yang diterima secara umum untuk mendapatkan nilai acak. Anda melempar dadu atau melemparkan koin, dan setiap kali Anda mendapatkan nilai yang tidak diketahui. Segalanya tampak sederhana.
Simulasi lemparan tulang secara acak
Saya akan overlay layer dengan label dan menggunakan animasi CSS untuk "memutar" dan berbagi layer apa yang ada di atas. Sesuatu seperti ini:

Kode untuk mensimulasikan pengacakan ini tidak terlalu rumit dan dapat dicapai menggunakan animasi dan berbagai penundaan animasi:
@keyframes changeOrder { from { z-index: 6; } to { z-index: 1; } } label { animation: changeOrder 3s infinite linear; background: #ddd; cursor: pointer; display: block; left: 1rem; padding: 1rem; position: absolute; top: 1rem; user-select: none; } label:nth-of-type(1) { animation-delay: -0.0s; } label:nth-of-type(2) { animation-delay: -0.5s; } label:nth-of-type(3) { animation-delay: -1.0s; } label:nth-of-type(4) { animation-delay: -1.5s; } label:nth-of-type(5) { animation-delay: -2.0s; } label:nth-of-type(6) { animation-delay: -2.5s; }
Animasi diperlambat untuk menyederhanakan interaksi (tetapi masih cukup cepat untuk melihat kendala yang dijelaskan di bawah). Keacakan semu juga lebih jelas.
<label for="d1">Click here to roll the dice</label> <label for="d2">Click here to roll the dice</label> <label for="d3">Click here to roll the dice</label> <label for="d4">Click here to roll the dice</label> <label for="d5">Click here to roll the dice</label> <label for="d6">Click here to roll the dice</label> <div> <input type="radio" id="d1" name="dice"> <input type="radio" id="d2" name="dice"> <input type="radio" id="d3" name="dice"> <input type="radio" id="d4" name="dice"> <input type="radio" id="d5" name="dice"> <input type="radio" id="d6" name="dice"> <p>You got a: <span id="random-value"></span></p> </div>
@keyframes changeOrder { from { z-index: 6;} to { z-index: 1; } } label { animation: changeOrder 3s infinite linear; background: #ddd; cursor: pointer; display: block; left: 1rem; padding: 1rem; position: absolute; top: 1rem; user-select: none; } label:nth-of-type(1) { animation-delay: 0s; } label:nth-of-type(2) { animation-delay: -0.5s; } label:nth-of-type(3) { animation-delay: -1.0s; } label:nth-of-type(4) { animation-delay: -1.5s; } label:nth-of-type(5) { animation-delay: -2.0s; } label:nth-of-type(6) { animation-delay: -2.5s; } div { left: 1rem; position: absolute; top: 5rem; width: 100%; } #d1:checked ~ p span::before { content: "1"; } #d2:checked ~ p span::before { content: "2"; } #d3:checked ~ p span::before { content: "3"; } #d4:checked ~ p span::before { content: "4"; } #d5:checked ~ p span::before { content: "5"; } #d6:checked ~ p span::before { content: "6"; }
Tetapi kemudian saya menemukan batasan tertentu. Saya mendapat angka acak, tetapi kadang-kadang, bahkan ketika saya mengklik "dadu", bidang tidak mengembalikan nilai apa pun.
Saya mencoba menambah waktu animasi, dan sepertinya sedikit membantu, tetapi saya masih memiliki beberapa nilai yang tidak terduga.
Saat itulah saya melakukan apa yang dilakukan kebanyakan pengembang ketika mereka menemukan hambatan yang tidak dapat mereka selesaikan - saya muncul untuk meminta bantuan pada StackOverflow. Saya merekomendasikannya.
Untungnya bagi saya, akan selalu ada orang yang mau membantu, dalam kasus saya adalah
Temani Afif dengan penjelasannya .
Jika Anda mencoba untuk menyederhanakan, masalahnya adalah bahwa browser menembakkan peristiwa klik hanya ketika elemen dalam keadaan aktif (ketika mouse diklik), dengan kata lain, itu adalah elemen yang sama yang aktif ketika tombol mouse ditekan.
Karena animasi yang berubah, lapisan atas (label), ketika Anda mengklik mouse, sebenarnya, bukan lapisan atas (label) ketika mouse ditekan, kecuali saya melakukannya dengan cukup cepat, baik, atau lambat, sehingga animasi sudah berhasil melewati semua nilai siklus. Inilah sebabnya mengapa peningkatan waktu animasi telah menyembunyikan masalah ini.
Solusinya adalah menerapkan posisi "statis" untuk memecah konteks tumpukan, dan menggunakan elemen pseudo seperti :: before atau :: after dengan indeks-z yang lebih tinggi untuk menggantikannya. Dengan demikian, label aktif akan selalu di atas ketika Anda mengarahkan mouse.
label:active { margin-left: 200%; position: static; } label:active::before { content: ""; position: absolute; top: 0; right: 0; left: 0; bottom: 0; z-index: 10; }
Berikut adalah kode dengan solusi dengan waktu animasi yang lebih cepat:
Setelah melakukan perubahan ini, tetap membuat antarmuka kecil untuk menggambar kubus pseudo yang dapat diklik dengan mouse, dan
permainan CSS
Snakes and Ladders telah selesai.
Teknik ini memiliki beberapa kelemahan yang jelas.
- Diperlukan interaksi dengan pengguna - perlu mengklik label untuk menyebabkan "pembentukan angka acak".
- Metode ini tidak skala dengan baik - ini bekerja dengan baik dengan set nilai yang kecil, tetapi itu menyulitkan untuk rentang yang besar.
- Ini bukan Acak nyata, tetapi masih merupakan keacakan pseudo, dan komputer dapat dengan mudah menentukan nilai apa yang akan dihasilkan pada setiap saat.
Tetapi di sisi lain, ini adalah 100% CSS (tidak perlu untuk preprosesor atau penolong eksternal lainnya), dan bagi seseorang dapat terlihat 100% acak.
Dan, ya, metode ini dapat digunakan tidak hanya untuk angka acak, tetapi juga untuk semuanya acak. Dalam hal ini, kami menggunakannya untuk "tidak sengaja" memilih komputer di game "Rock-paper-scissors".