HW02: Hledání min

Odevzdávání úkolu je ukončeno.
Autoři zadání Ondřej Šebek Daniel Rozehnal Dominik Masár Peter Stanko
Odevzdávané soubory minesweeper.c
Začátek odevzdávání viz diskusní fórum
Bonus za brzké odevzdání 2022-03-21 24:00
Konec odevzdání 2022-03-24 24:00
Vzorová implementace /home/kontr/pb071/hw02/minesweeper
Opravy v zadání 2022-03-19 00:42 11

Představení úkolu

V této úloze vám představíme tradiční hledání min a procvičíte si především práci s poli.

Vašim úkolem bude dokončit implementaci hry a většinu její logiky tak, aby se dala zahrát v terminálu. Pokud jste sami ještě hledání min nehráli, tak si ho můžete vyzkoušet například online.

Zadání

Hledání min je jednoduchá puzzle hra, ve které je vašim cílem nalézt všechny miny na hracím poli. Políčko na hracím poli je buď prázdné, nebo obsahuje minu. Během hry jsou políčka ve třech stavech: skryté, odkryté nebo označené vlajkou.

Jako hráč máte během tahu možnost odkrýt skryté políčko nebo nějaké políčko označit vlajkou (respektive odznačit). Pokud odkryjete minu, vaše hra končí a prohráli jste. Naopak pokud se vám podaří odkrýt všechna prázdná políčka bez odhalení miny, vyhráli jste. Pokud máte podezření, že políčko skrývá minu, můžete ho označit vlajkou - takové pole nelze omylem odkrýt, ale na výhru to nemá vliv.

Pokud během tahu odkryjete volné políčko, zobrazí se na něm počet sousedících min. Pokud s volným políčkem sousedí alespoň jedna mina, zobrazí se na něm počet sousedních min a odkryje se pouze toto políčko. Pokud kolem sebe žádnou minu nemá, zůstane prázdné a dojde k řetězovému odkrytí sousedních polí (tzv. floodfill). Tato políčka se postupně odkrývají podle stejných pravidel. Odkryje se tak „jezero“ volných políček s „břehy“ číselných políček - ty už sousedí s minami a floodfill u nich končí.

V našem programu budeme navíc uvažovat, že vedoucí předmětu svou hru vždy začíná postupným kliknutím na všechny rohy herního pole, kde nesmí být umístěna mina.

Také nebudeme uvažovat herní plán, který by měl některou dimenzi menší než 3 nebo větší než 99 (viz konstanty MIN_SIZE a MAX_SIZE v kostře).

Herní plán

Pro reprezentaci herního plánu použijeme dvourozměrné obdélníkové pole.

Při indexování v tomto 2D poli budeme vždy považovat první index jako řádek a druhý jako sloupec. V tomto pořadí budou pak také zadány např. instrukce tahů. Ilustrujeme si to na jednoduchém plánku 4x4 s minou na pozicích (0,1) a (1,3):

     0   1   2   3
   +---+---+---+---+
 0 | . | M | . | . |
   +---+---+---+---+
 1 | . | . | . | M |
   +---+---+---+---+
 2 | . | . | . | . |
   +---+---+---+---+
 3 | . | . | . | . |
   +---+---+---+---+

Políčka v tomto plánu budeme reprezentovat hodnotou typu uint16_t. Tedy funkcím budeme předávat proměnnou znázorňující plán v podobě uint16_t board[row_size][col_size].

Připomeňme, že během hry mohou být políčka (ne)odkrytá, případně označená vlaječkou. Ukažme zde kompletní průběh krátké hry:

     0   1   2   3                       0   1   2   3
   +---+---+---+---+                   +---+---+---+---+
 0 |XXX|XXX|XXX|XXX|                 0 |XXX|XXX|XXX|XXX|
   +---+---+---+---+                   +---+---+---+---+
 1 |XXX|XXX|XXX|XXX|  Klik na [2,1]  1 | 1 | 1 | 2 |XXX|  Flag na [1,3]
   +---+---+---+---+       ->          +---+---+---+---+       ->
 2 |XXX|XXX|XXX|XXX|   (floodfill)   2 |   |   | 1 | 1 |
   +---+---+---+---+                   +---+---+---+---+
 3 |XXX|XXX|XXX|XXX|                 3 |   |   |   |   |
   +---+---+---+---+                   +---+---+---+---+

     0   1   2   3                       0   1   2   3
   +---+---+---+---+                   +---+---+---+---+
 0 |XXX|XXX|XXX|XXX|                 0 |XXX| M |XXX|XXX|
   +---+---+---+---+                   +---+---+---+---+
 1 | 1 | 1 | 2 |_F_|  Klik na [0,1]  1 | 1 | 1 | 2 |_F_|
   +---+---+---+---+       ->          +---+---+---+---+  -> Prohra kliknutím na minu
 2 |   |   | 1 | 1 |                 2 |   |   | 1 | 1 |
   +---+---+---+---+                   +---+---+---+---+
 3 |   |   |   |   |                 3 |   |   |   |   |
   +---+---+---+---+                   +---+---+---+---+

