Yapbozumun her zaman mümkün olup olmadığını nasıl bilebilirim?


68

Amacın tüm beyaz taşlardan kurtulmak olduğu bir tür bulmaca oyunu yaptım. Sorunun sonunda deneyebilirsiniz.

Her seferinde tahta, 5 * 5 ızgara üzerinde rastgele yerlerde beyaz çinilerle rastgele oluşturulur. Bu ızgaradaki herhangi bir döşemeye tıklayabilirsiniz ve rengini ve yanlarına dokunan tüm döşemelerin rengini değiştirir. İkilemim, imkansız bir tahta üretip üretmeyeceğini bilmememdir. Böyle şeyleri kontrol etmenin en iyi yolu nedir?

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>


9
Bu tür bulmaca oyunlarıyla ilgileniyorsanız, Simon Tatham'ın Taşınabilir Bulmaca Koleksiyonuna bir göz atın . Bu tür dışında (orada Flip olarak adlandırılır), birçok Japonca ve diğer bulmacaların çeşitlerini bulabilirsiniz. Her şey BSD lisansı altında ve muhtemelen ilginç bir okuma.
Dubu

10
Tersine mühendislik yapmaya ne dersin? Bir pano ile başlayın, sonra otomatikleştirin, rastgele karelere 20 tıklama söyleyin. Bu şekilde biliyorsun sonunda bir çözüm olmalı.
AJFaraday

3
Oynamaya devam etmek istiyorum, ama sorunuza göre, gerçekten kazanıp kazanamayacağımın belirsizliği bana yiyor! Eğlenceli oyun :)
MrDuk

@MrDuk codepen.io/qwertyquerty/pen/WMGwVW işte bitmiş proje! Bu, sabittir ve cilalanmıştır. Ayrıca bir elektron uygulaması yaptım.
Qwerty

@ Kaleminizi tam sayfa görünümünde görüntülemeye çalıştığımda, "Bu Kalemin sahibinin Tam Sayfa Görünümü'nü etkinleştirmek için e-posta adreslerini doğrulaması gerekiyor." İletisini aldım. Lütfen e-posta adresinizi CodePen üzerinden doğrulayın, böylece oyununuzun tadını tam pencerede çıkarabilirsiniz! :)
stephenwade

Yanıtlar:


161

Bu, iki kez yapılan aynı hamlenin oyun tahtasını önceki durumuna döndürdüğü oyun türüdür. Bir tahtanın çözülebilir olmasını sağlamak için tersten oynayarak oluşturun. Çözülmüş (boş) bir tahta ile başlayın, daha sonra belirli bir sayıda rasgele olarak veya tahta istenen sayıda beyaz kareye sahip olana kadar programlı olarak "tıklamaya" başlayın. Bir çözüm, daha sonra aynı işlemleri tersine sırayla yapmaktır. Başka kısa çözümler olabilir, ancak en az bir tanesine sahip olduğunuz garanti edilir.

Çok daha karmaşık bir başka çözüm, çözümü bulmaya çalışmak için tüm olası oyun durumlarını başlangıç ​​konumunuzdan geçen bir çözme algoritması tanımlamaktır. Bu, uygulanması ve çalışması çok daha uzun sürecek, ancak panoların gerçekten rastgele üretilmesine izin verecek. Bu çözümün özelliklerine girmeyeceğim, çünkü bu bir fikir kadar iyi değil.


22
@Qwerty: Özel probleminiz için, aynı kareyi iki kez tıklamak kendiliğinden iptal olur, bu nedenle herhangi bir kareyi bir defadan fazla tıklatmak için hiçbir neden yoktur. Tekrar etmeden tıklatmak için belirli sayıda kare seçmek veya tahtadaki her kareye% XX tıklama şansı atayan bir çözüm düşünebilirsiniz. (Ed: Güzel cevap, + 1!)
Jeff Bowman,

3
Neredeyse aynı oyunu daha önce yaptım ve bu yaklaşımı kullanarak bittim. Başlangıçta çözülen durumun çözülmemiş duruma hızlı bir şekilde gittiğini gösteren bir animasyon ekledim; güzeldi.
Jared Goguen,

1
@JaredGoguen garip, ben ekledim ve buraya yorumunuzu görmek için geri geldi.
Qwerty

4
@JeffBowman Aslında, çözülebilir oyunlar seti, 25 bitlik bir değer olarak ele alınabilir, her bit, mod 2'nin çevrilme sayısı olan bir kareye karşılık gelir. .33,554,432 ve daha sonra tahtadaki her bir karenin değerini kısa bir şekilde hesaplayın.
Monty Harder

