Dvourozměrné pole - konzole
3. C#
3.4. Plnění pole
Do regionu s názvem Plnění pole umístíme metodu bez návratu s názvem PlnitPole. Tato metoda, která je volána v hlavní metodě, zajišťuje plnění matice celými čísly v rozsahu intervalu definované dolní a horní meze - viz Kód 1. Pro tyto účely jsou přijímány následující parametry:
- m - aktuální počet řádků matice
- n - aktuální počet sloupců matice
- minHodnota - dolní mez prvků matice
- maxHodnota- horní mez prvků matice
- pole - matice, která má být naplněna
/// <summary> /// Metoda bez návratu - výběr metody plnění matice /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="minHodnota"> dolní mez prvků matice </param> /// <param name="maxHodnota"> horní mez prvků matice </param> /// <param name="pole"> matice, která má být naplněna </param> static void PlnitPole(int m, int n, int minHodnota, int maxHodnota, int[,] pole) { <span style="color:green;">/* Deklarace: 'zpusobPlneni' ... způsob plnění matice('0'...Náhodně, '1'...Jednotlivě, * '2'...Nulovat) */</span> <span style="color:blue;">int</span> <span style="color:#1f377f;">zpusobPlneni</span>; <span style="color:#8f08c4;">do</span> { <span style="color:green;">// Výzva k zadání způsobu plnění matice</span> <span style="color:#2b91af;">Console</span>.<span style="color:#74531f;">Write</span>(<span style="color:#a31515;">"Zvolte způsob plnění pole (0...Náhodně, 1...Jednotlivě, 2...Nulovat): "</span>); <span style="color:green;">// Načtení způsobu plnění</span> <span style="color:blue;">int</span>.<span style="color:#74531f;">TryParse</span>(<span style="color:#2b91af;">Console</span>.<span style="color:#74531f;">ReadLine</span>(), <span style="color:blue;">out</span> <span style="color:#1f377f;">zpusobPlneni</span>); } // Načtení způsobu plnění proběhne znovu, pokud nebyl zadán validní celočíselný kód způsobu plnění while ((zpusobPlneni != 0) && (zpusobPlneni != 1) && (zpusobPlneni != 2)); // Přepnutí na různý způsob plnění switch (zpusobPlneni) { <span style="color:green;">// Plnění matice náhodnými čísly</span> <span style="color:#8f08c4;">case</span> 0: <span style="color:green;">// Zavolání metody pro plnění matice náhodnými čísly</span> <span style="color:#74531f;">NahodnePole</span>(<span style="color:#1f377f;">m</span>, <span style="color:#1f377f;">n</span>, <span style="color:#1f377f;">minHodnota</span>, <span style="color:#1f377f;">maxHodnota</span>, <span style="color:#1f377f;">pole</span>); <span style="color:#8f08c4;">break</span>; <span style="color:green;">// Plnění matice jednotlivými zadanými hodnotami uživatelem</span> <span style="color:#8f08c4;">case</span> 1: <span style="color:green;">// Volání metody pro plnění matice uživatelem zadanými čísly</span> <span style="color:#74531f;">PlnitJednotlive</span>(<span style="color:#1f377f;">m</span>, <span style="color:#1f377f;">n</span>, <span style="color:#1f377f;">minHodnota</span>, <span style="color:#1f377f;">maxHodnota</span>, <span style="color:#1f377f;">pole</span>); <span style="color:#8f08c4;">break</span>; <span style="color:#8f08c4;">case</span> 2: <span style="color:green;">// Volání metody, kdy všem prvkům matice je přiřazena hodnotu nula</span> <span style="color:#74531f;">NulovatPole</span>(<span style="color:#1f377f;">m</span>, <span style="color:#1f377f;">n</span>, <span style="color:#1f377f;">pole</span>); <span style="color:#8f08c4;">break</span>; } }
Kód 1: Deklarace statické metody bez návratu s názvem PlnitJednotlive
Na začátku metody je uživatel informován o možnostech různého způsobu plnění matice. Způsob plnění je specifikován pomocí celočíselných indexů představující různé způsoby plnění. Načtená hodnota způsobu plnění matice je uložena do proměnné zpusobPlneni. V metodě je specifikována pojistka proti možné chybě programu, kdyby uživatel zadal neplatný index vyjadřující způsob plnění vektoru. Tato pojistka je reprezentována cyklem s podmínkou na konci, kde v těle cyklu je již zmiňovaný výpis a načtení indexu od uživatele do proměnné zpusobPlneni. Ve zdrojovém kódu metody je použito vícenásobné větvení pomocí příkazu switch. Pokud je hodnota uložená v proměnné zpusobPlneni rovna:- 0 - matice s názvem pole je plněna náhodnými čísly pomocí metody bez návratu NahodnePole
- 1 - matice pole je plněna celočíselnými hodnotami specifikovanými uživatelem. Uživatel zároveň definuje kterému prvku matice patří tato jím zadaná hodnota. Plnění je prováděno pomocí metody bez návratu s názvem PlnitJednotlive. Vzhledem k tomu, že v C# dvourozměrné pole představuje referenční datový typ, není zapotřebí nulovat pole, tzn. pokud není nastavena hodnota prvku pole, prvek je inicializován počáteční hodnotou v závislosti na příslušném datovém typu (např. u datového typu int je to 0)
- 2 - matice pole je plněna nulami pomocí metody bez návratu NulovatPole
První metodou , která je volána když zpusobPlneni == 0, je metoda bez návratu NahodnePole - viz Kód 2.
/// <summary> /// Metoda bez návratu - plnění matice náhodnými čísly /// </summary> /// <param name="m"> aktuální počet řádků matice </param> /// <param name="n"> aktuální počet sloupců matice </param> /// <param name="minHodnota"> dolní mez prvků matice </param> /// <param name="maxHodnota"> horní mez prvků matice </param> /// <param name="pole"> matice, který má být naplněna </param> static void NahodnePole(int m, int n, int minHodnota, int maxHodnota, int[,] pole) { <span style="color:green;">/* Deklarace: 'rnd' ... náhodné číslo (generované na základě rovnoměrného rozdělení); * 'i' ... index řádku prvku matice, 'j' ... index sloupce prvku matice */</span> <span style="color:green;">// Deklarace náhodného čísla (objektu) včetně inicializace</span> <span style="color:#2b91af;">Random</span> <span style="color:#1f377f;">rnd</span> = <span style="color:blue;">new</span> <span style="color:#2b91af;">Random</span>(); <span style="color:green;">// Pro všechny řádky matice od '0' (počátečního) do 'm-1'-tého (posledního) řádku</span> <span style="color:#8f08c4;">for</span> (<span style="color:blue;">int</span> <span style="color:#1f377f;">i</span> = 0; <span style="color:#1f377f;">i</span> < <span style="color:#1f377f;">m</span>; <span style="color:#1f377f;">i</span>++) { <span style="color:green;">// Pro všechny sloupce matice od '0' (počátečního) do 'n-1'-tého (posledního) sloupce</span> <span style="color:#8f08c4;">for</span> (<span style="color:blue;">int</span> <span style="color:#1f377f;">j</span> = 0; <span style="color:#1f377f;">j</span> < <span style="color:#1f377f;">n</span>; <span style="color:#1f377f;">j</span>++) <span style="color:green;">/* Vygenerování náhodného čísla uloženého do 'rnd' v rozsahu 'minHodnota' až 'maxHodnota' * Přiřazení náhodného čísla do aktuálního prvku */</span> <span style="color:#1f377f;">pole</span>[<span style="color:#1f377f;">i</span>, <span style="color:#1f377f;">j</span>] = <span style="color:#1f377f;">rnd</span>.<span style="color:#74531f;">Next</span>(<span style="color:#1f377f;">minHodnota</span>, <span style="color:#1f377f;">maxHodnota</span> + 1); } }
Kód 2: Deklarace statické metody bez návratu s názvem NahodnePole
Tato metoda na základě hodnot uložených ve formálních parametrech, plní náhodnými čísly jednotlivé prvky matice náležící polouzavřenému intervalu od dolní meze do horní meze. Abychom mohli uložit vygenerovanou náhodnou hodnotu do prvku matice, je zapotřebí dvou indexů - první pro určení řádku, na které se nachází prvek matice. Druhý index bude určovat, v jakém sloupci se nachází prvek matice. Vzhledem k tomu, že při plnění potřebujeme projít všechny prvky matice, využijeme k tomuto účelu dva cykly s krokem, protože víme kolik řádků a sloupců obsahuje matice (celkový počet prvků matice je
). Schématicky bychom mohli vyjádřit plnění prvků ve vývojovém diagramu následujícím způsobem - viz Obrázek 1.