Reprezentace těchto stavů políčka na 16 bitech je zcela na vás. Musíte vědet reprezentovat všechny stavy políčka, včetně počtu sousedících min. V závislosti na vámi zvolené reprezentaci tak mohou být některé požadované funkce jednodušší.

Formátování vstupu a výstupu

Několik funkcí v našem programu bude pracovat se vstupem a výstupem (v tomto kontextu budeme vždy myslet standardní vstup a výstup), proto si zadefinujeme, jak se má k určitým znakům přistupovat a jak zobrazovat určité stavy políčka.

Pro načítání pole ze vstupu budeme používat tuto tabulku pro převod validního znaku na políčko:

X

Neodkryté políčko

M

Políčko skrývající minu (Mine)

F

Políčko správně označené vlajkou (Flag)

W

Políčko špatně označené vlajkou (Wrong flag)

.

Odkryté políčko (nerozlišujeme počet sousedních min)

0-8

Odkryté políčko s počtem sousedních min

Velká a malá písmena budeme při načítání považovat za ekvivalentní. Toto je nutné mít na paměti a řádně ošetřit.

Pro vypsání konkrétního políčka, budeme používat tuto tabulku pro převod validního políčka na řetězec:

Neodkryté políčko

XXX

Políčko označené vlajkou

_F_

Číselně označené pole sousedící s minami (podle jejich počtu)

1-8

Prázdné políčko (vyplněné mezerami)

Všimněte si prosím, že z pohledu vstupu (hry) je důležité rozlišit vnitřní stavy políček, které z pohledu výstupu (hráče) nejsou známé, jako jsou například skrytá mina nebo špatně umístěná vlajka.

Práce se spustitelnými soubory

V souboru main.c je naprogramovaná základní funkcionalita min, která využívá vaše implementované funkce.

Přepínače pro binární soubor minesweeper sloužící k hraní jsou následující:

--rows x

Nastavuje počet řádků na x 1.

--cols y

Nastavuje počet sloupců na y 1.

--generate

Namísto načítání se herní plán vygeneruje (nutné mít implementovanou funkci generate_random()).

--mines m

V případě použití --generate nastavuje počet min na m (defaultně rows * cols / 10).

--find-mines

Spustí bonusové rozšíření find_mines() a vypíše výsledek.

1 Výchozí hodnota je 10.

Výchozí hodnoty si můžete na vlastní zodpovědnost změnit v souboru main.c

Po spuštění je nutné na standardní vstup zadat herní plán, který se předá vaší funkci load_board() (neplatí při použití přepínače --generate). Následně se spustí hra, kterou můžete hrát pomocí dvou jednoduchých příkazů:

r row col

Odhalí políčko na souřadnicích [row, col].

f row col

Položí / odstraní vlajku z políčka [row, col].

Druhý ze spustitelných souborů (tedy minesweeper-tests) nemá žádné přepínače a po spuštění otestuje vaší implementaci pomocí testů nanečisto.

Na zkompilování spustitelných souborů, viz poznámky na konci stránky.

Požadavky

Od programu budeme očekávat mnoho různých funkcí. Proto si na začátek připravíme pomocné funkce, které vám pomohou s dekompozicí programu a nám zase ulehčí testovaní.

Pomocné funkce

Vrátí true, když se na políčku, daném parametrem, nachází mina. Jinak vrátí false.

bool is_mine(uint16_t cell)

Vrátí true, když se na políčku, daném parametrem, nachází vlajka. Jinak vrátí false.

bool is_flag(uint16_t cell)

