Faktoriál

Stránky: Moodle ZČU
Kurz: KPV/TI Technická informatika ve strojírenství - šablona
Kniha: Faktoriál
Vytiskl(a): Nepřihlášený host
Datum: neděle, 8. listopadu 2026, 17.32

1. Faktorial

Úlohou je vytvořit aplikaci na výpočet faktoriálu:

  • Pomocí cyklu s podmínkou na začátku (While)
  • Pomocí cyklu s podmínkou na konci (Do While)
  • Pomocí cyklu s krokem (for)
  • Pomocí rekurze

Účel příkladu
  • Rekurze
Typ aplikace
  • Konzolová aplikace
Popis úkolu 
  • Výpočet faktoriálu
Funkčnosti
  • Po načtení přirozeného čísla v hlavním programu je toto číslo skutečným parametrem předaným 4 podprogramům volaných z hlavního programu:
    • Podprogram (funkce s celočíselným návratem) FaktorialWhile - výpočet faktoriálu pomocí cyklu s podmínkou na začátku
    • Podprogram (funkce s celočíselným návratem) FaktorialDoWhile - výpočet faktoriálu pomocí cyklu s podmínkou na konci
    • Podprogram (funkce s celočíselným návratem) FaktorialFor - výpočet faktoriálu pomocí cyklu s krokem
    • Podprogram (funkce s celočíselným návratem) FaktorialVolaniRekurze - výpočet faktoriálu pomocí volání funkce s rekurzí
  • Hodnoty vypočtených faktoriálů, předané z podprogramů, budou vypsány bez desetinných míst v hlavním programu 
  • Po výpisu všech čísel bude aplikace ukončena po stisku klávesy
Výstup programu

Ukázka výpisu číselných řad v hlavní metodě programu Faktorial

Výstup programu: Ukázka výpisu faktoriálu v hlavní metodě programu Faktorial

1.1. Analýza a návrh řešení

Z matematiky víme, že faktoriál čísla n (značeno jako n!) je roven součinu všech přirozených čísel menších nebo rovných n (přičemž platí 0! = 1) např. 3! = 3*2*1 = 1*2*3 = 6. Z předchozí číselné rostoucí řady vidíme, že se jedná o součin hodnot, které postupně stoupají o hodnotu 1 až do konečné prvku této řady představující zadané číslo uživatelem - viz Obrázek 1. Vidíme, že čísla také mohou klesat od čísla n až do 1 - tímto možným přístupem se však nyní nebudeme zabývat.

Princip faktoriálu - součin řady zvyšujících se čísel

Obrázek 1: Princip faktoriálu - součin řady zvyšujících se čísel

Matematicky bychom při násobení čísel mezi sebou postupovali např. zleva doprava (lze i opačně), tedy 1*2 = 2 a pak tento výsledek 2 násobíme 3, tedy 2*3 = 6. Jedná se tedy o pravidelný postup, na který lze uplatnit cykly. Součin všech prvků lze rozdělit do jednotlivých iterací, kde v každé iteraci je provedeno násobení hodnoty součinu z předchozí iterace (náš předchozí výsledek součinu uložený v proměnné f) aktuálním číslem (uloženým v proměnné i), tj. f * i. Výsledek tohoto součin budeme ukládat do proměnné f (hodnota v f tedy bude v každé iteraci přepisována), tedy f = f * i. Aktuální číslo uložené v proměnné i je následně zvětšeno o hodnotu 1, tj. i + 1, abychom jej mohli využít v součinu v další iteraci. Myšlenku v předchozí větě aplikujeme na příklad našeho faktoriálu, tj. 3! = 1*2*3. 

V první iteraci je v proměnné f a v proměnné i uložena počáteční hodnota 1. V první iteraci je tedy f = f * i = 1*1 = 1. Následně zvedneme hodnotu i o 1, tj. i = i + 1 = 1 + 1 = 2. V další iteraci provedeme součin f = f * i = 1*2 (vidíme že jde o první dva členy v součinu všech čísel v rozepsané rovnici faktoriálu). Hodnotu součinu si uložíme do proměnné f, abychom ji mohli využít v další iteraci. Ještě než přejdeme do další iterace, musíme inkrementovat aktuální číslo z hodnoty 2 na hodnotu 3. V další iteraci tedy násobíme f = 2*3 (hodnota v f * hodnota aktuálního čísla v i). Tato iterace byla poslední, protože aktuální číslo je rovnu číslu, pro něhož jsme chtěli vypočítat faktoriál - viz Obrázek 2. 

Všimněte si, že počet iterací je roven 3, což je naše číslo, pro něhož počítáme faktoriál. Všimněte si, že bychom také mohli vynechat první iteraci, pokud bychom inicializovali proměnnou i hodnotou 2. Pak by namísto 3 iterací bylo zapotřebí pouze 2 iterací.

Princip výpočtu faktoriálu

Obrázek 2: Princip výpočtu faktoriálu

Tento princip využijeme ve volaných podprogramech - funkcích, které navracejí do hlavního programu vypočtenou hodnotu faktoriálu. Tyto funkce jsou volány z hlavního programu - viz Obrázek 1. 


Obrázek 3: Hlavní program Faktorial pro výpis faktoriálu

První volanou funkcí je FaktorialWhile. Tento podprogram využívá cyklu while, v jehož těle je implementována podstata násobení jednotlivých prvků řady. Počátečním krokem je inicializace obou proměnných i a f  na hodnotu 1. V lokální proměnné i je uloženo aktuální číslo, které využíváme v součinu f * i prováděného v každé iteraci. Výsledek tohoto součinu stávající hodnoty f z předchozí iterace a aktuálního čísla i je uložen do proměnné f. V každé iteraci je tedy hodnota v proměnné f přepsána novou hodnotou součinu. Jako následný krok je provedena inkrementace aktuálního čísla i o hodnotu 1 - viz Obrázek 4. 

Podprogram FaktorialWhile - výpočet faktoriálu pomocí cyklu s podmínkou na začátku

 Obrázek 4: Podprogram FaktorialWhile - funkce pro výpočet faktoriálu pomocí cyklu s podmínkou na začátku

