Tema 4 – Pregătire Examen

Responsabili

  • Data publicare: 30 Noiembrie 2020
  • Deadline: 22 Ianuarie 2021, ora 23:55 Soft + Hard
Întrebări

Dacă aveți nelămuriri, puteți să ne contactați pe forumul dedicat temei de casă nr. 4.
La orice întrebare vom răspunde în maxim 24 de ore.
Nu se acceptă întrebări în ultimele 24 de ore înainte de deadline.

Obiective

  • să se respecte formate stricte de intrare/ieșire
  • să se însușească cunoștințele necesare pentru examen
  • să se înțeleagă si sa se utilizeze operații cu pointeri la functii
  • sa se înțeleagă si sa se utilizeze operații cu array-uri de pointeri

Introducere

Topicul temei este jocul “Among us”. Pentru această temă se cere o implementare simplificată a unui model asemănător cu jocul cunoscut.

Organizarea temei

TOATE modificările de cod se vor realiza DOAR in fișierul tema4.c. Modificarea oricărui alt fișier nu va fi luata in considerare.

Urmăriți indicațiile din fișierul tema4.c si completați funcțiile notate cu TODO. In fișierul tema4.c se pot implementa si funcții adiționale.

Pentru implementarea temei trebuie înțelese următoarele 3 structuri prezente în “utils.h”:

  • Location:
    • x – întreg care reprezintă coordonata x a poziției
    • y – întreg care reprezintă coordonata y a poziției
  • Game:
    • name – șir de caractere care reprezintă numele jocului curent
    • killRange – întreg care reprezintă distanța maximă de la care un Impostor poate să omoare un alt jucător
    • numberOfCrewmates – întreg care reprezintă numărul de colegi de echipaj
    • crewmates – vector de referințe la structuri de tip Player care reprezintă colegii de echipaj
    • impostor – referința la structura de tip Player care reprezintă impostorul din joc
  • Player:
    • name – șir de caractere care reprezintă numele jucătorului
    • color – șir de caractere care reprezintă culoarea jucătorului
    • hat – șir de caractere care reprezintă pălăria jucătorului
    • alive – întreg care reprezintă dacă jucătorul este în viață sau nu
    • indexOfLocation – indicele din vectorul de locații care reprezintă locația curentă a jucătorului
    • numberOfLocations – numărul de locații în care se poate afla jucătorul
    • locations – vector de structuri de tip Location
    • playerRole – enum de tip PlayerRoles care reprezintă tipul de jucător
    • ability – referință la funcție de tipul void * task(void *) care reprezintă task-ul jucătorului curent

Rolurile jucătorilor sunt salvate în enum-ul playerRole. Valorile din enum sunt:

  • Rotator
  • Decoder
  • Invertor
  • Impostor

Task-urile pe care jucătorii trebuie să le facă sunt salvate în vectorul de referințe la funcții: void* (* Abilities[4])(void* x) = {RotateMatrix, DecodeString, InvertArray, KillPlayer};.

Valorile din playerRole corespund indicilor din vectorul de referințe la funcții.

Jocul constă în prezența unei structuri de tip Game în care sunt prezente setările jocului, vectorul de colegi de echipaj si impostorul. Fiecare jucător, inclusiv impostorul, este o structura de tipul Player si are date despre numele, culoarea si pălăria sa. Acesta mai conține si dacă jucătorul este sau nu în viață și traseul lui în joc (un vector de structuri de tip Location, un număr de locații pentru acel jucător care reprezintă lungimea vectorului de locații și un indice care reprezintă locația din vector în care se afla jucătorul acum). Pe lângă acestea, un jucător mai are un rol (Rotator, Decoder, Invertor sau Impostor) care îi definește rolul lui în joc și, prin urmare task-ul pe care îl are de făcut. Task-ul lui este salvat ca o referință la o funcție.

Fiecare jucător se mișcă circular prin vectorul de locații. Dacă un jucător are 3 locații, în următoarele 5 cicluri de joc se va mișca astfel:

0 -> 1 -> 2 -> 0 -> 1-> 2

Jocul se desfășoară în modul următor:

  • se citește de la input un joc si jucătorii lui
  • se inițializează jucătorii lui și se afișează datele importante despre joc la output
  • se calculează ciclurile jocului(rundele)

Jocul se desfășoară pe cicluri(runde). Un ciclu este reprezentat de următoarele acțiuni:

  • fiecare coleg de echipaj se mișcă la următoarea sa locație din vectorul de locații (jucătorii încep de la locația cu indicele 0 din vector și în primul ciclu se duc la locația 1 si așa mai departe)
  • fiecare coleg de echipaj își face task-ul, apelând câmpul ability, care este o referința la o funcție, apoi își afișează rezultatul task-ului său
  • urmează rândul impostorului să se miște la următoarea sa locație și să își facă task-ul adică să încerce să omoare un jucător

Dacă un coleg de echipaj este mort atunci el nu mai face nicio acțiune, ci doar se afișează la output că acesta este mort.

Tema este organizată în următorul fel:

  • 3 task-uri care reprezintă task-urile colegilor de echipaj
  • 5 task-uri care asigură inițializarea și desfășurarea jocului
  • 1 task care reprezintă task-ul impostorului

Pentru primele 3 task-uri se impune următoarea structura:

  • Input-ul este un singur parametru de forma void * care urmează sa îi fie făcut cast la tipul de date specificat de fiecare task în parte
  • Output-ul este un șir de caractere căruia îi este făcut cast la void *

Prin urmare, antetele primelor 3 task-uri sunt de forma: void * task(void *input)

Cerință

Task 1 (10p)

Trebuie să se completeze funcția RotateMatrix din tema4.c.

Funcția primește un void * care este un pointer la un int (n). Să se creeze o matrice n*n cu elementele de forma ij cu i, j indicii elementului curent (i și j pornesc de la 1) și apoi să se rotească matricea la dreapta. Output-ul este un șir de caractere care reprezintă afișarea matricei de sus in jos, de la stânga la dreapta.

Între liniile matricei trebuie sa existe cate un \n.

După ultima linie NU trebuie să existe un \n!.

Input

3

Output

31 21 11
32 22 12
33 23 13

Task 2 (10p)

Trebuie să se completeze funcția DecodeString din tema4.c.

Funcția primește un void * care este un șir de caractere. Șirul este de forma a1_a2_a3_…_an, unde ai este un întreg. Să se calculeze suma elementelor ai. Output-ul este un șir de caractere care reprezintă suma calculată.

Input

4_3_7_15_1_5

Output

35

Dupa numărul reprezentat de suma calculată NU trebuie să existe un \n!

Task 3 (10p)

Trebuie să se completeze funcția InvertArray din tema4.c.

Funcția primește un void * care reprezintă un vector. Primul element al vectorului este numărul de elemente rămase în vector. Dacă lungimea vectorului rămas este număr par să se interschimbe elementele de pe pozițiile 2k + 1 cu elementele de pe pozițiile 2k + 2. Dacă lungimea vectorului rămas este număr impar să se inverseze vectorul. Output-ul este vectorul fără primul element sub formă de sir de caractere.

Cazul 1

Input

4 1 2 3 4

Output

2 1 4 3
Cazul 2

Input

3 1 2 3

Output

3 2 1

Dupa vector NU trebuie să existe un \n!

Task 4 (10p)

Trebuie să se completeze funcțiile allocPlayer si allocGame din tema4.c.

Se dorește alocarea structurilor Player și Game și a câmpurilor lor. Pentru Player trebuie să se aloce câmpurile name, color și hat și să ii se atribuie valoarea 1 pentru alive. Pentru Game trebuie să se aloce câmpul name. Toate șirurile de caractere sunt alocate cu lungimea MAX_LEN_STR_ATR.

Funcțiile nu primesc niciun parametru și returnează referința la structura pe care o aloca.

Task 5 (10p)

Trebuie să se completeze funcțiile ReadPlayer si ReadGame din tema4.c.