Vrátí true, když je políčko, daném parametrem, odkryté. Jinak vrátí false.

bool is_revealed(uint16_t cell)

Vrátí počet min v okolí políčka, které je zadané parametrem. Pokud se jedná o minu, vrátí 0.

int get_number(uint16_t cell)

Funkce pro vstup a výstup

Dále budeme potřebovat funkce, které budou pracovat s vstupem a výstupem.

bool set_cell(uint16_t *cell, char val)

Funkce má za úkol přeložit hodnotu val do vaší reprezentace na dané políčko v plánku. Jako parametry dostane ukazatel na políčko v herním plánu a znak, který má na daném políčku být. Význam znaku naleznete v sekci o formátování.

Pokud proběhne zápis do buňky v pořádku, vrátí true, jinak false. Dobře si rozmyslete, jaké nevalidní případy mohou nastat.

Bez správného fungování této funkce nejsme schopní pracovat s vámi zvolenou reprezentací jednotlivých stavů políčka a pravděpodobně vám neprojdou žádné testy. Dejte si na jejím správném fungování záležet, protože s její pomocí budeme testovat v podstatě celou vaší implementaci.

int postprocess(size_t rows, size_t cols, uint16_t board[rows][cols])

Funkce postprocess() bude ošetřovat všechny nevalidní stavy načteného herního plánu. Máte garantované, že funkce postprocess() bude volána těsně po volání set_cell(). Tedy pole bude nastaveno dle vaší reprezentace políček. Jejím úkolem je především dopočítat počet okolních min pro načtené odkryté a zakryté políčka ('.', 'X'), ale také zkontrolovat, že načítaná čísla odpovídají počtu okolních min.

Tato funkce může při kontrole načteného plánku narazit na několik nevalidních stavů:

  • dimenze herního pole (tedy rows nebo cols) je menší než 3 (MIN_SIZE) nebo větší než 99 (MAX_SIZE)

  • odkrytá políčka označená číslicemi nesouhlasí se skutečným počtem sousedících min

  • v rohu herního plánku je umístěna mina (nechcete přeci naštvat vedoucího předmětu)

  • neobsahuje žádnou minu, čímž by hra nedávala smysl

V těchto zmíněných případech vaše funkce musí skončit s návratovým kódem -1 a samotný obsah pole je nedefinovaný (tedy nebude testován).

Pokud nedojde k žádnému nekorektnímu stavu, tak funkce vrátí počet min v herním plánu a board bude korektní herní plán s dopočítanými okolními minami na všech políčkách (kromě samotných min).

I tato funkce je důležitá pro testování všeho ostatního. Dejte si na implementaci záležet.

int load_board(size_t rows, size_t cols, uint16_t board[rows][cols])

Tato funkce dostane jako parametry velikost herního plánu a pole, do kterého plán načte. Velikost plánu (parametry rows a cols) zjistí program používající vaše funkce a není to součástí zadání.

Úlohou této funkce je načíst plánek ze standardního vstupu (viz sekce formátování vstupu) , převést každý validní znak do vámi zvolené reprezentace a tuto reprezentaci uložit do pole uint16_t board[rows][cols]. Přitom přeskakuje znaky, které nejsou v tabulce definovány.

Vyplňování pole probíhá zleva doprava, počínaje prvním řádkem a sloupcem. Po naplnění celého řádku (do velikosti cols) se přejde na první sloupec o řádek níže a takto pokračuje do posledního řádku a sloupce (tedy až na políčko board[rows-1][cols-1]).

Po načítání je potřeba ověřit, že herní plán je korektní. Na to můžete použít předcházející funkci postprocess(), ta vám zároveň dopočítá i okolní miny.

Pokud funkce úspěšně načte rows * cols validních znaků do pole, tak vrátí návratovou hodnotu funkce postprocess(). Toto chování je v kostře již připravené. V případe chyby vrací hodnotu -1.


To by bylo vše pro vstup, nyní budeme chtít funkce, které nám na standardní výstup v konkrétním formátu vypíší aktuální stav herního plánku tak, jak jej uvidí hráč.

char show_cell(uint16_t cell)

Vrátí znak, který reprezentuje políčko zadané v argumentu z pohledu hráče (dle tabulky pro formátování výstupu). Zde uvažujeme pouze prostřední znak z tabulky formátování. Tedy při neodkrytém políčku vracíte pouze X místo XXX a při vlajce pouze znak F místo _F_, při označení sousedních min pouze číslo, minu jako M a při prázdném políčku znak mezery ' '.

