start     Articole     Despre mine    

Cum se programeaza jocul Reversi

Studentii ataca din nou (dupa mega-succesul Flappy Bird) :-)! Niste studenti talentati de la Facultatea de Electronica, Comunicatii si Calculatoare din Pitesti (Alin Savu, Ioan Stefan si Adrian Panoiu) au programat o versiune a jocului Reversi (sau Othello, cum ii zic altii) pentru simulatorul online de pe site. Detalii de la creatorii jocului vei gasi mai jos, dar mai intai te invit sa te bucuri de joc.

Apasa butonul “Reseteaza” si apoi “Executa”. Apoi joaca punand piese pe tabla prin click de mouse. (Bordura se va colora cu rosu daca punctajul negrului este mai mare, cu albastru daca punctajul albului este mai mare, si cu verde daca punctajele celor doi jucatori sunt egale.) Nu stii regulile jocului? Nicio problema — le vei descoperi jucand. Pe locuri.. gata… START! ūüôā

(Browserul tau nu suporta Canvas!…)

 

Probabil multi dintre voi nici nu ati auzit vreodata de acest joc (situatie in care, sa fiu sincer, si eu m-am aflat pana acum cateva zile ‚ėļ), insa cu ajutorul colegilor mei Adrian x 2, si a profesorului indrumator, domnul Florin Birleanu, am reusit sa descoperim tainele acestui joc, precum si modul de constructie al sau plecand de la o simpla tabla alba.

O sa incercam sa explicam modul de constructie al jocului cat mai simplu, cat mai putin stufos, cat mai la indemana oricui, deoarece nu dorim ‚Äúsa va pierdem pe drum‚ÄĚ.

 

In primul rand, ce presupune acest joc?

Jocul REVERSI porneste cu o tabla de joc (identica cu cea de sah) de 8×8 patrate. La inceput pe tabla se adauga ¬†4 piese (2 albe,2 negre) in centrul tablei de joc. Se muta pe rand (intai Negrul, apoi Albul) prin punerea cate unei piese pe tabla, mutarea fiind valabila doar daca are loc o trecere peste piese de culoare diferita pe linie, coloana sau diagonala, transformand acele piese in culoarea jucatorului la rand. (Altfel spus, o mutare este valabila doar daca “face sandwich” cel putin o piesa de culoare adversa intre piesa pusa pe tabla in timpul acelei mutari si o alta piesa proprie deja existenta pe tabla. In urma efectuarii unei mutari valide, piesele “facute sandwich” vor deveni de culoarea jucatorului¬†care a facut mutarea.)

 

 

 

 

 

 

 

 

 

Ideile au fost multe, insa si dificultatile intalnite au fost pe masura. Totul a plecat de la pasii stabiliti pentru crearea programului, si anume:

1. Crearea tabelei initiale de joc (cu chenar si primele 4 piese).

2. Crearea matricei tablei de joc in care se introduc valorile pieselor.

3. Crearea conditiilor de validare si a tot ce tine de functionarea jocului.

4. Crearea afisarii intr-un mod cat mai placut.

 

 

1. Crearea tablei initiale de joc

Intregul joc porneste odata cu stabilirea variabilelor initiale (nu va imaginati ca noi le-am stiut pe toate la inceput, ci le-am adaugat odata cu avansarea programului):

//Variabile

var i;

var j;

var a = 3;//pt a seta culoarile (3-VERDE,2-ROSU,4-ALBASTRU)

var ok;// pt a valida

var esand;// pt a valida

var col;

var lin;

var jucator;

jucator=1;

Intregul desen il consideram o matrice de 10×10, astfel chenarul va ocupa marginea matricei, iar tabla de joc va fi practic in interiorul acesteia.

 

1.1    Se iau in considerare toate marginile matricei, umplandu-se astfel intreg chenarul tablei de joc cu VERDE (codul 3).

//Chenar principal

j=1;

while(j<=10)

{ AprindeNrCul(1,j,VERDE);

j++;

}

i=2;

while(i<=10)

{

 AprindeNrCul(i,10,VERDE);

 i++;

}

i=9;

while(i>0)

{

 AprindeNrCul(10,i,VERDE);

¬†i–;

}

i=9;

while(i>1)

{

 AprindeNrCul(i,1,VERDE);

¬†i–;

}

 

1.2  Se umple tabla de joc cu culoarea GRI (codul 5), pentru a se putea observa spatiile unde inca se mai pot face mutari:

//Matricea jocului