Dalším podprogramem (funkcí) využívající cyklus je FaktorialDoWhile, který má svém těle implementován cyklus s podmínkou na konci - viz Obrázek 5. Podstata podprogramu je téměř stejná jako v předchozím podprogramu FaktorialWhile.

Podprogram FaktorialDoWhile - výpočet faktoriálu pomocí cyklu s podmínkou na konci

Obrázek 5: Podprogram FaktorialDoWhile - funkce pro výpočet faktoriálu pomocí cyklu s podmínkou na konci

Vzhledem k tomu, že víme, kolikrát iterací má proběhnout v cyklu, lze použít v dalším podprogramu FaktorialFor cyklus s krokem - viz Obrázek 6. Inicializace řídící proměnné cyklu probíhá před první iterací cyklu. Inkrementace řídící proměnné cyklu probíhá po proběhnutí iterace, taktéž v bloku for.   

Podprogram FaktorialDoWhile - funkce pro výpočet faktoriálu pomocí cyklu s krokem

 Obrázek 6: Podprogram FaktorialDoWhile - funkce pro výpočet faktoriálu pomocí cyklu s krokem

Posledním podprogramem je FaktorialVolaniRekurze. Podprogram je taktéž funkce, která v sobě volá další funkci pro výpočet faktoriálu pomocí rekurze - FaktorialRekurze - viz Obrázek 7.

Podprogram FaktorialVolaniRekurze - volání funkce s rekurzí  

Obrázek 7: Podprogram FaktorialVolaniRekurze - volání funkce s rekurzí

Pomocí rekurze bychom mohli faktoriál kladného čísla rozepsat jako 3! = 3*2!, kde bychom 2! uvnitř výrazu mohli zase rozepsat 2! = 2*1! a další rozepsání již není zapotřebí, protože 1! je roven 1. Postupným zpětným dosazením nám tedy vznikl výraz 3! = 3*2*1!, tedy 3! = 3*2*1 = 6. Výpočet faktoriálu rekurzivním způsobem, lze zapsat jako n*(n-1)! . Pokud bychom použili metodu pro výpočet faktoriálu, nazvěme ji např. FaktorialRekurze, můžeme náš předchozí zápis výpočtu faktoriálu rekurzivním způsobem zapsat jako n*FaktorialRekurze(n-1). Tohoto principu využijeme v následující funkci využívající princip rekurze - viz Obrázek 8.

Podprogram FaktorialRekurze - funkce pro výpočet faktoriálu pomocí rekurze

Obrázek 8: Podprogram FaktorialRekurze - funkce pro výpočet faktoriálu pomocí rekurze

V těle této funkce je definována podmínka, která určuje, kdy se vnořování funkce do sebe samé musí zastavit, tzn., že krok, kdy se funkce postupným snižováním parametru na základě výrazu (n – 1), dostane až do stavu, kdy je předávaná hodnota parametru rovna 0 (tehdy je 0! = 1). Je také možností zastavit vnořování funkce již o jednu iteraci dříve, tj. kdy je předávaná hodnota parametru rovna 1 (protože 1! = 1). Uživateli jsme však dali možnost vypočítat faktoriál pro číslo z definičního oboru přirozených čísel, proto povolíme i vložení 0.

Samotnou rekurzi vidíme ve větvi false rozhodovacího bloku uvnitř těla funkce, kdy funkce volá sama sebe (svým jménem FaktorialRekurze) a předává si postupně snižovanou hodnotu parametru o jedna. Až se volaná funkce dostane do stavu, že daný parametr už nejde snížit (splnění podmínky ukončení další rekurze v těle funkce, tj. n == 0), funkce předá hodnotu 1 zpět do funkce, která ji naposledy volala. Pak tato volající metoda vypočte hodnotu svého výrazu a tuto hodnotu zase postupně dosazuje zpět do volající funkce. Tento cyklus probíhá tak dlouho, dokud neobdržíme výsledek příkazu, který odstartoval volání vnořených funkcí.

Použití rekurze je velmi účinný ale často také nebezpečný trik!

1.2. C#

Načtení čísla, pro které bude následně ve statické hlavní metodě vypočten faktoriál, je realizováno pomocí příkazu (metody s výstupními parametry) TryParse. V hlavní statické metodě jsou pomocí jednotlivých výpisů odděleny hodnoty faktoriálu vypočtené pomocí volaných metod s celočíselným návratem, jejichž těla obsahují různé typy cyklu - viz Kód 1. Tyto celočíselné návraty (datového typu long) jsou konvertovány pomocí příkazu ToString  vyvolaného pomocí tečkové notace.  Datový typ long umožňuje větší rozsah celočíselných hodnot (horní mez až 9,223,372,036,854,775,807). Tím umožníme uživateli zadávat i větší čísla, pro které má být vypočten faktoriál (horní mez datového typu int je 2,147,483,647), aniž bychom způsobili přetečení. Např. 12! =  479,001,600 a faktoriál čísla 13 je již 13! = 6,227,020,800. 

Číslice jsou formátovány pomocí formátu "N0", což znamená, že jsou to celá čísla bez desetinných míst ("N" ... Number, "0" ... počet vypsaných desetinných míst).

static void Main(string[] args)
{
    // Výpis textu 
    Console.WriteLine("Výpočet faktoriálu");
 
    // Výzva k zadání čísla pro výpočet faktoriálu
    Console.Write("Zadejte číslo: ");
 
    /* Načtení čísla - 'n' ... číslo, pro které bude vypočten 
     * faktoriál (výstupní parametr TryParse) */
    int.TryParse(Console.ReadLine(), out int n);
 
    /* Výpis textu a hodnoty faktoriálu, který je výstupem zavolané funkce 
     * s předaným parametrem 'n'; specifikace výstupního formátu 
     * čísla "N0", tj. bez čísel za desetinnou čárkou */
    Console.WriteLine("Faktoriál (cyklus while): " + FaktorialWhile(n).ToString("N0"));
    Console.WriteLine("Faktoriál (cyklus do-while): " + FaktorialDoWhile(n).ToString("N0"));
    Console.WriteLine("Faktoriál (cyklus for): " + FaktorialFor(n).ToString("N0"));
    Console.WriteLine("Faktoriál (rekurze): " + FaktorialVolaniRekurze(n).ToString("N0"));
 
    // Čekání na stisk klávesy -> ukončení programu
    Console.ReadKey();
}

