Základy programovania v JavaScripte

Lekcia 9

Milan Herda, 05/2020

Video k tejto prezentácii:

Čo nás čaká

  • opakovanie
  • polia

Opakovanie

Funkcie

Nástroj na rozdeľovanie kódu na časti

Každá funkcia rieši nejakú úlohu

  • niečo vykonávajú
  • niečo počítajú a vracajú nám výsledok
  • oboje

Funkcie

function krokAPoloz() {
    krokDopredu();
    polozZnacku();
}
const krokAPoloz = function () {
    krokDopredu();
    polozZnacku();
};

Premenné

Slúžia na uchovávanie hodnôt, s ktorými sa pracuje

const trebaPrejst = 5;

let prejdene = 1;

var pocetStvorcov = 10;

Typy premenných

Primitívne

  • boolean
  • číslo
  • reťazec
  • null
  • undefined

Zložené

  • objekt
  • pole
  • funkcia

Objekt

Typ zloženej premennej.

Môže obsahovať skupinu primitívnych

a/alebo zložených hodnôt.

Každej položke objektu hovoríme

vlastnosť

Ak je vlastnosť funkciou, hovoríme jej

metóda

const prazdnyObjekt = {};

const fero = {
    vek: 45,
    vyska: 183,
    adresa: {
        ulica: 'Farská 42',
        obec: 'Nitra',
    },
    zmenVek: function (novyVek) {
        this.vek = vek;
    },
};

Pole

Pole / array

Pole je zoskupenie viacerých prvkov v jednej premennej

Prvky sú zoradené a každý má svoju (číselnú) pozíciu

Vo väčšine jazykov je to samostatný dátový typ

V JavaScripte nie. Tam je pole objekt

Index

Číselnému označeniu pozície sa hovorí index.

Čísluje sa on nuly, takže prvý prvok bude mať index 0.

Pole / array

const objekt = {
    meno: 'Ferko',
    priezvisko: 'Mrkvička',
    vek: 42,
    vyska: 183,
};

console.log(objekt.meno);
console.log(objekt.vyska);

objekt.hmotnost = 75;
const pole = [
    'čierna',
    'biela',
    'červená',
    'zelená',
];

console.log(pole[0]);
console.log(pole[3]);

pole[4] = 'modrá';

Dĺžka poľa

Počet prvkov v poli

Najvyššie číslo pozície + 1

var pole = [
    'cierna',
    'biela',
    'cervena',
    'zelena',
];

console.log(
    pole.length
);

Použitie napr. pri pridávaní prvku vždy na koniec poľa:

pole[pole.length] = 'fialová';
pole[pole.length] = 'žltá';
pole[pole.length] = 'sivá';

Pole je v JS objekt

A objekty majú metódy

pole.push(prvok) pridá na koniec poľa prvok
prvok = pole.pop() odoberie prvok z konca poľa
pole.unshift() / pole.shift() push() a pop() pre začiatok poľa
novePole = pole.filter(funkcia) prefiltruje pole pomocou funkcie
prvok = pole.find(funkcia) nájde prvok v poli
novePole = pole.map(funkcia) nad každým prvok zavolá funkciu a vráti nové pole

Úloha 1:

Vytvorte premennú lavyStlpec, ktorá bude predstavovať ľavý krajný stĺpec na mape a bude typu pole.

Každý prvok poľa bude hovoriť, či sa na danom políčku má (true) alebo nemá nachádzať (false) značka.

Nechajte Karla prejsť celým ľavým stĺpcom a ukladať značky podľa toho, ako predpisuje premenná lavyStlpec.

Vytvorte pole tak, aby pre každé párne políčko bola predpísaná značka. (Číslujeme od 0)

Pracujeme v súbore js/sandbox.js a nepoznáme objekt karel.

Úloha 1:

Súradnicová os začína v ľavom hornom rohu.

Prvý riadok je ten najvyššie.

Jeho index v súradnicovej osi je 0.

Posledný riadok má index 19.

Obdobne pre stĺpce.

Karel teda svoj pohyb začína

v stĺpci 0, riadku 19.

Riešenie:

Najskôr pomocné funkcie

const jeCisloParne = function (cislo) {
    const zvysokPoDeleni = cislo % 2;
  
    if (zvysokPoDeleni === 0) {
        return true;
    }
    
    return false;
};

Doplnková úloha: skúste túto funkciu ešte skrátiť.

Riešenie:

Najskôr pomocné funkcie

const vytvorLavyStlpec = function () {
    const lavyStlpec = [];
  
    for (let i = 0; i < 20; i = i + 1) {
        if (jeCisloParne(i)) {
            lavyStlpec[i] = true;
        } else {
            lavyStlpec[i] = false;
        }
    }
  
    return lavyStlpec;
};

Viete to napísať kratšie? Skúste.

Riešenie:

const cviceniePole = function () {
    const lavyStlpec = vytvorLavyStlpec();
  
    for (let cisloRiadku = 19; cisloRiadku >= 0; cisloRiadku = cisloRiadku - 1) {
        if (lavyStlpec[cisloRiadku]) {
            polozZnacku();
        }
      
        if (!jePredTebouStena()) {
            krokDopredu();
        }
    };
};

document.addEventListener("DOMContentLoaded", function (event) {
    cviceniePole();
});

Pole / array

  • Každý prvok poľa môže byť ľubovoľného typu.
  • Môže to byť teda aj pole.
  • Prvok na danom indexe nemusí existovať (vtedy sa vráti hodnota undefined).
  • Prvky nemusia byť rovnakého typu.

Úloha 2:

Vytvorte premennú stlpec, ktorá bude predstavovať ľavý krajný stĺpec na mape a bude typu pole.

Každý prvok poľa bude objekt predstavujúci jednotlivé políčko.

Políčko má vlastnosti:

  • cisloRiadku
  • cisloStlpca
  • jeOznacene

Pracujeme v súbore js/karel.js.

Riešenie:

const stlpec = [];

for (let i = 0; i < 20; i = i + 1) {
    stlpec[i] = {
        cisloRiadku: i,
        cisloStlpca: 0,
        jeOznacene = false,
    };
}

Úloha 2 (pokračovanie):

Presuňte kód do funkcie nazvanej vytvorStlpec.

Skúste urobiť funkciu tak, aby vedela vytvoriť reprezentáciu hociktorého stĺpca (nielen nultého).

Pracujeme v súbore js/karel.js.

Riešenie:

const vytvorStlpec = function (cisloStlpca) {
    const stlpec = [];
  
    for (let i = 0; i < 20; i = i + 1) {
        stlpec[i] = {
            cisloRiadku: i,
            cisloStlpca: cisloStlpca,
            jeOznacene: false,
        };
    }
  
    return stlpec;
};

Porozmýšľajte, prečo funguje zápis na riadku 7

cisloStlpca: cisloStlpca

Úloha 2 (pokračovanie):

Vytvorte stĺpce pre celú mapu, v ktorej sa Karel pohybuje.

Tj. 20 stĺpcov.

Pracujeme v súbore js/karel.js.

Riešenie:

const stlpec0 = vytvorStlpec(0);
const stlpec1 = vytvorStlpec(1);
const stlpec2 = vytvorStlpec(2);
const stlpec3 = vytvorStlpec(3);
const stlpec4 = vytvorStlpec(4);
const stlpec5 = vytvorStlpec(5);
const stlpec6 = vytvorStlpec(6);
const stlpec7 = vytvorStlpec(7);
const stlpec8 = vytvorStlpec(8);
const stlpec9 = vytvorStlpec(9);
const stlpec10 = vytvorStlpec(10);
const stlpec11 = vytvorStlpec(11);
const stlpec12 = vytvorStlpec(12);
const stlpec13 = vytvorStlpec(13);
const stlpec14 = vytvorStlpec(14);
const stlpec15 = vytvorStlpec(15);
const stlpec16 = vytvorStlpec(16);
const stlpec17 = vytvorStlpec(17);
const stlpec18 = vytvorStlpec(18);
const stlpec19 = vytvorStlpec(19);

Pracujeme v súbore js/karel.js.

Riešenie:

const vytvorVsetkyStlpce = function () {
    const stlpce = [];

    for (let cisloStlpca = 0; cisloStlpca < 20; cisloStlpca = cisloStlpca + 1) {
        stlpce[cisloStlpca] = vytvorStlpec(cisloStlpca);
    }

    return stlpce;
}

Pracujeme v súbore js/karel.js.

Pole / array

Keď prvky poľa obsahujú iné pole, tak tomu hovoríme viacrozmerné pole.

V našom prípade sme vytvorili dvojrozmerné pole.

Dvojrozmerné polia sú užitočné na reprezentáciu vecí v 2D priestore (graf, súradnice, mapa)

Počet rozmerov nie je obmedzený

Úloha 2 (pokračovanie):

Pracujeme v súbore js/karel.js.

Súbor karel.js obsahuje konštantu mapa.

Pridajte jej vlasnosť nazvanú "bunky".

Každá bunka tak predstavuje jedno políčko na mape a má číslo riadku, číslo stĺpca a príznak, či je označená.

Hodnotou tejto vlastnosti bude pole stĺpcov, ktoré vytvoríme pomocou funkcie vytvorVsetkyStlpce.

Zároveň je každá bunka umiestnená v dvojrozmernom poli pod indexom stĺpca a riadku.

Riešenie:

Pracujeme v súbore js/karel.js.

const mapa = {
    sirka: 20,
    vyska: 20,
    bunky: vytvorVsetkyStlpce(),
};

Úloha 3:

Pracujeme v súbore js/karel.js a index.html

Na stránku s Karlom pridajte vedľa smeru aj informáciu o tom, na akom riadku a stĺpci sa Karel nachádza

