Labirintus játék 2D tömbben
A mai órán egy összetett programot készítünk el. Ez egy labirintus játék, amelyben egy játékos egy előre adott labirintusban mozoghat, kincseket gyűjtve. A labirintust, amely egy kétdimenziós pálya, kétdimenziós karaktertömbben, vagyis sztringek tömbjében tároljuk.
A programot több forrásfájl, valamint fejlécfájl alkalmazásával valósítsd meg!
Megoldás
A program teljes forráskódja letölthető innen: lab14/labirintus.c.
Tartalom
1 Labirintus játék
A labirintus egy fallal körülvett 10×10-es tábla. A labirintust körülvevő falon egy kijárat található. A labirintusban több kincset rejtettek el. A játékos feladata, hogy összeszedje a kincseket és eljusson a kijáratig.
A labirintust a következő formában kell megjeleníteni:
###### ### #$ # # #### ### # # # # #### ### # # #$# # ##$# # # #@ ### # # # $# # ##########
ahol a falakat a # jelzi, a járható részeket pedig a szóköz. Az elrejtett kincseket a $ karakter, a játékost pedig a @. Ha a játékos felvette, a kincs helyére is szóköz kerül.
Ebben a feladatban az alább látható részfeladatok mind egymásra épülnek, vagyis sorban kell megcsinálnod őket. Minden függvény megírásakor írj egy rövid programrészt a főprogramba, amely meghívja a függvényt – így lépésenként ellenőrizni tudod azt, hogy helyesen működik-e.
Tömb
Hozz létre egy tömböt a labirintus tárolására! A tömb tárolja a labirintus egyes sorait sztringként. Mivel a sztringek maguk is tömbök, ezért ennek a tömbnek két dimenziósnak kell lennie (tömbök tömbje). Figyelj arra, hogy a sztringként tárolt sorok miatt eggyel nagyobbra kell választanod a tömböt vízszintesen (vagyis szélesebbre), hogy a sztringet lezáró nulla is beleférjen.
Inicializáld a tömböt úgy, hogy a fent látható labirintust tartalmazza. Ehhez azt át tudod másolni a forráskódba.
Emlékeztető: kétdimenziós tömböt így lehet létrehozni:
tipus nev[sorok_szama][oszlopok_szama];Vajon melyik itt a sztringek mérete? Melyiket kell eggyel nagyobbra választani?
Kirajzolás
Írj függvényt, amely paraméterként veszi a labirintust tároló tömböt és kirajzolja a labirintust a képernyőre!
A játékos koordinátái
Hozz létre alkalmas struktúratípust a labirintusbeli koordináták tárolására! Írj függvényt, amely paraméterként veszi át a labrintust tároló tömböt, és visszaadja a játékos koordinátáit. Ennek visszatérési típusa a korábban definiált struktúra legyen. A függvény keresse meg a játékost a tömbben, és állítsa be a struktúrában a megfelelő pozíciót!
Emlékeztető: struktúratípust a következőképpen lehet létrehozni:
typedef struct opcionalis_struct_nev { tipus mezo_1; tipus mezo_2; … } struktura_nev;
Kincsek száma
Írj függvényt, amely paraméterként veszi át a labirintust tároló tömböt, és visszaadja a benne található kincsek számát!
Kétdimenziós tömb függvény-paramétert így kell definiálni:
visszateresi_tipus fuggveny_nev(tipus nev[][oszlopok_szama], unsigned sorok_szama);vagyis ebben a speciális esetben a szögletes zárójelek közt meg kell adni méretinformációt, de csak az oszlopok számát. Enélkül ugyanis nem tudna működni az összetett indexelő operátor, hiszen a C-ben a kétdimenziós tömbök sorfolytonosan vannak tárolva, tehát a fordítónak tudnia kell, hogy milyen hosszú egy sor, vagyis hány elemet kell ugrani indexeléskor. A képlet, ami egy elem pozícióját megadja ugyanis a következő:
elem_index = sor_index * oszlopok_szama + oszlop_index
Irányok
Definiálj felsorolt típust, amely alkalmas az irányok (le, fel, jobbra, balra) tárolására!
Emlékeztető: felsorolt típust így kell definiálni (ez is
typedef
-elhető):enum nev { azonosito_1, azonosito_2, … };
Mehet-e arra?
Írj függvényt, amely paraméterként veszi át a labirintust tároló tömböt valamint egy irányt! A visszatérési típusa logikai legyen, ami akkor vegye fel az IGAZ értéket, ha a játékos elmozdulhat az adott irányba. A játékos akkor nem mehet egy irányba, ha ott fal van.
Gondolj arra, hogy ennek a függvénynek nem kell paraméterként átvennie a játékos helyzetét, hanem azt az egyik előbb megírt függvénnyel meg tudja határozni.
Léptetés
Írj függvényt, amely paraméterként átveszi a labirintust tároló tömböt és egy adott irányt, és lépteti a játékost, ha ez lehetséges! Azt, hogy az adott irányba léphet-e a játékos, az előző pontban elkészített függvény segítségével ellenőrizd! A léptetés azt jelenti, hogy a játékos aktuális pozíciójára egy szóköz, az új pozíciójára pedig egy @ kerül.
A függvény a visszatérési értékében jelezze, ha
- az irány rossz, mert ott fal van!
- a játékos a kijáratba lépett!
- a játékos kincset talált!
- a játékos üres mezőre lépett!
Tipp: a visszatéréshez érdemes létrehozni egy újabb felsorolt típust, amely a fenti négy lehetőséget jelöli egy-egy konstanssal. Így a főprogramban a lépés eredményének ellenőrzése egy nagyon jól olvasható
switch()
segítségével valósítható meg.Tipp: azt, hogy a játékos kijáratra lépett, úgy döntheti el, hogy a lépés-ellenőrző függvény visszatérése IGAZ és a játékos új koordinátáinak valamelyike 0 vagy 9.
main()
A main függvényben írj egy ciklust, amely bekéri a felhasználótól a mozgás irányát és ennek megfelelően lépteti a játékost!
- Tartsd számon, hogy a játékos hány kincset talált!
- Ha a játékos a kijáraton kiment, akkor nézd meg, hogy megtalált-e minden kincset (a 3. feladatban megírt függvény segítségével)! Ha már nincs több kincs a labirintusban, akkor nyert, ha van, akkor veszített. Írd ki a végeredményt a képernyőre!
- Ha nem mehet a kívánt irányba a játékos, akkor ezt írd ki a képernyőre!
- Rajzold ki lépésről-lépésre az új táblát!
2 További feladatok
Iránysorozat
Írd át a labirintus programot úgy, hogy a játékos egyszerre több irányt is megadhasson! Például ha az irányokat a következő betűk segítségével kell bevinni: 'f', 'l', 'j', 'b', akkor a "fjjlb" jelentse azt, hogy a játékos egy öt lépésből álló sorozatot kíván megtenni: fel-jobbra-jobbra-le-balra.
Útkereső
Írj függvényt, ami paraméterként kapja a labirintust tartalmazó tömböt és a játékos indulási koordinátáit, a visszatérési értéke pedig egy logikai érték legyen, ami akkor IGAZ, ha a játékos ki tud jutni a labirintusból, tehát ha létezik út a két pont között!
Tipp: keresd meg a labirintusban a játékost, és „színezd ki” a mellette lévő üres helyeket. Ezután fésüld végig újra a labirintust, és a „kiszínezett” cellák melletti üres helyeket is színezt. Folytasd ezt addig, amíg van színezés. Ha nincs már több, végeztél – ha a kijárat ki lett színezve, akkor a játékos ki tud jutni.