Kód 1: Program Faktorial - deklarace hlavní statické metody Main 

První volanou metodou pro výpočet faktoriálu pomocí cyklu s podmínkou na začátku je metoda s celočíselným návratem (datový typ long) FaktorialWhile - viz Kód 2. V této metodě jsou použity dvě lokální proměnné i a f. Proměnná i představuje čítač cyklu, ale zároveň představuje aktuální číslo v součinu. Tato proměnná je datového typu int, protože není zapotřebí velký rozsah zadávaných čísel vzhledem k horní mezi datového typu long vybraného pro proměnnou f, která představuje hodnotu vypočteného faktoriálu. Výraz f = f * i; bychom mohli zkrátit pomocí zápisu f *= i; . Dále jsme také zkrátili zápis inkrementace i = i + 1; na i++.

// Metoda s celočíselným návratem (datový typ long) pro výpočet faktoriálu pomocí cyklu while
static long FaktorialWhile(int n)
{
    /* Deklarace: 'i' ... čítač (aktuální číslo v součinu); 
     * 'f' ... hodnota faktoriálu */
    int i;
    long f;
 
    // Inicializace
    i = 1;
    f = 1;
 
    // Opakuj, pokud je čítač menší, nebo roven číslu pro výpočet faktoriálu
    while (i <= n)
    {
        // Výpočet faktoriálu
        f = f * i;
 
        // Inkrementace čítače
        i++;
    }
 
    // Návrat vypočtené hodnoty faktoriálu
    return f;
}

Kód 2: Deklarace statické metody s celočíselným návratem s názvem FaktorialWhile

Další volanou metodu pro výpočet faktoriálu pomocí cyklu s podmínkou na konci je metoda s celočíselným návratem FaktorialDoWhile - viz Kód 3.

// Metoda s celočíselným návratem pro výpočet faktoriálu pomocí cyklu do-while
static long FaktorialDoWhile(int n)
{
    /* Deklarace: 'i' ... čítač (aktuální číslo v součinu); 
     * 'f' ... hodnota faktoriálu */
    int i;
    long f;
 
    // Inicializace
    i = 1;
    f = 1;
    do
    {
        // Výpočet faktoriálu
        f = f * i;
 
        // Inkrementace čítače
        i++;                
    }
    // Opakuj, dokud je čítač menší, nebo roven číslu pro výpočet faktoriálu
    while (i <= n);
 
    // Návrat vypočtené hodnoty faktoriálu
    return f;
}

Kód 3: Deklarace statické metody s celočíselným návratem s názvem FaktorialDoWhile

Poslední typem cyklu, použitým při výpočtu faktoriálu, je cyklus s krokem, který je využit v metodě FaktorialFor - viz Kód 4. Na rozdíl od předchozích metod je řídící proměnná deklarována a inicializována přímo v cyklu for. 

// Metoda s celočíselným návratem pro výpočet faktoriálu pomocí cyklu for
static long FaktorialFor(int n)
{
    // Deklarace: 'f' ... hodnota faktoriálu
    long f;
 
    // Inicializace
    f = 1;
 
    // Cyklus s krokem; deklarace: 'i' ... čítač (aktuální číslo v součinu)
    for (int i = 1; i <= n; i++)
    {
        // Výpočet faktoriálu
        f = f * i;
    }
 
    // Návrat vypočtené hodnoty faktoriálu
    return f;
}

Kód 4: Deklarace statické metody s celočíselným návratem s názvem FaktorialFor

Metoda s celočíselným návratem pro výpočet faktoriálu pomocí volání funkce využívající rekurzi je metoda FaktorialVolaniRekurze - viz Kód 5. V této metodě je volána rekurzivní metoda FaktorialRekurze. 

/* Metoda s celočíselným návratem pro výpočet faktoriálu pomocí
 * volání funkce využívající rekurzi */
static long FaktorialVolaniRekurze(int n)
{
    /* Návrat vypočtené hodnoty faktoriálu pomocí 
     * volání metody pro výpočet faktoriálu pomocí rekurze */
    return FaktorialRekurze(n);
}

Kód 5: Deklarace statické metody s celočíselným návratem s názvem FaktorialVolaniRekurze 

Metoda FaktorialRekurze využívá principu rekurze, kde metoda volá sama sebe (tím se postupně zanořuje sama do sebe) - viz Kód 6. Při každém takovém zanořování je předán parametr o hodnotu o 1 menší než v předchozím volání. V metodě tedy musí být definována podmínka, kdy je toto vnořování zastaveno, tj. n == 0. Až tato podmínka bude vyhodnocena jako true, nastane postupné předávání vypočtené hodnoty faktoriálu zpět do volajících metod. Tento cyklus postupného předávání zpět probíhá tak dlouho, dokud neobdržíme výsledek příkazu, který odstartoval volání vnořených metod.

// Metoda s celočíselným návratem pro výpočet faktoriálu pomocí rekurze 
static long FaktorialRekurze(int n)
{
    // Deklarace: 'f' ... hodnota faktoriálu
    long f;
 
    // Pokud je předaná hodnota v parametru rovna nule
    if (n == 0)
    {
        // Faktoriál je 1
        f = 1;
    }
    else
    {
        // Rekurzivní volání metody(metoda volá sama sebe)
        f = n * FaktorialRekurze(n - 1);
    }
    
    // Přiřazení návratu metody
    return f;
}

Kód 6: Deklarace statické rekurzivní metody s celočíselným návratem s názvem FaktorialRekurze

1.3. Výsledný kód