Toto je další funkce, která bude použita na testování, takže musí fungovat korektně, aby prošly testy na ostatních funkcích.

int print_board(size_t rows, size_t cols, uint16_t board[rows][cols]);

Parametry rows a cols stejně jako při vstupu udávají velikost herního pole. Všimněte si, že funkce nic nevrací, jejím úkolem je tak pouze výpis, kdy vypíše celé herní pole na standardní výstup, dle pravidel v sekci o formátování výstupu.

Návratová hodnota této funkce bude 0 v případě, že se funkci rozhodnete implementovat, jinak ji ponechte -1. U této funkce nepředpokládáme, že by mohly nastat chybové stavy, které byste museli ošetřit.

Samotný výstup této funkce v sobě musí obsahovat i očíslování řádků, sloupců a také ohraničení pole a buněk. Zde se můžete řídit pravidlem, že každá buňka (políčko) má 3 znaky na šířku a zabírá 1 řádek.

Zde je konkrétní případ výstupu pro náhodně rozehranou hru:

     0   1   2   3   4   5   6   7   8   9  10
   +---+---+---+---+---+---+---+---+---+---+---+
 0 |XXX| 1 |   |   |   |   | 1 | 1 | 1 |   |   |
   +---+---+---+---+---+---+---+---+---+---+---+
 1 |XXX| 1 |   |   |   |   | 1 |XXX| 1 |   |   |
   +---+---+---+---+---+---+---+---+---+---+---+
 2 |XXX| 2 | 1 |   |   |   | 1 | 2 | 2 | 1 |   |
   +---+---+---+---+---+---+---+---+---+---+---+
 3 |XXX|XXX| 2 |   |   |   |   | 1 |XXX| 1 |   |
   +---+---+---+---+---+---+---+---+---+---+---+
 4 |XXX|XXX| 2 |   |   |   |   | 1 | 1 | 1 |   |
   +---+---+---+---+---+---+---+---+---+---+---+
 5 |XXX| 3 | 2 |   |   |   |   |   |   | 1 | 1 |
   +---+---+---+---+---+---+---+---+---+---+---+
 6 |XXX|XXX| 2 |   |   |   |   |   | 2 |_F_|XXX|
   +---+---+---+---+---+---+---+---+---+---+---+
 7 |XXX|XXX| 2 |   |   |   |   | 1 |_F_|_F_|XXX|
   +---+---+---+---+---+---+---+---+---+---+---+
 8 |XXX| 3 | 1 |   | 1 | 1 | 1 | 1 | 2 | 2 |XXX|
   +---+---+---+---+---+---+---+---+---+---+---+
 9 | 1 | 1 |   |   | 2 |_F_| 2 |   | 2 |_F_|XXX|
   +---+---+---+---+---+---+---+---+---+---+---+
10 |   |   |   |   | 2 |_F_| 2 | 1 |_F_|XXX|XXX|
   +---+---+---+---+---+---+---+---+---+---+---+

Všimněte si především formátování dvouciferných číslování řádků (resp. sloupců) nebo použitých znaků pro oddělování buněk.

Pokud je číselné označení sloupce resp. řádku jednociferné číslo, zarovnáváme jej "na střed" (tedy před ním i za ním je mezera). Pokud je takové číslo dvojciferné, zarovnáváme jej "doleva" (tedy má mezeru pouze za sebou).

Pokud si nejste v této funkci něčím jistí, je vždy směrodatné chování vzorové implementace, kde si můžete sami různé situace namodelovat a vyzkoušet.

Herní mechanika

int reveal_cell(size_t rows, size_t cols, uint16_t board[rows][cols], size_t row, size_t col)

Simuluje kliknutí hráče na políčko v herním plánu dle zadaných souřadnic row a col. Pokud je odkryté políčko prázdné (tedy nemá číslo a nesousedí s žádnou minou), spustí se na tomto místě voláním funkce reveal_floodfill() proces floodfillu.

Mezi nevalidní tahy patří:

  • pokus o odkrytí již odkrytého políčka

  • pokus o odkrytí políčka označeného vlajkou

  • pokus o odkrytí políčka mimo hranice herního plánu