7
Ne pahasına olursa olsun , bu, bu sorunun nasıl cevaplanacağı ile ilgili matematiksel sorunun doğru cevabı olsa da , bu genellikle tasarım açısından şüpheli bir uygulamadır. Bu tür bir nesil, belirli bir planı olmadan, genellikle herhangi bir özel ilgi alanı veya birleştirici tema olmadan çok 'samey' hisseden bulmacalara yol açar. Bir puzzle oyunu için ilginç prosedür örnekleri 'usule uygun şekilde üretmek' mümkündür, ancak genellikle bulmacalarınızın ilginç özelliklerinin ne olduğuna daha sert bir bakış gerektirir.
Steven Stadnicki

92

Yukarıdaki cevaplar zekice olsa (ve yine de nasıl yapardım), bu oyun çok iyi bilinmektedir. Buna Lights Out adı verildi ve matematiksel olarak çözüldü. İki elementin (toplamları wikipedia sayfasında verilen) toplamı sıfır mod 2'ye (yani çift sayıya) eklenirse ve bununla ilgili bir çözüm vardır. Genel olarak, küçük bir doğrusal cebir, herhangi bir tahtadaki oyunlar için benzer çözüm koşulları vermelidir.


2
Çoktan yapıldığını öğrenmek biraz üzücü. Bir şey yaptığımı sanıyordum.
Qwerty

39
@Qwerty çok az orijinal fikir var ve kesinlikle başarılı olmak için bir tanesine sahip olmanıza gerek yok (cf Rovio, King).
OrangeDog

14
Bu özel oyun var, ama fikri her zaman genişletebilirsin! Daha fazla özellik ekleyin! Bir yere tıkladığınızda, hangi yönden etkinleştirildiğini / devre dışı bırakıldığına bağlı olarak ekleyen renkler gibi farklı kurallar ekleyin. Kullanmanız gereken farklı “araçlar” ekleyin. Dikdörtgen olmayan panolar ekleyin! Yapılacak eğlenceli şeyler var. Sadece bir hareketin daima kendisini tersine çevirmesi gerektiğini unutmayın.
Ed Marty

7
@OrangeDog: 'Lights Out' bile orijinal değildi, 90'larda popüler olan sadece marka adıydı. Örneğin, wikipedia makalesi, bunu ve bunu
BlueRaja - Danny Pflughoeft

1
Hangi cevapları "yukarıdaki cevaplar" olarak adlandırıyorsunuz? Tamamen belirsiz, çünkü benim ekranımda sizinkilerin üstünde sadece bir cevap var. Cevapların oylara ve kullanıcı seçeneklerine bağlı olarak değişiklik sırasını değiştirdiğini unutmayın. Her zaman "yukarıdaki" bir şeye gönderme yapmak yerine, belirli cevaplara bağlanmalısınız.
David Richerby

13

Bulmacanızı oluştururken etrafta diğer tarafa gidin.

Döşemeleri rastgele seçmek ve beyazdan siyaha çevirmek yerine, boş bir sayfadan başlayın, ardından döşemeleri seçin, ancak bu döşemeyi siyaha çevirmek yerine , kullanıcının seçtiği gibi tüm döşemeleri çevirerek yapın etrafında.

Bu şekilde, en azından sahip olmanız garanti edilir . bir çözüme sahip olduğunuzdan emin olabilirsiniz: kullanıcı, "AI" oynatıcısının seviyeyi oluşturmak için yaptıklarını geri almak zorunda kalacak.


7

Ed ve Alexandre buna hakkı var.

Ama eğer sen do her çözümün mümkün olup olmadığını bilmek istiyorum, yolu vardır.

Sınırlı sayıda olası bulmaca var

Aynı kareye iki kez tıklamak, aralarında kaç tıklama yapıldığına bakılmaksızın, hiç tıklamamakla aynı sonucu verir. Bu, her karenin her kareye 'tıklanan' veya 'tıklanmayan' bir ikili değeri vererek tanımlanabileceği anlamına gelir. Benzer şekilde, her yapboz, her kareye 'değiştirilmiş' veya 'değiştirilmemiş' bir ikili değer vererek tanımlanabilir. Bu, 2 ^ 25 olası bulmaca ve 2 ^ 25 olası çözüm olduğu anlamına gelir. Her bir çözümün benzersiz bir bulmacayı çözdüğünü kanıtlayabilirseniz, her bulmacanın bir çözümü olmalıdır. Benzer şekilde, aynı bulmacayı çözen iki çözüm bulursanız, o zaman her bulmacanın çözümü olamaz.

Ayrıca, 2 ^ 25, 33,554,432'dir. Bu oldukça fazla, ama yönetilemez bir sayı değil. İyi bir algoritma ve iyi bir bilgisayar muhtemelen birkaç saat içinde, bilmecenin diğer yarının tersi olduğunu düşündüğünüzde birkaç saat içinde kaba bir şekilde zorlayabilir.