Následující zdrojový kód je kompletací předešlých kódů programu Faktorial, který je umístěn v souboru Program.cs - viz Kód 1.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Faktorial
{
    class Program
    {
        static void Main(string[] args)
        {
            // Výpis textu 
            Console.WriteLine("Výpočet faktoriálu");
 
            // Výzva k zadání čísla pro výpočet faktoriálu
            Console.Write("Zadejte číslo: ");
 
            /* Načtení čísla - 'n' ... číslo, pro které bude vypočten 
             * faktoriál (výstupní parametr TryParse) */
            int.TryParse(Console.ReadLine(), out int n);
 
            /* Výpis textu a hodnoty faktoriálu, který je výstupem zavolané funkce 
             * s předaným parametrem 'n'; specifikace výstupního formátu 
             * čísla "N0", tj. bez čísel za desetinnou čárkou */
            Console.WriteLine("Faktoriál (cyklus while): " + FaktorialWhile(n).ToString("N0"));
            Console.WriteLine("Faktoriál (cyklus do-while): " + FaktorialDoWhile(n).ToString("N0"));
            Console.WriteLine("Faktoriál (cyklus for): " + FaktorialFor(n).ToString("N0"));
            Console.WriteLine("Faktoriál (rekurze): " + FaktorialVolaniRekurze(n).ToString("N0"));
 
            // Čekání na stisk klávesy -> ukončení programu
            Console.ReadKey();
        }
 
 
        // Metoda s celočíselným návratem (datový typ long) pro výpočet faktoriálu pomocí cyklu while
        static long FaktorialWhile(int n)
        {
            /* Deklarace: 'i' ... čítač (aktuální číslo v součinu); 
             * 'f' ... hodnota faktoriálu */
            int i;
            long f;
 
            // Inicializace
            i = 1;
            f = 1;
 
            // Opakuj, pokud je čítač menší, nebo roven číslu pro výpočet faktoriálu
            while (i <= n)
            {
                // Výpočet faktoriálu
                f = f * i;
 
                // Inkrementace čítače
                i++;
            }
 
            // Návrat vypočtené hodnoty faktoriálu
            return f;
        }
 
        // Metoda s celočíselným návratem pro výpočet faktoriálu pomocí cyklu do-while
        static long FaktorialDoWhile(int n)
        {
            /* Deklarace: 'i' ... čítač (aktuální číslo v součinu); 
             * 'f' ... hodnota faktoriálu */
            int i;
            long f;
 
            // Inicializace
            i = 1;
            f = 1;
            do
            {
                // Výpočet faktoriálu
                f = f * i;
 
                // Inkrementace čítače
                i++;                
            }
            // Opakuj, dokud je čítač menší, nebo roven číslu pro výpočet faktoriálu
            while (i <= n);
 
            // Návrat vypočtené hodnoty faktoriálu
            return f;
        }
 
        // Metoda s celočíselným návratem pro výpočet faktoriálu pomocí cyklu for
        static long FaktorialFor(int n)
        {
            // Deklarace: 'f' ... hodnota faktoriálu
            long f;
 
            // Inicializace
            f = 1;
 
            // Cyklus s krokem; deklarace: 'i' ... čítač (aktuální číslo v součinu)
            for (int i = 1; i <= n; i++)
            {
                // Výpočet faktoriálu
                f = f * i;
            }
 
            // Návrat vypočtené hodnoty faktoriálu
            return f;
        }
 
        // Metoda s celočíselným návratem pro výpočet faktoriálu pomocí rekurze 
        static long FaktorialRekurze(int n)
        {
            // Deklarace: 'f' ... hodnota faktoriálu
            long f;
 
            // Pokud je předaná hodnota v parametru rovna nule
            if (n == 0)
            {
                // Faktoriál je 1
                f = 1;
            }
            else
            {
                // Rekurzivní volání metody s návratem (metoda volá sama sebe)
                f = n * FaktorialRekurze(n - 1);
            }
 
            // Návrat vypočtené hodnoty faktoriálu
            return f;
        }
 
        /* Metoda s celočíselným návratem pro výpočet faktoriálu pomocí
         * volání metody využívající rekurzi */
        static long FaktorialVolaniRekurze(int n)
        {
            /* Návrat vypočtené hodnoty faktoriálu pomocí 
             * volání metody pro výpočet faktoriálu pomocí rekurze */
            return FaktorialRekurze(n);
        }
    }
}

Kód 1: Program Faktorial - deklarace hlavní statické metody Main včetně deklarací dalších metod

Výstup programu

Na následujícím výstupu programu vidíme výpis vypočtených hodnot faktoriálu pomocí různých typů cyklu a za použití rekurze - viz Výstup programu - Kód 1.   

Ukázka výpisu vypočtených hodnot faktoriálu v hlavní metodě programu Faktorial

Výstup programu - Kód 1: Ukázka výpisu vypočtených hodnot faktoriálu v hlavní metodě programu Faktorial

2. FaktorialWPF

Úlohou je vytvořit aplikaci na výpočet faktoriálu:

  • s cyklem s krokem (for)
  • s cyklem s podmínkou na začátku (while)
  • s cyklem s podmínkou na konci (do while)
  • pomocí rekurze

Účel příkladu
  • Rekurze
Typ aplikace
  • WPF aplikace
Popis úkolu 
  • Výpočet faktoriálu
Funkčnosti
  • Při stisku tlačítka For se provede načtení čísla z pole Zadejte číslo. Následně bude vypočten faktoriál tohoto čísla pomocí cyklu s pevným krokem. Vypočtená hodnota faktoriálu bude vypsána do pole Faktoriál 
  • Při stisku tlačítka While se provede načtení čísla z pole Zadejte číslo. Následně bude vypočten faktoriál tohoto čísla pomocí cyklu s podmínkou na začátku. Vypočtená hodnota faktoriálu bude vypsána do pole Faktoriál 
  • Při stisku tlačítka Do While se provede načtení čísla z pole Zadejte číslo. Následně bude vypočten faktoriál tohoto čísla pomocí cyklu s podmínkou na konci. Vypočtená hodnota faktoriálu bude vypsána do pole Faktoriál 
  • Při stisku tlačítka Rekurze se provede načtení čísla z pole Zadejte číslo. Následně bude vypočten faktoriál tohoto čísla pomocí zavolání funkce, která obsahuje rekurzi. Vypočtená hodnota faktoriálu bude vypsána do pole Faktoriál 
  • Při stisku tlačítka Konec se provede zavření formuláře 
