Tema 3. TetriPic
Responsabili
Data publicare: 11.12.2019
Deadline Soft: 16.01.2019
Deadline Hard: 16.01.2019
04.01.2019: Update checker - Actualizare teste si checker
Obiective
Utilizarea structurilor de date
Lucrul cu fisiere
Lucrul cu alocarea memoriei
Abordarea cu pasi mici a unei probleme mai complexe
Cuprins
Introducere
Sper ca il mai tineti minte pe Gigel, acum deja initiat in tainele programarii, dar care doreste sa isi extinda cunostintele in continuare. Dupa finalizarea cu succes a proiectului TetriBit, i-a placut atat de mult incat a zis ca poate sa faca ceva si mai bine de atat. Asa a ajuns la ideea de a-si face propiul joc de Tetris, dar in imagini. Atunci a stiu ca se va distra de minune in vacanta de iarna cu acest nou proiect pe care l-a intitulat intr-un mod foarte inspirat TetriPic. :D
Vom lucra cu fisiere BMP, deci, cu fisiere binare.
O imagine BMP are urmatoarea structura:
un File Header care are urmatoarele campuri:
signature – 2 octeti - literele 'B' si 'M' in
ASCII;
file size – 4 octeti – dimensiunea intregului fisier;
reserved – 4 octeti – nefolosit;
offset – 4 octeti – offsetul de la inceputul fisierului pana la inceputului bitmap-ului, adica al matricii de pixeli.
un Info Header care poate avea structuri diferite, insa noi vom lucra cu cel care se numeste BITMAPINFOHEADER. Are urmatoarele campuri:
size – 4 octeti – dimensiunea Info Header-ului, care are o valoare fixa, 40;
width – 4 octeti – latimea matricii de pixeli (numarul de coloane);
height – 4 octeti – inaltimea matricii de pixeli (numarul de randuri);
planes – 2 octeti – setat la valoarea fixa 1;
bit count – 2 octeti – numarul de biti per pixel. In cazul nostru va avea mereu valoarea 24, adica reprezentam fiecare pixel pe 3 octeti, adica cele 3 canale, RGB;
compression – 4 octeti – tipul de compresie. Acest camp va fi 0;
image size – 4 octeti – se refera la dimensiunea matricii de pixeli, inclusiv padding-ul adaugat (vedeti mai jos);
x pixels per meter – 4 octeti – se refera la rezolutia de printare. Pentru a simplifica putin tema, veti seta acest camp pe 0. Nu o sa printam imaginile :).
y pixels per meter – la fel ca mai sus;
colors used – numarul de culori din paleta de culori. Aceasta este o sectiune care va lipsi din imaginile noastre BMP, deoarece ea se afla in general imediat dupa Info Header insa doar pentru imaginile care au campul bit count mai mic sau egal cu 8. Prin urmare, campul va fi setat pe 0;
colors important – numarul de culori importante. Va fi, de asemenea, setat pe 0, ceea ce inseamna ca toate culorile sunt importante.
BitMap-ul, care este matricea de pixeli si care ocupa cea mai mare parte din fisier. Trei lucruri trebuie mentionate despre aceasta:
pixelii propriu-zisi se afla intr-o matrice de dimensiune height x width, insa ea poate avea o dimensiune mai mare de atat din cauza paddingului. Acest padding este adaugat la sfarsitul fiecarei linii astfel incat fiecare linie sa inceapa de la o adresa (offset fata de inceputul fisierului) multiplu de 4. Mare atentie la citire, pentru ca acest padding trebuie ignorat (fseek). De asemenea, la scriere va trebui sa puneti explicit valoarea 0 pe toti octetii de padding.
este rasturnata, ceea ce inseamna ca prima linie in matrice contine de fapt pixelii din extremitatea de jos a imaginii. Vedeti exemplul de mai jos;
canelele pentru fiecare pixel sunt in ordinea BGR (Blue Green Red).
Header-ele pe care le puteti folosi in implementare se afla in scheletul de cod asociat temei.
Urmatiti cu foarte mare atentie exemplul de pe
aici si incercati sa intelegeti cum e reprezentata o imagine BMP
inainte de a incepe implementarea. Va recomandam sa faceti mai intai citirea si scrierea unei imagini BMP
inainte de a incepe rezolvarea task-urilor. Daca e ceva neclar, puteti intreba oricand pe forum.
Cerinte
Pentru inceput Gigel se gandeste in ce fel ar putea sa isi deseneze piesele de joc. Incepe sa caute ce forma ar trebui sa aiba si ajunge la urmatoarele concluzii:
Va folosi 7 piese cu formele, dimensiunile si culorile urmatoare:
Piesa I: → patru unitati puse una dupa alta pe orizontala; Culoarea: albastru rgb(0,0,255)
Piesa O: → patru unitati puse in forma de patrat; Culoarea: galben rgb(255,255,0)
Piesa S: → patru unitati puse doua cate doua pe orizantala; Culoarea: rosie rgb(255,0,0)
Piesa Z: → patru unitati puse doua cate doua pe orizontala; Culoarea: verde rgb(0,255,0)
Piesa L: → patru unitati puse una dupa alta pe orizontala; Culoarea: portocaliu rgb(255,140,0)
Piesa J: → patru unitati puse in forma de J; Culoarea: roz rgb(255,0,255)
Piesa T: → patru unitati puse una dupa alta pe orizontala; Culoarea: mov rgb(130,0,255)
Atentie!
O unitate este formata dintr-un patrat cu latura egala cu 10 pixeli.
Atentie!
Pentru fiecare piesa va trebui sa tineti cont ca se poate roti in directia acelor de ceas si poate fi pozitionata pe orice coloana din cadrul tabelei (atat timp cat nu iese in afara tablei de joc)
Memoria necesara pentru lucrul cu imagini va trebui alocata dinamic, iar dimensiunile folosite sa nu fie hard-codate!
Cerinta I (28p)
Creati 7 imagini de tip bmp, cate una pentru fiecare piesa de joc. Imaginile vor avea urmatorul format: piesa in pozitia initiala (rotatie 0 → ca in imaginea 1) + un chenar alb, de dimensiune 10 px (255,255,255). Imaginile se vor numi: piesa_{nume_piesa}.bmp
Exemplu: Pentru piesa L, vom crea o imagine de 40×50 pixeli, iar coltul din stanga sus al piesei va fi amplasat la coordonata 10:10.
In imaginea de sus avem piesa S, asezata pe coloana 1 (coloana 1 incepe de la pixelul 10 si se termina la pixelul 19). Marginile (liniile 0, 3 si coloanele 0, 4) fac parte din bordura, si vor fi colorate cu alb. De asemenea, fundalul va fi tot alb.
Cerinta II (42p)
Creati cate 3 imagini pentru fiecare piesa (total: 21 imagini), reprezentand cele 3 rotatii ale piesei (90º, 180º, respectiv 270º). Se aplica aceleasi reguli ca in cazul primei cerinte (dupa rotire, se aplica o bordura de 10×10 pixeli in jurul piesei). Imaginile se vor numi: piesa_{nume_piesa}_{rotatie}.bmp
Nume imagine: piesa_I_90.bmp
Cerinta III (30p)
Fiind data o lista de piese si mutari, reconstruiti imaginea tablei dupa ce toate piesele au fost puse pe pozitie.
Pasii pe care trebuie sa ii urmati pentru a aseza piesele sunt urmatorii:
Piesa trebuie rotita
Piesa trebuie pusa, cu cea mai din stanga patratica, pe coloana primita in comanda
Se garanteaza ca, indiferent de comanda primita, piesa nu va iesi din imagine
Daca un rand este plin, acesta va disparea, iar toate patratele de mai sus, vor cadea cu un rand.
Daca miscarea ce urmeaza ar incheia jocul (in momentul in care pozitionam noua piesa, aceasta iese in partea de sus din tabla de joc), mutarile ulterioare vor fi ignorate si se va genera imaginea tablei de dupa pozitionarea piesei ce a incheiat jocul (bucata ce iese in afara tablei de joc va fi desenata peste chenarul alb).
Pentru a primi rezultate corecte, verificarea de sfarsit de joc trebuie sa aiba loc inainte de verificarea pentru randuri pline
Atentie!
Numerotarea coloanelor se face de la 0.
Din fisierul cerinta3.in veti citi miscarile. Formatul fisierului:
N H L
(N mutari cu urmatorul format:)
numePiesa rotatie coloana
Legenda:
N → numarul de mutari; se garanteaza N < = 50
H → inaltimea imaginii; se garanteaza H < = 30
L → latimea imaginii; se garanteaza L < = 20
numePiesa → un caracter ce reprezinta piesa ce urmeaza sa fie folosita ( O, I, L, etc)
rotatie → 0, 90, 180 sau 270
coloana → coloana pe care va fi plasata cea mai din stanga patratica a piesei 0 < = coloana < H - lungime_piesa - nu va exista cazul in care piesa sa nu se afle integral in tabla de joc (partea neagra)
Fisierul de iesire:
Atentie!
Tabla de joc va fi constituita din doua parti:
partea alba formata din patratele albe (255, 255, 255) care are dimensiunea 4 x L (4 linii de L coloane)
partea neagra (aflata sub partea alba) formata din patratele negre (0, 0, 0) care are dimensiunea H x L (H linii si L coloane)
Piesele vor fi plasate in partea neagra a tablei.
Exemplu:
Pentru un input de forma:
7 7 11
I 90 0
I 0 0
S 180 1
O 90 4
S 270 0
S 270 7
I 0 6
Va rezulta urmatoarea imagine de output:
Cerinta IV (40p)
Fiind data o tabla de joc intr-o imagine bmp si o lista de miscari, dorim sa continuam jocul, pornind de la tabla deja existenta. Astfel, piesele din lista trebuie asezate in mod corespunzator in imaginea data. Spre deosebire de punctul anterior, de data aceasta nu vom mai porni de la o tabla goala, ci de la una care deja are unele piese asezate.
In momentul in care executati comenzile, trebuie sa tineti cont de urmatarele reguli:
Se citeste tabla de joc din cerinta4.bmp
Se citesc miscarile din cerinta4.in
fisierul de output se va numi: task4.bmp
Exemplu:
Imaginea de input
Pentru un input de forma:
2
Z 0 4
I 0 11
Se vor adauga doua piese:
Va rezulta urmatoarea imagine de output
Bonus (30p)
Fiind data o tabla de joc intr-o imagine bmp, dorim sa generati un fisier in care sa listati, in orice ordine doriti, piesele din imagine + rotatiile lor. Numele imaginii de intrare va fi: bonus.bmp.
In fisierul text bonus.out, va trebui sa generati datele in urmatorul format:
N
(N linii cu formatul:)
numePiesa rotatie coloana
* N -> numarul total de piese; Se garanteaza N <= 5000
* numePiesa -> caracterul ce identifica piesa
* rotatie -> rotatia piesei in imagine (in cazul pieselor care arata la fel pentru 2 rotatii diferite, se va alege rotatia cu valoarea mai mica)
* coloana de pe care incepe piesa
* nu este importanta ordinea in care sunt puse piesele
Atentie!
tabla primita la intrare contine doar piese intregi (nu exista cazul in care o piesa nu este completa)
piesele sunt cele mentionate mai sus, inclusiv culorile
nu vor exista cazuri in care o anumita imagine sa aibe metode diferite de generare, fiecare imagine va avea o singura solutie posibila corecta
Exemplu:
Pentru aceasta imagine de input va rezulta urmatorul output:
4 5 7
I 0 0
I 0 1
I 0 2
L 180 5
Mentiuni
task-urile au un total de 140 puncte (fara bonus). Celelalte 10 puncte se vor acorda pentru coding style si README.
o patratica va avea dimensiunea de 10×10 pixeli, cu toti pixelii de aceeasi culoare (nu vor avea bordura neagra), in functie de piesa din care fac parte.
rezolvarea oricarei cerinte nu este conditionata de rezolvarea/corectitudinea celorlalte. Daca vreti sa rezolvati doar cerinta 3 si bonusul faceti doar fisierele specifice lor si o sa primiti punctajul corespunzator.
Atentie!
Sistemul de coordonate folosit pentru constructia tablei nu este acelasi cu sistemul de coordonate al imaginii. Sistemul de coordonate al tablei se refera la patratele (10×10 pixeli), in timp ce sistemul de coordonate al imaginii foloseste pixelul drept unitate de masura.
Exemplu:
Comanda: S 0 5 va genera o piesa de tip S, cu rotatie 0, pe coloana 5 a tablei de joc. Acest lucru se traduce, in imagine, prin construirea piesei incepand cu pixelul 50.
Testare
Testarea se va face automat, cu ajutorul unui checker. Trimiterea temei se va face pe vmchecker. Arhiva trebuie sa contina header-ul bmp_header.h, fisierele header si fisierele .c facute de voi, Makefile si README.
Makefile-ul pe care il veti incarca va contine urmatoarele reguli:
build
run_task1
run_task2
run_task3
run_task4
run_bonus
clean
Resurse
Resursele pentru tema se pot descarca de aici. Sunt prezente:
Imaginile din enuntul temei nu au formatul BMP (nu este permisa incarcarea fisierelor BMP pe aceasta pagina). Folositi doar imaginile din arhiva de mai sus pentru a va testa tema!
Observații
Listă depunctări
o temă care nu compilează și nu a rulat pe vmchecker nu va fi luată în considerare
o temă care nu rezolvă cerința și trece testele prin alte mijloace nu va fi luată în considerare
[-1.0]: warning-uri la compilare (este obligatorie folosirea în fișierul Makefile a flag-ului de compilare -Wall pentru regula build)
[-1.0]: numele variabilelor nu sunt sugestive
[-1.0]: linii mai lungi de 80 de caractere
[-5.0]: abordare ineficientă
în cadrul cursului de programare nu avem ca obiectiv rezolvarea în cel mai eficient mod posibil a programelor; totuși, ne dorim ca abordarea să nu fie una ineficientă, de genul să nu folosiți instrucțiuni repetitive acolo unde clar nu era cazul, etc.