Sakk játék - gyűjtsd össze a futóval a többi bábut

Használható segédanyagok: Haskell könyvtárainak dokumentációja, (lokális!) Hoogle, a tárgy honlapja és a BE-AD rendszerbe feltöltött beadandók. Ha bármilyen kérdés, észrevétel felmerül, azt a felügyelőknek kell jelezni, nem a diáktársaknak!

A feladatok egymásra épülnek ezért érdemes ezeket a megadásuk sorrendjében megoldani, de legalább megérteni az aktuális feladatot megelőző feladatokat! A függvények definíciójában lehet, sőt javasolt is alkalmazni a korábban definiált függvényeket (függetlenül attól, hogy sikerült-e azokat megadni).

Tekintve, hogy a tesztesetek, bár odafigyelés mellett íródnak, nem fedik le minden esetben a függvény teljes működését, határozottan javasolt még külön próbálgatni a megoldásokat beadás előtt, vagy megkérdezni a felügyelőket!

Részpontszámokat csak az elégséges szint elérése után lehet kapni!

A feladat összefoglaló leírása

A gyerekek sakkoktatásában egy fontos elem a különböző bábuk lehetséges mozgásának begyakoroltatása. Ennek egyik eszköze egy olyan játék, ahol egy meghatározott sakkbábunak kell sorban leütnie (összegyűjtenie) a táblán lévő többi bábut. A többféle nehézségi fokozat közül a legegyszerűbb, amikor minden lépésnél csak egyetlen lehetséges továbbhaladás létezik, a feladatunk során csak ilyen feladványokkal foglalkozunk.

A feladatunkban adott egy hagyományos, 8*8-as sakktábla, ahol a sorokat és az oszlopokat az 1-8 egész számokkal azonosítjuk (először oszlop, majd sorszám). Egy adott pozícióról induló futóval fogunk mozogni, célunk a megadott pozíciókon lévő bábuk mindegyikének ütése. A sakkban a futó átlós irányba léphet, bármennyi mezőt, amíg egy másik bábu az útjába nem kerül (nem “ugorhat át” bábukat).

A feladat során használt típusszinonímák:

A bábuk pozícióját a mező sor-oszlop azonosítójából képzett párral adjuk meg. Minden feladatnál feltételezhetjük, hogy 1-8 közötti egész számok szerepelnek a párban (nem kell ellenőrizni).

A játék állapotát egy rendezett párral adjuk meg, ahol a pár első eleme tartalmazza a futó aktuális pozícióját, a második eleme pedig a többi (leütésre váró) bábu pozícióit egy listában.

Példa feladványok

A futó üt-e egy bábut (1 pont)

Adjunk meg egy függvényt, amely eldönti, hogy az első paraméterben megadott pozíción lévő futó (szabályos lépéssel) ütheti-e a második paraméterben megadott pozíción lévő bábut.

Segítség: a sor illetve oszlop azonosítók különbségének abszolútértéke megegyezik-e.


Test>
True :: Bool
Test>
True :: Bool

Az üthető bábuk kiválogatása (1 pont)

Egy listából válogassuk ki azokat a bábukat, amelyeket üthet az első paraméterben megadott pozíción álló futó. Itt még nem kell figyelembe venni, hogy a futó szemszögéből a listában megadott bábuk egymás előtt állnak-e, egyesével vizsgáljuk meg őket úgy, mintha senki más nem lenne a táblán.


Test>
[(6, 7)] :: [Position]
Test>
[(1, 7), (2, 6), (3, 5)] :: [Position]
Test>
[(4, 1), (2, 3), (3, 2)] :: [Position]

Takarások kizárása (2 pont)

A függvény az előzőhöz hasonlóan itt is a futó pozícióját és a többi bábuhoz tartozó pozíciókat kapja paraméterként, viszont itt már figyelembe vesszük azt is, ha egy bábu a futó szemszögéből egy másik bábu előtt áll. Feltételezhetjük, hogy olyan paraméterekkel hívjuk meg a függvényt, hogy a futó pontosan egy bábut tud valójában ütni. Keressük meg ezt az egyet!

Segítség: a candidates függvény által visszaadott bábuk közül azt tudja ütni a futó ténylegesen, amelyik a legközelebb van hozzá.