Výstup programu


Výstup programu 1: Ukázka GUI při počátečním spuštění programu FaktorialWPF 

Výsledek:


Výstup programu 2: Ukázka výpisu vypočteného faktoriálu programu FaktorialWPF

2.1. Analýza a návrh řešení

V příkladu bude využit stejný princip výpočtu faktoriálu jako v příkladu Faktorial, proto již není zapotřebí provádět detailní analýzu. 

Formulář bude obsahovat následující prvky - viz Obrázek 1.


Obrázek 1: Návrh GUI pro aplikaci FaktorialWPF

Pro rozložení jednotlivých prvků použijeme Grid, který rozdělíme na 2 řádky a 2 sloupce. Do prvního řádku Grid  (s indexem 0) do každého sloupce umístíme objekt typu WrapPanel do nichž budeme pokaždé vkládat 2 objekty. První vložený objekt slouží pro popisek (objekt typu Label ). Za tento objekt umístíme objekt typu TextBox. V TextBox umístěném v prvním sloupci budeme zadávat hodnotu, pro níž budeme počítat faktoriál. V dalším objektu TextBox umístěném ve druhém sloupci budeme vypisovat vypočtenou hodnotu faktoriálu.  Do druhého řádku řádku Grid umístíme StackPanel, do něhož umístíme dva objekty typu WrapPanel. Do prvního WrapPanel umístíme tlačítka pro výpočet faktoriálu. Do druhého WrapPanel umístíme tlačítko pro ukončení aplikace.


Obrázek 2: Návrh GUI - rozložení prvků v mřížce formuláře

2.2. XAML

Na základě našich zkušeností s XAML bude již stručně popsán postup tvorby formuláře. Formulář rozdělíme na dva řádky a dva sloupce. Výška prvního řádku se bude přizpůsobovat roztažení okna. Druhý řádek se přizpůsobí obsahu vložených prvků. - viz Kód 1. 

<Grid.RowDefinitions>
    <RowDefinition Height="*"/>
    <RowDefinition Height="Auto"/>
</Grid.RowDefinitions>

Kód 1: Rozdělení Grid na řádky

Šířka obou sloupců se budou přizpůsobovat roztažení okna - viz Kód 2. 

<Grid.ColumnDefinitions>
    <ColumnDefinition Width="*"/>
    <ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>

Kód 2: Rozdělení Grid na sloupce

Do prvního řádku Grid  (s indexem 0) a prvního sloupce umístíme objekt typu WrapPanel. První objekt typu Label je popisek dalšího vloženého objektu typu TextBox. V TextBox budeme zadávat hodnotu, pro níž bude vypočten faktoriál pomocí stisknutí některého z tlačítek. Číslo (číslice) vepsané do TextBox je vystředěno jak v horizontální tak i vertikální ose - viz Kód 3.

<WrapPanel Margin="5,20,5,5" HorizontalAlignment="Center">
    <Label Content="Zadejte číslo:" Margin="5" />
    <TextBox Name="TxtCislo" Margin="5" TextWrapping="Wrap" Text="0" Width="120" HorizontalContentAlignment="Center" 
             VerticalContentAlignment="Center"/>
</WrapPanel>

Kód 3: WrapPanel s popiskem (Label) a zadávanou hodnotou (v TextBox), pro níž bude vypočten faktoriál

V dalším WrapPanel v prvním řádku a ve druhém sloupci Grid bude také umístěn popisek (objekt typu Label) a objekt TextBox, do nějž budeme vypsána vypočtená hodnota faktoriálu. Tento TextBox zamkneme pro vkládání dat (vlastnost IsReadOnly) a podbarvíme (Background). Umožníme také zalamování textu do více řádků (vlastnost TextWrapping). Hodnota faktoriálu vypsaného do TextBox bude vystředěna jak v horizontální tak vertikální ose - viz Kód 4.

<WrapPanel Margin="5,20,5,5" Grid.Column="1" HorizontalAlignment="Center">
    <Label Content="Faktoriál:" Margin="5" />
    <TextBox Name="TxtFaktorial" Margin="5" TextWrapping="Wrap" Text="0" Width="200" IsReadOnly="True" 
             Background="AliceBlue" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
</WrapPanel>

Kód 4: WrapPanel s popiskem (Label) a vypisovanou hodnotou (v TextBox) vypočteného faktoriálu

Do druhého řádku řádku Grid umístíme StackPanel, do něhož umístíme dva objekty typu WrapPanel. Do prvního WrapPanel umístíme tlačítka pro výpočet faktoriálu. Do druhého WrapPanel umístíme tlačítko pro ukončení aplikace. Pro tlačítka vygenerujeme obsluhu události stisknutí tlačítka (událost Click) pomocí nastavení vlastnosti Click a zvolení položky <New Event Handler> - viz Kód 5.

<StackPanel Grid.Row="1" Grid.ColumnSpan="2">
    <WrapPanel HorizontalAlignment="Center">
        <Button Name="BtnFor" Content="For" Margin="5" Width="110" Height="30" Click="BtnFor_Click"/>
        <Button Name="BtnWhile" Content="While" Margin="5" Width="110" Click="BtnWhile_Click"/>
        <Button Name="BtnDoWhile" Content="Do While" Margin="5" Width="110" Click="BtnDoWhile_Click"/>
        <Button Name="BtnRekurze" Content="Rekurze" Margin="5" Width="110" Click="BtnRekurze_Click"/>
        <Button Name="BtnMazat" Content="Mazat" Margin="5"  Width="110" Click="BtnMazat_Click"/>
    </WrapPanel>
    <WrapPanel HorizontalAlignment="Right">
        <Button Name="BtnKonec" Content="Konec" Margin="5" Width="80" Padding="5" Click="BtnKonec_Click"/>
    </WrapPanel>
