Tema 3. TetriPic

Responsabili

Informații

  • 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

  • Obiective
  • Introducere
  • Formatul BMP
  • Cerinte
  • Formatul datelor de intrare
  • Formatul datelor de iesire
  • Observatii si mentiuni
  • Testare
  • Notare

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

Structura formatului BMP

Vom lucra cu fisiere BMP, deci, cu fisiere binare.

O imagine BMP are urmatoarea structura:

  • un File Header care are urmatoarele campuri:
    1. signature – 2 octeti - literele 'B' si 'M' in ASCII;
    2. file size – 4 octeti – dimensiunea intregului fisier;
    3. reserved – 4 octeti – nefolosit;
    4. 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:
    1. size – 4 octeti – dimensiunea Info Header-ului, care are o valoare fixa, 40;
    2. width – 4 octeti – latimea matricii de pixeli (numarul de coloane);
    3. height – 4 octeti – inaltimea matricii de pixeli (numarul de randuri);
    4. planes – 2 octeti – setat la valoarea fixa 1;
    5. 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;
    6. compression – 4 octeti – tipul de compresie. Acest camp va fi 0;
    7. image size – 4 octeti – se refera la dimensiunea matricii de pixeli, inclusiv padding-ul adaugat (vedeti mai jos);
    8. 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 :).
    9. y pixels per meter – la fel ca mai sus;
    10. 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;
    11. 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:
    1. 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.
    2. 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;
    3. 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)

1. Piese

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

Pentru a face rotirea pieselor intr-un mod cat mai usor puteti folosi matrici de rotatie.

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.

Formatul datelor de intrare si iesire

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:

  • fisierul de output se va numi: task3.bmp

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.

Formatul datelor de intrare si iesire

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:

  • Z cu rotatie de 0 grade pe coloana 4
  • I cu rotatia de 0 grade pe coloana 11

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.

Formatul datelor de iesire:

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

Pentru a rula taskurile, va sfatuim sa folositi parametrii in linia de comanda.

Exemplu:

./myProgram 1 - va rula taskul numarul 1

Resurse

Resursele pentru tema se pot descarca de aici. Sunt prezente:

  • bmp_header.h: headerul care contine declaratiile struct-urilor pe care le veti folosi in citirea unui fisier BMP;
  • checkerul si testele folosite pentru corectarea temei;

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

  • Nu folosiți variabile globale.
  • Fiți consistenți în ceea ce privește Coding Style-ul.

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.
programare/teme_2018/tema3_2018_cbd.txt · Last modified: 2019/01/04 14:32 by bianca.tazlauanu
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