Dvojrozmerné polia

<< Polia a "poľové" algoritmy | Obsah | Výnimky (odchytávanie) >>

Polia sme doposiaľ využívali na uloženie nejakého počtu hodnôt rovnakého typu (napr. pole čísel, či pole referencií na korytnačky). Jedna z predstáv o poli je tá, že je to objekt, ktorý sa skladá z nejakej postupnosti políčok schopných uchovávať hodnoty. Pri programovaní stolových hier, či pri komplikovanejšej matematike (sústavy rovníc) sa nám ale môže objaviť potreba niečoho, čo by uchovávalo dáta v dvoch rozmeroch - v tabuľke. Samozrejme 2-rozmerné polia dokážeme simulovať pomocou jednorozmerného, ale takáto práca nie je veľmi praktická. 2-rozmerné pole, nazývané aj matica, je taktiež Java objekt. Narozdiel o klasických jednorozmerných polí, sú políčka v 2-rozmernom poli prístupné na základe dvojice čísel: index riadka políčka a index stĺpca políčka. Pozrime sa ako deklarovať a ako vytvoriť "poľový" objekt pre 2-rozmerné polia.

// Deklarácia premennej schopnej referencovať 2-rozmerné pole
int[][] referenciaNa2DPole;

// Vytvorenie 2-rozmerného poľa (matice) s 10 riadkami a 15 stĺpcami
referenciaNa2DPole = new int[10][15];

Ako môžeme vidieť vo vyššie uvedenom príklad, 2-rozmerné polia sa nejako zásadné nelíšia od klasických jednorozmerných polí. Akurát pri deklarovaní premennej referencujúcej 2D pole namiesto jedného páru [] zátvoriek dáme dva páry. Podobne je to aj s vytvorením poľa ("poľového" objektu). Za new a typ políčka dáme dve dvojice hranatých zátvoriek. Do prvej z nich uvedieme počet riadkov vytváraného poľa a do druhej počet stĺpcov vytváraného poľa.

Aj 2-rozmerné polia podporujú skrátený príkaz kombinujúci vytvorenie poľa s definovaním hodnôt jednotlivých políčok poľa.

int[][] matica = {{3, 4, 5, 6}, {10, 11, 2, 3}, {1, 7, 3, 1}};

// je to isté ako:
int[][] matica = new int[3][4];
matica[0][0] = 3;
matica[0][1] = 4;
matica[0][2] = 5;
matica[0][3] = 6;
matica[1][0] = 10;
matica[1][1] = 11;
matica[1][2] = 2;
...
matica[2][3] = 1;
3 4 5 6
10 11 2 3
1 7 3 1

Na prístup k políčkam poľa využívame dvojicu indexov:

[0][0] [0][1] [0][2] [0][3]
[1][0] [1][1] [1][2] [1][3]
[2][0] [2][1] [2][2] [2][3]

Ľahko sa dovtípime, že pri inicializácií 2D poľa píšeme do kučeravých zátvoriek postupnosť hodnôt pre jednotlivé riadku. Hodnoty pre jeden riadok sú tiež uzavreté vo vnorených kučeravých zátvorkách.

Finty pre 2-rozmerné polia

Pre 2D polia vieme s menšou obmenou využiť stratégie pre jednorozmerné polia predstavené v predošlej prednáške (všetky majú nejakú vlastnosť, či naj prvok). Druhý rozmer poľa so sebou prináša aj možnosť komplikovanejšieho pohybu v poli. Zoberme si implementáciu hry piškvorky, v ktorej je obsadenosť políčok hracej plochy uložená v nejakom 2-rozmernom poli. Aby sme zistili, či posledným ťahom nedošlo k dosiahnutiu výhernej konfigurácie, musíme overiť, či niekde v niektorom z 8 smerov nie je uložených 5 hracích kameňov rovnakej farby. V prípade hry piškvorky sa nám oplatí mať metódu, ktorá nám pre dané políčko (určené súradnicami [riadok][stĺpec]) povie, koľko kameňov rovnakej farby uložených za sebou stretneme, ak sa z daného políčka vyberieme niektorým s 8 smerov. Všimnime si, že v skutočnosti nám stačí skúmať len 4 smery (prečo ?):

  • zľava doprava (rastie index stĺpca)
  • zhora nadol (rastie index riadka)
  • po uhlopriečke zľava doprava a zhora nadol (rastie aj index stĺpca aj index riadka)
  • po uhlopriečke sprava doľava a zhora nadol (index stĺpca klesá, index riadka rastie)

V prvom prípade platí, že ak aktuálne políčko má súradnice [r][s], tak jeho sused pri pohybe zľava doprava bude mať súradnice [r+0][s+1]. Analogicky, v prípade pohybu zhora nadol, bude mať sused súradnice [r+1][s+0]. V zostávajúcich 2 prípadoch bude sused na súradniciach [r+1][s+1], resp. [r+1][s-1]. Súradnice suseda sa líšia stále o akúsi dvojicu hodnôt: pre [r+1][s-1] je to napríklad [1, -1]. Túto dvojicu môžeme v matematicko-fyzikálnej terminológii nazvať vektorom posunutia. Prirodzene, každý "priamočiary" pohyb v 2D poli vieme stále charakterizovať nejakým takýmto vektorom posunutia. Typicky ale potrebujeme skúmať viacero vektorov posunutia. V tejto situácii je preto veľmi výhodné mať jednotlivé vektory "posunutia" uložené v niečom "poľovom". Tým získame možnosť využiť výhody indexovania políčok. Keďže vektor má 2 zložky, veľmi výhodne sa javí použiť 2-rozmerné pole s 2 stĺpcami a k riadkami. Každý riadok z tejto tabuľke vie uchovávať vektor posunutia pre jeden z k smerov.

Pohyb v 2D poli môžeme zachytiť takto:

int[][] pole = ...;
...
int smer = ...;
while (existujePolicko(r, s)) {
       spracujPolicko(pole[r][s]);

       r = r + smery[smer][0];
       s = s + smery[smer][1];
}

Po vypočítaní súradníc nového políčka sa nám môže stať, že políčko s vypočítanými indexami neexistuje ("vypadli" sme mimo poľa). Preto je nutné pred spracovaním políčka overiť, či indexy, ktoré máme k dispozícii, sú naozaj platnými indexami do 2-rozmerného poľa.

<< Polia a "poľové" algoritmy | Obsah | Výnimky (odchytávanie) >>