</StackPanel>

Kód 5: StackPanel - umístění tlačítek v objektech typu WrapPanel v posledním řádku Grid

Výsledný formulář

Navržené rozložení prvků na formuláři, včetně formuláře samotného, je vidět na následujícím obrázku - viz Obrázek 1.


Obrázek 1: Výsledný formulář WPF aplikace

Objekty na formuláři:

Formulář obsahuje následující objekty (kontrolky):

  • Grid
  • StackPanel
  • WrapPanel
  • Label
  • TextBox
    • TxtCislo
    • TxtFaktorial
  • Button
    • BtnFor
    • BtnWhile
    • BtnDoWhile
    • BtnBezCyklu
    • BtnMazat
    • BtnKonec
které jsou umístěny následujícím způsobem - viz Obrázek 2.


Obrázek 2: VS - okno Document Outline - seznam objektů

2.3. XAML - prvky formuláře

Následující XAML kód obsahuje nastavení formuláře - viz Kód 1. Pokud je zapotřebí zkopírujte XAML kód a vložte jej namísto řádky s nastavením vlastností okna (řádek začíná Title=....).

Title="Výpočet faktoriálu" Height="250" Width="800">

Kód 1: Nastavení vlastností formuláře

Grid

Následující zdrojový kód XAML obsahuje potřebné prvky na formuláři pro řešení úlohy, bez nastavení událostí - viz Kód 2. Pokud je zapotřebí, zkopírujte XAML kód a vložte jej mezi počáteční a koncovou značku prvku Grid.

<Grid.RowDefinitions>
    <RowDefinition Height="*"/>
    <RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
    <ColumnDefinition Width="*"/>
    <ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<WrapPanel Margin="5,20,5,5" HorizontalAlignment="Center">
    <Label Content="Zadejte číslo:" Margin="5" />
    <TextBox Name="TxtCislo" Margin="5" TextWrapping="Wrap" Text="0" Width="120" HorizontalContentAlignment="Center" 
             VerticalContentAlignment="Center"/>
</WrapPanel>
<WrapPanel Margin="5,20,5,5" Grid.Column="1" HorizontalAlignment="Center">
    <Label Content="Faktoriál:" Margin="5" />
    <TextBox Name="TxtFaktorial" Margin="5" TextWrapping="Wrap" Text="0" Width="200" IsReadOnly="True" 
             Background="AliceBlue" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
</WrapPanel>
<StackPanel Grid.Row="1" Grid.ColumnSpan="2">
    <WrapPanel HorizontalAlignment="Center">
        <Button Name="BtnFor" Content="For" Margin="5" Width="110" Height="30"/>
        <Button Name="BtnWhile" Content="While" Margin="5" Width="110"/>
        <Button Name="BtnDoWhile" Content="Do While" Margin="5" Width="110"/>
        <Button Name="BtnRekurze" Content="Rekurze" Margin="5" Width="110"/>
        <Button Name="BtnMazat" Content="Mazat" Margin="5"  Width="110"/>
    </WrapPanel>
    <WrapPanel HorizontalAlignment="Right">
        <Button Name="BtnKonec" Content="Konec" Margin="5" Width="80" Padding="5"/>
    </WrapPanel>
</StackPanel>

Kód 2: Prvky v Grid

2.4. C#

V souboru MainWindow.xaml.cs obsahující kód na pozadí (Code Behind) byla vygenerována základní struktura našeho programu v C#. Vedle konstruktoru MainWindow této třídy byly také vygenerovány soukromé (private) metody bez návratu:

  • BtnFor_Click
  • BtnWhile_Click
  • BtnDoWhile_Click
  • BtnRekurze_Click
  • BtnMazat
  • BtnKonec_Click

Tyto metody umístíme do regionu Události, abychom oddělili kódy pro obsluhu události Click jednotlivých tlačítek od regionu Výpočty, do kterého umístíme metodu s rekurzivním volání funkce pro výpočet faktoriálu.

Prvním typem cyklu, použitým při výpočtu faktoriálu, je cyklus s krokem, který je využit v metodě pro obsluhu události tlačítka BtnFor - viz Kód 1. Hodnota pro níž je vypočten faktoriál, je načtena přímo z formuláře. Řídící proměnná cyklu je deklarována a inicializována přímo v cyklu for. Výpis vypočteného faktoriálu (konvertovaného čísla na text ve formátu bez desetinných míst) je vypsán na formulář.

private void BtnFor_Click(object sender, RoutedEventArgs e)
{
    // Deklarace: 'f' ... hodnota faktoriálu - inicializace
    long f = 1;
 
    // Načtení čísla pro výpočet faktoriálu a jeho konverze na číslo
    int.TryParse(TxtCislo.Text, out int n);
 
    // Cyklus s krokem; deklarace: 'i' ... čítač (aktuální číslo v součinu)
    for (int i = 1; i <= n; i++)
    {
        // Výpočet faktoriálu
        f = f * i;
    }
 
    // Zformátovaný výpis vypočteného faktoriálu (konverze na text)
    this.TxtFaktorial.Text = f.ToString("N0");
}

Kód 1: Deklarace metody pro výpočet faktoriálu pomocí cyklu s krokem (BtnFor_Click)

Pro výpočet faktoriálu jsme v metodě pro obsluhu události stisknutí tlačítka BtnWhile využili cyklus s podmínkou na začátku - viz Kód 2. V této metodě jsou použity dvě lokální proměnné i a f. Proměnná i představuje čítač cyklu, ale zároveň představuje aktuální číslo v součinu. Tato proměnná je datového typu int, protože není zapotřebí velký rozsah zadávaných čísel vzhledem k horní mezi datového typu long vybraného pro proměnnou f, která představuje hodnotu vypočteného faktoriálu. Výraz f = f * i; bychom mohli zkrátit pomocí zápisu f *= i; . Dále jsme také zkrátili zápis inkrementace i = i + 1; na i++.