var mat=Matrice(8,8);

i=2;

 while(i<10)

{ j=2;

   while(j<10)

  {

    mat[i-2][j-2]=0;

    AprindeNrCul(i,j,GRI);

   j++;

  }

 i++;

}

 

1.3  In final se adauga piesele de la care pleaca intregul joc.

//Piesele cu care incepe jocul

AprindeNrCul(5,6,1);mat[3][3]=1;

AprindeNrCul(6,5,1);mat[4][4]=1;

AprindeNrCul(5,5,0);mat[3][4]=2;

AprindeNrCul(6,6,0);mat[4][3]=2;

Probabil acum va veti pune intrebarea de unde valorile de 0, 1 sau 2 in matrice. Vom explica acest lucru la punctul 2.

 

2. Crearea matricei tablei de joc (mod de gandire)

Asa cum spuneam mai sus, intregul spatiu de joc este considerat o matrice de 10×10, unde tabla de joc se afla in interiorul matricei de 8×8.

Astfel, intreaga tabla de joc este initializata cu valoarea 0, semnificand spatiu gol, neocupat (asa cum se poate observa la punctual 1.2). Pentru piesele de culoare alba in matrice se adauga valoarea 2, iar pentru piesele de culoare neagra valoarea 1 (1.3). Astfel, intreaga matrice va fi ocupata cu valori de 0, 1 sau 2, reprezentand practic tabla de joc virtuala (creata in ‚Äúmintea calculatorului‚ÄĚ).

In urma fiecarei mutari se vor adauga in matrice valori de 1 sau de 2, pana cand aceasta va fi umpluta sau pana in momentul in care unul din jucatori detine toate piesele.

 

3. Crearea conditiilor de validare si a tot ce tine de functionarea jocului

Intreaga functionare a jocului se desfasoara in FunctieMouse, despre care nu are rost sa discutam prea multe, acestea fiind explicate in cursurile introductive de pe site.

Pentru functionarea jocului sunt necesare 8 validari pentru fiecare posibila mutare (coloana-sus/jos, linie-stanga/dreapta, diagonala-stanga sus/stanga jos, diagonala-dreapta sus/dreapta jos).

FunctiaMouse contine 2 variabile

    var x = XMouse(ev);

     var y = YMouse(ev);