Obrázek 1: Vnější a vnitřní cyklus pro plnění prvků dvourozměrného pole
První (vnější) cyklus nám zajišťuje přístup k jednotlivým řádkům matice pomocí řídící proměnné i. Druhý vnitřní cyklus nám zajišťuje přístup k jednotlivým sloupcům matice pomocí řídící proměnné j - viz Obrázek 2.

Obrázek 2: Indexování prvků dvourozměrného pole
V následujícím obrázku vidíme, jak jsou postupně plněny prvky počátečního řádku matice. Vnější cyklus prvním průchodem (iterací) zajistil nastavení hodnoty indexu počátečního řádku, tedy i = 0. Následně je prováděn vnitřní cyklus, který zajišťuje procházení prvků po jednotlivých sloupcích v tomto počátečním řádku. Po naplnění posledního prvku počátečního řádku (vnitřní cyklus s řídící proměnnou je ukončen) vnější cyklus zajistí zvýšení indexu i o hodnotu 1, tzn. bude zajištěn přesun do dalšího řádku a tento řádek je opětovně postupně plněn po jednotlivých sloupcích - viz Obrázek 3. Generování náhodného čísla je na základě rovnoměrného rozdělení. Pro generování je použit objekt rnd odvozený od třídy Random (instance třídy Random). Abychom mohli vytvořit objekt rnd, je zapotřebí zavolat konstruktor objektu pomocí klíčového slova new. Pro generování náhodného čísla využijeme metodu Next přidruženou k objektu rnd.

