Windows işletim sistemiyle çalışan herkes Mayın Tarlası oyununa aşinadır. Bu bölümde benzer bir program anlatılmaktadır.
Oyunun sonundaki program penceresinin bir örneği (oyuncu mayının bulunduğu hücreyi açtıktan sonra) Şekil 1'de gösterilmektedir. 10.7.
Pirinç. 10.7. Mayın Tarlası program penceresi
Oyun kuralları ve veri sunumu
Oyun alanı, her biri bir mayın içerebilen hücrelerden oluşur. Oyuncunun görevi tüm mayınları bulmak ve onları bayraklarla işaretlemektir.
Oyuncu, fare düğmelerini kullanarak bir hücreyi açabilir veya içine bir bayrak yerleştirebilir, böylece hücrenin bir mayın içerdiğini belirtebilir. Farenin sol tuşuna basılarak hücre açılır, sağ tuşuna basılarak onay kutusu işaretlenir. Oyuncunun açtığı hücrede bir mayın varsa, o zaman bir patlama meydana gelir (kazıcı bir hata yaptı ve bildiğimiz gibi sadece bir hata yapar) ve oyun biter. Bir hücrede mayın yoksa, o hücrede komşu hücrelerdeki mayın sayısına karşılık gelen bir sayı görünür.
Oyuncu, halihazırda açık olanların yanındaki hücrelerdeki mayın sayısı hakkındaki bilgileri analiz ederek tüm mayınları tespit edebilir ve bayraklarla işaretleyebilir. Bayraklarla işaretlenmiş hücrelerin sayısında herhangi bir kısıtlama yoktur. Ancak oyunu tamamlamak (kazanmak) için bayrakların yalnızca mayın bulunan hücrelere yerleştirilmesi gerekir. Yanlışlıkla seçilen bir onay kutusu, bulunduğu hücreye sağ tıklanarak kaldırılabilir.
Muhtemelen her birimiz Mayın Tarlası'nı oynamış veya en azından oynamayı denemişizdir. Oyunun mantığı basit ama bir zamanlar algoritmaya oyunu tamamlaması karşılığında bir ödül bile vaat etmişlerdi. Botumda mantığın sahadaki duruma göre kullanılan üç algoritması var. Ana algoritma, maden bulma olasılığı yüzde 100 ve yüzde 0 olan tüm hücreleri bulmanızı sağlar. Sadece bu algoritmayı kullanarak ve “Uzman” seviyesinde standart bir mayın tarama gemisinde güvenilir bir çözüm olmadığında rastgele hücreleri rastgele açarak %33 kazanç elde edebilirsiniz. Ancak bazı ek algoritmalar bu değeri %44'e çıkarabilir (Windows 7). Temel algoritma
Temel algoritma aşağıdaki gibidir. Bir açık hücreye bitişik bilinmeyen hücreler (Hücre sınıfı), aynı zamanda bitişik olduğu hücrenin değerini de kaydeden bir grup (Grup sınıfı) halinde oluşturulur.
Şekilde bazıları örtüşen, hatta bazıları başka gruplar içeren dört grup gösterilmektedir. (123,1)'i gösterelim - grup 1,2 ve 3 numaralı hücrelerden oluşur ve aynı zamanda içlerinde 1 mayın bulunur. (5678.2) - Dört hücrede 2 mayın var.
Öncelikle grupları dönüştürmeniz gerekir. Bunun için:
- Her grubu sonraki gruplarla karşılaştırırız.
- Gruplar aynıysa ikinciyi silin.
- Bir grup diğerini içeriyorsa, küçük olanı büyük olandan çıkarın. Yani iki grup (5678.2) ve (5.1), şimdi (678.1) ve (5.1) vardı; (2345.3) ve (5.1) → (234.2) ve (5.1)
- Kesişen grupları, örneğin (123,1) ve (234,2) aşağıdaki prensibe göre dönüştürüyoruz:
- Kesişen hücrelerden oluşan yeni bir grup oluşturun (23,?)
- Maden sayısını hesaplıyoruz yeni Grup, çok sayıda mayının bulunduğu gruptaki mayın sayısından (234.2) kesişen hücreleri (1,?) ayırdıktan sonra diğer gruptaki kalan hücre sayısının çıkarılmasına eşittir. Yani 2-1 = 1. (23,1) elde ederiz.
- Yeni gruptaki hesaplanan mayın sayısı (23,1), daha az mayın bulunan gruptaki mayın sayısına (123,1) eşit değilse dönüşümü durdururuz.
- Yeni oluşan grubu her iki kesişen gruptan çıkarıyoruz. (123.1)-(23.1) = (1.0), (234.2)-(23.1) = (4.1).
- Yeni oluşturulan grubu gruplar listesine ekleyin
- Hiçbir değişiklik yapılmayana kadar 1. adımdan itibaren tekrarlayın
Grup oluşturma ve dönüştürme yöntemi
/** * Bir açık alan değeriyle ilişkili hücre gruplarının bir listesini oluşturur ve aynı zamanda bunları daha küçük hücrelere bölerek kopyaları kaldırır. */ özel void setGroups() ( group.clear(); for (int x = 0; x< width; x++) for (int y = 0; y < height; y++) field[x][y].setGroup(groups); // создание групп boolean repeat; do{ repeat=false; for (int i = 0; i < groups.size() - 1; i++) { // проходим по списку групп Grup grubu ben = group.get(i); for (int j = i + 1; j< groups.size(); j++) { // сравниваем ее с остальными меньшими группами Group groupJ=groups.get(j); if (groupI.equals(groupJ)) // удаляем одинаковые группы {groups.remove(j--);break;} Group parent; // büyük grup Grup çocuğu; // daha küçük grup if (groupI.size()>groupJ.size()) // daha büyük ve daha küçük grupları hücre sayısına göre belirler (ebeveyn=grupI;çocuk=grupJ;) else (çocuk=grupI;ebeveyn=grupJ ; ) if (parent.contains(child)) ( // eğer büyük olan küçük olanı içeriyorsa parent.subtraction(child); // sonra küçük olanı büyük olandan çıkarın tekrar=true; // şunu kaydedin: gruplar değişti ) else if (groupI.overlaps(groupJ ) > 0) ( // aksi takdirde gruplar kesişirse if (groupI.getMines()>groupJ.getMines())// sayıya göre daha büyük ve daha küçük grupları belirleyin mayın sayısı (ebeveyn=grupI;çocuk=grupJ;) else (çocuk =grupI;ebeveyn=grupJ;) Grup örtüşmesi = parent.getOverlap(çocuk); // sonra kesişimin sonucunu alın if (overlap != null) ( // ve eğer mantıklıysa (kesişme sonucunda %0 veya 100'lük hücreler ortaya çıktı) group.add(overlap); // sonra listede uygun ayarlamaları yapın parent.subtraction(overlap); .çıkarma(örtüşme); )
Sonuç olarak üç tür grubumuz olacak.
- mayın sayısı sıfır
- mayın sayısı gruptaki hücre sayısına eşittir
- sıfır olmayan bir mayın sayısı gruptaki hücre sayısından azdır
Güvenilir bir çözüm yoksa
Ancak çoğu zaman duruma güvenilir bir çözüm bulunmadığı durumlar da vardır. Sonra aşağıdaki algoritma kurtarmaya geliyor. Özü olasılık teorisinin kullanılmasıdır. Algoritma iki aşamada çalışır:- Birkaç açık hücrenin etkisi dikkate alınarak tek tek hücrelerdeki olasılığın belirlenmesi
- Ortak hücreli grupların birbirleri üzerindeki karşılıklı etkileri dikkate alınarak olasılıkların ayarlanması
Birkaç açık hücrenin yanındaki bir hücrede mayın bulma olasılığını hesaplamak için en az bir olayın olasılığını hesaplamaya yönelik formülü kullanırız:
Toplamda bağımsız A 1, A 2,..., A n olaylarından en az birinin meydana gelmesinden oluşan bir A olayının meydana gelme olasılığı, bir ile çarpımı arasındaki farka eşittir. Zıt olayların olasılıkları. A=1- (1-A 1)*(1-A 2)*....*(1-A n)Bitişik hücrelerde bu formül uygulandıktan sonra sonuç 1-(1-0,57)*(1-0,28)=0,69 olur.
Ancak her hücre grubundaki olasılıkların toplamının gruptaki mayın sayısına eşit olması gerektiği unutulmamalıdır. Bu nedenle, her gruptaki tüm değerlerin çarpılması gerekir, böylece sonuçta toplamları dakika sayısına eşit olur. Bu sayı, gruptaki mayın sayısının grup hücrelerinin olasılıklarının mevcut toplamına bölünmesine eşittir:
4/(0,57+0,57+0,57+0,69+0,69+0,69+0,69)=0,895
0,57*0,895=0,485 0,69*0,895=0,618
Şimdi olasılığı 0,57 olan hücrelerde 0,485 var ve olasılığı 0,69 → 0,618 olan hücrelerde
Benzer bir hesaplamayı ikinci grup için de bir öncekinden yapılan ayarlamaları dikkate alarak yapıyoruz.
2/(0,28+0,28+0,28+0,618+0,618+0,618+0,618)=0,604
0,28*0,604=0,169 0,618*0,604=0,373
Genel hücrelerdeki olasılığın yeniden değiştiğini görüyoruz, dolayısıyla her grup için böyle bir ayarlamanın, sistem hücrelerde mayın bulmanın gerçek olasılıkları olacak bazı kararlı değerlere ulaşana kadar birkaç kez tekrarlanması gerekiyor.
4/(0,485+0,485+0,485+0,373+0,373+0,373+0,373)=1,357
0,485*1,357=0,658 0,373*1,357=0,506
2/(0,169+0,169+0,169+0,506+0,506+0,506+0,506)=0,79
0,169*0,79=0,134 0,506*0,79=0,4
… vesaire.
Geriye kalan tek şey hücrelerden birini minimum olasılıkla seçip hamle yapmaktır.
Bu yöntem kodda
/** * Yöntem, komşu hücrelerin olasılıklarının birbirleri üzerindeki karşılıklı etkisini dikkate alarak hücrelerde mayın bulma olasılıklarında ayarlamalar yapar */ Private void CorrectPosiibility())( Map
Son hamleler
Oyunun son aşamasında işaretlenmemiş mayınların sayısı büyük rol oynuyor. Bu sayıyı bildiğinizde, bunları bilinmeyen hücrelere kaba kuvvetle yerleştirebilir ve uygun seçenekleri işaretleyebilirsiniz. Her hücre için uygun seçenekleri arama sürecinde işaret sayısını sayarız. Ortaya çıkan değerleri toplam işaret sayısına bölerek her hücre için mayın bulma olasılığını elde ederiz. Örneğin tek güvenilir çözümü var gibi görünen bu durumda, son yöntem (LastTurns) mayın bulma olasılığı %0 olan 3 hücre buldu.LastTurns(9,21) mümkün olan 293930 kombinasyondan 144'ünü kontrol etti ve minimum %0 olasılıkla 3 hücre buldu
Fikri anlamanın karmaşıklığı açısından bu yöntem en kolay yöntemdir, bu yüzden henüz ayrıntılı olarak analiz etmeyeceğim.
Onun uygulanması
/** * Sıradan kaba kuvvet kullanan bağımsız hesaplama algoritması. Yalnızca bilinmeyen hücre sayısı 30'dan fazla değilse kullanılabilir * @return */ public ArrayList
Çözüm
Uygulamada, yeterli sayıda örnekle, bir hücrede mayın bulma olasılıklarının hesaplanan ve gerçek değerleri neredeyse örtüşmektedir. Aşağıdaki tabloda, botun Windows XP altında Mayın Tarlası'nda bir gece çalıştırılmasının sonuçları gösterilmektedir;- Tahmini %
- Hesaplanan % ile toplam hücre açıklığı sayısı
- Mayın başına isabet sayısı
- Gerçek %
1. | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2. | 31 | 55 | 117 | 131 | 304 | 291 | 303 | 339 | 507 | 435 | 479 | 1201 | 152 | 146 | 118 | 143 | 164 | 141 | 367 | 3968 | 145 | 63 | 47 | 26 | 92 |
3. | 1 | 4 | 9 | 6 | 20 | 19 | 27 | 29 | 56 | 43 | 60 | 147 | 15 | 25 | 14 | 20 | 33 | 26 | 65 | 350 | 14 | 5 | 12 | 4 | 23 |
4. | 3 | 7 | 7 | 4 | 6 | 6 | 8 | 8 | 11 | 9 | 12 | 12 | 9 | 17 | 11 | 13 | 20 | 18 | 17 | 8 | 9 | 7 | 25 | 15 | 25 |
1. | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2. | 18 | 10 | 24 | 18 | 9 | 11 | 6 | 135 | 8 | 2 | 4 | 2 | 1 | 3 | 16 | 2 | 2 | 1 | 462 | ||||||
3. | 1 | 9 | 2 | 3 | 3 | 2 | 1 | 43 | 1 | 0 | 1 | 0 | 0 | 1 | 4 | 1 | 1 | 0 | 210 | ||||||
4. | 5 | 37 | 11 | 30 | 33 | 18 | 16 | 31 | 12 | 0 | 25 | 0 | 0 | 33 | 25 | 50 | 50 | 0 | 45 |
%20-22'lik alandaki büyük tutarsızlık muhtemelen bu yüzdedeki hücrelerin genellikle yakınlarda açık olmayan hücrelere sahip olmasından (örneğin, oyunun başında) ve bazen oyuncuya uyarlanmış "Mayın Tarlası"ndan kaynaklanmaktadır. açılan hücrenin altından bir mayının çıkarılması. Çalışma algoritması java'da uygulandı ve standart bir Windows mayın tarama gemisi (7 ve XP), VK'daki bir uygulama ve oyun üzerinde test edildi. Bu arada, IP'mden hesabıma erişirken birkaç gün süren "teknik sorunlar" sonrasında oyun, sahanın bir bölümünü açma ödül kurallarını değiştirdi: başlangıçta açık alanın %10'u için bahsin %10'unu geri verdi, sonra %5, sonra %2 ve oynamayı bıraktığımda %5'e geri döndüm.