05. Podmienky a logické výrazy

V tejto lekcii sa naučíme vytvárať v programe časti, ktoré sa nevykonávajú vždy, ale iba ak bola splnená nejaká podmienka – napríklad ak bolo stlačené ľavé tlačidlo myši.

Začnime však sériou experimentov.

  • Vytvorte nový skript Podmienky a priraďte ho na game objekt Main Camera.
  • Deaktivujte dočasne komponent Health na game objekte Main Camera, nech nám neprekážajú jeho výpisy

Otvorte si skript Podmienky v editore, do jeho metódy Start budeme postupne dopĺňať výpisy, začneme jednoduchým výrazom 3*7:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Podmienky : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log(3 * 7);
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

Toto už poznáme a nebudeme asi prekvapení, že konzola po spustení vypíše 21:

Doplňte výpis, ktorý vypíše hodnotu výrazu 3 < 7. Čo vypíše konzola?

Konzola vypísala True. To je niečo nové, to sme ešte nevideli. Skúste dať vypísať aj hodnotu výrazu 3 > 7:

Logické výrazy

Hodnota výrazu 3 * 7 je 21. Je to jednoduchý matematický výraz (tzv. aritmetický) a jeho výsledkom je číslo.

Hodnotou výrazu 3 < 7 už nie je číslo, ale je to hodnota „pravda“. Takýto výraz sa volá logický. Ako výraz má nejaké operandy (3 a 7) aj nejaký operátor ( < ) ale výsledkom nie je číslo. Počítač pri vyhodnocovaní takéhoto výrazu porozmýšľa, či je pravda to, čo je vo výraze zapísané. Ak áno, tak vyhodí ako výsledok true. Ak nie, vyhodí ako výsledok false.

Aj keď výpis v konzole ukazuje slovo True s veľkým T, v skutočnosti sa v kóde hodnota true píše s malým t. To len konzola poľudšťuje výpisy a môže to byť preto trochu zmätočné. Nech nás to nemýli, v zdrojovom kóde budeme vždy písať true s malým t.

Hodnoty true a false tvoria špeciálny typ hodnôt, ktorým sa hovorí logické hodnoty a v jazyku C# pre ne máme typ bool. Keď teda celočíselné hodnoty ukladáme do typu int, desatinné hodnoty ukladáme do typu float a textové hodnoty ukladáme do typu string, tak potom logické hodnoty budeme ukladať do typu bool.

  • Vytvorte v metóde Start novú premennú typu bool, nazvite ju porovnanie a uložte do nej hodnotu výrazu 5 > 10.
  • Vytvorte výpis, ktorý do konzoly vypíše hodnotu premennej porovnanie ako na obrázku nižšie:

Logické operátory

My už poznáme aritmetické operátory +, -, *, /, ktorých výsledkom sú číselné hodnoty. A už sme asi aj pochopili, že < je logický operátor a jeho výsledkom je logická hodnota true alebo false.

Aké všetky logické operátory máme? Pre začiatok tieto:

  • „menší“ a „väčší“: <, >
  • „menší alebo rovný“ a „väčší alebo rovný“: <= , >=
  • „rovný“: ==
  • „nerovný“: !=

Teraz si ich otestujeme:

  • Vytvorte v metóde Start novú premennú s názvom x a priraďte do nej hodnotu 4.
  • Vytvorte výpisy, ktoré premennú x porovnajú s nasledujúcimi číslami a vypíšu výsledok (viď obrázok nižšie)
    • je x menšie ako 10?
    • je x väčšie ako 4?
    • je x väčšie alebo rovné ako 4?
    • je x rovné 5?
    • je x rôzne od 5?

POZOR! Jednou z najčastejších chýb z nepozornosti je zámena == a = .

Dvojité rovnítko je porovnanie a výsledkom je logická hodnota pravda/nepravda, podľa toho, či sa ľavá a pravá strana rovnajú alebo nerovnajú.

Jednoduché rovnítko je priradenie do premennej.

Vyskúšajte si, akú hodnotu vypíše Debug.Log(x == 99) a akú Debug.Log(x = 99)

Moja prvá podmienka

Logický výraz má vlastne formu otázky. Rovná sa x číslu 99? Je číslo 3 menšie ako číslo 7? Ak vieme takto formulovať otázky, vieme počítaču povedať, aby vykonal isté príkazy len ak je splnená nejaká podmienka.

Máš doma vajíčka? Ak áno, urob praženicu.

Bolo stlačené ľavé tlačidlo na myši? Ak áno, uber zo zdravia.

Podmienka sa v C# píše pomocou konštruktu if a vyzerá napríklad takto:

if (vek >= 18)
{
    Debug.Log("Si plnolety")
}

