Saya telah membuat semacam permainan puzzle di mana tujuannya adalah untuk menyingkirkan semua ubin putih. Anda dapat mencobanya di akhir pertanyaan.
Setiap kali, papan dihasilkan secara acak dengan ubin putih di tempat-tempat acak pada kotak 5 * 5. Anda dapat mengeklik ubin apa saja pada kisi itu dan itu akan mengubah warna dan semua ubin menyentuhnya di sisinya. Dilema saya adalah kenyataan bahwa saya tidak tahu apakah itu akan menghasilkan papan yang mustahil. Apa cara terbaik untuk memeriksa hal-hal seperti ini?
function newgame() {
moves = 0;
document.getElementById("moves").innerHTML = "Moves: "+moves;
for (var i = 0; i < 25; i++) {
if (Math.random() >= 0.5) {
$(document.getElementsByClassName('block')[i]).toggleClass("b1 b2")
}
}
}
newgame();
function toggle(a,b) {
moves += 1;
document.getElementById("moves").innerHTML = "Moves: "+moves;
$(document.getElementsByClassName('block')[a+(b*5)]).toggleClass("b1 b2");
if (a<4) {$(document.getElementsByClassName('block')[(a+1)+(b*5)]).toggleClass("b1 b2")}
if (a>0) {$(document.getElementsByClassName('block')[(a-1)+(b*5)]).toggleClass("b1 b2")}
if (b<4) {$(document.getElementsByClassName('block')[a+((b+1)*5)]).toggleClass("b1 b2")}
if (b>0) {$(document.getElementsByClassName('block')[a+((b-1)*5)]).toggleClass("b1 b2")}
}
body {
background-color: #000000;
}
.game {
float: left;
background-color: #000000;
width: 300px;
height: 300px;
overflow: hidden;
overflow-x: hidden;
user-select: none;
display: inline-block;
}
.container {
border-color: #ffffff;
border-width: 5px;
border-style: solid;
border-radius: 5px;
width: 600px;
height: 300px;
text-align: center;
}
.side {
float: left;
background-color: #000000;
width: 300px;
height: 300px;
overflow: hidden;
overflow-x: hidden;
user-select: none;
display: inline-block;
}
.block {
transition: background-color 0.2s;
float: left;
}
.b1:hover {
background-color: #444444;
cursor: pointer;
}
.b2:hover {
background-color: #bbbbbb;
cursor: pointer;
}
.row {
width: 300px;
overflow: auto;
overflow-x: hidden;
}
.b1 {
display: inline-block;
height: 50px;
width: 50px;
background-color: #000000;
border-color: #000000;
border-width: 5px;
border-style: solid;
}
.b2 {
display: inline-block;
height: 50px;
width: 50px;
background-color: #ffffff;
border-color: #000000;
border-width: 5px;
border-style: solid;
}
.title {
width: 200px;
height: 50px;
color: #ffffff;
font-size: 55px;
font-weight: bold;
font-family: Arial;
display: table-cell;
vertical-align: middle;
}
.button {
cursor: pointer;
width: 200px;
height: 50px;
background-color: #000000;
border-color: #ffffff;
border-style: solid;
border-width: 5px;
color: #ffffff;
font-size: 25px;
font-weight: bold;
font-family: Arial;
display: table-cell;
vertical-align: middle;
border-radius: 5px;
transition: background-color 0.3s, color 0.3s;
}
.button:hover {
background-color: #ffffff;
color: #000000;
}
.sidetable {
padding: 30px 0px;
height: 200px;
}
#moves {
width: 200px;
height: 50px;
color: #aaaaaa;
font-size: 30px;
font-weight: bold;
font-family: Arial;
display: table-cell;
vertical-align: middle;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<center>
<div class="container">
<div class="game"><div class="row"><div onclick="toggle(0,0);" class="block b1"></div><div onclick="toggle(1,0);" class="block b1"></div><div onclick="toggle(2,0);" class="block b1"></div><div onclick="toggle(3,0);" class="block b1"></div><div onclick="toggle(4,0);" class="block b1"></div></div><div class="row"><div onclick="toggle(0,1);" class="block b1"></div><div onclick="toggle(1,1);" class="block b1"></div><div onclick="toggle(2,1);" class="block b1"></div><div onclick="toggle(3,1);" class="block b1"></div><div onclick="toggle(4,1);" class="block b1"></div></div><div class="row"><div onclick="toggle(0,2);" class="block b1"></div><div onclick="toggle(1,2);" class="block b1"></div><div onclick="toggle(2,2);" class="block b1"></div><div onclick="toggle(3,2);" class="block b1"></div><div onclick="toggle(4,2);" class="block b1"></div></div><div class="row"><div onclick="toggle(0,3);" class="block b1"></div><div onclick="toggle(1,3);" class="block b1"></div><div onclick="toggle(2,3);" class="block b1"></div><div onclick="toggle(3,3);" class="block b1"></div><div onclick="toggle(4,3);" class="block b1"></div></div><div class="row"><div onclick="toggle(0,4);" class="block b1"></div><div onclick="toggle(1,4);" class="block b1"></div><div onclick="toggle(2,4);" class="block b1"></div><div onclick="toggle(3,4);" class="block b1"></div><div onclick="toggle(4,4);" class="block b1"></div></div></div>
<div class="side">
<center class="sidetable">
<div class="title">Tiles</div>
<br>
<div class="button" onclick="newgame()">New Game</div>
<br><br>
<div id="moves">Moves: 0</div>
</center>
</div>
</div>
</center>
game-design
logic
puzzle
playtesting
Qwerty
sumber
sumber
Jawaban:
Ini adalah jenis permainan di mana gerakan yang sama dilakukan dua kali membalikkan papan ke keadaan sebelumnya. Jadi untuk memastikan papan dapat dipecahkan, buat dengan memutar secara terbalik. Mulailah dengan papan yang dipecahkan (kosong), kemudian mulailah secara terprogram "mengklik" secara acak beberapa kali, atau sampai papan memiliki jumlah kotak putih yang diinginkan. Salah satu solusinya adalah dengan hanya melakukan gerakan yang sama dalam urutan terbalik. Solusi lain yang lebih pendek mungkin ada, tetapi Anda dijamin memiliki setidaknya satu.
Solusi lain, yang jauh lebih kompleks, adalah mendefinisikan algoritma penyelesaian yang melewati semua status permainan yang mungkin dari posisi awal Anda untuk mencoba menemukan solusinya. Ini akan membutuhkan waktu lebih lama untuk diimplementasikan dan dijalankan, tetapi akan memungkinkan papan untuk benar-benar dihasilkan secara acak. Saya tidak akan membahas secara spesifik solusi ini, karena itu bukan ide yang bagus.
sumber
Meskipun jawaban di atas cerdas (dan mungkin bagaimana saya akan melakukannya), permainan khusus ini sangat terkenal. Ini disebut Lights Out , dan telah dipecahkan secara matematis. Ada solusi jika dan hanya jika dua jumlah dari berbagai elemen (diberikan pada halaman wikipedia) tambahkan ke nol mod 2 (yaitu bilangan genap). Secara umum, aljabar linear kecil harus memberikan kondisi solusi yang serupa untuk game di papan mana pun.
sumber
Pergi sebaliknya ketika menghasilkan puzzle Anda.
Alih-alih secara acak memilih ubin dan mengubahnya dari putih menjadi hitam, mulai dari batu tulis kosong, kemudian pilih ubin tapi bukannya beralih bahwa ubin hitam, membuatnya seolah-olah pengguna yang dipilih itu, mengakibatkan membalik semua ubin lainnya di sekitarnya.
Dengan cara ini Anda akan dijamin memiliki setidaknya satu solusi: pengguna harus membatalkan apa yang pemain "AI" Anda lakukan untuk membuat level.
sumber
Ed dan Alexandre punya hak untuk itu.
Tapi jika Anda tidak ingin tahu jika setiap solusi yang mungkin, ada cara.
Ada sejumlah kemungkinan teka-teki
Mengklik pada kotak yang sama dua kali menghasilkan hasil yang sama dengan tidak mengkliknya sama sekali, tidak peduli berapa banyak klik yang dibuat di antara mereka. Itu berarti bahwa setiap solusi dapat dideskripsikan dengan memberikan setiap kotak nilai biner dari 'diklik' atau 'tidak diklik'. Demikian pula, setiap teka-teki dapat dideskripsikan dengan memberikan nilai kuadrat 'toggled' atau 'not toggled' kepada setiap kotak. Itu berarti ada 2 ^ 25 kemungkinan teka-teki, dan 2 ^ 25 kemungkinan solusi. Jika Anda dapat membuktikan bahwa setiap solusi memecahkan teka-teki unik maka harus ada solusi untuk setiap teka-teki. Demikian pula, jika Anda menemukan dua solusi yang memecahkan puzzle yang sama maka tidak ada solusi untuk setiap puzzle.
Juga, 2 ^ 25 adalah 33.554.432. Itu cukup banyak, tetapi itu bukan angka yang tidak dapat dikelola. Algoritme yang baik dan komputer yang bagus mungkin dapat memaksa hal itu dalam beberapa jam, terutama ketika Anda menganggap bahwa setengah dari teka-teki tersebut adalah kebalikan dari setengah lainnya.
sumber
Jawaban umum:
sumber
Yang lain telah menyebutkan cara untuk menemukan apakah teka-teki yang Anda buat secara acak dapat dipecahkan. pertanyaan yang juga harus Anda tanyakan adalah apakah Anda benar-benar ingin puzzle yang dihasilkan secara acak.
Teka-teki yang dihasilkan secara acak semua memiliki kelemahan inti yang sama: Kesulitan mereka cukup banyak yang tidak terduga. Teka-teki yang mungkin Anda dapatkan bisa berkisar dari yang sudah dipecahkan, ke sepele (solusi jelas) ke sulit (solusi tidak jelas) hingga tidak mungkin (puzzle tidak dapat dipecahkan sama sekali). Karena kesulitannya tidak dapat diprediksi, itu membuat pengalaman yang tidak memuaskan bagi pemain, terutama jika mereka melakukan banyak teka-teki berturut-turut. Mereka sangat tidak mungkin mendapatkan kurva kesulitan yang mulus, yang bisa membuat mereka bosan atau frustrasi tergantung pada teka-teki apa yang mereka dapatkan.
Masalah lain dari generasi acak adalah bahwa waktu yang dibutuhkan untuk menginisialisasi puzzle tidak dapat diprediksi. Secara umum, Anda akan mendapatkan teka-teki yang dapat dipecahkan (hampir) segera, tetapi dengan sedikit nasib buruk, teka-teki Anda yang dihasilkan secara acak mungkin berakhir pada rentetan teka-teki yang tidak dapat diselesaikan.
Salah satu cara untuk memecahkan kedua hal ini adalah dengan memiliki vektor yang telah ditentukan dari setiap teka-teki yang dapat dipecahkan yang tersedia, disusun menjadi kelompok-kelompok kesulitan, dan kemudian memilih teka-teki acak dari teka-teki yang dapat dipecahkan berdasarkan kesulitan. Dengan cara ini, Anda akan yakin bahwa setiap puzzle dapat dipecahkan, bahwa kesulitannya dapat diprediksi dan bahwa generasi akan dilakukan dalam waktu yang konstan.
sumber