
Interesantna tema za samostalni rad, koja može da se pretoči u maturski rad je bot za minesweeper.
Klasičan Minesweeper možete naći na https://minesweeper.online/
Igra se na tabli mxn, na kojoj su sakrivene mine. Igrač treba da pronađe i označi sva polja na kojima se nalaze mine. Polja su inicijalno zatvorena. Igrač u jednom potezu otvara jedno polje. Ako se na polju nalazi mina igra se završava gubitkom. Ako se na polju ne nalazi mina igrač dobija informaciju koliko mina ima u susednim poljima, tj. na polju se prikazuje broj. Na osnovu te informacije igrač može da zaključi gde se nalaze mine, označi ta polja, otvori sva ostala i dokaže da je pronašao sva polja na kojima su mine. Broj sakrivenih mina je unapred poznat.
|
|
0 |
0 |
|
0 |
1 |
1 |
|
0 |
1 |
|
Uzmimo za primer mapu 3x3 na kojoj su neka polja već otvorena. Dva polja, gore levo i dole desno, nisu otvorena. Na mapi se nalazi jedna mina. U kom polju? U ovakvoj situaciji igrač će zaključiti da se mina nalazi u donjem desnom polju, jer samo tako brojevi u otvorenim poljima imaju smisla.
Agent
Agent donosi odluke na osnovu trenutne baze znanja i izvođenju zaključaka pomoću pravila na osnovu trenutnog znanja.
Jedan način da modelujemo znanje o igri je da svako polje predstavimo kao jednu varijablu/parametar koja će imati vrednost TAČNO ako se na tom polju nalazi mina, odnosno NETAČNO ako se ne nalazi mina.
Koje informacije o igri ima agent, šta opaža senzorima? Agent zna da li je otvoreno polje sa ili bez mine, i ako je polje bez mine zna koliko ima mina oko tog polja. Pogledajmo sledeći slučaj, gde je polje u sredini otvoreno, a susedna polja nisu. Susedna polja označena su slovima A,B,C…,H. Inače bismo koristili koordinate matrice, pa bi ovo bilo npr. Mapa[0,0], Mapa[0,1], …
|
A |
B |
C |
|
D |
1 |
E |
|
F |
G |
H |
Znamo da je jedno od susednih polja minirano ali ne znamo koje. Ako se na polju A nalazi mina parametar A će biti TRUE, itd. Logički iskaz kojim možemo opisati trenutno stanje je:
A+B+C+D+E+F+G+H ili drugačije zapisano: Or(A,B,C,D,E,F,G,H)
Ovaj iskaz je sigurno tačan jer jedan od njih je tačan.
Zapravo znamo više od toga. U ovako napisanom iskazu iskaz će biti tačan i ako ih ima nekoliko koji su tačni, zbor prirode operatora OR. Agent zna da je tačno jedan od A,B,C,D,E,F,G,H tačan a ostali nisu, pa možemo da formulišemo precizniji iskaz:
Or( And(A, Not(B), Not(C), Not(D), Not(E), Not(F), Not(G), Not(H)), And(Not(A), B, Not(C), Not(D), Not(E), Not(F), Not(G), Not(H)), And(Not(A), Not(B), C, Not(D), Not(E), Not(F), Not(G), Not(H)), And(Not(A), Not(B), Not(C), D, Not(E), Not(F), Not(G), Not(H)), And(Not(A), Not(B), Not(C), Not(D), E, Not(F), Not(G), Not(H)), And(Not(A), Not(B), Not(C), Not(D), Not(E), F, Not(G), Not(H)), And(Not(A), Not(B), Not(C), Not(D), Not(E), Not(F), G, Not(H)), And(Not(A), Not(B), Not(C), Not(D), Not(E), Not(F), Not(G), H))
Ovaj iskaz je u DNF. Ako bismo ga zapisali u indeksnom obliku to bi bilo:
DNF(A,B,C,D,E,F,G,H) = Σ(1,2,4,8,18,32,64,128)
Prilično veliki broj kombinacija, i prilično velika formula. Stvar se dodatno komplikuje kada je na polju broj 2, gde imamo 8*7=56 klauza u DNF, broj 3 gde imamo 8*7*6=336 klauza itd.
Za mapu 8x8 ovo postaje realno veliki problem da se predstavi i sračuna.
Možemo da predstavimo znanje na drugačiji način: ako znamo da se u okolini ovog polja nalazi tačno jedan koji je miniran, imamo skup od osam polja od kojih se na tačno jednom nalazi mina:
set1=count1 {A,B,C,D,E,F,G,H} = 1
Sada možemo da razmatramo neke specifične slučajeve koji nam mogu dalje dati korake algoritma (u stilu DPLL):
- Ako za neko polje znamo da na njemu nije mina, možemo da ga uklonimo iz skupova u kojima se pojavljuje, pri čemu count tih skupova ostaje isti:
- x=FALSE and x in set1 -> set1 = set1\x
- Ako za neko polje odredimo da je minirano, možemo da ga uklonimo iz svih skupova u kojima se pojavljuje i da smanjimo count tih skupova za 1, jer smo sigurni da je to jedno polje minirano:
- x=TRUE and x in set1 -> set1=set1\x, count1=count1-1
- Ako u nekom skupu imamo onoliko polja koliki je broj mina u tom skupu, onda je svako polje minirano:
- set1==count1 -> sva polja u set1=TRUE
- Ako je jedan skup podskup drugog skupa, onda možemo da taj drugi skup podelimo na dva dela, i da odredimo count za oba dela:
- set1 subsetof set2 -> set3 = set2\set1, count3=count2-count1
- Ako za neko polje izvedemo da je minirano označićemo ga kao minirano
- x=TRUE -> M = M + x (dodajemo polje u skup miniranih)
- Ako za neko polje odredimo da nije minirano označićemo ga kao neminirano
- x=FALSE -> N = N + x
- Ako skup miniranih ima očekivan broj mina možemo izvršiti proveru-otvaranje svih ostalih polja
- Ako skup neminiranih ima ukupno-broj mina možemo označiti ostala polja kao minirana (i proglasiti kraj-proveriti sva ostala polja).
- Ako u skupu neminiranih polja postoji neko polje koje nije otvoreno otvorićemo ga
- Ako su sva polja označena kao neminirana otvorena, otvorićemo nasumično polje koje se ne nalazi ni u jednom skupu. Ako nema takvog polja, otvorićemo neko nasumično polje. Ovde postoji prostor za optimizaciju verovatnoće (bolje je otvoriti polje koje je 1 od 7 nego polje koje je 2 od 3).
Svaku činjenicu (polje jeste-nije otvoreno, polje jeste-nije minirano, polje jeste-nije bezbedno) možemo da predstavimo kao polje u matrici dimenzija istih kao tabla. Nepoznata vrednost bi bila null. Za svaku vrstu činjenica (otvoreno, minirano, slobodno) bismo imali zasebnu matricu. Skupove predstavljamo tipom Skup, i čuvamo niz skupova koji ažuriramo operacijama.
Ovo je jedan način kako možemo da izgradimo algoritam. Potrebno je formirati konzistentan skup pravila, opisati ih kao logičke iskaze i implementirati funkciju koja će prolaziti kroz trenutno stanje „sveta“, vršiti izvođenje novih zaključaka (koja su polja sigurna a koja sumnjiva) i na osnovu toga birati akciju-koje se polje otvara.
https://cs50.harvard.edu/extension/ai/2020/spring/projects/1/minesweeper/