Skúsme teraz doplniť do metódy Start takúto podmienku:

    void Start()
    {
        Debug.Log(3 * 7);
        Debug.Log(3 < 7);
        Debug.Log(3 > 7);

        bool porovnanie = 5 > 10;
        Debug.Log("Hodnota premennej porovnanie je " + porovnanie);

        int x = 4;
        Debug.Log(x < 10);
        Debug.Log(x > 4);
        Debug.Log(x >= 4);
        Debug.Log(x == 5);
        Debug.Log(x != 5);
        Debug.Log(x == 99);
        Debug.Log(x = 99);

        if (x > 10)
        {
            Debug.Log("x je vacsie ako 10");
        }
    }

Ak je x väčšie ako 10, konzola vypíše:

Čo ak podmienka nie je splnená?

Príkaz Debug.Log("x je vacsie ako 10") sa vykoná, len ak je splnená podmienka if (x > 10). A čo sa udeje, ak nebude splnená, ak napríklad predtým x nastavíme na hodnotu menšiu ako 10? Vyskúšajme:

Doplňte pred podmienku if riadok, ktorý nastaví x na hodnotu 5.

Po spustení sa všetko doteraz vykonalo ako predtým, iba príkaz Debug.Log("x je vacsie ako 10") sa nevykonal a vo výpise v konzole chýba:

Čo ak by sme chceli, aby v takejto situácii konzola vypísala napríklad „x nie je mensie ako 10“?

Na to máme k slovu if ešte kamaráta – slovo else. Vyzerá to takto:

        x = 5;
        if (x > 10)
        {
            Debug.Log("x je vacsie ako 10");
        }
        else
        {
            Debug.Log("x nie je vacsie ako 10");
        }

Blok príkazov za if sa vykoná, ak je predpoklad splnený. Blok príkazov za else sa vykoná, ak predpoklad splnený nie je. Každý blok je vymedzený párom zátvoriek { a }.

Vyskúšajte teraz vyrobiť jednoduchý test na to, či niekto je alebo nie je plnoletý:

  • Vytvorte v metóde Start novú premennú s názvom vek.
  • Pridajte výpis „Tvoj vek je …“
  • Doplňte podmienky a príkazy, aby program vypísal „Si plnolety“, ak je vek väčší alebo rovný 18, alebo „Nie si plnolety“ v ostatných prípadoch.
  • Skúšajte obmieňať hodnotu premennej vek, či výpis funguje správne. Vyskúšajte hodnoty 17, 18, 19.

Obmeňte svoj program tak, aby podľa hodnoty veku vypísal aj „Tvoj vek je uz …“ alebo „Tvoj vek je este len …“
Ako na nasledujúcich obrázkoch:

Čo všetko môže byť podmienkou?

V minulej lekcii sme opisovali do metódy Update v skripte Health.cs tiež nejaké podmienky. To sme ešte nevedeli, o čo ide, a sľúbili sme si, že sa k tomu vrátime. Bolo to tu:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Health : MonoBehaviour
{
    public float zdravie = 100f;
    public float lekarnicka = 10f;
    public float zasah;

    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("Zdravie je " + zdravie);
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            zdravie -= zasah;
            Debug.Log("Zdravie je " + zdravie);
        }

        if (Input.GetMouseButtonDown(1))
        {
            zdravie += lekarnicka;
            Debug.Log("Zdravie je " + zdravie);
        }
    }
}

Ako logickú podmienku v if sme tu nepoužili nejaké porovnanie v štýle menší, väčší, rovný, ale samostatný príkaz Input.GetMouseButtonDown

To je v poriadku, niektoré prikazy – napríklad aj Input.GetMouseButtonDown – nadobúdajú samé o sebe logickú hodnotu true alebo false a dajú sa použiť do podmienky.

Zhrnutie

Pomocou podmienok v kóde vieme usmerniť program, aby vykonal nejakú sadu príkazov alebo nejakú inú sadu príkazov. V podmienke if sa pýtame na nejaký logický výraz, ktorý má hodnotu buď pravda (true) alebo nepravda (false). Môže to byť napríklad porovnanie nejakých číselných hodnôt, alebo aj nejaký príkaz, ktorý v tomto prípade funguje ako logický výraz a tiež má hodnotu pravda alebo nepravda.

Anatómia podmienky if .. else .. je takáto:

V bloku príkazov ohraničených zátvorkami {} môže byť koľko príkazov chceme. Dokonca v nich môže byť aj ďalšia podmienka s nejakým iným predpokladom.

Časť else {...} je nepovinná a nemusí byť v podmienke if vôbec prítomná.

  • Ak ste túto lekciu dokončili, deaktivujte si komponent Podmienky na game objekte Main Camera a aktivujte naspäť komponent Health
  • V skripte Health.cs upravte metódu Update tak, aby sa pri poklese zdravia na nulu vypísalo do konzoly „Game Over“.

Hotový projekt po tejto lekcii: Programovanie_05.zip