Problem Set IV.: Sokoban - The Levels Part

Ciele

  • Pracovať so súbormi.
  • Aplikovať dynamický údajový typ jednosmerný spájaný (spojkový) zoznam.

Úvod

Upozornenie:  Kasci bol prvý, ktorý upozornil na problém pri funkcii save() a ako Biňas povedal na prednáške - vyhrávaš cukrík (treba si ho vypýtať priamo po prednáške). V tejto súvislosti bola aktualizovaná štruktúra GAME a aj opis zadania spolu so zip-om štruktúry riešenia.
  • Zadanie je potrebné odovzdať do konca 12. týždňa, teda do pondelka 12.mája.2014, 1230 hod.
  • Pri práci na zadaní dodržiavajte etický kódex!

Naposledy ste vytvorili jadro hry Sokoban. Jedinou nevýhodou tejto implementácie je zatiaľ nemožnosť hrať viac ako jeden level. Práve toto zadanie je venované odstráneniu tohto nedostatku - v rámci implementácie vytvoríte potrebné funkcie, pomocou ktorých budete vedieť načítať naraz všetky levely zo súboru do pamäte, po prejdení jedného sa dostanete do nasledujúceho levelu a v prípade potreby budete vedieť po zadaní správneho hesla sa do príslušného levelu dostať.

Na zatraktívnenie hry môžete napríklad využiť knižnicu ncurses, pomocou ktorej môžete hru ovládať (v rámci funkcie play_game()) a vykresľovať na obrazovku napr. použitím farieb (v rámci funkcie render()).

Zoznam úloh

Vašou úlohou je v tomto zadaní implementovať vybrané funkcie deklarované v súboroch sokoban.h a level.h. Ich zoznam a špecifikácia sa nachádza v nasledujúcom texte.

Úloha #1: Načítanie levelov do pamäte

Cieľom tejto úlohy je naprogramovať funkciu LEVEL* load_levels(char* path) z hlavičkového súboru level.h, pomocou ktorej postupne načítate všetky levely, ktoré sú uložené v súbore, do jednosmerného spájaného zoznamu.

Funkcia má nasledovný parameter:

  • char* path - Cesta k súboru, v ktorom sa všetky levely nachádzajú. (Cesta môže byť relatívna aj absolútna.)

Funkcia vráti referenciu na prvý level v zozname, ak sa zo súboru podarilo všetky levely úspešne načítať. V prípade, že súbor neexistuje alebo nie je možné zo súboru čítať alebo pri jeho parsovaní dôjde k chybe (napr. kvôli nesprávnemu formátu levelu alebo súboru, ktorý rozhodne neobsahuje levely do tejto hry), funkcia vráti NULL. V tomto prípade by mal váš program vypísať na štandardný chybový výstup vhodnú správu a skončiť s návratovým kódom 1.

Poznámka:  Žiadny riadok, ktorý reprezentuje level, nebude dlhší ako 1024B.

Úloha #2: Uvoľnenie obsadenej pamäte pri ukončení programu

Po skončení hry (v hlavnom menu zvolíte voľbu Quit) sa hra ukončí. Korektné ukončenie programu však znamená, že ešte pred ním dôjde k uvoľneniu všetkých prostriedkov, ktoré program pre svoju činnosť využíval.

Vytvoríte preto funkciu void levels_free(LEVEL *root), ktorá postupne uvoľní pamäť, ktorá bola vyhradená pre jednotlivé levely uložené v jednosmernom spájanom zozname.

Táto funkcia má nasledovný parameter:

  • LEVEL* root - Referencia na prvý level zoznamu.

Táto funkcia nemá žiadnu návratovú hodnotu.

Úloha #3: Výber levelu podľa hesla

Každý level obsahuje aj heslo, pomocou ktorého sa viete do levelu dostať priamo. Stačí, ak si v menu vyberiete položku Enter password a po zadaní správneho hesla nemusíte jednotlivé levely prechádzať od začiatku, ale priamo sa vám spustí vybraný level.