private void BtnWhile_Click(object sender, RoutedEventArgs e)
{
    /* Deklarace: 'i' ... čítač (aktuální číslo v součinu) - inicializace; 
     * 'f' ... hodnota faktoriálu - inicializace */
    int i = 1;
    long f = 1;
 
    // Načtení čísla pro výpočet faktoriálu a jeho konverze na číslo
    int.TryParse(TxtCislo.Text, out int n);
 
    // Opakuj, pokud je čítač menší, nebo roven číslu pro výpočet faktoriálu
    while (i <= n)
    {
        // Výpočet faktoriálu
        f = f * i;
 
        // Inkrementace čítače
        i++;
    }
 
    // Zformátovaný výpis vypočteného faktoriálu (konverze na text)
    this.TxtFaktorial.Text = f.ToString("N0");
}

Kód 2: Deklarace metody pro výpočet faktoriálu pomocí cyklu s podmínkou na začátku (BtnWhile_Click)

Další volanou metodou pro výpočet faktoriálu pomocí cyklu s podmínkou na konci je metoda pro obsluhu události tlačítka BtnDoWhile - viz Kód 3.

private void BtnDoWhile_Click(object sender, RoutedEventArgs e)
{
    /* Deklarace: 'i' ... čítač (aktuální číslo v součinu) - inicializace; 
     * 'f' ... hodnota faktoriálu - inicializace */
    int i = 1;
    long f = 1;
 
    // Načtení čísla pro výpočet faktoriálu a jeho konverze na číslo
    int.TryParse(TxtCislo.Text, out int n);
 
    do
    {
        // Výpočet faktoriálu
        f = f * i;
 
        // Inkrementace čítače
        i++;
    }
    // Opakuj, dokud je čítač menší, nebo roven číslu pro výpočet faktoriálu
    while (i <= n);
 
    // Zformátovaný výpis vypočteného faktoriálu (konverze na text)
    this.TxtFaktorial.Text = f.ToString("N0");
}

Kód 3: Deklarace metody pro výpočet faktoriálu pomocí cyklu s podmínkou na konci (BtnDoWhile_Click)

Další metodou pro obsluhu události stisknutí tlačítka BtnRekurze je metoda, kdy je výpočet faktoriálu realizován pomocí volání rekurzivní metody FaktorialRekurze s návratem - viz Kód 4. Tuto metodu umístíme mimo region Události do regionu s názvem Výpočty. 

private void BtnRekurze_Click(object sender, RoutedEventArgs e)
{
    // Deklarace: 'f' ... hodnota faktoriálu
    long f;
 
    // Načtení čísla pro výpočet faktoriálu a jeho konverze na číslo
    int.TryParse(TxtCislo.Text, out int n);
 
    // Volání rekurzivní funkce - předání čísla pro výpočet faktoriálu
    f = FaktorialRekurze(n);
 
    // Zformátovaný výpis vypočteného faktoriálu (konverze na text)
    this.TxtFaktorial.Text = f.ToString("N0");
}

Kód 4: Deklarace metody pro výpočet faktoriálu pomocí rekurze (BtnRekurze_Click)

Soukromá metoda s celočíselným návratem využívá principu rekurze, kde metoda volá sama sebe (tím se postupně zanořuje sama do sebe) - viz Kód 5.

/// <summary>
/// Metoda s celočíselným návratem pro výpočet faktoriálu pomocí rekurze
/// </summary>
/// <param name="n"> číslo pro výpočet faktoriálu </param>
/// <returns> vypočtený faktoriál </returns>
private long FaktorialRekurze(int n)
{
    // Pokud je předaná hodnota v parametru rovna nule
    if (n == 0)
    {
        // Faktoriál je 1
        return 1;
    }
    else
    {
        // Rekurzivní volání metody(metoda volá sama sebe)
        return n * FaktorialRekurze(n - 1);
    }
}

Kód 6: Deklarace soukromé rekurzivní metody s celočíselným návratem (FaktorialRekurze)

Předposlední metodou, kterou budeme vytvářet, je metoda pro výmaz vypsané hodnoty faktoriálu na formuláři. Pro vymazání textu v objektu typu TextBox použijeme příkaz (Clear) - viz Kód 7.

private void BtnMazat_Click(object sender, RoutedEventArgs e)
{
    // Vymazání předchozího výpisu faktoriálu
    this.TxtFaktorial.Clear();
}

Kód 7: Deklarace metody pro výmaz vypočteného faktoriálu vypsaného na formuláři (BtnMazat_Click)

Poslední metodou, kterou musíme upravit je metoda pro obsluhu události Click tlačítka Konec. Tato metoda nám zavře formulář - viz Kód 8.

private void BtnKonec_Click(object sender, RoutedEventArgs e)
{
    // Zavření formuláře
    this.Close();
}

Kód 8: Deklarace metody bez návratu pro zavření formuláře (BtnKonec_Click)


2.5. Výsledný kód

XAML kód

Výsledný XAML kód formuláře (MainWindow.xaml) - viz Kód 1.

