NIMproved

Introducere

Proiectul de fata este un joc similar cu jocul de Nim. Jucatorul uman va concura impotriva unui AI implementat pe microprocesor. Scopul proiectului poate fi incadrat in categoria divertisment.

Descriere generală

Initial se considera N gramezi, fiecare gramada avand un numar de pietre. La fiecare pas, jucatorul aflat la mutare elimina un numar nenul de pietre (eventual toate) dintr-o singura gramada. In plus, numarul de pietre eliminat trebuie sa fie egal cu 1 sau cu un numar prim. Jucatorii muta alternativ. Va pierde jucatorul care nu mai poate efectua nicio mutare (toate gramezile contin 0 pietre).

Pe placuta este implementata varianta cu 3 gramezi. Initial, fiecare din cele 3 gramezi contine cate 7 pietre. Pentru aceasta configuratie de test, jucatorul care efectueaza prima mutare are intotdeauna strategie sigura de castig.

Mai jos se gaseste o imagine cu circuitul final precum si cu stari posibile din joc:

Hardware Design

La placa de baza am adaugat inca o placa cu gauri, folosind suplimentar urmatoarele componente:

  • un ecran alfanumeric 2 x 16
  • 2 barete de 20 de pini
  • 3 butoane
  • 3 rezistente de 10k
  • un semireglabil de 10k

Toate aceste componente au fost achizitionate de la Syscom. Schema proiectului se gaseste mai jos.

Software Design

Pentru dezvoltarea software am folosit Programmers Notepad, iar pentru compilare librariile AVRLib. Pentru interactiunea cu ecranul LCD am folosit libraria de la [3].

Jocul prezentat este un joc in care unul din cei doi jucatori are strategie sigura de castig. Astfel, primul jucator are strategie de castig daca si numai daca suma xor a resturilor modulo 4 a numarului de pietre din gramezi este diferit de 0. Se observa ca pentru o singura gramada castiga primul jucator doar daca numarul nu e divizibil la 4 (astfel, acesta il poate aduce mereu pe cel de-al doilea jucator intr-o pozitie pierzatoare). Demonstratia pentru mai multe gramezi se realizeaza folosind numere Sprague-Grundy [5]. Pseudocodul pentru algoritm este ilustrat mai jos:

pentru i = 1,3

    if (nr_pietre[i] > 0)
       pentru p prim intre 1 si nr_pietre[i]
            copie = nr_pietre
            copie[i] -= p // scade p pietre din gramada i
            daca (copie[1] % 4) xor (copie[2] % 4) xor (copie[3] % 4) == 0)
                 return (gramada i, p pietre)

nu exista o mutare “sigura”: alege o gramada aleatoare si un numar de pietre din aceasta gramada

Pe parcursul implementarii am avut probleme cu fenomenul de “bouncing”: atunci cand un buton era apasat, numarul de pietre se schimba foarte rapid, deoarece la apasarea/eliberarea unui buton, acesta trecea de multe ori prin 0 si 1, pana la stabilizare. Rezolvarea software se gaseste in functia debounce(int pin) - cand starea unui buton se schimba, se seteaza un delay de cateva zeci de microsecunde, pentru ca acesta sa aiba timp sa se stabilizeze. De abia dupa acest delay se verifica starea butonului. Codul pentru functia debounce se gaseste mai jos:

int debounce(int but_pin) {

if(read(but_port,but_pin)) {		
	_delay_us(40);
	if(read(but_port,but_pin)) {		
	  while(read(but_port,but_pin)); //nu fa nimic cat timp e apasat; asteapta eliberarea
	  return 1;
	}
}	
return 0;

}

Concluzii

Proiectul functioneaza corespunzator. Printre problemele intampinate au fost cele legate de fenomenul de “bouncing”, explicat mai sus.

Resurse

Schema Eagle si sursele implementarii se gasesc in arhiva_filip_buruiana.zip.

Bibliografie

pm/prj2011/rtataroiu/joc_cu_pietre.txt · Last modified: 2021/04/14 17:07 (external edit)
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0