Se dorește citirea câmpurilor structurilor Player și Game. Funcțiile primesc la input fișierul(text) de intrare și returnează referința la structura pe care o aloca si o citesc.

Funcția de ReadGame trebuie să apeleze funcția de ReadPlayer pentru fiecare jucător din joc, inclusiv pentru impostor.

La citirea unui jucător, când se citește rolul unui jucător trebuie ca variabilei de tip enum playerRole să i se atribuie valoarea corespunzătoare. În fișierul tema4.c există un vector de referințe Abilities la funcțiile RotateMatrix, DecodeString, InvertArray și KillPlayer care corespund ca abilitate/task jucătorilor care au rolurile Rotator, Decoder, Invertor respectiv Impostor. Tot la citire trebuie să ii se atribuie pentru fiecare jucător referința ability la una dintre valorile din vectorul de referințe Abilities în funcție de enum-ul PlayerRole.

Input-ul este de forma următoare:

[nume_joc]
[killRange]
[numar_crewmates]
[crewmate_1]
…
[crewmate_n]
[impostor]

Unde [crewmate_1], …, [crewmate_n] si [impostor] au următoarea structura:

[nume_jucator]
[culoare]
[palarie]
[numar_locatii]
([x_1],[y_1])[spatiu]([x_2],[y_2])[spatiu]…
[rol_jucator]

Exemplu de input:

Game_1
5
3
John
Blue
Witch_Hat
2
(2,1) (2,0)
Decoder
Adam
Pink
Top_Hat
3
(5,5) (7,7) (2,2)
Rotator
Michel
Green
Yes_Hat
2
(6,6) (5,3)
Invertor
Mark
Red
No_Hat
1
(1,1)
Impostor

Task 6 (10p)

Trebuie să se completeze funcțiile WritePlayer si WriteGame din tema4.c.

Se dorește afișarea structurilor Player și Game. Trebuie să se completeze funcțiile WritePlayer și WriteGame. Funcțiile primesc ca parametrii structura pe care trebuie să o afișeze și fișierul(text) de output.

Funcția de WriteGame trebuie să apeleze funcția de WritePlayer pentru fiecare jucător din joc, inclusiv pentru impostor.

La finalul apelării funcției de WriteGame în fișierul de output trebuie să existe următoarea informație:

Game [nume_joc]  has just started!
[TAB]Game options:
Kill Range: [killRange]
Number of crewmates: [numberOfCrewmates]
[LINIE_GOALA]
[TAB]Crewmates:
Player [player_name] with color [player_color], hat [player_hat] and role [player_role] has entered the game.
Player's locations: ([x1],[y1])[spatiu]…
…
[LINIE_GOALA]
[TAB]Impostor:
Player [impostor_name] with color [impostor_color], hat [impostor_hat] and role Impostor has entered the game.
Player's locations: ([x1],[y1])[spatiu]…

Exemplu de output:

Game Football_Game has just started!
	Game options:
Kill Range: 4
Number of players: 2

	Crewmates:
Player Cristiano with color White, hat Cool_Hat and type Rotator has entered the game.
Player's locations: (1,1) (0,0) (7,7) 
Player Messi with color Red_Blue, hat Nice_Hat and type Decoder has entered the game.
Player's locations: (0,0) (1,1) (10,10) 

	Impostor:
Player Mutu with color Blue, hat Caviar_Hat and type Impostor has entered the game.
Player's locations: (3,4) (0,7) (0,10)

Task 7 (10p)

Trebuie să se completeze funcția KillPlayer din tema4.c.

Se dorește implementarea abilitații/task-ului impostorului. Input-ul funcției este un void * care este o referință la o structura de tip Game. Abilitatea impostorului este de a ucide cel mai apropriat coleg de echipaj dacă acesta este la o distanță mai mică sau egală ca killRange. Distanța dintre 2 puncte se calculează ca Distanta Manhattan.

Distanța calculată este de tip întreg.