<Window x:Class="FaktorialWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:FaktorialWPF"
        mc:Ignorable="d"
        Title="Výpočet faktoriálu" Height="250" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <WrapPanel Margin="5,20,5,5" HorizontalAlignment="Center">
            <Label Content="Zadejte číslo:" Margin="5" />
            <TextBox Name="TxtCislo" Margin="5" TextWrapping="Wrap" Text="0" Width="120" HorizontalContentAlignment="Center" 
                     VerticalContentAlignment="Center"/>
        </WrapPanel>
        <WrapPanel Margin="5,20,5,5" Grid.Column="1" HorizontalAlignment="Center">
            <Label Content="Faktoriál:" Margin="5" />
            <TextBox Name="TxtFaktorial" Margin="5" TextWrapping="Wrap" Text="0" Width="200" IsReadOnly="True" 
                     Background="AliceBlue" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
        </WrapPanel>
        <StackPanel Grid.Row="1" Grid.ColumnSpan="2">
            <WrapPanel HorizontalAlignment="Center">
                <Button Name="BtnFor" Content="For" Margin="5" Width="110" Height="30" Click="BtnFor_Click"/>
                <Button Name="BtnWhile" Content="While" Margin="5" Width="110" Click="BtnWhile_Click"/>
                <Button Name="BtnDoWhile" Content="Do While" Margin="5" Width="110" Click="BtnDoWhile_Click"/>
                <Button Name="BtnRekurze" Content="Rekurze" Margin="5" Width="110" Click="BtnRekurze_Click"/>
                <Button Name="BtnMazat" Content="Mazat" Margin="5"  Width="110" Click="BtnMazat_Click"/>
            </WrapPanel>
            <WrapPanel HorizontalAlignment="Right">
                <Button Name="BtnKonec" Content="Konec" Margin="5" Width="80" Padding="5" Click="BtnKonec_Click"/>
            </WrapPanel>
        </StackPanel>
    </Grid>
</Window>

Kód 1: Výsledný XAML kód vytvořeného formuláře

C# kód

Code Behind - C# kód pro veškeré události vyvolané uživatelem při manipulaci s aplikací (MainWindow.xaml.cs) - viz Kód 2.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
 
namespace FaktorialWPF
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
 
        #region Výpočty
 
        /// <summary>
        /// Metoda s celočíselným návratem pro výpočet faktoriálu pomocí rekurze
        /// </summary>
        /// <param name="n"> číslo pro výpočet faktoriálu </param>
        /// <returns> vypočtený faktoriál </returns>
        private long FaktorialRekurze(int n)
        {
            // Pokud je předaná hodnota v parametru rovna nule
            if (n == 0)
            {
                // Faktoriál je 1
                return 1;
            }
            else
            {
                // Rekurzivní volání metody(metoda volá sama sebe)
                return n * FaktorialRekurze(n - 1);
            }
        }
 
        #endregion
 
        #region Události
        private void BtnFor_Click(object sender, RoutedEventArgs e)
        {
            // Deklarace: 'f' ... hodnota faktoriálu - inicializace
            long f = 1;
 
            // Načtení čísla pro výpočet faktoriálu a jeho konverze na číslo
            int.TryParse(TxtCislo.Text, out int n);
 
            // Cyklus s krokem; deklarace: 'i' ... čítač (aktuální číslo v součinu)
            for (int i = 1; i <= n; i++)
            {
                // Výpočet faktoriálu
                f = f * i;
            }
 
            // Zformátovaný výpis vypočteného faktoriálu (konverze na text)
            this.TxtFaktorial.Text = f.ToString("N0");
        }
 
        private void BtnWhile_Click(object sender, RoutedEventArgs e)
        {
            /* Deklarace: 'i' ... čítač (aktuální číslo v součinu) - inicializace; 
             * 'f' ... hodnota faktoriálu - inicializace */
            int i = 1;
            long f = 1;
 
            // Načtení čísla pro výpočet faktoriálu a jeho konverze na číslo
            int.TryParse(TxtCislo.Text, out int n);
 
            // Opakuj, pokud je čítač menší, nebo roven číslu pro výpočet faktoriálu
            while (i <= n)
            {
                // Výpočet faktoriálu
                f = f * i;
 
                // Inkrementace čítače
                i++;
            }
 
            // Zformátovaný výpis vypočteného faktoriálu (konverze na text)
            this.TxtFaktorial.Text = f.ToString("N0");
        }
 
        private void BtnDoWhile_Click(object sender, RoutedEventArgs e)
        {
            /* Deklarace: 'i' ... čítač (aktuální číslo v součinu) - inicializace; 
             * 'f' ... hodnota faktoriálu - inicializace */
            int i = 1;
            long f = 1;
 
            // Načtení čísla pro výpočet faktoriálu a jeho konverze na číslo
            int.TryParse(TxtCislo.Text, out int n);
 
            do
            {
                // Výpočet faktoriálu
                f = f * i;
 
                // Inkrementace čítače
                i++;
            }
            // Opakuj, dokud je čítač menší, nebo roven číslu pro výpočet faktoriálu
            while (i <= n);
 
            // Zformátovaný výpis vypočteného faktoriálu (konverze na text)
            this.TxtFaktorial.Text = f.ToString("N0");
        }
 
        private void BtnRekurze_Click(object sender, RoutedEventArgs e)
        {
            // Deklarace: 'f' ... hodnota faktoriálu
            long f;
 
            // Načtení čísla pro výpočet faktoriálu a jeho konverze na číslo
            int.TryParse(TxtCislo.Text, out int n);
 
            // Volání rekurzivní funkce - předání čísla pro výpočet faktoriálu
            f = FaktorialRekurze(n);
 
            // Zformátovaný výpis vypočteného faktoriálu (konverze na text)
            this.TxtFaktorial.Text = f.ToString("N0");
        }
 
        private void BtnMazat_Click(object sender, RoutedEventArgs e)
        {
            // Vymazání předchozího výpisu faktoriálu
            this.TxtFaktorial.Clear();
        }
 
        private void BtnKonec_Click(object sender, RoutedEventArgs e)
        {
            // Zavření formuláře
            this.Close();
        }
 
        #endregion
    }
}

Kód 2: Výsledný C# kód vytvořeného formuláře a metod jeho prvků

Výstup programu

Na následujícím obrázku vidíme výstup naší aplikace pro výpočet faktoriálu ze zadaného čísla - viz Výstup programu - Kód 1 a 2. Výpočet faktoriálu s následným výpisem hodnoty faktoriálu je spouštěn pomocí příslušného tlačítka s určitým typem cyklu, nebo rekurze. Aplikaci lze ukončit pomocí tlačítka Konec, nebo pomocí zavíracího tlačítka umístěného v pravém rohu aplikace.

Výstup programu - Kód 1 a 2: Výpis hodnoty vypočteného faktoriálu pomocí cyklu s krokem