Construirea Unui Joc de Memorie
Capitolul 1
Introducere
1.1. Rezumat
Lucrarea este structurată în 4 capitole cu următorul conținut:
Capitolul 1 prezintă propunerea și structura aplicației din această lucrare.
Capitolul 2 descrie limbajele și mediile de programare în care a fost realizată aplicația, conceptele generale, le este explicată funcționalitatea și tipurile de date utilizate, de asemenea tot în acest capitol se prezintă programele în care au fost create și editate imaginile ce apar în aplicația propusă, acest capitol putându-se numi astfel Generalități.
Capitolul 3 prezintă structura aplicației din punctul de vedere al programatorului, la nivelul programării orientate pe obiecte, algoritmica principalelor funcții și de asemenea conceptele matematice folosite și introduse pe parcursul acestei lucrări.
Capitolul 4 este o parte a lucrării destinată utilizatorului, prin prezentarea modului de utilizare a aplicației și accesul la facilitățile oferite de aceasta, prin prezentarea principalelor butoane și acțiunea acestora din urmă.
1.2. Propunerea aplicației
În această lucrare se dorește construirea unui joc de memorie “Memory cards”, pentru copii de vârste cuprinse între 4-7 ani, care are următoarele condiții:
Jocul va avea 6 nivele pe diferite grade de dificultate: nivelul 1, respectiv nivelul 2 vor fi nivele cu grad de dificultate redus, ușor; nivelul 3, respectiv 4 vor fi nivele cu grad de dificultate mediu; iar ultimele două nivele: nivelul 5 și nivelul 6 vor avea grad de dificultate puțin mai ridicat.
La fiecare nivel vom avea steluțe de diferite culori, chei și jokeri.
Pentru fiecare nivel vom avea de găsit perechi de steluțe de aceeași culoare, pereche sau perechi de cheie-joker toate pentru a putea trece la următorul nivel.
Nivelul de dificultate va crește cu fiecare nivel deoarece va crește și numărul de chei, iar o cheie în plus trebuie să ne sporească atenția și să memorăm cât mai bine piesele, pentru că dacă nu memorăm cu atenție și vom da click pe pereche de chei, vom ajunge foarte ușor către Game over.
Pentru fiecare nivel trebuie să existe un timp, la primele două nivele timpul disponibil pentru găsirea perechilor să fie de 30 de secunde pentru fiecare nivel, iar la ultimele nivele timpul alocat să fie de 60 de secunde pentru fiecare nivel.
Pentru găsirea perechilor de steluțe să se acorde un punctaj de 10 puncte pentru fiecare pereche, iar pentru găsirea unei perechi cheie-joker să se acorde un punctaj de 50 puncte.
1.3. Structura aplicației
În prima fază a construcției aplicației se vor cuantifica datele conform cerințelor propuse anterior, aplicația fiind structurată pe 6 nivele cu diferite grade de dificultate.
La primul nivel vom avea două chei, un joker, iar restul pieselor vor fi perechi de steluțe. Pentru a putea trece la nivelul al doilea va trebui să găsim o pereche cheie-joker. Dacă vom găsi o pereche cheie-cheie jocul se va termina și va fi Game over.
La cel de-al doilea nivel vom avea trei chei, doi jokeri, iar restul pieselor vor fi perechi de steluțe. Pentru a putea trece la nivelul al treilea va trebui să găsim două perechi cheie-joker. Dacă vom găsi o pereche cheie-cheie jocul se va termina și va fi Game over.
La cel de-al treilea nivel vom avea patru chei, trei jokeri, iar restul pieselor vor fi perechi de steluțe. Pentru a putea trece la nivelul patru va trebui să găsim trei perechi cheie-joker. Dacă vom găsi o pereche cheie-cheie jocul se va termina și va fi Game over.
La nivelul 4 vom avea cinci chei, patru jokeri, iar restul pieselor vor fi perechi de steluțe. Pentru a putea trece la nivelul 5 va trebui sa găsim patru perechi cheie-joker. Dacă vom găsi o pereche cheie-cheie jocul se va termina și va fi Game over.
La nivelul 5 vom avea șase chei, cinci jokeri, iar restul pieselor vor fi perechi de steluțe. Pentru a putea trece la nivelul 6 va trebui să găsim cinci perechi cheie-joker. Dacă vom găsi o pereche cheie-cheie jocul se va termina și va fi Game over.
La nivelul 6 vom avea șapte chei, șase jokeri, iar restul pieselor vor fi perechi de steluțe. Pentru a putea câștiga jocul va trebui să găsim șase perechi cheie-joker. Dacă vom găsi o pereche cheie-cheie jocul se va termina, adică va fi Game over, iar dacă vom găsi cele 6 perechi chei-jokeri vom câștiga.
Capitolul 2
Generalități
2.1. Limbajul de programare C#
În dezvoltarea aplicației “Memory Cards” am folosit limbajul C# care este parte a arhitecturii .NET. C# este un limbaj de programare orientat-obiect conceput la sfârșitul anilor 90. C# simplifică mult scrierea de programe pentru sistemul de operare Windows. Ca parte a ansamblului strategiei .NET, dezvoltat de Microsoft, C# este direct înrudit cu C, C++ si Java. “Bunicul” limbajului C# este C-ul. De la C, C# moștenește sintaxa, multe din cuvintele cheie și operatorii. De asemenea, C# construiește peste modelul de obiecte definit in C++. Limbajul C# conține mai multe facilități inovatoare, dintre care cele mai importante se referă la suportul incorporat pentru componente software. C# dispune de facilități care implementează direct elementele care alcătuiesc componentele software, cum ar fi proprietățile, metodele și evenimentele. Poate cea mai importantă facilitate de care dispune C# este posibilitatea de a lucra într-un mediu cu limbaj mixt. C# are o legătură deosebită cu mediul său de rulare, arhitectura .NET. Pe de o parte, C# a fost dezvoltat pentru crearea codului pentru arhitectura .NET, iar pe de altă parte bibliotecile utilizate de C# sunt cele ale arhitecturii .NET. În C# există două categorii de tipuri de date pe care le-am folosit în crearea aplicației:
tipuri valoare
– tipul simplu predefinit: byte, char, int, float etc.
– tipul enumerare – enum
– tipul structură – struct
tipuri referință
– tipul clasă – class
– tipul interfață – interface
– tipul delegat – delegate
– tipul tablou – array
Toate tipurile de date sunt derivate din tipul System.Object. Toate tipurile valoare sunt derivate din clasa System.ValueType, derivată la rândul ei din clasa Object (alias pentru System.Object).
Pentru tipurile valoare, declararea unei variabile implică și alocarea de spațiu. Dacă inițial, variabilele conțin valoarea implicită specifică tipului, la atribuire, se face o copie a datelor în variabila destinație care nu mai este legată de variabila inițială. Acest proces se numește transmitere prin valoare.
2.2. Programarea orientată pe obiecte și principiile sale
Programarea orientată pe obiecte este o paradigmă de programare, axată pe ideea încapsulă- rii, adică grupării datelor și codului care operează asupra lor, într-o singură structură. Un alt concept important asociat programării orientate obiect este polimorfismul, care permite abstractizări ce permit o descriere conceptuală mai simplă a soluției.
Abstractizarea – Este posibilitatea ca un program să ignore unele aspecte ale informației pe care o manipulează, adică posibilitatea de a se concentra asupra esențialului. Fiecare obiect în sistem are rolul unui “actor” abstract, care poate executa acțiuni, își poate modifica și comunica starea și poate comunica cu alte obiecte din sistem fără a dezvălui cum au fost implementa-te acele facilitați. Procesele, funcțiile sau metodele pot fi de asemenea abstracte, și în acest caz sunt necesare o varietate de tehnici pentru a extinde abstractizarea.
Încapsularea – numită și ascunderea de informații: Asigură faptul că obiectele nu pot schimba starea internă a altor obiecte în mod direct (ci doar prin metode puse la dispoziție de obiectul respectiv); doar metodele proprii ale obiectului pot accesa starea acestuia. Fiecare tip de obiect expune o interfață pentru celelalte obiecte care specifică modul cum acele obiecte pot interacționa cu el.
Polimorfismul – Este abilitatea de a procesa obiectele în mod diferit, în funcție de tipul sau de clasa lor. Mai exact, este abilitatea de a redefini metode pentru clasele derivate. De exemplu pentru o clasă: figura putem defini o metodă arie, iar dacă Cerc, Dreptunghi, etc. vor extinde clasa Figura, acestea pot redefini metoda arie.
Moștenirea – Organizează și facilitează polimorfismul și încapsularea, permițând definirea și crearea unor clase specializate plecând de la clase (generale) deja definite – acestea pot împăr-tăși (și extinde) comportamentul lor, fără a fi nevoie de a-l redefini. Aceasta se face de obicei prin gruparea obiectelor în clase și prin definirea de clase ca extinderi ale unor clase existente. Conceptul de moștenire permite construirea unor clase noi, care păstrează caracteristicile și comportarea, deci datele și funcțiile membru, de la una sau mai multe clase definite anterior, numite clase de bază, fiind posibilă redefinirea sau adăugarea unor date și funcții noi. Se utilizează ideea: ”Anumite obiecte sunt similare, dar în același timp diferite”. O clasă moștenitoare a uneia sau mai multor clase de bază se numește clasă derivată. Esența moștenirii constă în posibilitatea refolosirii lucrurilor care funcționează.
Ideea POO (Programare Orientată Obiectual) este de a crea programele ca o colecție de obiecte, unități individuale de cod care interacționează unele cu altele, în loc de simple liste de instrucțiuni sau de apeluri de proceduri.
Obiectele POO sunt de obicei reprezentări ale obiectelor din viața reală, astfel încât programele realizate prin tehnica POO sunt mai ușor de înțeles, de depanat și de extins decât programele procedurale. Aceasta este adevărată mai ales în cazul proiectelor software com- plexe și de dimensiuni mari, care se gestionează făcând apel la ingineria programării.
2.3. Arhitectura .NET
Arhitectura .NET definește un mediu de programare care permite dezvoltarea și execuția apli-cațiilor indiferent de platformă. Aceasta permite programarea în limbaj mixt și oferă facilități de securitate și portabilitate a programelor. Este disponibilă deocamdată pentru platformele Windows. Legat de C#, arhitectura .NET definește două entități importante și anume biblioteca de clase .NET și motorul comun de programare sau Common Language Runtime (CLR). C# nu are o bibliotecă de clase proprie, ci utilizeaza direct biblioteca de clase .NET. De exemplu, când se rulează un program care efectuează operații de intrare-ieșire, cum ar fi afișarea unui text pe ecran, se utilizează biblioteca de clase .NET.
Figura 2.1 reprezintă un API (Application Programming Interface), adică o interfață pentru programarea de aplicații care structurează o parte din arhitectura .NET
Sursa imaginii precedente este următoarea:
https://en.wikipedia.org/wiki/Windows_Forms
2.4. Windows Forms Application
Multe dintre sistemele de operare creează evenimente și utilizează ferestre pentru a interacționa cu utilizatorii. În ceea ce privește Microsoft Windows, pentru a crea o fereastră sunt utilizate rutinele bibliotecii Win32. Pentru realizarea acestei aplicații am folosit Windows Forms Application din pachetul Microsoft Visual Studio Express 2013 for Windows Desktop.
Figura 2.2
În figura anterioară este prezentat Microsoft Visual Studio Express 2013 for Windows Desktop și crearea unui nou proiect în Windows Forms Application.
Arhitectura .NET conține un număr impresionant de clase, structuri, interfețe, metode etc. utile pentru crearea de aplicații, iar unele dintre acestea sunt destinate pentru a crea ferestre. Ceea ce in programarea Windows se numește o fereastră, în programarea .NET se numește form.
Figura 2.3 Figura reprezintă un nou form creat.
Acest form este caracterizat de un titlu, conține bare de navigare, un meniu, toolbars (toate acestea sunt opționale), iar ceea ce rămâne se numește zona client.
Pentru a crea un form creați în fapt un obiect de tipul unei clase care mostenește clasa Form din spațiul de nume System.Windows.Forms. Clasa Form este derivată din ContainerControl care este derivată la rândul ei din ScrollableControl. De fapt, lanțul moștenirilor este:
Object-MarshalByRefObject-Component-Control-ScrollableControl-ContainerControl-Form
Form-urile sunt obiecte care expun proprietăți ce definesc modul de afișare și metode care răspund evenimentelor ce definesc interacțiunea cu utilizatorul. Setând proprietățile unui form și scriind codul ce răspunde la evenimente, în fapt realizăm obiecte care se comportă conform cerințelor cerute de aplicație. Form-urile sunt instanțe ale clasei Form (sau ale unor clase derivate din aceasta).
Clasa Form conține un număr mare de metode, proprietăți, evenimente pentru a putea fi descrise într-o carte. Indicii privind funcționalitatea membrilor clasei Form pot fi găsite și în mediul de programare Visual Studio .NET. Voi începe să descriu câteva proprietăți asociate barei de titlu. Bara de titlu (control box) oferă utilizatorului informații despre program. În exemplele precedente s-a observat că aceasta conține câțiva itemi precum Minimize, Maximize, și Close. Aceștia pot fi controlați prin intermediul proprietăților:
ControlBox (determină dacă control box este afișat), HelpButton (indică dacă butonul de help este afișat. Acest buton este disponibil doar dacă MinimizeBox și MaximizeBox sunt ambii false), MaximizeBox (indică dacă butonul Maximize este inclus), MinimizeBox (indică dacă butonul Minimize este inclus), Text (include titlul ferestrei).
2.5. Funcționalitatea Windows Forms Application
Pentru a schimba culoarea de fundal a unui form se utilizează proprietatea BackColor. Culorile pot fi luate din structura Color aflată in spațiul de nume System.Drawing. Pentru a schimba culoarea de fundal se poate utiliza o imagine de fundal importată dintr-un fișier. O imagine este setată prin intermediul proprietății BackgroundImage care păstrează ca valoare un obiect de tip Image. Clasa Image din spațiul de nume System.Drawing conține metoda statică FromFile( ) care returnează un obiect de tip Image. Un obiect din clasa Image include proprietățile Width si Height. În program înălțimea și lungimea zonei client sunt setate în așa fel încât să aibă aceeași valoare ca și înălțimea și lățimea imaginii.
Schimbarea frontierei (border) unui form controlarea border-ului unui form este necesară din punct de vedere estetic. De asemenea determină dacă un form poate fi redimensionat sau nu. Pentru a modifica un border trebuie setată proprietatea FormBorderStyle cu una din următoarele enumerații:
Fixed3D – formul este fixat (nu redimensionat) și are border 3D. FixedDialog – formul este fixat (nu redimensionat) și are border gros. FixedSingle – formul este fixat (nu redimensionat) și are o singură linie ca border, etc.
Adăugarea componentelor și control-erelor. Cuvântul control este folosit pentru a se referi la obiectele de interfață cum ar fi butoane, bare de defilare (scroll bars), câmpuri de editare (labels), etc. Clasa Control implementează aspectul vizual al Form-urilor, iar fiecare obiect particular (buton, câmpuri de editare, etc.) implementează particularități specifice și știe să răspundă la mesajele adresate direct sau indirect.
Tehnic termenul Control se referă la orice obiect .NET care implementează clasa Control. În practică, utilizăm cuvântul Control pentru a ne referi la orice obiect vizual găzduit de un form. Aceasta este in contrast cu o componentă care are la fel de multe caracteristici asemănătoare cu un control însă nu expune o interfață vizuală. Spre exemplu un button este un control, însă un timer este o componentă.
În mediul de programare Visual Studio.Net, control-erele, componentele cât și containerele (acestea din urmă grupează un set de control-ere) se găsesc în Toolbox.
Figura 2.4, reprezintă containerele (Pointer, GroupBox, Panel, etc.) care se găsesc în Toolbox.
Există trei posibilități pentru a insera codul de tratare pentru un anumit eveniment. Primul dintre acestea începe prin a face dublu-click pe control-erul avut în discuție. Suntem duși la metoda care tratează evenimentul asociat prin default control-erului. (Dacă controlerul este un Button evenimentul asociat prin default este Click, dacă este un TextBox atunci evenimentul este TextChanged etc.). Dacă acesta este evenimentul dorit atunci codul dorit se introduce in blocul metodei care tratează evenimentul. Dacă însă se dorește un alt eveniment decât evenimentul default atunci sunt două posibilități. Una dintre acestea este de a alege evenimentul dorit din lista de evenimente a ferestrei Properties. Evenimentul scris pe fond gri este evenimentul default. Pentru a alege un alt eveniment și a adăuga metoda de tratare a evenimentului se face dublu click pe evenimentul dorit din lista de evenimente. Metoda care tratează evenimentul considerat este generata automat, numele metodei fiind foarte sugestiv. Spre exemplu, dacă controlerul se numește textBox1, evenimentul considerat este Click atunci metoda care tratează evenimentul se va numi textBox1_Click. Altfel, puteți tasta numele dorit de dumneavoastră pentru metoda de tratare a evenimentului în dreptul evenimentului dorit, iar apoi sa apăsați enter. Metoda având numele dorit de dumneavoastră va fi generată automat.
O altă opțiune este de a adăuga codul care crează evenimentul în blocul constructorului, după apelul metodei InitializeComponent(), iar apoi de a adăuga metoda care tratează evenimentul, bineînțeles în afara blocului constructorului.
Aceste ultime două posibilități necesită doi pași: crearea evenimentului și crearea metodei de tratare a evenimetului. În cele ce urmează voi prezenta utilitatea a câteva control-ere (Clase derivate din clasa Control a căror instanțe asigură o funcționalitate specifică).
Evenimente (Button): Cel mai important eveniment este Click. Acesta se produce atunci când utilizatorul face click pe button. De asemenea, evenimentul este lansat și atunci când button-ul este focalizat (is focused) și se apasă tasta Enter.
Clasa Label. Instanțele clasei Label sunt cele mai utilizate control-ere dintre toate. Aproape fiecare fereastră conține cel puțin un Label. Label-ul este un control-er simplu care își propune un singur lucru și anume sa afișeze un text pe un form.
Arhitectura .NET include două control-ere label:
-Label, label-ul standard din Windows;
-LinkLabel, un label similar celui anterior și derivat din acesta, însă se prezintă ca un link Internet. În mod uzual, nu este necesar nici un eveniment pentru Label-ul standard. În schimb, în cazul LinkLabel-ului este necesar cod suplimentar pentru a permite utilizatorului să acceseze pagina de internet afișată de Text-ul linkLabel-ului. Un număr mare de proprietăți pot fi setate pentru un Label. Multe dintre acestea sunt derivate din clasa Control.
Un TextBox se utilizează de regula atunci când se dorește introducerea unui text care este necunoscut la momentul design-ului. În egală măsură se pot introduce orice caractere, sau se poate forța introducerea doar a unor caractere, spre exemplu doar valori numerice.
Un RichTextBox are multe din proprietățile unui TextBox, însă prezintă și unele aspecte mai diverse. Dacă scopul principal al unui TextBox este acela de a obține, de la utilizator, un text scurt, un RichTextBox se utilizează pentru a introduce și afișa un text sub un anumit format (spre exemplu bold, underline sau italic). Utilizează un format standard pentru text numit Rich Text Format sau RTF.
2.6. Editoarele de imagini
Imaginile le-am creat folosind aplicația Paint și PiZap.
Paint este o caracteristică din Windows 7 care se poate utiliza pentru a crea desene într-o zonă de desenat goală sau în imagini existente. Multe dintre instrumentele pe care le utilizați în Paint se află în panglică, situată în partea de sus a ferestrei Paint.
Figura 2.5 reprezentând aplicația Paint și o imagine creată în aplicația amintită anterior.
PiZap este un program online, gratuit care poate fi folosit pentru a edita o anumită poză, pentru a face un colaj sau putem alege o imagine din galeria PiZap.
Figura 2.6 reprezintă aplicația PiZap și o imagine creată în aplicația amintită mai înainte.
Sursa imaginii anterioare este următoarea:
http://www.pizap.com/pizap
Capitolul 3
Creația programatorului(intervenția)
3.1. Crearea imaginilor
Prima dată am creat imaginile, cu numele bulina1.png, bulina2.png, bulina3.png, bulina4.png, bulina5.png, bulina6.png, cheie.png, joker.png, coperta.png, fundal1.png, fundal2.png și am pus extensia png pentru fiecare imagine creată.
Figura 3.1 reprezentând imaginile create în aplicațiile amintite în capitolul anterior, Paint respectiv PiZap folosite în jocul propus.
3.2. Stabilirea componentelor form-ului 1 și a form-ului 2
Pentru imaginile coperta.png, fundal1.png, fundal2.png nu trebuie să găsim imagini pereche, ele vor fi imagini inițiale, respectiv imagini de fundal pentru aplicația creată, iar pentru restul imaginilor bulina1.png, bulina2.png, bulina3.png, bulina4.png, bulina5.png, bulina6.png, cheie.png, joker.png va trebui să le găsim perechile corespunzătoare. Imaginea coperta.png care va fi imaginea inițială va fi folosită de funcția de reset pentru ca jocul să pornească din nou și din nou.
În Form1, respectiv în Form2 am pus pentru fiecare nivel un număr impar de căsuțe (PictureBox) pentru că dorim să găsim pentru fiecare steluță perechea potrivită, iar pentru cheie găsim jokerul potrivit și la fiecare nivel vom avea numărul cheilor mai mare cu unu decât numărul jokerilor.
În Form2 am pus un număr mai mare de PictureBoxes, deoarece jocul trebuie să se mai complice puțin.
La fiecare imagine, modul dimensiunii (Size Mode) îl vom pune pe întinderea imaginii (StretchImage).
Figura 3.2 reprezintă form-ul cu PictureBoxes la care Size Mode a fost selectat ca StretchImage.
Pentru a adăuga imaginile în form trebuie să mergem la proprietățile (Properties) proiectului, iar apoi la resurse (Resources), adăugăm toate imaginile create, pe care dorim sa le adaugăm în joc.
Figura 3.3 reprezintă resursele jocului, acestea conținând imaginile utiliazate în joc.
Am adăugat pe form un label (Label Time) cu textul (00:30) in form1, care arată timpul disponibil pentru jucarea primelor nivele, un label cu textul (00:60) in form2, care arată timpul disponibil pentru jucarea ultimelor nivele adică a nivelului 3, nivelului 4 , nivelului 5 , nivelului 6, respectiv un label Scor care va arăta punctajul în fiecare moment al jocului.
3.3. Namespace-uri utilizate
Namespace-ul (spațiul de nume) System.Windows.Forms oferă o varietate de clase de control pe care le puteți utiliza pentru a crea interfețe bogate. Unele controale sunt proiectate pentru introducerea datelor în aplicație, cum ar fi controlul TextBox și ComboBox. Alte controale afișază date de aplicație, cum ar fi etichete și ListView. Spațiul de nume prevede, de asemenea controale pentru comenzile din cadrul aplicației, cum ar fi butone. Controlul WebBrowser și clasele HTML administrate, cum ar fi HtmlDocument, vă permit să afișați și pagini HTML reușite în Windows Forms. Controlul MaskedTextBox este un control avansat de introducere de date care vă permite să definiți măști care acceptă în mod automat sau resping datele introduse de utilizator. În plus, puteți utiliza controlul PropertyGrid pentru a crea propriul Windows Forms Designer care afișează proprietățile de designer vizibile ale controalelor .
Namespace-ul System.Collections.Generic conține interfețe și clase care definesc colecțiile generice, care permit utilizatorilor să creeze colecții puternice care oferă o mai bună siguranță și performanță.
Spațiul de nume System.ComponentModel prevede clase care sunt utilizate pentru a pune în aplicare run-time și design-time comportamentului componentelor și controalelor . Acest spațiu de nume include clasele de bază și interfețele de punere în aplicare a atributelor și convertoare de tip, cu caracter obligatoriu la surse de dat , precum și a componentelor de acordare a licențelor .
Spațiul de nume System.Data oferă acces la clase care reprezintă arhitectura ADO.NET. ADO.NET vă permite să creați componente care gestionează eficient datele din sursele de date multiple.
System.Drawing namespace oferă acces la GDI (Graphics Device Interface) + funcționalitatea graficelor de bază. Mai multe funcționalități avansate sunt furnizate în spațiile de nume System.Drawing.Drawing2D , System.Drawing.Imaging și System.Drawing.Text.
Namespace-ul System.Text conține clase care reprezintă codificările de caractere ASCII și Unicode; clasele de bază abstracte pentru transformarea blocurilor de caractere și blocurilor de bytes; și o clasă ajutor care manipulează și obiecte formate String fără a crea instanțe intermediare de String.
Spațiul de nume System.Linq oferă clase și interfețe care susțin interogări care utilizează Language-Integrated Query (LINQ).
Spațiul de nume System.Threading.Tasks prevede tipuri care simplifică activitatea de a scrie cod concurent și asincron. Principalele tipuri sunt System.Threading.Tasks.Task care reprezintă o operațiune asincron care poate fi pus pe pauză și anulat , precum și System.Threading.Tasks.Task <TResult> , care are sarcina de a returna o valoare. Clasa System.Threading.Tasks.TaskFactory oferă metode statice pentru crearea și pornirea sarcinilor, iar clasa System.Threading.Tasks.TaskScheduler asigură firul în infrastructura de programare implicită.
System.Threading spațiul de nume oferă clase si interfețe care permit programarea multifir. În plus față de clasele pentru sincronizarea activităților fir și acces la date (Mutex, Monitor, AutoResetEvent, etc), acest spațiu de nume include o clasă ThreadPool care vă permite să utilizați un grup de fire de sistem furnizate și o clasă timer care execută metode de apel invers pe fir.
3.4. Funcții, metode, variabile, clase utilizate pentru crearea aplicației
În cod am declarat o variabilă de tip Boolean care acceptă doar true sau false, deci dacă are voie să dea click, îl punem true, pentru că are voie sa dea click. Apoi am pus un PictureBox, numit _firstGuess, adică prima imagine dintre cele două care se vor nimeri sau nu să fie perechi, apoi un număr Random pentru că imaginile vor apărea în mod aleator în acele PictureBoxes.
Declarăm un timer, numit _clickTimer care e un nou timer, un interval de 30 de secunde și un alt timer care l-am numit Timer, care are deja Interval=1000, adică o secundă.
Declarăm un alt timer, numit _copertaTimer care e un nou timer, va ține imaginile pereche o secundă să le vedem și apoi le va ascunde. Mai declarăm încă un timer, numit _copertinaTimer care e tot un nou timer.
În public Form1() dupa InitializeComponent(); scriem timerul de click și timer-ul _copertaTimer să aibă tot timpul o secundă, adică atunci când dăm click pe două imagini care nu sunt la fel sau sunt la fel, să aștepte o secundă pentru ca noi să putem da din nou click pe alte imagini și acesta va fi un nou delegate, adică un nou timer.
Scriem _copertinaTimer care e un timer și va aștepta o secundă, iar apoi va întoarce jokerii și nu îi va considera pereche.
Apoi am setat încă de la inceput condițiile cu care jocul va porni: la primul nivel numărul de chei va fi egal cu 2, iar numărul de jokeri va fi 1. Numărul de perechi de chei și jokeri îl vom seta și îi vom da valoarea de start 0. Pentru jocul nostru vom avea nevoie și de un scor care îl vom inițializa pentru început cu valoarea 0.
Am folosit o funcție PictureBoxes care prin metoda Get va returna fiecare control de tip PictureBox din acest form de tip Array.
IEnumerable este echivalent cu un Array, apoi spunem să ne returneze o nouă imagine, iar apoi am dat numele imaginilor care dorim să le pună in form: bulina1.png, bulina2.png, bulina3.png, bulina4.png, bulina5.png, bulina6.png, cheie.png, joker.png.
Start Game Timer –
Aici avem un timer Start și un timer Stop și intervalul de 30 de secunde dintre cele 2 amintite anterior, iar timer.tick inseamnă atunci când se incrementează de fiecare dată cu secunda respectivă. Am declarat o metodă delegate și tot timpul acel ticks va primi un -1, se decrementează cu câte un 1. Când ajunge la -1, adică la 00:00, îl oprește îmi apare mesajul că timpul s-a scurs, “Time up” și apoi apare mesajul “Game over” și apoi închide jocul. Ieșind din if va primi tot timpul o variabilă dinamică (secunde). TimeSpan este o clasă care are o funcție, FromSeconds care operează cu timpul din secunde: 30 pentru aplicația noastră. Acel label, lblTime, va fi egal cu stringul “00:” + time.ToString “ss”, un string format din secunde.
Setează nivelul:
În această funcție se crează un nivel nou, iar la primul nivel are setat un număr de perechiSpecialeGasite = 0. Apoi este folosită instrucțiunea switch. Aceasta instrucțiune e folosită pentru a compara o valoare cu altele dintr-o listă și în funcție de acea valoare se execută codul asociat ei in lista "switch". Astfel avem câte un caz pentru fiecare nivel. Primul nivel este setat in funcție de ceea ce găsește în primul caz. Se vor pune 2 chei, 1 joker, iar in labelul de nivel va pune Nivel 1, apoi pe măsura ce crește numărul nivelului va crește și numărul de jokeri, respectiv numărul de chei cu 1.
Funcția de resetare: ResetImages
Pentru fiecare variabilă pic din PictureBoxes, va selecta tagul imaginii ca null și vizibilitatea ca true, deci va pune prima imagine, coperta.png, peste tot și o va face vizibilă peste tot.
Apoi va ascunde imaginile, va crea iarăși un Random imagini să își schimbe pozițiile, ticks iarăși va fi 30 și va porni din nou timpul.
HideImages
Pentru fiecare variabilă pic din PictureBoxes, va primi această imagine de copertă, care este aproape echivalentul tagului null din funcția de ResetImages.
GetFreeSlot
Înseamnă că imaginea bulina1.png, bulina2.png, bulina3.png, bulina4.png, bulina5.png, bulina6.png, cheie.png să apară maxim de două ori, la primul nivel. Va lua o variabilă PictureBox din PictureBoxes, dacă tagul nu este null, va returna PictureBox, altfel returnează null.
SetRandomImages
În această funcție vom folosi GetFreeSlot creată anterior. Avem o variabilă rnd care este un nou Random, o variabilă images pentru imaginile din listă, o variabilă pictureboxes pentru PictureBoxes din listă. Pentru i pornind de la 0 și mergând până la numarMaximJokeri, merge tot adunând câte un 1, ia o variabilă picturebox = GetFreeSlot și tagul imaginii 7 care se numește joker, apoi tot pentru aceleși condiții ia o variabilă picturebox = GetFreeSlot și tagul imaginii 6 care se numește cheie.
Apoi pune nextPicturebox = GetFreeSlot(); și cât timp nextPicturebox este nul, ia un întreg randomBulina și într-un do-while pune ca random următoarea bulină cât timp
randomBulina == 6 || randomBulina == 7. Operatorii logici || compară operații, expresii de cod, iar rezultatul lor este unul din valorile TRUE (Adevărat) sau FALSE (Fals). Apoi in următorul picture box pune random o altă bulină și tot așa, iar apoi pune bulinele încă o dată pentru a fi bulinele pereche.
Procesează selecția
Aici am stabilit că dacă vom găsi cheie-chei va fi Game over sau dacă perechiSpecialeGasite = numarMaximJokeri va fi Next Level. Perechile speciale găsite sunt perechile de cheie – joker sau joker – cheie.
Altfel nu sunt îndeplinite condițiile de mai sus va AscundePerechea găsită. Alfel dacă găsește pereche de joker – joker nu trebuie să facă nimic, va întoarce perechea și ne va da posibilitatea să căutăm perechile dorite.
Ascunde perechea
ClickImage
Acestă funcție face următorul lucru: dacă nu este voie sa dea click pe PictureBox, atunci se returnează din nou, adică atâta verifică dacă are voie să dea click, până are voie. Apoi declar o variabilă dinamică pic, care este sender transformat în PictureBox. Acest sender care este obiect, este cel are trimite click-ul respectiv pe imagine, pe PictureBox.
private void ClickImage (object sender, EventArgs e) este un eveniment care înștiințează, PictureBox, pentu că sender-ul (adică noi) am trimis un click pe el și apoi sa execute următorul lucru, dacă firstGuess, adică prima imagine descoperită, pe care am dat click este null, atunci prima imagine va deveni pic, pe care noi pointăm și imaginea acelui pic va fi tagul respectiv, convertit în imagine și va returna doar atât.
_clickTimer
Este un eveniment care ne lasă o secundă să stăm, până când avem voie să dăm click pe celelalte, are doar HideImages.
_allowClick= true, zice că avem voie, așteaptă o secundă și apoi îl oprește _clickTimer.Stop();
_copertaTimer
Este un eveniment care ne lasă o secundă să stăm, până când avem voie să dăm click pe celelalte imagini. Pune _pb1, _pb2 ca și fals, iar apoi are HideImages(). Îți dă voie sa dai click, iar apoi se oprește _copertaTimer.Stop();
_copertinaTimer
Este un eveniment care ne lasă o secundă să stăm, până când avem voie să dăm click pe celelalte, are doar HideImages. _allowClick= true, zice că avem voie, așteaptă o secundă și apoi îl oprește _copertinaTimer.Stop();
Tot ce am explicat mai sus cu referire la funcții, metode, variabile erau pentru Form1, dar aceleași lucruri sunt valabile și în Form2 doar că în cel de-al doilea form, avem mai multe PictureBoxes puse, pentru că vor trebui să fie mai multe perechi de jokeri-chei față de formul anterior.
3.5. Butoanele din formul Start
Pentru fiecare din butoanele: Play, Help, Extra și Exit am pus câte un Button din Toolbox.
Figura 3.4 reprezintă form-ul de Start al jocului.
Pentru fiecare din butoanele din form-ul Start am creat evenimente cu următoarele instrucțiuni:
pentru butonul Play am creat un eveniment ca atunci când vom da click pe el să ne ducă în form1 și să îl afișeze.
pentru butonul Help am creat un eveniment
pentru ca atunci când vom da click pe el să ne ducă în form3, iar acesta din urmă are următorul cod și are creat un eveniment care va încărca fișierul extern help.rtf (rich text format), care conține instrucțiuni pentru utilizator cu privire la joc.
Figura 3.5 Conținutul Form3.cs
pentru butonul Extra am creat un eveniment, care atunci când dăm click pe el va deschide formul extra.text și îl va afișa. Extra.txt se găsește în directorul curent, mye este o variabilă locală, iar ShowDialog(); afișează formul ca o casetă de dialog modală.
pentru butonul Exit am creat tot un eveniment, care atunci când dăm click pe el va închide aplicația.
Capitolul 4
Utilizare
Așa cum am promis lucrarea se încheie cu un capitol destinat utilizatorului, prin prezentarea modului de utilizare a aplicației și accesul la facilitățile oferite de aceasta.
4.1. Instrucțiuni
Jocul are 6 nivele pe diferite grade de dificultate, iar la fiecare nivel avem steluțe de diferite culori, chei și jokeri. Pentru fiecare nivel trebuie găsite perechi de steluțe de aceeași culoare, pereche sau perechi de cheie-joker toate pentru a putea trece la următorul nivel. Gradul de dificultate va crește cu fiecare nivel deoarece va crește și numărul de chei, iar o cheie în plus trebuie să ne sporească atenția și trebuie gc f,să memorăm cât mai bine piesele, pentru că dacă nu memorăm cu atenție și vom da click pe pereche de chei, vom ajunge foarte ușor către Game over și mai greu către Finish. Pentru fiecare nivel există un timp, la primele două nivele timpul disponibil pentru găsirea perechilor să fie de 30 de secunde pentru fiecare nivel,
Figura 4.1 – Design pentru Form1
iar la ultimele nivele timpul alocat să fie de 60 de secunde pentru fiecare nivel.
Figura 4.2 – Design pentru Form2.
Dacă cele 30 de secunde, respectiv cele 60 de secunde expiră atunci va apărea mesajul:
Figura 4.3 – MessageBox pentru Times Up
iar apoi dând click pe butonul OK va afișa următorul mesaj care va indica și scorul obținut până când timpul a expirat, iar dacă timpul s-a terminat va fi Game over.
Figura 4.4 – MessageBox pentru GameOver
Pentru găsirea perechilor de steluțe se acordă un punctaj de 10 puncte pentru fiecare pereche, iar pentru găsirea unei perechi cheie-joker se acordă un punctaj de 50 puncte.
La primul nivel vom avea două chei, un joker, iar restul pieselor vor fi perechi de steluțe. Pentru a putea trece la nivelul al doilea va trebui să găsim o pereche cheie-joker. Dacă vom găsi o pereche cheie-cheie jocul se va termina și va fi Game over.
La cel de-al doilea nivel vom avea trei chei, doi jokeri, iar restul pieselor vor fi perechi de steluțe. Pentru a putea trece la nivelul al treilea va trebui să găsim două perechi cheie-joker. Dacă vom găsi o pereche cheie-cheie jocul se va termina și va fi Game over.
La cel de-al treilea nivel vom avea patru chei, trei jokeri, iar restul pieselor vor fi perechi de steluțe. Pentru a putea trece la nivelul patru va trebui să găsim trei perechi cheie-joker. Dacă vom găsi o pereche cheie-cheie jocul se va termina și va fi Game over.
La nivelul 4 vom avea cinci chei, patru jokeri, iar restul pieselor vor fi perechi de steluțe. Pentru a putea trece la nivelul 5 va trebui sa găsim patru perechi cheie-joker. Dacă vom găsi o pereche cheie-cheie jocul se va termina și va fi Game over.
La nivelul 5 vom avea șase chei, cinci jokeri, iar restul pieselor vor fi perechi de steluțe. Pentru a putea trece la nivelul 6 va trebui să găsim cinci perechi cheie-joker. Dacă vom găsi o pereche cheie-cheie jocul se va termina și va fi Game over.
La nivelul 6 vom avea șapte chei, șase jokeri, iar restul pieselor vor fi perechi de steluțe. Pentru a putea câștiga jocul va trebui să găsim șase perechi cheie-joker. Dacă vom găsi o pereche cheie-cheie jocul se va termina, adică va fi Game over, iar dacă vom găsi 6 perechi de chei-jokeri vom ajunge la Finish, adică vom câștiga.
4.2. Interfața
Jocul Memory Cards începe prin următoarea fereastră:
Figura 4.5 – Design pentru form-ul Start
Dacă dăm click pe butonul Play vom putea juca jocul Memory Cards, unde observăm mai multe căsuțe, ele fiind cărțile noastre de joc.
Figura 4.6 – Nivelul 1
Observăm ca pe ecran mai apare numărul nivelului, in cazul de față Nivel 1, care are alocat un timp de 30 de secunde pentru a trece la nivelul 2, deci pentru a găsi perechile de steluțe sau perechile de chei-jokeri. Tot aici mai avem afișat un scor, în funcție de perechile găsite primim 10 puncte pentru perechi de steluțe, respectiv 50 de puncte pentru perechi chei-jokeri.
Dând click pe butonul Help, vedem faptul că utilizatorul are la dispoziție următoarele instrucțiuni:
Figura 4.7 – conținutul butonului Help
Prin click pe butonul Extra aflăm unele informații despre autorul lucrării:
Figura 4.8 – conținutul butonului Extra.
Dacă dăm click pe butonul Exit, vom închide aplicația înainte de a începe să jucăm.
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Construirea Unui Joc de Memorie (ID: 149654)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