Dacă impostorul reușește să omoare un coleg de echipaj, atunci câmpul alive al acelui coleg de echipaj devine 0 (moare). Dacă există mai mulți colegi de echipaj la aceeași distanță fată de impostor este omorât colegul de echipaj cu indicele cel mai mare. Output-ul funcției este un șir de caractere castat la void * .

Dacă impostorul reușește să omoare pe cineva output-ul o să fie de forma:

Impostor [nume_impostor] has just killed crewmate [nume_crewmate] from distance [distanta].

Daca impostorul nu reușește să omoare pe nimeni output-ul o să fie de forma:

Impostor [nume_impostor] couldn't kill anybody.

La finalul șirului de caractere NU trebuie să existe un \n!

Task 8 (10p)

Trebuie să se completeze funcția CalcuateNextCycleOfGame din tema4.c.

Se dorește implementarea unui ciclu de joc. Funcția primește ca parametrii o referință la o structura de tipul Game, un fișier de output și un void** care este un vector de input-uri de tip void * .

Pentru fiecare coleg de echipaj funcția trebuie să îi calculeze următoarea poziție și să afișeze acest lucru în următorul format:

Player [nume_jucator] went to location ([x],[y]).[\n]

Apoi funcția trebuie să apeleze pentru fiecare coleg de echipaj abilitatea/task-ul lui apelând referința la funcție ability cu input-ul void * luat din vectorul de input-uri dat ca parametru funcției CalculateNextCycleOfGame. Indicele colegului de echipaj în vectorul de crewmates dă indicele din vectorul de input-uri.

Output-ul fiecărui task al jucătorilor trebuie afișat sub forma:

Player [nume_jucator]'s output:[\n]
[Output]

Asemănător trebuie să se facă și pentru impostor.

Dacă un coleg de echipaj este mort atunci el nu se va mișca niciunde și nu își va mai face task-ul. În schimb va afișa:

Player [nume_jucator] is dead.[\n]

Exemplu:

Crewmate John is dead.
Crewmate Adam went to location (2,2).
Crewmate Adam's output:
61 51 41 31 21 11
62 52 42 32 22 12
63 53 43 33 23 13
64 54 44 34 24 14
65 55 45 35 25 15
66 56 46 36 26 16
Crewmate Michel went to location (6,6).
Crewmate Michel's output:
7 6 5 4 3 2 1
Impostor Mark went to location (1,1).
Impostor Mark's output:
Impostor Mark has just killed crewmate Adam from distance 2.

Task 9 (10p)

Trebuie să se completeze funcțiile FreePlayer si FreeGame din tema4.c.

Se dorește eliberarea structurilor de tip Player și Game. Trebuie să se elibereze toată memoria prezenta în aceste structuri, inclusiv cea care nu a fost alocată în funcțiile alloc.

Pentru a primi punctaj pe acest task trebuie să nu existe pierderi de memorie la restul task-urilor.

Punctaj

  • [90p] Teste
  • [5p] Fișier README în care să se descrie implementarea

TOTAL: 100p

Listă depunctări

  • o temă care nu compilează și nu a rulat pe v2.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]: linii mai lungi de 80 de caractere
  • [-1.0]: funcții mai lungi de 100 de linii
  • [-0.5]: folosirea de magic numbers
  • [-0.5]: numele variabilelor nu sunt sugestive
  • [-0.5]: cod comentat
  • [-0.5]: trailing whitespaces
    • î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 era cazul, etc.

Trimitere temă

Tema va fi trimisă folosind V2.vmchecker, cursul Programarea Calculatoarelor (CB & CD).

Găsiți arhiva cu checker-ul si scheletul temei aici.

Formatul arhivei care va fi încărcata pe platforma de testare a temelor va fi următorul:

  1. fișierul tema4.c.
  2. Un fișier README în care vă descrieți rezolvarea fiecărui task.

  1. Arhiva trebuie să fie de tipul ZIP si sa conțină toate fișierele menționate IN RADACINA ARHIVEI.

programare/teme_2020/tema4_2020_cbd.txt · Last modified: 2020/11/30 14:11 by vlad_matei.draghici
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