4
Yarıdan fazlası “ters” dir - yatay yansımaların yanı sıra dikey yansımalara ve rotasyonlara sahipsiniz.
Clockwork-Muse,

@ Clockwork-Muse, evet, ancak kesin bir sayıyı hesaplamak daha zordur, çünkü asimetrik tasarımlar 8 permütasyonda döndürülebilir ve çevrilebilirken, simetrik tasarımlar daha az permütasyona sahiptir. Bu yüzden sadece beyaz / siyah ters çevirmeden bahsettim, çünkü her çözüm tam olarak 1 tersine sahip. (Çalışması için bunun tersi olsa da, tüm tahtayı çevirebileceğinizi kanıtlamanız gerekir)
Arcanist Lupus

Robert Mastragostino'nun cevabında bahsettiği gibi, bu aslında iyi bilinen, iyi çalışılmış bir sorundur. Her çözülebilir yapboz tam olarak 4 çözüme sahiptir ve rastgele tahtaların çoğu çözülemez. Tüm bu alanların aranması eğlenceli olabilir, ancak bir kanıt olduğundan ( math.ksu.edu/math551/math551a.f06/lights_out.pdf ) birkaç nokta ürünü de yapabilir ve birkaç cevapta aynı cevabı alabilirsiniz. mikrosaniye. :)
GrandOpener

Matematiksel zaman: Eğer tüm simetrileri dikkate alarak , farklı panoların sayısını (çözülebilirliğe bakılmaksızın) hesaplamak istiyorsanız , Burnside'nin lemması gitme yoludur: 16 simetri vardır (bir önemsiz, üç dönüş, dört yansıma ve sonra bu 8'in her biri açma / kapama inversiyonuyla birleştirilmiştir) ve bu simetrilerin her biri için bazı paneller tamamen değişmemiştir. Simetri başına tamamen değişmeyen panoların ortalamasını alırsanız, bu farklı panoların sayısına eşittir.
Arthur,

1
@PeterTaylor Simülatörü kodlamak, sonuçları çalıştırmaktan çok daha uzun sürecektir.
corsiKa

4

Genelleştirilmiş cevap:

  1. Bir boyut matrisi oluşturun (# hamle) x (# ışık).
  2. Aksi takdirde 0, o satıra karşılık gelen hareketi yaparsa o sütuna karşılık gelen ışığı değiştirirse, hücreye 1 koyun.
  3. Matris üzerinde Gauss-Jordan eliminasyonu (modulo 2) yapın.
  4. Elde edilen matris her sütunda tek bir 1'e sahipse ve her satırda en fazla tek bir 1 varsa, o zaman her ızgara çözülebilir.

1

Diğerleri, rastgele oluşturulmuş bulmacanızın çözülebilir olup olmadığını bulma yollarından çoktan bahsetti. Yine de sormanız gereken soru, aslında rastgele oluşturulmuş bulmacaları isteyip istemediğinizdir.

Rasgele oluşturulmuş bulmacaların hepsinde aynı temel kusur var: Zorlukları neredeyse tahmin edilemez. Alabileceğiniz olası bulmacalar zaten çözülmüş, önemsiz (çözüm açık), zor (çözüm açık değil) ile imkansız (bulmaca hiç çözülemez) arasında değişebilir. Zorluk tahmin edilemez olduğu için, özellikle arka arkaya birden fazla bulmaca yaparlarsa, oyuncu için tatmin edici bir deneyim yaratmaz. Hangi bulmacaları alacağına bağlı olarak sıkılmaları veya sinirlerini bozabilecek yumuşak bir zorluk eğrisi elde etmeleri pek olası değildir.

Rastgele üretmenin bir başka problemi, bulmacanın başlaması için geçen sürenin tahmin edilemez olmasıdır. Genel olarak konuşursak, hemen (hemen hemen) çözülebilir bir bilmece elde edersiniz, ancak bazı kötü şanslarla, rastgele oluşturulmuş bulmacalarınız çözülemez bir bulmaca dizisine neden olabilir.

Bunların her ikisini de çözmenin bir yolu, her çözülebilir bulmacanın önceden tanımlanmış vektörlerinin mevcut olması, zorluk grupları halinde düzenlenmesi ve ardından çözülebilir bulmacalardan rastgele bir bulmacanın seçilmesidir. Bu şekilde, her bulmacanın çözülebilir olduğundan, zorluğun tahmin edilebilir olduğundan ve kuşağın sürekli bir zamanda yapılacağından emin olacaksınız.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.