O čom je lab
V rámci tohto cvičenia naprogramujete ďalšiu hru - zjednodušenú verziu hry Piškvorky (Tic Tac Toe).
Ciele
- Rutinne pracovať s poliami.
- Rutinne pracovať s vetvením a cyklením programov.
- Osvojiť si prácu s parametrami funkcií.
- Oboznámiť sa s dvojrozmerným poľom.
Postup
Krok 1: Piškvorky
V tomto kroku implementujete jednoduchú hru Piškvorky (jednorozmerné). Hrací plán je v tomto prípade jednorozmerné pole o dĺžke N
. Hru hrajú dvaja hráči a obaja do tohto poľa zapisujú krížiky (znak X). Prvý, ktorému sa podarí vytvoriť aspoň tri krížiky vedľa seba, vyhráva.
Pre ladenie programu a odstraňovanie prípadných chýb použite nástroj cgdb z minulého cvičenia.
Úloha 1.1
Vytvorte funkciu void draw(const int size, char field[])
, ktorá na obrazovku vykreslí aktuálny stav hracieho poľa.
Ak obsah poľa field
bude nasledovný:
char field[] = { ' ', 'X', ' ', 'X', ' '};
tak funkcia na obrazovku vypíše obsah v nasledovnom tvare:
+-+-+-+-+-+
| |X| |X| |
+-+-+-+-+-+
1 2 3 4 5
Okrem obsahu samotného poľa teda funkcia vypíše aj indexy jednotlivých prvkov. Pomocou týchto indexov budú môcť hráči do poľa vkladať svoje krížiky. Všimnite si, že indexovanie pre hráčov začína číslom 1.
Úloha 1.2
Upravte hlavnú funkciu programu tak, aby hráč najskôr zadal veľkosť hracieho poľa, ktoré sa následne zobrazí.
Pre veľkosť hracieho poľa platí, že jeho minimálna veľkosť je 4 a maximálna veľkosť je 9. Ak hráč zadá nesprávnu veľkosť hracieho poľa, voľbu musí zopakovať.
$ ./tictactoe Enter the size of field: 3 Enter the size of field: 22 Enter the size of field: 7 +-+-+-+-+-+-+-+ | | | | | | | | +-+-+-+-+-+-+-+ 1 2 3 4 5 6 7
Úloha 1.3
Vytvorte funkciu int add_cross(const int size, char field[], const int position)
, ktorá na pozíciu danú parametrom position
hracieho poľa umiestni krížik.
V prípade, že sa na danej pozícii už krížik nachádza, funkcia vráti hodnotu 0. Ak je naopak toto miesto voľné, po úspešnom vložení krížika vráti funkcia hodnotu 1.
Úloha 1.4
Upravte funkciu int add_cross()
tak, aby vrátila hodnotu -1, ak je hráčom daná pozícia mimo rozsahu hracieho poľa.
Úloha 1.5
Vytvorte funkciu int is_solved(const int size, char field[])
, ktorá overí, či už hra nie je vyriešená.
Funkcia vráti hodnotu 1, ak sa v poli nachádzajú vedľa seba min. 3 krížiky. V opačnom prípade vráti hodnotu 0.
Úloha 1.6
Pomocou vytvorených funkcií implementujte hru.
Dialóg dvoch hráčov môže vyzerať nasledovne:
$ ./tictactoe Enter the size of field: 9 +-+-+-+-+-+-+-+-+-+ | | | | | | | | | | +-+-+-+-+-+-+-+-+-+ 1 2 3 4 5 6 7 8 9 Player A: 2 +-+-+-+-+-+-+-+-+-+ | |X| | | | | | | | +-+-+-+-+-+-+-+-+-+ 1 2 3 4 5 6 7 8 9 Player B: 5 +-+-+-+-+-+-+-+-+-+ | |X| | |X| | | | | +-+-+-+-+-+-+-+-+-+ 1 2 3 4 5 6 7 8 9 Player A: 9 +-+-+-+-+-+-+-+-+-+ | |X| | |X| | | |X| +-+-+-+-+-+-+-+-+-+ 1 2 3 4 5 6 7 8 9 Player B: 10 Wrong position! Player A: 2 X is already there! Player B: 8 +-+-+-+-+-+-+-+-+-+ | |X| | |X| | |X|X| +-+-+-+-+-+-+-+-+-+ 1 2 3 4 5 6 7 8 9 Player A: 7 +-+-+-+-+-+-+-+-+-+ | |X| | |X| |X|X|X| +-+-+-+-+-+-+-+-+-+ 1 2 3 4 5 6 7 8 9 Player A wins!
Krok 2: 2D
V tomto kroku zmeníte hru tak, aby používala dvojrozmerné pole.
- Program teda upravíte tak, aby pole
field[]
bolo dvojrozmerné. Hracie pole má byť štvorcové, t.j. jeho veľkosť bude rovnaká do výšky aj do šírky. - Hráč zadáva dve hodnoty. Prvá predstavuje pozíciu na osi x a druhá na osi y.
- Os x je horizontálna os číslovaná zľava doprava od hodnoty 1. Zobrazuje sa pod hracím poľom. Os y je vertikálna os číslovaná zdola nahor od hodnoty 1. Zobrazuje sa naľavo vedľa hracieho poľa.
- Hráčovi A sa zobrazujú krížiky X a hráčovi B sa zobrazujú krúžky O.
- Dialóg dvoch hráčov môže vyzerať nasledovne:
$ ./tictactoe Enter the size of field: 5 +-+-+-+-+-+ 5 | | | | | | +-+-+-+-+-+ 4 | | | | | | +-+-+-+-+-+ 3 | | | | | | +-+-+-+-+-+ 2 | | | | | | +-+-+-+-+-+ 1 | | | | | | +-+-+-+-+-+ 1 2 3 4 5 Player A: 0 3 Wrong position! Player B: 3 3 +-+-+-+-+-+ 5 | | | | | | +-+-+-+-+-+ 4 | | | | | | +-+-+-+-+-+ 3 | | |O| | | +-+-+-+-+-+ 2 | | | | | | +-+-+-+-+-+ 1 | | | | | | +-+-+-+-+-+ 1 2 3 4 5 Player A: 2 2 +-+-+-+-+-+ 5 | | | | | | +-+-+-+-+-+ 4 | | | | | | +-+-+-+-+-+ 3 | | |O| | | +-+-+-+-+-+ 2 | |X| | | | +-+-+-+-+-+ 1 | | | | | | +-+-+-+-+-+ 1 2 3 4 5 Player B: 4 4 +-+-+-+-+-+ 5 | | | | | | +-+-+-+-+-+ 4 | | | |O| | +-+-+-+-+-+ 3 | | |O| | | +-+-+-+-+-+ 2 | |X| | | | +-+-+-+-+-+ 1 | | | | | | +-+-+-+-+-+ 1 2 3 4 5 Player A: 6 5 Wrong position! Player B: 5 5 +-+-+-+-+-+ 5 | | | | |O| +-+-+-+-+-+ 4 | | | |O| | +-+-+-+-+-+ 3 | | |O| | | +-+-+-+-+-+ 2 | |X| | | | +-+-+-+-+-+ 1 | | | | | | +-+-+-+-+-+ 1 2 3 4 5 Player B wins!
Úloha 2.1
Upravte definíciu poľa field
vo funkcii main()
tak, aby pole bolo dvojrozmerné.
Obidva rozmery poľa sú rovnaké. To udáva premenná, v ktorej je uložený rozmer hracieho poľa. Tento rozmer zadal hráč.
Všetky prvky poľa na začiatku obsahuju znak ' ' (medzera).
Úloha 2.2
Upravte deklaráciu aj definíciu funkcie draw()
tak, aby používala dvojrozmerné pole.
Deklarácia sa zmení nasledovne: void draw(const int size, char field[][size])
, kde size
je rozmer poľa (vertikálny aj horizontálny) a field
je dvojrozmerné pole. Druhý rozmer (údaj v druhej zátvorke) je pri dvojrozmerných poliach povinný. Preto je parameter size
uvedený ako prvý (v mieste svojho použitia už musí byť známy).
Funkcia má vykresliť hracie pole tak, aby os x bola číslovaná zľava doprava od hodnoty 1, zobrazená pod hracím poľom. Os y je číslovaná zdola nahor od hodnoty 1, zobrazená naľavo vedľa hracieho poľa.
Úloha 2.3
Upravte deklaráciu aj definíciu funkcie add_cross()
tak, aby používala dvojrozmerné pole.
Deklarácia sa zmení nasledovne: int add_cross(const int size, char field[][size], const int x, const int y, const char player)
, kde size
je rozmer poľa (vertikálny aj horizontálny) a field
je dvojrozmerné pole. Parametre x
a y
predstavujú horizontálnu a vertikálnu súradnicu, na ktorú chce hráč pridať krížik alebo krúžok. Parameter player
udáva, ktorý hráč je aktuálne na ťahu.
Funkcia má do poľa field
pridať krížik (znak X), ak je na ťahu hráč A, a krúžok (znak O), ak je na ťahu hráč B. To, ktorý hráč je na ťahu, udáva parameter player
.
Nezabudnite upraviť aj miesto volania funkcie (pribudli nám parametre).
Úloha 2.4
Upravte deklaráciu aj definíciu funkcie is_solved()
tak, aby používala dvojrozmerné pole.
Deklarácia sa zmení nasledovne: int is_solved(const int size, char field[][size])
, kde size
je rozmer poľa (vertikálny aj horizontálny) a field
je dvojrozmerné pole.
Funkcia má zistiť, či je hra vyhratá, ak sa v hracom poli vedľa seba nachádzajú tri krížiky resp. tri krúžky. To platí v štyroch smeroch: horizontálny (sú vedľa seba), vertikálny (sú nad resp. pod sebou), hlavná diagonála a vedľajšia diagonála.
Úloha 2.5
Overte funkčnosť Vášho riešenia.
Doplňujúce úlohy
Úloha A.1
Vytvorte funkciu void make_turn(const int size, char field[][size])
. Táto funkcia bude predstavovať súpera proti hráčovi, ktorým bude samotný počítač.
Úloha A.2
Vytvorte funkcie int find_min(const int size, char field[][size])
a int find_max(const int size, char field[][size])
, ktoré vrátia pozíciu najmenšieho a najväčšieho prvku v poli. Ak je takýchto prvkov v poli viac, vráťte prvý z nich.
Úloha A.3
Vytvorte funkciu int compare(const int size1, char field1[][size1], const int size2, char field2[][size2])
, ktorá vráti hodnotu 1, ak sú obe polia rovnaké. V opačnom prípade vráti hodnotu 0.