reprezentand practic coordonatele fiecarui punct in matricea de joc. Astfel, plecand de la aceste 2 variabile se creeaza fiecare validare in parte. Conditia valabila pentru fiecare validare este ca aceasta sa nu depaseasca coordonatele matricei de joc.

 

    if ( ((x>=2)&&(x<=9)) && ((y>=2)&&(y<=9)) )

    {  //aici urmeaza a fi scrise toate cele 8 cazuri  de validare

De exemplu, validarea pentru linie ‚Äďstanga:

if (mat[9-y][x-2]==0)

      {

        e_mutare_ok = 0;         (0)

        col = x-2 Р1;

        if (col >= 0)                  (1)

        {

          if (mat[9-y][col]==(jucator%2+1))        (1)

          {

            e_sand = 0;

            e_gol = 0;                  (2)

            while ((col>=0) && (e_sand==0) && (e_gol==0))    (3)

            {

              if (mat[9-y][col]==jucator)            (4)

                e_sand = 1;

              else if (mat[9-y][col]==0)        (5)

                e_gol = 1;

              col = col-1;

            }

        if (e_sand==1)            (6)

            {

              // inversez piesele din sandwhich

              col = x-2 Р1;

              while (mat[9-y][col] != jucator)

              {

                mat[9-y][col] = jucator;

                col = col-1;

              }

              e_mutare_ok = 1;

            }

      }

 

Explicatie:

Fiecare punct in matrice adaugat prin click-ul de la mouse are coordonatele in matrice [9-y][x-2]. Prima conditie pentru validare este aceea ca in casuta unde se apasa click sa nu se afle nicio alta piesa ,deci casuta sa aiba in matrice valoarea 0.

(0) ‚Äď Se foloseste o variabila locala e_mutare_ok considerata initial 0 (adica nu se indeplineste¬†niciuna din cele 8 validari, deci nu se poate efectua mutarea). Daca cel putin una din cele 8 validari este corecta, e_mutare_ok va primi valoarea 1, insemnand ca se poate efectua mutarea acolo.

(1) ‚Äď Pentru ca mutarea sa fie valida pe linie la stanga, este necesar ca pe pozitia din stanga cea mai apropiata (atunci cand coloana este x-2-1) sa se gaseasca o piesa de culoare diferita fata de cea a jucatorului aflat la mutare si coloana sa nu iasa din matricea initiala de 8×8.

(2) ‚Äď Se introduc 2 variabile suplimentare, e_sand si e_gol, primind initial valoarea 0.

–¬†e_sand verifica daca poate avea loc comutarea pieselor, adica daca intre 2 piese de aceeasi culoare se gasesc piese de culoare contrara, acestea sa fie transformate in culoarea jucatorului aflat la mutare.

–¬†e_gol verifica daca intre piese se afla si goluri, fapt ce ar face imposibila mutarea.

(3) ‚Äď Se parcurge matricea pe linie la stanga pana in punctul in care una din cele 2 variabile primeste valoarea 1 sau coloana depaseste spatiul alocat matricei (reprezentand tabla de joc).

(4) ‚Äď Daca la punctul 1 s-a verificat ca prima piesa din stanga (cea mai apropiata de locul unde s-a facut click cu¬†mouse-ul) este de culoare diferita, acum se incearca cautarea unei piese de culoarea jucatorului aflat la rand. Daca piese este gasita,¬†e_sand devine 1 oprind astfel cautare din while.

(5)‚Äď Daca se gaseste un spatiu (valoarea 0), e_gol devine 1 oprind instructiunea¬†while.

(6) ‚Äď In cazul in care e_sand este 1 inseamna ca poate avea loc comutarea, astfel ca toate piesele de culoare contrara aflate intre cele 2 piese ale jucatorului curent sunt transformate in piese ale jucatorului curent, iar e_mutare_ok devine 1 confirmand ca validarea pe unul din cazuri are loc, deci se poate efectua mutarea.

Celelalte cazuri sunt absolut asemanatoare, numai ca pentru fiecare difera conditiile in functie de locul unde se doreste validarea (coloana, diagonala, …)

Astfel, in matricea de joc se adauga valorile 1 sau 2 specifice jucatorului aflat la mutare.

Ce este cu acest jucator?

Variabila jucator poate primi doar valoarea 1 sau 2, specifica fiecarei culoari (1 pt mutare neagra, 2 pentru mutare alba). Astfel, dupa trecerea prin toate cele 8 cazuri de validare, daca cel putin intr-unul din cazuri are loc comutarea inseamna ca se poate valida mutarea si se permite trecerea la mutare a urmatorului jucator, adaugandu-se astfel in matrice in locul unde a fost pozitionat cursorul (click) valoarea corespunzatoare jucatorului aflat la mutare (1 sau 2)

if (e_mutare_ok==1)

        {

          mat[9-y][x-2] = jucator;

          jucator = (jucator%2)+1;

        }

 

4. Crearea afisarii matricei

Pentru inceput am avut nevoie de schita matricei afisajului pentru a sti ce casute trebuie aprinse. Dupa 10 minute de desenat a iesit o schita pe care apoi am inceput s-o transformam in instructiuni.

Chenarul verde si dragut l-am creat folosind linile de cod mai sus mentionate.

Si functia AprindeNrCul(x,y,CULOARE). In cod am folosit variabila a pentru a da mai usor o valoare culorii, fara a ne complica cu numele acesteia (e mai avantajos sa lucrezi cu numere, parerea mea ‚ėļ). Am afisat chenarul o data in programul principal pentru a porni cu culoarea VERDE (deoarece numarul pieselor negre e egal cu cel al pieselor albe) si o data in functia FuntieMouse(ev), pentru a putea schimba culoarea chenarului (VERDE cand e egal, ROSU cand Negrul conduce si isi umple de ketchup adversarul si ALBASTRU¬†cand Albul il face fleasca de apa pe Negru ‚ėļ).

Bun, am glumit, am ras, dar trebuia cumva ca jocul sa stie cand sa afiseze aceste culori, nu sa ne pomenim in mijlocul jocului ca negrul castiga cu 3 piese pe tabla ‚ėļ. Pentru inceput am declarat in programul principal 2 variabile contor: contorNegru si contorAlb, un contor pentru fiecare, sa nu se certe ‚ėļ.

S-a pus problema ‚Äúplasarii‚ÄĚ acestor doua variabile contor, ele trebuind sa numere piesele de pe tabla (desigur, nu numarau Negru sau Alb, ci 1 sau 2). Bun bun, ele trebuie sa numere, dar cum sa numere ceva daca nu se afla ceva acolo? Deci trebuia intai sa cautam in matrice, astfel am obtinut in functia FunctieMouse(ev)¬†(asta dupa nenumaratele validari ‚ėļ) urmatoarele linii :

     i=0;

    while(i<=7)

    {

      j=0;

      while(j<=7)

      {  

        if(mat[i][j]===0)

         Aprinde(2+j,9-i,GRI);

        if(mat[i][j]==1)

        {

          Aprinde(2+j,9-i,NEGRU);

          contorNegru = contorNegru + 1;//Numara piesele negre

        }

        if(mat[i][j]==2)

        {

          Aprinde(2+j,9-i,ALB);

          contorAlb = contorAlb + 1;//Numara piesele albe

        }

      j = j+1;

     }

     i = i+1;

    }

Acum sa explic putin ce am facut pe acolo.

Dimensiunea matricei, cum am spus mai sus, este de 8×8. Cum bine stim de la orele de informatica (sau din articolele de pe site), o matrice incepe cu i si j de la 0, la fel ca in cazul de fata, mergand pana la 7 (daca aveti nedumerire de ce 7 si nu 8, numarati pe degete de la 0 la 7, veti avea o surpriza ‚ėļ). Matricea se parcurge cu 2 while-uri, unul pentru linii si unul pentru coloane. Apoi am considerat 3 cazuri :

  1. Daca in matrice la linia i si coloana j se afla valoarea 0 pe ecran se va pastra culoarea GRI, folosind functia Aprinde(2+j,9-i,GRI)¬†(2+j si 9-i deoarece afisajul este in coordonate carteziene). Aici nu ne intereseaza sa contorizam valorile de 0 (tabla nu joaca, doar tine piesele ‚ėļ).
  2. Daca in matrice la linia i si coloana j se afla valoarea 1, pe ecran se va schimba culoarea in Negru, folosind functia Aprinde(2+j,9-i,NEGRU)(din nou vorbim despre coordinate carteziene la afisaj). Desigur imediat va si contoriza valoarea gasita in contorNegru.
  3. Daca in matrice linia i si coloana j se afla valoarea 2, pe ecran se va schimba culoarea in Alb, folosind functia Aprinde(2+j,9-I,ALB) (din nou vorbim despre coordonate carteziene). Desigur, imediat va si contoriza valoarea gasita in contorAlb.

Am rezolvat si cu asta, dar trebuia totusi in functie de contor sa schimbam culoarea chenarului verde.

Cum sa facem, cum sa facem ? ‚ėļ

Pai raspunsul a venit repede: mai adaugam 3 if-uri pe acolo ‚ėļ. Zis si facut.¬†Bineinteles, nu le-am aruncat aiurea prin cod, ca n-ar mai fi iesit Reversi, ci le-am adaugat imediat dupa contorizare.

Arata cam asa :

if( contorNegru == contorAlb )

      a = 3;

    else

    if( contorNegru > contorAlb )

      a = 2;

    else

    if( contorNegru < contorAlb )

      a = 4;

Pai sa vedem ce avem pe aici:

  1. Daca sunt egale variabilele contor, variabila a primeste valoarea 3 ( 3 = VERDE), deci se pastreaza culoarea verde a chenarului.
  2. Daca Negrul il domina pe Alb (domina ‚ėļ), variabila a primeste valoarea 2 (2 = ROSU, putin ketchup‚ėļ), deci culoarea chenarului se face rosie.
  3. Daca Albul il domina pe Negru (asta s-a tot intamplat de-a lungul istoriei), variabila a primeste valoarea 4 (4 = ALBASTRU, putina apa pe oponent), deci culoarea chenarului se face albastra.

Urmeaza din nou sa afisez chenarul ce va arata informatile obtinute de-a lungul parcurgerii programului in timpul jocului.

Pai cam asta ar fi tot.¬†V-am plictisit destul cu datele tehnice si probabil vreti sa jucati, deci ca sa nu o mai lungesc mult, va urez distractie placuta ‚ėļ.

 

Te asteptai ca doar cu cele cateva instructiuni pe care ti le-am predat pana aici sa se poata construi jocuri atat de faine? ūüôā (Uite aici si Flappy Bird, daca nu l-ai vazut deja. Atentie! Creeaza dependenta :-).)

(Daca ti-a placut acest articol, te invit sa te abonezi introducandu-ti adresa de email in formularul din partea dreapta (sus) si sa dai Like la pagina de Facebook Igotopia.)

 

Spor la gandit! (<– creeaza dependenta dupa cateva doze)
Florin