V těchto případech vrací hodnotu -1, jinak vrací 0 a při odkrytí a výbuchu miny vrací 1.


int reveal_single(uint16_t *cell)

Funguje stejně jako reveal_cell(), ale odkrývá právě jedno políčko (tedy bez floodfillu). Tuto funkci je vhodné použít k zabránění duplikace kódu ve funkci reveal_cell() a reveal_floodfill().


void reveal_floodfill(size_t rows, size_t cols, uint16_t board[rows][cols], size_t row, size_t col)

Tato funkce odkrývá všech osm polí sousedících s prázdným políčkem zadaném souřadnicemi row a col. Při nalezení prázdného políčka se pokračuje v odkrývání jeho sousedů. V tomto případě je pro vás velmi elegantním a nejjednodušším řešením použití rekurze, i když to v jazyce C není nejoptimálnější řešení. Rekurze ale není pro splnění této funkce podmínkou.

Volání této funkce nad neprázdným políčkem není definované a nebude se testovat.


int flag_cell(size_t rows, size_t cols, uint16_t board[rows][cols], size_t row, size_t col)

Označí políčko vlajkou. Pokud toto políčko již vlajkou označené bylo, odstraní ji. V obou případech vrátí nový počet zbývajících min, tedy mine_count - flagged_cells.


bool is_solved(size_t rows, size_t cols, uint16_t board[rows][cols])

Tato funkce rozhodne, zda je herní pole vyřešené. To nastane v případě, kdy počet neodkrytých políček je roven počtu min. Pokud je vyřešené, vrací hodnotu true, jinak false.

Bonusové rozšíření

int generate_random_board(size_t rows, size_t cols, int mines, uint16_t board[rows][cols])

Vygeneruje herní plán určený počtem řádků, sloupců a min. Miny musí být náhodně rozložené po herním pláně. V případě, že bude „náhodnost“ splňovat nějaký očividný vzor, budou za to ztržené body (opravuje cvičící). Pozorně se zamyslete, jaké podmínky musí pole splňovat, dle zadání této úlohy.

Navrátovou hodnotu určuje funkce postprocess() (jako v load_board()), která dopočítá u políček okolní miny a tím vytvoří z plánu korektní herní plán připraven na hru. V případe chyby vrací -1.


int find_mines(size_t rows, size_t cols, uint16_t board[rows][cols])

Tato funkce v zadaném herním poli označí všechny jednoznačné miny (označí je vlajkou). Pojmem jednoznačná mina se rozumí neodkryté políčko, které leží v okolí odkrytého čísla n, které má jako své sousedy právě n neodkrytých políček.

Pozor, v této funkci nebudete vědět, kde se miny nachází. Proto je vaší úlohou zároveň i znovu načíst herní plán a uložit ho do board zadaným parametrem funkce. Herní pole bude zadané na standardní vstup stejně, jak ve funkci load_board() s dvěma malými změnami:

  • Na vstupu akceptujte pouze znaky 'X' a '0' - '8', všechny ostatní ignorujte. Načítavat se jich bude přesně rows * cols.

  • Nemusíte kontrolovat správnost vstupu (to koneckonců ani nejde, když nevíte, kde jsou miny).

Návratová hodnota je počet nálezených min. V případe chyby vrací -1.

Poznámky

Myslete na to, že v některých funkcích je nutné uvažovat i nad situací, že herní plán do nich vstupuje se „špinavými“ daty. Tedy nemusí být např. nutně vynulovaný.

Pro pokročilé vlastní testování se vám může hodit nový soubor main.c který bude volat vaše implementované řešení.

Vzorovou implementaci najdete na Aise /home/kontr/pb071/hw02/minesweeper.

Pro zkompilování vašich souborů a testů je přiložený CMakeLists.txt soubor. Díky němu si můžete kompilaci zjednodušit do následujícího příkazu:
mkdir out && cd out && cmake .. && make
Výsledkem jsou spustitelné soubory v adresáři hw02/out, ve kterém se budete nacházet po zadání daného příkazu.

Vzorová implementace podporuje i tah debug (kromě reveal a flag), který nebere žádné parametry a vypíše vám na obrazovku odkryté pole.

Opravy v zadání

Postpone deadline by 1 day

48c056f 2022-03-19 00:42 Roman Lacko
 -6,4 +6,4  solution-path: /home/kontr/pb071/hw02/minesweeper
 publish: now