Vytvorte preto funkciu LEVEL* get_level_by_password(LEVEL *root, char *password), pomocou ktorej túto funkčnosť zabezpečíte.

Táto funkcia má tieto parametre:

  • LEVEL *root - Referencia na prvý level v spájanom zozname.
  • char *password - Heslo na prístup do príslušného levelu.

Ak heslo, ktoré hráč zadal, zodpovedá heslu pre vstup do niektorého levelu, funkcia vráti referenciu na tento level. Ak však takýto level neexistuje, funkcia vráti referenciu na prvý level zoznamu.

Úloha #4: Rozohratá partia

Ak si hráč bude chcieť popri hraní z rozličných dôvodov "odskočiť" (na záchod? do obchodu? na prednášku? alebo rovno z prednášky?), bude mať vaša implementácia k dispozícii možnosť uložiť aktuálny stav rozohratej hry na disk a neskôr tento stav z disku načítať.

Vytvorte preto funkciu int save(GAME* game, char* path) pre uloženie stavu rozohratej hry a funkciu GAME *load(char* path) pre načítanie stavu hry.

Funkcia save() má tieto parametre:

  • GAME *game - Referencia na rozohranú hru
  • char *path - Cesta k súboru, do ktorého sa má stav uložiť

Funkcia save() vráti hodnotu 1, ak sa stav hry podarilo úspešne uložiť. V opačnom prípade vráti funkcia hodnotu 0.

Stav hry bude uložený ako CSV súbor v nasledovnej štruktúre:

názov levelu;hráč x; hráč y;počet krokov;výška levelu;šírka levelu;mapa

Pre uloženie mapy bude použitý Sokoban Level Format.

Funkcia load() má tento parameter:

  • char *path - Cesta k súboru, ktorý obsahuje uložený stav.

Funkcia vráti referenciu na načítaný stav hry. Ak sa tento stav nepodarilo načítať úspešne (napr. súbor neexistuje, nie je možné zo súboru čítať, súbor neobsahuje potrebné údaje a pod.), funkcia vráti NULL.

Odovzdávanie projektu

Zadanie sa odovzdáva prostredníctvom systému na správu verzií Git na serveri git.cnl.sk. Názov projektu musí byť prog-2014 a okrem súborov, ktoré tvorili zadania ps1, ps2 a ps3 sa rozšíri o súbory obsahujúce zadanie ps4. Kódovanie všetkých odovzdávaných súborov musí byť UTF8 alebo ASCII.

Pri názvoch vytváraných súborov a priečinkov záleží na veľkosti písmen! Projekt musí mať nasledujúcu štruktúru, pričom počiatočné lomítko '/' reprezentuje koreňový priečinok projektu:

  • /ps4/sokoban.c - Zdrojový kód knižnice pre hru sokoban.
  • /ps4/sokoban.h - Hlavičkový súbor knižnice sokoban.
  • /ps4/level.c - Zdrojový kód knižnice pre prácu s levelmi v hre.
  • /ps4/level.h - Hlavičkový súbor pre knižnicu pracujúcu s levelmi v hre.
  • /ps4/gui.c - Zdrojový kód zabezpečujúci prácu so vstupom a výstupom.
  • /ps4/gui.h - Hlavičkový súbor zabezpečujúci prácu so vstupom a výstupom.
  • /ps4/main.c - Zdrojový kód obsahujúci funkciu main().
  • /ps4/Makefile - Makefile súbor obsahujúci minimálne tieto dva ciele:
    • all pre vygenerovanie spustiteľného programu s menom sokoban,
    • clean pre odstránenie priebežne vytvorených objektových a spustiteľných súborov.
  • /ps4/screenshots/ - Nepovinný priečinok, do ktorého môžete uložiť niekoľko snímiek z vašej hry. Tieto súbory by mali byť nazvané ako screenshotX.png, kde X je poradové číslo vášho obrázka (prvý obrázok bude mať samozrejme číslo 1).

Štruktúra vášho projektu bude teda vyzerať nasledovne:

.
|-- ps1
|   |-- tesco.c
|   `-- tiktak.c
|-- ps2
|   |-- hangman.c
|   |-- hangman.h
|   |-- main.c
|   `-- Makefile
|-- ps3
|   |-- gui.c
|   |-- gui.h
|   |-- level.c
|   |-- level.h
|   |-- main.c
|   |-- sokoban.c
|   |-- sokoban.h
|   `-- Makefile
|-- ps4
|   |-- gui.c
|   |-- gui.h
|   |-- level.c
|   |-- level.h
|   |-- main.c
|   |-- sokoban.c
|   |-- sokoban.h
|   |-- Makefile
|   `-- screenshots
|       |-- screenshot1.png
|       `-- screenshot2.png
`-- README

Upozornenie:  Je dôležité, aby vaše súbory zachovali uvedenú štruktúru. Ak sa niektorý zo súborov síce v repozitári nachádza, ale v inom priečinku, bude to považované za chybu a takýto projekt nebude považovaný za správny.
Poznámka:  V závislosti od toho, aké vývojové prostredie používate, sa vo vašom projekte môžu nachádzať aj priečinky vytvorené práve týmto prostredím (napr. projekt vytvorený v prostredí NetBeans bude obsahovať priečinok /nbproject/). Existencia týchto priečinkov v repozitári nebude považovaná pri hodnotení za chybu.

Kostra projektu

Z nasledujúceho odkazu si stiahnite súbor sokoban.zip, ktorý obsahuje kostru projektu. Tento balíček obsahuje nasledujúce súbory:

  • levels.dat - súbor, ktorý obsahuje 91 rozličných úrovní hry
  • sokoban.h - hlavičkový súbor, v ktorom sa nachádzajú deklarácie všetkých požadovaných funkcií pre hlavnú časť hry.
  • level.h - hlavičkový súbor, v ktorom sa nachádzajú deklarácie všetkých požadovaných funkcií pre prácu s úrovňami.
  • gui.h - hlavičkový súbor, v ktorom sa nachádzajú deklarácie všetkých požadovaných funkcií pre prácu so vstupom a výstupom.

V prostredí OS Linux môžete pre stiahnutie použiť príkaz wget v tvare:

wget http://it4kt.cnl.sk/c/pvjc/resources/download/sokoban.zip

Hodnotenie a testovanie

Za zadanie môžete získať max. 10 bodov. Počet získaných bodov sa bude odrážať od výsledku testov, ktorými vaše zadanie úspešne prejde. Overovať sa bude:

  • Štruktúra vášho projektu (či sa v ňom nachádzajú všetky potrebné súbory).
  • Funkčnosť vami vytvorených funkcií pomocou unit testov.

Testovať sa nebude grafická podoba hry, nakoľko v tomto prípade máte voľnosť a jej grafickú stránku môžete implementovať s využitím ľubovoľnej knižnice.

Váš kód sa bude prekladať prekladačom gcc s nasledovnými prepínačmi:

-std=gnu99 -Werror -Wall -lm 

Za chybu sa bude považovať:

  • Ak vo vašej implementácii použijete globálnu premennú.
  • Ak vo vašej implementácii budete miesto názvov položiek enumeračných typov používať ich číselnú reprezentáciu.
  • Ak počas prekladu dôjde ku chybe (upozornenia sú priamo konvertované na chyby).
  • Ak váš Makefile nevygeneruje spustiteľný súbor s názvom sokoban v aktuálnom priečinku.
  • Ak vaša implementácia neprejde niektorým z testov.

Testovanie vašich riešení sa bude vykonávať automaticky 4x do dňa a to konkrétne o 0600, 1200, 1800 a 2400. Keďže však spracovanie všetkých riešení trvá istú chvíľu, o výsledkoch by ste mali byť notifikovaní e-mailom v priebehu 20 minút.

Vaše riešenia opäť prejdú kontrolou originality. Preto sa pri práci na vašom zadaní správajte podľa pravidiel etického kódexu! V prípade, že odovzdáte zadanie, ktoré nie je vaše, budete vylúčení z predmetu!