Vždy, keď sa Karel pohne dopredu (pomocou volania karel.krok()), tak táto informácia sa zmení.

Riešenie:

Pracujeme v súbore js/karel.js

const karel = {
    riadok: 10,
    stlpec: 0,
  
    poZmenePozicie: null,
  
    // ostatne vlastnosti a metody
  
    krok: function () {
        if (!jePredTebouStena()) {
            krokDopredu();
          
            this.zmenPoziciu();
            this.upravInformaciuOPozicii();
        }
    },
    
    // ... pokracovanie na dalsom slajde
};

Riešenie:

Pracujeme v súbore js/karel.js

const karel = {
    // doterajsi kod

    zmenPoziciu: function () {
        if (this.smer === SEVER) {
            this.riadok = this.riadok - 1;
        } else if (this.smer === JUH) {
            this.riadok = this.riadok + 1;
        } else if (this.smer === ZAPAD) {
            this.stlpec = this.stlpec - 1;
        } else {
            this.stlpec = this.stlpec + 1;
        }
    },
  
    upravInformaciuOPozicii: function () {
        if (this.poZmenePozicie) {
            this.poZmenePozicie(this.riadok, this.stlpec);
        }
    },
};

Riešenie:

Pracujeme v súbore index.html

<div class="level-item has-text-centered">
    <div>
        <p class="heading">riadok</p>
        <p class="title" id="row">19</p>
    </div>
</div>
<div class="level-item has-text-centered">
    <div>
        <p class="heading">stĺpec</p>
        <p class="title" id="col">0</p>
    </div>
</div>

Riešenie:

Pracujeme v súbore index.html

<script>
    karel.poZmeneSmeru = /* ... */;
    
    karel.poZmenePozicie = function (novyRiadok, novyStlpec) {
        document.querySelector('#row').innerHTML = novyRiadok;
        document.querySelector('#col').innerHTML = novyStlpec;
    };
</script>

Úloha 4:

Pracujeme v súbore js/karel.js a index.html

Na stránku s Karlom pridajte nové tlačidlo "značka", pomocou ktorého položíte alebo zdvihnete značku

(podľa toho, či sa na pozícii značka už nachádza)

Zároveň pri zmene upravte aj príznak jeOznacene v bunke, ktorá reprezentuje dané políčko na mape.

Riešenie:

Pracujeme v súbore index.html

<div class="buttons has-addons">
    <button id="btn-marker" class="button is-danger">
        Značka
    </button>
</div>

<!-- .... -->
<script>
    const btnMarker = document.querySelector('#btn-marker');
    btnMarker.addEventListener('click', function () {
        karel.zmenZnacku();
    });
</script>

Riešenie:

Pracujeme v súbore js/karel.js

const karel = {
    // ... doterajší kód
    
    zmenZnacku: function () {
        if (stojisNaZnacke()) {
            zdvihniZnacku();
            mapa.bunky[this.stlpec][this.riadok].jeOznacene = false;
        } else {
            polozZnacku();
            mapa.bunky[this.stlpec][this.riadok].jeOznacene = true;
        }
    }
};
mapa.bunky[this.stlpec][this.riadok].jeOznacene = false;

mapa.bunky[this.stlpec][this.riadok].jeOznacene = true;

Tieto dva riadky urobia, čo treba, ale nie je to úplne OK.

Karel totiž takto vie príliš veľa o tom, ako je vo svojom vnútri organizovaný objekt mapa.

Manažovanie vnútorného stavu mapy by sme mali nechať na mapu a len jej povedať, že niečo chceme zmeniť.

Riešenie:

Pracujeme v súbore js/karel.js

const karel = {
    // ... doterajší kód
    
    zmenZnacku: function () {
        if (stojisNaZnacke()) {
            zdvihniZnacku();
            mapa.zrusOznacenie(this.stlpec, this.riadok);
        } else {
            polozZnacku();
            mapa.oznacBunku(this.stlpec, this.riadok);
        }
    }
};

Riešenie:

Pracujeme v súbore js/karel.js

const mapa = {
    // ... doterajší kód
    
    oznacBunku: function (stlpec, riadok) {
        this.bunky[stlpec][riadok].jeOznacena = true;
    },

    zrusOznacenie: function (stlpec, riadok) {
        this.bunky[stlpec][riadok].jeOznacena = false;
    },
};

Bonusová úloha:

Skúste Karla rozpohybovať pomocou klávesnice.

Zistite si (google, MDN), ako reagovať na stlačenie klávesy a zabezpečte, aby fungovali štyri klávesy (obdobne, ako naše štyri tlačidlá):

  • šípka hore: pohnutie Karla o jeden krok
  • šípka doprava: otočenie doprava
  • šípka doľava: otočenie doľava
  • medzerovník: uloženie/zodvihnutie značky

Riešenie:

Ukážeme si nabudúce.

Všetok kód z dnešnej lekcie:

Ďakujem za pozornosť