-deadline-early: 2022-03-20 24:00
-deadline-final: 2022-03-23 24:00
+deadline-early: 2022-03-21 24:00
+deadline-final: 2022-03-24 24:00
 authors:

Add return value of load in case of error

9a3b9b1 2022-03-10 21:38 Dominik Masar
 -289,2 +289,3  Pokud funkce úspěšně načte `rows * cols` validních znaků do pole,
 tak vrátí návratovou hodnotu funkce `postprocess()`. Toto chování je v kostře již připravené.
+V případe chyby vrací hodnotu `-1`.
 

Fix mistake in find_mines()

9bd98dd 2022-03-10 21:37 Dominik Masar
 -466,3 +466,3  s dvěma malými změnami:
 
-* Na vstupu **akceptujte pouze** znaky `'X'` a `'0'` - `'9'`, všechny ostatní ignorujte.
+* Na vstupu **akceptujte pouze** znaky `'X'` a `'0'` - `'8'`, všechny ostatní ignorujte.
   Načítavat se jich bude přesně `rows * cols`.

Fix indexing in print_board()

75a2b55 2022-03-09 16:31 Dominik Masar
 -331,24 +331,26  Zde je konkrétní případ výstupu pro náhodně rozehranou hru:
 ----
-     1   2   3   4   5   6   7   8   9  10
-   +---+---+---+---+---+---+---+---+---+---+
- 1 |XXX| 1 |   |   |   |   | 1 |XXX| 1 |   |
-   +---+---+---+---+---+---+---+---+---+---+
- 2 |XXX| 2 | 1 |   |   |   | 1 | 2 | 2 | 1 |
-   +---+---+---+---+---+---+---+---+---+---+
- 3 |XXX|XXX| 2 |   |   |   |   | 1 |XXX| 1 |
-   +---+---+---+---+---+---+---+---+---+---+
- 4 |XXX|XXX| 2 |   |   |   |   | 1 | 1 | 1 |
-   +---+---+---+---+---+---+---+---+---+---+
- 5 |XXX| 3 | 2 |   |   |   |   |   |   | 1 |
-   +---+---+---+---+---+---+---+---+---+---+
- 6 |XXX|XXX| 2 |   |   |   |   |   | 2 |_F_|
-   +---+---+---+---+---+---+---+---+---+---+
- 7 |XXX|XXX| 2 |   |   |   |   | 1 |_F_|_F_|
-   +---+---+---+---+---+---+---+---+---+---+
- 8 |XXX| 3 | 1 |   | 1 | 1 | 1 | 1 | 2 | 2 |
-   +---+---+---+---+---+---+---+---+---+---+
- 9 | 1 | 1 |   |   | 2 |_F_| 2 |   | 2 |_F_|
-   +---+---+---+---+---+---+---+---+---+---+
-10 |   |   |   |   | 2 |_F_| 2 | 1 |_F_|XXX|
-   +---+---+---+---+---+---+---+---+---+---+
+     0   1   2   3   4   5   6   7   8   9  10 
+   +---+---+---+---+---+---+---+---+---+---+---+
+ 0 |XXX| 1 |   |   |   |   | 1 | 1 | 1 |   |   |
+   +---+---+---+---+---+---+---+---+---+---+---+
+ 1 |XXX| 1 |   |   |   |   | 1 |XXX| 1 |   |   |
+   +---+---+---+---+---+---+---+---+---+---+---+
+ 2 |XXX| 2 | 1 |   |   |   | 1 | 2 | 2 | 1 |   |
+   +---+---+---+---+---+---+---+---+---+---+---+
+ 3 |XXX|XXX| 2 |   |   |   |   | 1 |XXX| 1 |   |
+   +---+---+---+---+---+---+---+---+---+---+---+
+ 4 |XXX|XXX| 2 |   |   |   |   | 1 | 1 | 1 |   |
+   +---+---+---+---+---+---+---+---+---+---+---+
+ 5 |XXX| 3 | 2 |   |   |   |   |   |   | 1 | 1 |
+   +---+---+---+---+---+---+---+---+---+---+---+
+ 6 |XXX|XXX| 2 |   |   |   |   |   | 2 |_F_|XXX|
+   +---+---+---+---+---+---+---+---+---+---+---+
+ 7 |XXX|XXX| 2 |   |   |   |   | 1 |_F_|_F_|XXX|
+   +---+---+---+---+---+---+---+---+---+---+---+
+ 8 |XXX| 3 | 1 |   | 1 | 1 | 1 | 1 | 2 | 2 |XXX|
+   +---+---+---+---+---+---+---+---+---+---+---+
+ 9 | 1 | 1 |   |   | 2 |_F_| 2 |   | 2 |_F_|XXX|
+   +---+---+---+---+---+---+---+---+---+---+---+
+10 |   |   |   |   | 2 |_F_| 2 | 1 |_F_|XXX|XXX|
+   +---+---+---+---+---+---+---+---+---+---+---+
 ----