Szemléltetés a lépések bemutatásához az első majd a második táblán:


Test>
(6, 7) :: Position
Test>
(3, 5) :: Position
Test>
(2, 3) :: Position

Üres-e a tábla (1 pont)

Adjunk meg egy függvényt, amellyel ellenőrizhető, hogy a sakktábla (Board) egyetlen bábut sem tartalmaz a futón kívül.


Test>
False :: Bool
Test>
False :: Bool
Test>
True :: Bool

A megoldás egy lépése (2 pont)

A függvény paraméterként egy sakktábla állapotot (Board) kap. Megkeresi azt az egy bábut, amelyet ütni tud a futó, a futó ezen bábu helyére áll, a pozíció listából pedig kikerül a leütött bábu. A függvény visszatérési értéke az így előálló tábla állapot. Az üres táblát hagyjuk változatlanul.


Test>
((6, 7), [(1, 6), (3, 8), (5, 2), (8, 5)]) :: Board
Test>
((3, 5), [(2, 8), (4, 2), (6, 4), (1, 7), (2, 6), (3, 1)]) :: Board

A feladvány megoldása (2 pont)

Egy tábla állapotból kiindulva addig tegyünk újabb lépéseket, amíg a futó minden bábut le nem ütött a tábláról (a step nem változtat az eredményen). Feltételezhetjük, hogy a feladványnak pontosan egy megoldása létezik, és a megoldáskeresés során nem juthatunk “zsákutcába”. A függvény visszatérési értéke azon tábla állapotok listája, amely az egyes lépések után kapott állapotokat tartalmazza a kiinduló állapottól az üres tábláig.


Test>
[((2, 3), [(1, 6), (3, 8), (5, 2), (6, 7), (8, 5)]), ((6, 7), [(1, 6), (3, 8), (5, 2), (8, 5)]), ((8, 5), [(1, 6), (3, 8), (5, 2)]), ((5, 2), [(1, 6), (3, 8)]), ((1, 6), [(3, 8)]), ((3, 8), [])] :: [Board]
Test>
[((4, 4), [(2, 8), (4, 2), (6, 4), (1, 7), (2, 6), (3, 1), (3, 5)]), ((3, 5), [(2, 8), (4, 2), (6, 4), (1, 7), (2, 6), (3, 1)]), ((2, 6), [(2, 8), (4, 2), (6, 4), (1, 7), (3, 1)]), ((1, 7), [(2, 8), (4, 2), (6, 4), (3, 1)]), ((2, 8), [(4, 2), (6, 4), (3, 1)]), ((6, 4), [(4, 2), (3, 1)]), ((4, 2), [(3, 1)]), ((3, 1), [])] :: [Board]

A futó által bejárt út (1 pont)

A feladvány végső megoldásában nem szeretnénk a teljes tábla állapotokat szerepeltetni, hanem csak azon mezők sorozatát, amelyeket a futó bejárt a bábuk begyűjtése során.


Test>
[(2, 3), (6, 7), (8, 5), (5, 2), (1, 6), (3, 8)] :: [Position]
Test>
[(4, 4), (3, 5), (2, 6), (1, 7), (2, 8), (6, 4), (4, 2), (3, 1)] :: [Position]

Mennyi utat tett meg a futó? (2 pont)

Számítsuk ki, hogy egy adott feladvány megoldása során a futó összesen mennyi utat tett meg, azaz mennyi mezőt érintett.

Példa: a futó az (1,4) pozícióból a (3,2) pozícióba 2 mező érintésével jut el.


Test>
15 :: Int
Test>
11 :: Int

A legrövidebb megoldás kiválasztása (3 pont)

Adjunk meg egy függvényt, amellyel megállapítható, hogy több feladvány közül melyikben kellett a legrövidebb utat megtennie, és milyen hosszú volt ez az út.


Test>
(((4, 4), [(2, 8), (4, 2), (6, 4), (1, 7), (2, 6), (3, 1), (3, 5)]), 11) :: (Board, Int)
Test>
(((4, 4), [(2, 8), (4, 2), (6, 4), (1, 7), (2, 6), (3, 1), (3, 5)]), 11) :: (Board, Int)

Pontozás (elmélet + gyakorlat)