Obrázek 3: Postupné procházení jednotlivých prvků matice při plnění
Další možností plnění prvků matice, je plnění jednotlivých prvků na základě hodnot zadaných uživatelem pomocí metody bez návratu PlnitJednotlive, tedy pokud uživatel zadal v metodě PlnitPole hodnotu indexu způsobu plnění rovné 1 - viz Kód 3. Po deklaraci je matice implicitně naplněna nulami. Pomocí následujícího kódu umožníme uživateli naplnit prvky matice od zadané pozice prvku (zadaného indexu řádku a sloupce) až do koncového prvku matice. Plnění tímto způsobem bylo využito zejména z důvodu zjednodušení zadávání jednotlivých prvků, protože při použití předchozího způsobu zadávání jednotlivých prvků vektoru (viz kniha Jednorozměrné pole - konzole - kapitola 3.3 Plnění pole) by uživatel po každém zadání prvku musel potvrdit, že chce zadávat další prvek.
/// <summary> /// Metoda pro plnění jednotlivých prvků matice specifikovaných uživatelem /// </summary> /// <param name="m"> aktuální počet řádků matice </param> /// <param name="n"> aktuální počet sloupců matice </param> /// <param name="minHodnota"> dolní mez prvků matice </param> /// <param name="maxHodnota"> horní mez prvků matice </param> /// <param name="pole"> matice, který má být naplněna </param> static void PlnitJednotlive(int m, int n, int minHodnota, int maxHodnota, int[,] pole) { <span style="color:green;">/* Deklarace: 'indexRadku' ... index řádku prvku, který má být naplněn; 'indexSloupce' ... index * sloupce prvku, který má být naplněn; 'hodnota' ... hodnota prvku, který má být naplněn; * 'plnit' ... informace, zda má zadán (naplněn) další prvek ('true'...Ano, 'false'...Ne) */</span> <span style="color:blue;">int</span> <span style="color:#1f377f;">indexRadku</span>, <span style="color:#1f377f;">indexSloupce</span>, <span style="color:#1f377f;">hodnota</span>; <span style="color:blue;">bool</span> <span style="color:#1f377f;">plnit</span>; <span style="color:green;">/* Cyklus s podmínkou na konci pro načtení indexu řádku plněného prvku - první souřadnice * prvku, od kterého lze postupně plnit další prvky matice */</span> <span style="color:#8f08c4;">do</span> { <span style="color:green;">// Výzva k zadání indexu řádku plněného prvku</span> <span style="color:#2b91af;">Console</span>.<span style="color:#74531f;">Write</span>(<span style="color:#a31515;">"Zadejte index řádku u prvku, který chcete naplnit (0 - {0}): ", m - 1); // Načtení indexu řádku int.TryParse(Console.ReadLine(), out indexRadku); } /* Podmínka cyklu, zda načtený index řádku je mimo meze. Pokud ano, opakování * načtení indexu řádku */ while (!Validace(indexRadku, 0, m-1)); // Cyklus s podmínkou na konci pro načtení indexu sloupce plněného prvku do { <span style="color:green;">// Výzva k zadání pořadového čísla sloupce plněného prvku</span> <span style="color:#2b91af;">Console</span>.<span style="color:#74531f;">Write</span>(<span style="color:#a31515;">"Zadejte index sloupce u prvku, který chcete naplnit (0 - {0}): ", n - 1); // Načtení indexu sloupce int.TryParse(Console.ReadLine(), out indexSloupce); } /* Podmínka cyklu, zda načtený index sloupce je mimo meze. Pokud ano, opakovaní * načtení indexu sloupce */ while (!Validace(indexSloupce, 0, n-1)); // Matice má být plněna prvky zadanými uživatelem plnit = true; // Cyklus s podmínkou na konci pro plnění prvků matice do { <span style="color:green;">// Cyklus s podmínkou na konci - validace zadané hodnoty zda je hodnota mimo rozsah intervalu </span> <span style="color:#8f08c4;">do</span> { <span style="color:green;">/* Výzva k zadání hodnoty prvku, včetně vypsání dolní a horní meze včetně indexu * řádku a sloupce v hranatých závorkách */</span> <span style="color:#2b91af;">Console</span>.<span style="color:#74531f;">Write</span>(<span style="color:#a31515;">"Zadejte hodnotu prvku ({0} - {1}) na pozici [{2}, {3}]: ", minHodnota.ToString(), maxHodnota.ToString(), indexRadku.ToString(), indexSloupce.ToString()); // Načtení hodnoty prvku int.TryParse(Console.ReadLine(), out hodnota); } /* Podmínka cyklu, zda načtená hodnota prvku je mimo meze. Pokud ano, opakovaní * načtení hodnoty */ while (!Validace(hodnota, minHodnota, maxHodnota)); // Přiřazení hodnoty z lokální proměnné do prvku matice na určenou pozici pole[indexRadku, indexSloupce] = hodnota; // Pokud bylo dosaženo posledního řádku a posledního sloupce, pak... if ((indexRadku == m - 1) && (indexSloupce == n - 1)) // Zastavení plnění matice plnit = false; // Pokud index sloupce je menší než celkový počet sloupců - 1, pak... if (indexSloupce < n - 1) { <span style="color:green;">//zvýšení indexu sloupce o 1</span> <span style="color:#1f377f;">indexSloupce</span>++; } // Jinak ... else { <span style="color:green;">// Pokud index řádku je menší než celkový počet řádků - 1, pak...</span> <span style="color:#8f08c4;">if</span> (<span style="color:#1f377f;">indexRadku</span> < <span style="color:#1f377f;">m</span> - 1) { <span style="color:green;">// Zvýšení indexu řádku o 1</span> <span style="color:#1f377f;">indexRadku</span>++; <span style="color:green;">// Přiřazení 0 do indexu sloupce</span> <span style="color:#1f377f;">indexSloupce</span> = 0; } } } /* Podmínka cyklu, zda má být provedeno další načtení prvku. Pokud ano (hodnota 'true'), * opakovaní načtení hodnoty */ while (plnit == true); }
Kód 3: Deklarace statické metody bez návratu s názvem PlnitJednotlive
Metoda PlnitJednotlive přijímá stejné parametry jako předchozí metoda NahodnePole, tj. celkový počet řádků, sloupců, minimální a maximální přípustná hodnota prvku matice a samotnou matici. Pro tuto metodu jsou deklarovány následující proměnné:
- indexRadku - index řádku prvku, který má být naplněn
- indexSloupce - index sloupce prvku, který má být naplněn
- hodnota - hodnota prvku, který má být naplněn
- plnit - logická proměnná, která reprezentuje informaci, zda má zadán (naplněn) další prvek (true ... Ano, false ... Ne)
Pomocí prvního cyklu s podmínkou na konci je zajištěno zadání validní hodnoty indexu řádku prvku uloženého v proměnné indexRadku. Uživatel je v každé iteraci informován pomocí výpisu mezí intervalu, jaké hodnoty mohou být zadány. Pokud byla zadána hodnota indexu, která nenáleží uzavřenému intervalu <0, m - 1>, je pomocí těla cyklu zadávání opakováno do té doby, dokud nebude zadán validní index řádky. V podmínce cyklu je využito volání metody s logickým návratem pro validaci rozměru matice s názvem Validace - viz Kód 4.
Tato metoda poskytuje informaci, zda předaná hodnota (vyjadřující index) není menší, nebo zda nepřesahuje rozměr matice ve vybrané ose. V prvním případě je v cyklu podmínky zadání indexu validován index vertikální osy představující jednotlivé řádky matice.
Metoda je dále použita pro validaci indexu sloupce a dokonce i pro validaci načtené hodnoty ukládané do prvku. Princip validace je totiž pořád stejný, tzn., zda se daná hodnota nachází uvnitř intervalu. V případě nevalidní hodnoty je výstup metody Validace hodnota false včetně výpisu, že zadaná hodnota je mimo meze intervalu. Pokud je hodnota validní, výstup metody je true.
/// <summary> /// Metoda s logickým návratem - validace, zda předaná hodnota náleží intervalu /// </summary> /// <param name="hodnota"> předaná hodnota </param> /// <param name="minRozmer"> dolní mez intervalu </param> /// <param name="maxRozmer"> horní mez intervalu </param> /// <returns> Logická informace, zda předaná hodnota náleží intervalu povolených hodnot /// </returns> static bool Validace(int hodnota, int dolniMez, int horniMez) { <span style="color:green;">// Informace, že předaná hodnota je validní</span> <span style="color:blue;">bool</span> <span style="color:#1f377f;">validni</span> = <span style="color:blue;">true</span>; <span style="color:green;">// Test, zda načtená hodnota je mimo interval povolených hodnot ...</span> <span style="color:#8f08c4;">if</span> ((<span style="color:#1f377f;">hodnota</span> < <span style="color:#1f377f;">dolniMez</span>) || (<span style="color:#1f377f;">hodnota</span> > <span style="color:#1f377f;">horniMez</span>)) { <span style="color:green;">// Výpis o chybě</span> <span style="color:#2b91af;">Console</span>.<span style="color:#74531f;">WriteLine</span>(<span style="color:#a31515;">"Zadaná hodnota je mimo povolené meze <{0}, {1}>", dolniMez, horniMez); // Hodnota není validní validni = false; } // Návrat metody return validni; }
Kód 4: Deklarace statické metody Validace s logickým návratem
Vraťme se zpět k metodě PlnitJednotlive. Pomocí druhého cyklu s podmínkou na konci je zajištěno zadání validní hodnoty indexu sloupce prvku uloženého v proměnné indexSloupce. Uživatel je v každé iteraci informován, jaké hodnoty mohou být zadány. Pokud bylo zadán takový index sloupce, které nenáleží uzavřenému intervalu <0, n - 1>, je pomocí těla cyklu zadávání opakováno do té doby, dokud nebude zadán validní index sloupce. V podmínce cyklu je znovu využito volání metody s logickým návratem pro validaci rozměru matice s názvem Validace.
Další cyklus s podmínkou na konci je určen k plnění prvků matice. V podmínce na konci tohoto cyklu je zohledněno, zda uživatel bude pokračovat v dalším zadávání hodnot, tj. proměnná plnit == true; . Před vstupem do cyklu je proměnné plnit přiřazena hodnota true, tzn., že uživatel bude plnit jednotlivé prvky matice. Pokud bylo dosaženo posledního řádku a posledního sloupce, je hodnota v této proměnné plnit nastavena na false, tzn., že podmínka cyklu zadávání prvků není splněna a cyklus zajišťující plnění prvků je ukončen.
Hodnota prvku je uložena do proměnné hodnota. Ve výpisu vyzývajícího uživatele k zadání hodnoty prvku, je v kulaté závorce uvedena jak dolní, tak i horní přípustná mez, aby byla redukována chybovost uživatele při zadávání. Dále je také uživateli v hranatých závorkách vypsána pozice naplňovaného prvku pomocí indexu řádku a sloupce. Pokud došlo k zadání nevalidní hodnoty prvku, která je testována pomocí metody Validace, je výstupem této metody false, což vede k opětovnému zadávání hodnoty prvku. Metodě Validace je předána načtená hodnota a meze intervalu povolených hodnot. Pokud je hodnota mimo uzavřený interval <minHodnota, maxHodnota>, je uvnitř metody Validace vypsána informace o tom, že zadaná hodnota je mimo povolené meze a celý cyklus načítání hodnoty je znovu opakován.
Po načtení validní hodnoty prvku je tato hodnota uložena do prvku matice na specifikovanou pozici. Automatické přenastavení indexu sloupce na další sloupec je zajištěno pomocí podmínky prováděné v těle cyklu. Podmínka zajišťuje, že pokud index sloupce je menší než celkový počet sloupců matice - 1 (tj. indexSloupce < n - 1), je provedena inkrementace indexu sloupce o hodnotu 1. Pokud tato podmínka neplatí, je testována další podmínka týkající se indexu řádku. Pokud je index řádku menší než celkový počet řádků - 1 (tj. indexRadku < m - 1), je provedena inkrementace indexu řádku o hodnotu 1 pro uložení dalšího prvku v příští iteraci. Protože jsme ve větvi else prvního rozhodování (tj. není splněna podmínka indexSloupce < n - 1), nacházíme se v prvku posledního sloupce. Je tedy nutné do další iterace přenastavit index sloupce na 0.
Poslední metodou bez návratu s názvem NulovatPole, je metoda, která přijímá pouze tři parametry určující počet řádků matice, počet sloupců matice a matici samotnou. V této metodě jsou prvky procházeny pomocí dvou cyklů s krokem, kde každému prvku na pozici i (index řádku) a j (index sloupce) je přiřazena hodnota 0, tj. příkaz pole[i, j] = 0; Tyto dva cykly odráží základní podstatu procházení prvků matice - viz Kód 5.
/// <summary> /// Metoda bez návratu - plnění prvků matice hodnotou nula /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> Matice, která má být naplněna </param> static void NulovatPole(int m, int n, int[,] pole) { <span style="color:green;">/* Pro všechny řádky od počátečního do posledního řádku matice; * 'i' ... index (pozice) řádku matice */</span> <span style="color:#8f08c4;">for</span> (<span style="color:blue;">int</span> <span style="color:#1f377f;">i</span> = 0; <span style="color:#1f377f;">i</span> < <span style="color:#1f377f;">m</span>; <span style="color:#1f377f;">i</span>++) { <span style="color:green;">// Pro všechny sloupce</span> <span style="color:#8f08c4;">for</span> (<span style="color:blue;">int</span> <span style="color:#1f377f;">j</span> = 0; <span style="color:#1f377f;">j</span> < <span style="color:#1f377f;">n</span>; <span style="color:#1f377f;">j</span>++) { <span style="color:green;">// Přiřazení nuly prvku na pozici [i,j]</span> <span style="color:#1f377f;">pole</span>[<span style="color:#1f377f;">i</span>, <span style="color:#1f377f;">j</span>] = 0; } } }
Kód 5: Deklarace statické metody bez návratu s názvem NulovatPole