fix(assignment): reveal_single declaration

8304d2b 2022-03-08 19:10 Daniel Rozehnal
 -389,3 +389,3  miny vrací `1`.
 ----
-int reveal_single(size_t rows, size_t cols, uint16_t board[rows][cols], size_t row, size_t col)
+int reveal_single(uint16_t *cell)
 ----

Fix return type and value for the print_board

12c20d5 2022-03-08 15:27 Peter Stanko
 -313,3 +313,3  aby prošly testy na ostatních funkcích.
 ----
-void print_board(size_t rows, size_t cols, uint16_t board[rows][cols]);
+int print_board(size_t rows, size_t cols, uint16_t board[rows][cols]);
 ----
 -320,2 +320,6  celé herní pole na standardní výstup, dle pravidel v sekci o formátování
 
+Návratová hodnota této funkce bude `0` v případě, že se funkci rozhodnete implementovat,
+jinak ji ponechte `-1`. U této funkce nepředpokládáme, že by mohly nastat chybové stavy,
+které byste museli ošetřit.
+
 Samotný výstup této funkce v sobě musí obsahovat i očíslování řádků, sloupců a také

Fix the confusing part about the game board representation

bd1a7ea 2022-03-08 13:35 Peter Stanko
 -101,6 +101,5  Ukažme zde kompletní průběh krátké hry:
 
-Reprezentace těchto stavů políčka na 16 bitech *je zcela na vás*. Můžete si jen
-pamatovat zda je přítomna mina a zmiňovaný stav pole, ale také si například
-můžete (ale nemusíte) předpočítat počet sousedících min. V závislosti na vámi
-zvolené reprezentaci tak mohou být některé požadované funkce jednodušší.
+Reprezentace těchto stavů políčka na 16 bitech *je zcela na vás*. 
+Musíte vědet reprezentovat všechny stavy políčka, včetně počtu sousedících min. 
+V závislosti na vámi zvolené reprezentaci tak mohou být některé požadované funkce jednodušší.
 

Fix of definition of bonus function

d763df7 2022-03-08 11:12 Dominik Masar
 -432,3 +432,3  hodnotu `true`, jinak `false`.
 ----
-int generate_random(size_t rows, size_t cols, int mines, uint16_t board[rows][cols])
+int generate_random_board(size_t rows, size_t cols, int mines, uint16_t board[rows][cols])
 ----

Fix of description of bonus fuctions

4343c37 2022-03-08 11:10 Dominik Masar
 -443,3 +443,3  Navrátovou hodnotu určuje funkce `postprocess()` (jako v
 `load_board()`), která dopočítá u políček okolní miny a tím vytvoří z plánu
-korektní herní plán připraven na hru.
+korektní herní plán připraven na hru. V případe chyby vrací `-1`.
 
 -465,3 +465,3  s dvěma malými změnami:
 
-Návratová hodnota je počet nálezených min.
+Návratová hodnota je počet nálezených min. V případe chyby vrací `-1`.
 

Fix return values

2fcd2d4 2022-03-08 11:06 Dominik Masar
 -432,3 +432,3  hodnotu `true`, jinak `false`.
 ----
-void generate_random(size_t rows, size_t cols, int mines, uint16_t board[rows][cols])
+int generate_random(size_t rows, size_t cols, int mines, uint16_t board[rows][cols])
 ----
 -449,3 +449,3  korektní herní plán připraven na hru.
 ----
-unsigned int find_mines(size_t rows, size_t cols, uint16_t board[rows][cols])
+int find_mines(size_t rows, size_t cols, uint16_t board[rows][cols])
 ----

Add last-minute corrections

79bc448 2022-03-07 23:47 Roman Lacko
 -242,4 +242,4  int postprocess(size_t rows, size_t cols, uint16_t board[rows][cols])
 
-Funkce `postprocess` bude ošetřovat všechny nevalidní stavy načteného herního plánu.
-Máte garantované, že funkce `postprocess` bude volána těsně po volání `set_cell`.
+Funkce `postprocess()` bude ošetřovat všechny nevalidní stavy načteného herního plánu.
+Máte garantované, že funkce `postprocess()` bude volána těsně po volání `set_cell()`.
 Tedy pole bude nastaveno dle vaší reprezentace políček. Jejím úkolem
 -262,2 +262,5  plánu a `board` bude korektní herní plán s dopočítanými okolními minami
 
+NOTE: I tato funkce je důležitá pro testování všeho ostatního. Dejte si na
+implementaci záležet.
+
 '''
 -283,6 +286,6  posledního řádku a sloupce (tedy až na políčko `board[rows-1][cols-1]`).
 Po načítání je potřeba ověřit, že herní plán je korektní. Na to můžete použít
-předcházející funkci `postprocess`, ta vám zároveň dopočítá i okolní miny.
+předcházející funkci `postprocess()`, ta vám zároveň dopočítá i okolní miny.
 
 Pokud funkce úspěšně načte `rows * cols` validních znaků do pole,
-tak vrátí návratovou hodnotu funkce `postprocess`. Toto chování je v kostře již připravené.
+tak vrátí návratovou hodnotu funkce `postprocess()`. Toto chování je v kostře již připravené.
 
 -302,3 +305,4  Tedy při neodkrytém políčku vracíte pouze `X` místo `XXX` a při vlajce po
 místo `\_F_`, při označení sousedních min pouze číslo, minu jako `M` a při prázdném
-políčku znak mezery ` `.
+políčku znak mezery `' '`.
+
 NOTE: Toto je další funkce, která bude použita na testování, takže musí fungovat korektně,
 -340,3 +344,3  Zde je konkrétní případ výstupu pro náhodně rozehranou hru:
    +---+---+---+---+---+---+---+---+---+---+
- 8 |XXX| 3 | 1 |   | 1 | 1 | 1 | 1 | 2 | 1 |
+ 8 |XXX| 3 | 1 |   | 1 | 1 | 1 | 1 | 2 | 2 |
    +---+---+---+---+---+---+---+---+---+---+
 -367,3 +371,3  Simuluje kliknutí hráče na políčko v herním plánu dle zadaných souřadni
 Pokud je odkryté políčko prázdné (tedy nemá číslo a nesousedí s žádnou minou),
-spustí se na tomto místě voláním funkce `reveal_floodfill` proces _floodfillu_.
+spustí se na tomto místě voláním funkce `reveal_floodfill()` proces _floodfillu_.
 
 -385,4 +389,4  int reveal_single(size_t rows, size_t cols, uint16_t board[rows][cols], size_t r
 
-Funguje stejně jako `reveal_cell`, ale odkrývá právě jedno políčko (tedy bez _floodfillu_).
-Tuto funkci je vhodné použít k zabránění duplikace kódu ve funkci `reveal_cell` a `reveal_floodfill`.
+Funguje stejně jako `reveal_cell()`, ale odkrývá právě jedno políčko (tedy bez _floodfillu_).
+Tuto funkci je vhodné použít k zabránění duplikace kódu ve funkci `reveal_cell()` a `reveal_floodfill()`.
 
 -437,4 +441,4  této úlohy.
 
-Navrátovou hodnotu určuje funkce `postprocess` (jako v
-`load_board`), která dopočítá u políček okolní miny a tím vytvoří z plánu
+Navrátovou hodnotu určuje funkce `postprocess()` (jako v
+`load_board()`), která dopočítá u políček okolní miny a tím vytvoří z plánu
 korektní herní plán připraven na hru.
 -454,3 +458,3  Pozor, v této funkci nebudete vědět, kde se miny nachází. Proto je vaší 
 zároveň i znovu načíst herní plán a uložit ho do `board` zadaným parametrem funkce.
-Herní pole bude zadané na standardní vstup stejně, jak ve funkci `load_board`
+Herní pole bude zadané na standardní vstup stejně, jak ve funkci `load_board()`
 s dvěma malými změnami: