Dvourozměrné pole - konzole
| Site: | Moodle ZČU |
| Course: | KPV/TI Technická informatika ve strojírenství - cvičení |
| Book: | Dvourozměrné pole - konzole |
| Printed by: | Gast |
| Date: | Sunday, 8 November 2026, 5:20 PM |
1. DvourozmernePole
Úkolem je vytvořit aplikaci, která u celočíselného dvourozměrné pole (tj. matice obsahující celá čísla) dokáže provést následující operace:
- Naplnit matici automaticky nulami
- Naplnit matici automaticky náhodnými hodnotami v zadaném rozsahu
- Naplnit matici jednotlivě zadávanými hodnotami pro zadaný index
- Zobrazit matici jako text, kde prvky jsou odděleny čárkami
- Nalézt minimum z hodnot matice
- Nalézt maximum z hodnot matice
- Vypočítat průměr z hodnot matice
- Seřadit vzestupně prvky v každém řádku matice
- Provést transpozici podle hlavní diagonály
- Provést transpozici podle vedlejší diagonály
Účel příkladu
- Práce s dvourozměrným polem (maticí)
Typ aplikace
- Konzolová aplikace
Popis úkolu
- Základní operace s dvourozměrným polem
Funkčnosti
- V hlavním programu může uživatel pomocí zavolaného podprogramu (procedura) Inicializace měnit atributy pole pomocí indexu operace, který je využit ve vícenásobném větvení. V tomto podprogramu jsou nastaveny hodnoty atributů pole. Na základě zvoleného validního indexu operace je spuštěn některý z následujících podprogramů (funkcí):
- RozmerPole - změna rozměru (počet prvků) ve zvolené ose matice, tj. ve vertikální ose - počet řádků, v horizontální ose - počet sloupců
- DolniMez - změna dolní meze, od které se budou pohybovat hodnoty prvků matice
- HorniMez - změna horní meze, do které se budou pohybovat hodnoty prvků matice
- Z hlavního programu bude volán podprogram (procedura) PlnitPole, ve kterém uživatel volí způsob plnění vektoru:
- 0 ... Náhodně - náhodnými čísly
- 1 ... Jednotlivě - jednotlivě zadanými hodnotami uživatelem
- 2 ... Nulovat - plnění vektoru nulami
- Bude deklarován podprogram (funkce) PoleJakoText, pomocí kterého se prvky matice vypíší jako text (na 3 místa), kde jednotlivé prvky budou od sebe odděleny čárkami
- V hlavním programu bude volán podprogram (procedura) ZobrazitPole, který volá podprogram PoleJakoText
- V hlavním programu bude volán podprogram (funkce) MinimumVPoli, pomocí kterého je vyhledáno minimum z hodnot v matici. Ve výpisu bude také uvedena pozice (index řádku a sloupce) minima
- V hlavním programu bude volán podprogram (funkce) MaximumVPoli, pomocí kterého je vyhledáno maximum z hodnot v matici. Ve výpisu bude také uvedena pozice (index řádku a sloupce) maxima
- V hlavním programu bude volán podprogram (funkce) PrumerPole, pomocí kterého je vypočten aritmetický průměr z hodnot v matici
- V hlavním programu bude volán podprogram SeraditPole, pomocí kterého jsou jednotlivé prvky řádku matice seřazeny vzestupně podle jejich hodnoty. Seřazené řádky matice budou vypsány pomocí podprogramu určeného pro výpis matice (ZobrazitPole)
- V hlavním programu bude volán podprogram HlavniTranspozice, pomocí kterého jsou jednotlivé prvky matice transponovány podle hlavní diagonály. Transponovaná matice bude vypsána
- V hlavním programu bude volán podprogram VedlejsiTranspozice, pomocí kterého jsou jednotlivé prvky matice transponovány podle vedlejší diagonály. Transponovaná matice bude vypsána
- Po výpisu bude aplikace ukončena po stisku klávesy
Výstup programu
Výstup programu: Ukázka výpisu matice s náhodnými čísly v hlavní metodě programu DvourozmernePole
2. Analýza a návrh řešení
Jednorozměrná pole jsme vnímali jako seznam jednotlivých prvků umístěných za sebou, k nimž přistupujeme pomocí indexů. Pole ale může mít více než jednu dimenzi (dimenze značí počet rozměrů - pole mělo jen jednu). Zaměřme se nyní na dvourozměrné pole označované jako matice (dimenze takového pole je tedy rovna 2 - ve vertikální ose matice obsahuje řádky a v horizontální ose obsahuje sloupce). Upozorněme, že prvky matice musí být všechny stejného datového typu.
Dvourozměrné pole si lze představit jako tabulku o řádcích a sloupcích, nebo také jako více jednorozměrných polí uspořádaných za sebou. Pro přístup k jednotlivým prvkům matice je zapotřebí dvou celočíselných indexů - viz Obrázek 1.
- První celočíselný index pro řádky např. i (index řádky je číslován od 0. Počet řádků matice můžeme označit např. m)
- Druhý celočíselný index pro sloupce např. j (index sloupce je číslován od 0. Počet sloupců matice můžeme označit např. n)

Obrázek 1: Podstata dvourozměrného pole - matice (rozměr m × n)
Pro přístup k hodnotě uložené v prvku matice, nebo k uložení hodnoty do prvku matice (přiřazení hodnoty) využíváme v příkazu název dvourozměrného pole a za ním uvedené uzavřené hranaté závorky s dvěma indexy určující pozici prvku v řádku a sloupci.
Velikost dvourozměrného pole je určena počtem prvků pro jednotlivé osy - ve vertikální ose velikost matice určuje počet řádků a v horizontální ose určuje počet sloupců. Celkový počet prvků dvourozměrné matice je v našem případě m × n prvků.
Standardně bychom v této kapitole použili pro návrh řešení vývojové diagramy vytvořené v aplikaci Flowgorithm. Protože však tento software zatím nepodporuje použití dvourozměrných polí (tento nedostatek lze obejít skládáním řádků matice za sebou a umístit všechny řádky do jednorozměrného pole, ale tento přístup používat nebudeme), bude řešení implementováno přímo do zdrojového kódu v C#.
3. C#
SnippetMetoda s logickým návratem - validace, zda předaná hodnota náleží intervalu
V následujícím zdrojovém kódu je uvedena hlavní metoda algoritmu DvourozmernePole - viz Kód 1. V hlavní metodě je deklarována maximální velikost dvourozměrného pole, tj. konstanta Max pro každou osu, tj. řádky, nebo sloupce. Následně je v hlavní metodě volána metoda Inicializace, ve které jsou deklarovány a následně nastaveny základní atributy dvourozměrného pole (výstupní parametry). V metodě je také vytvořena instance dvourozměrného pole - matice.
Uživatel má v hlavní metodě možnost zvolit způsob plnění matice pomocí metody bez návratu PlnitPole. K dispozici má tři možnosti, které jsou zvoleny na základě zadání celočíselného indexu:
- 0 - Náhodně - náhodnými čísly
- 1 - Jednotlivě - jednotlivě zadanými hodnotami uživatelem
- 2 - Nulovat - plnění vektoru nulami
Uživateli je také v hlavní metodě vypsána vypočtená hodnota aritmetického průměru ze všech hodnot v matici. Pro výpočet je volána metoda PrumerPole, jenž navrací reálnou hodnotu aritmetického průměru.
Další operací prováděnou s maticí je vzestupné setřídění prvků v jednotlivých řádcích pomocí metody SeraditPole. Tato metoda využívá princip algoritmu bublinkového řazení. Seřazená matice je následně vypsána.
Prvky matice jsou transponovány (otočeny) podle hlavní a následně podle vedlejší diagonály, kde po provedení každé transpozice je matice vypsána. V závěru programu je očekáván stisk některé klávesy, aby mohl být program ukončen - viz Kód 1.
static void Main(string[] args) { /* Deklarace: 'pocetRadku' ... počet řádků matice; 'pocetSloupcu' ... počet sloupců matice; * 'Max' ... konstantní hodnota maximální velikosti matice pro každou osu (pro 1. vertikální osu * představuje maximální počet řádků matice, pro 2. osu představuje maximální počet sloupců matice; * 'minHodnota' ... přípustná minimální hodnota (dolní mez) prvků matice; 'maxHodnota' ... přípustná * maximální hodnota (horní mez) prvků matice; 'poradiRadku' ... pořadí řádku prvku (využití pro * vyhledání minima a maxima matice); 'poradiSloupce' ... pořadí sloupce prvku */ // Maximální velikost matice pro každou osu, tj. řádky, nebo sloupce const int Max = 10; // Metoda pro inicializaci atributů matice a jejich případnou změnu Inicializace(Max, out int minHodnota, out int maxHodnota, out int pocetRadku, out int pocetSloupcu, out int[,] pole); /* Zavolání metody pro plnění matice (náhodnými čísly, jednotlivě zadanými hodnotami, * plnění nulami) */ PlnitPole(pocetRadku, pocetSloupcu, minHodnota, maxHodnota, pole); // Výpis matice po jednotlivých řádcích, kde jednotlivé prvky jsou odděleny čárkami Console.WriteLine("Výpis matice: "); ZobrazitPole(pocetRadku, pocetSloupcu, pole); // Výpis hodnoty minima matice, včetně jeho pozice v matici Console.WriteLine("Minimum v matici: {0} na pozici [{1},{2}] ", MinimumVPoli(pocetRadku, pocetSloupcu, pole, out int indexRadku, out int indexSloupce), indexRadku, indexSloupce); // Výpis hodnoty maxima matice, včetně jeho pozice v matici Console.WriteLine("Maximum v matici: {0} na pozici [{1},{2}] ", MaximumVPoli(pocetRadku, pocetSloupcu, pole, out indexRadku, out indexSloupce), indexRadku, indexSloupce); // Výpis průměru všech prvků matice Console.WriteLine("Průměr prvků matice: " + PrumerPole(pocetRadku, pocetSloupcu, pole)); // Vzestupné řazení prvků v jednotlivých řádcích matice podle metody Bubble Sort SeraditPole(pocetRadku, pocetSloupcu, pole); // Výpis seřazené matice Console.WriteLine("Seřazená matice: "); ZobrazitPole(pocetRadku, pocetSloupcu, pole); // Transpozice matice podle hlavní diagonály HlavniTranspozice(pocetRadku, pocetSloupcu, pole); // Výpis transponované matice podle hlavní diagonály Console.WriteLine("Transpozice matice podle hlavní diagonály: "); ZobrazitPole(pocetRadku, pocetSloupcu, pole); // Transpozice matice podle vedlejší diagonály VedlejsiTranspozice(pocetRadku, pocetSloupcu, pole); // Výpis transponované matice podle vedlejší diagonály Console.WriteLine("Transpozice matice podle vedlejší diagonály: "); ZobrazitPole(pocetRadku, pocetSloupcu, pole); // Čekání na stisk klávesy -> ukončení programu Console.ReadKey(); }
Kód 1: Program DvourozmernePole - deklarace hlavní statické metody Main
Vzhledem k vyšší náročnosti na pochopení podstaty metod, rozčleníme zdrojový kód do jednotlivých regionů, které nám umožní sbalovat, nebo rozbalovat obsah jednotlivých regionů. Jedná se o následující regiony:
- Nastavení atributů pole - region bude obsahovat následující metody, které budou popsány v následujících kapitolách:
- Inicializace - metoda pro inicializaci a změnu atributů pole
- RozmerPole - metoda navracející velikost pole v ose
- DolniMez - metoda navracející dolní mez intervalu přípustných hodnot prvků matice
- HorniMez - metoda navracející horní mez intervalu přípustných hodnot prvků matice
- Plnění pole - region bude obsahovat následující metody:
- PlnitPole - metoda volající některou z metod plnění matice
- NahodnePole - metoda pro plnění matice náhodnými čísly
- Validace - metoda s logickým návratem - validace, zda předaná hodnota náleží intervalu
- PlnitJednotlive - metoda pro plnění jednotlivých prvků matice specifikovaných uživatelem
- NulovatPole - metoda pro plnění prvků matice hodnotou nula
- Zobrazení pole - region bude obsahovat následující metody:
- PoleJakoText - prvky v sloupcích matice jsou převedeny na text a odděleny čárkou, kde každá řádka matice je umístěna na novém řádku ve výstupním textovém řetězci
- ZobrazitPole - volání metody pro výpis prvků matice do textového řetězce
- Operace s polem - region bude obsahovat následující metody:
- MinimumVPoli - metoda navracející hodnotu minima matice - nejmenší prvek
- MaximumVPoli - metoda navracející hodnotu maxima matice - největší prvek
- PrumerPole - metoda navracející aritmetický průměr prvků matice
- HlavniTranspozice - metoda transponující prvky matice podle hlavní diagonály
- VedlejsiTranspozice - metoda transponující prvky matice podle vedlejší diagonály
Za počáteční značkou regionu #region budeme umísťovat název regionu, např. #region Nastavení atributů pole. Protože kód metod je delší, proto za koncovou značkou regionu, tj. #endregion umístíme také název příslušného regionu, např. #endregion Nastavení atributů pole, abychom rychle zjistili, zda již nejsme v oblasti jiného regionu.
3.1. Nastavení atributů pole
První metodou regionu Nastavení atributů pole je metoda bez návratu s názvem Inicializace - viz Kód 1. Tato metoda je volána v hlavní metodě. Tato metoda bez návratu slouží pro inicializaci (nastavení počátečních hodnot) atributů matice. Metoda přijímá jako první parametr konstantu Max deklarovanou a inicializovanou v hlavní metodě. V metodě jsou deklarovány základní atributy dvourozměrného pole pomocí výstupních parametrů:
- pocetRadku - počet řádků matice
- pocetSloupcu - počet sloupců matice
- minHodnota - přípustná minimální hodnota (dolní mez) prvků matice
- maxHodnota - přípustná maximální hodnota (horní mez) prvků matice
- pole - dvourozměrné pole, tj. matice
Po provedení inicializace všech vyjmenovaných atributů matice jsou vypsány nastavené hodnoty atributů matice. Každý atribut je vypsán na novém řádku pomocí vložení řídícího znaku \n do textového řetězce. Jak si můžete všimnout, ve výpisu jsme také pro přechod na druhý řádek využili volání vlastnosti NewLine třídy Environment (třída je podtřídou třídy System). V dalším kroku poskytneme uživateli možnost změnit atributy matice. Tuto možnost provedeme na základě použití cyklu s podmínkou na konci, tzn. že uživatel má možnost měnit různé atributy matice. Pokud zvolil možnost změny atributu, je načten index atribut pomocí něhož je ve vícenásobném větvení (příkaz switch) volána příslušná metoda pro změnu atributu. Index atribut je pomocí cyklu s podmínkou na konci validován zda jeho hodnota náleží povolenému intervalu hodnot celých čísel od 0 do 3.
První možnou volanou metodou pro změnu velikosti dvourozměrné pole pro každou osu, je metoda RozmerPole. Tato metoda s celočíselným návratem určuje velikost v dané ose matice. Metoda přijímá tři parametry - stávající počet prvků matice v dané ose, maximální přípustnou hranicí velikosti pole v ose, tj. Max a jako poslední parametr je předán text, který je použit ve výzvách pro zadání velikosti pole ve vybrané ose (jedná se buď o řádky, nebo o sloupce).
V případě, že hodnota uložená v proměnné atribut je rovna 0, bude návrat volané metody uložen do proměnné pocetRadku, tzn. bude určen počet řádků matice.
Pokud je index atribut roven 1, bude pomocí metody RozmerPole navrácen počet sloupců, který bude uložen do proměnné pocetSloupcu.
Pro specifikaci dolní meze, tj. minimální hodnoty, které může prvek matice nabýt, využijeme volání metody DolniMez, jejíž celočíselný výstup uložíme do proměnné minHodnota. Tento krok je proveden, pokud index atribut je roven 2.
Naproti tomu horní mez je uložena v proměnné maxHodnota, jejíž hodnota je návratem volané metody HorniMez, pokud index atribut je roven 3.
Pokud uživatel již nechce měnit žádný z atributů matice, je vytvořeno dvourozměrné pole pomocí implicitního konstruktoru na základě zadaných atributů týkajících se velikosti pole v každé ose, tj. počtu řádků a sloupců.
/// <summary> /// Metoda pro incializaci a změnu atributů pole /// </summary> static void Inicializace(int Max, out int minHodnota, out int maxHodnota, out int pocetRadku, out int pocetSloupcu, out int[,] pole) { // Dolní mez, které může nabýt prvek matice minHodnota = 1; // Horní mez, které může nabýt prvek matice maxHodnota = 100; // Počet řádků je roven horní mezi přípustného počtu řádků pocetRadku = Max; // Počet sloupců je roven horní mezi přípustného počtu sloupců pocetSloupcu = Max; // Výpis stávajících atributů matice Console.WriteLine("Matice je nastavena:" + Environment.NewLine + " Počet řádků: {0} \n Počet sloupců: {1} \n Dolní mez: {2} \n Horní mez: {3}", pocetRadku, pocetSloupcu, minHodnota, maxHodnota); // Index pro změnu atributů matice int zmena; do { // Výzva ke změně atributů matice Console.Write("Změnit nastavení atributů matice? (0...Ne, 1...Ano): "); // Načtení hodnoty, zda má dojít ke změně int.TryParse(Console.ReadLine(), out zmena); // Pokud má být atribut matice změněn, pak prováděj... while (zmena == 1) { // Index atributu ke změně int atribut; do { // Výzva k zadání indexu změny atributu matice Console.Write("Zvolte změnu atributu matice " + "(0...Počet řádků, 1...Počet sloupců, 2...Dolní mez, 3...Horní mez): "); // Načtení indexu změny atributu int.TryParse(Console.ReadLine(), out atribut); } /* Načtení indexu změny atributu matice proběhne znovu, pokud nebyl * zadán validní index změny atributu */ while ((atribut != 0) && (atribut != 1) && (atribut != 2) && (atribut != 3)); // Přepnutí do změny příslušného atributu matice switch (atribut) { // Změna počtu řádků matice case 0: // Zavolání metody s celočíselným návratem pro změnu počtu řádků pocetRadku = RozmerPole(pocetRadku, Max, "řádků"); break; // Změna počtu sloupců matice case 1: // Zavolání metody s celočíselným návratem pro změnu počtu sloupců pocetSloupcu = RozmerPole(pocetSloupcu, Max, "sloupců"); break; // Změna dolní meze prvků matice case 2: /* Zavolání metody s celočíselný návratem pro změnu dolní meze, které * mohou nabývat prvky matice */ minHodnota = DolniMez(minHodnota, maxHodnota); break; // Změna horní meze prvků matice case 3: /* Zavolání metody s celočíselným návratem pro změnu horní meze, které * mohou nabývat prvky matice */ maxHodnota = HorniMez(minHodnota, maxHodnota); break; } // Výzva ke změně atributů matice Console.Write("Změnit další nastavení atributů matice? (0...Ne, 1...Ano): "); // Načtení hodnoty, zda má dojít k další změně int.TryParse(Console.ReadLine(), out zmena); } } // Pokud načtená hodnota nebyla validní, cyklus zadání je znovu opakován while ((zmena < 0) || (zmena > 1)); // Deklarace a vytvoření instance matice se zadanými rozměry (počtem prvků pro každou osu) pole = new int[pocetRadku, pocetSloupcu]; }
Kód 1: Deklarace statické metody bez návratu s názvem Incializace
3.2. Rozměr pole
Další metodou umístěnou v regionu Nastavení atributů pole, která navrací uživatelem definovanou velikost pole je metoda RozmerPole - viz Kód 1. Tato metoda může být volána v metodě Inicializace. Metoda přijímá stávající počet prvků v ose, který je uložen do formálního parametru velikost. Dalším formálním parametrem je konstanta Max. Třetím parametrem je text, který určuje, zda uživatel nastavuje počet řádků, nebo počet sloupců matice. V aplikaci Flowgorithm nelze deklarovat konstantu, proto jsme v hlavní metodě pojmenovali konstantu velkým písmenem, abychom ji rozeznali od jiné proměnné, nebo parametru. V metodě jsou deklarována proměnná s názvem novaHodnota, která představuje uživatelem zadanou hodnotu představující novou velikost matice v ose.
Po vypsání stávajícího počtu prvků matice ve vybrané ose (záleží, zda jsme předali z metody Inicializace skutečný parametr pocetRadku, představující počet řádků - vertikální osa, nebo parametr pocetSloupcu reprezentující počet sloupců - horizontální osa) - viz Obrázek 1.

Obrázek 1: Velikost dvourozměrného pole ve vybraných osách
Aby uživatel rozeznal který rozměr matice právě nastavuje, je do třetího parametru z hlavní metody předán text ve formě: "řádků", nebo "sloupců". Tento text je vypsán ve výzvě k určení velikosti pole v ose.
Před načtením nové hodnoty určující počet prvků v ose matice do proměnné novaHodnota je ve výpisu uvedena dolní (1) a horní mez (Max) povoleného celočíselného intervalu, ve kterém se nová hodnota velikosti matice musí pohybovat. Pokud načtená hodnota neodpovídá intervalu, je do proměnné novaHodnota uložena maximální přípustná velikost matice v ose uložená v konstantě Max. Pokud nová hodnota neodpovídá stávající hodnotě velikosti v ose matice uložené v proměnné velikost, je do proměnné velikost přiřazena nově načtená hodnota. Tato proměnná velikost je následně přiřazena návratu metody - viz Kód 1.
/// <summary> /// Metoda s celočíselným návratem - navrací velikost pole v ose /// </summary> /// <param name="velikost"> aktuální velikost matice v ose </param> /// <param name="max"> maximální velikost matice v ose </param> /// <returns> Velikost matice v ose </returns> static int RozmerPole(int velikost, int max, string text) { // Deklarace: 'novaHodnota' ... nová velikost matice v ose int novaHodnota; // Vypsání stávající velikosti matice v ose Console.WriteLine("Stávající počet " + text + " matice {0}:", velikost); // Výzva k zadání velikosti matice v ose Console.Write("Zadejte počet " + text + " matice (1 - {0}): ", max); // Načtení velikosti matice int.TryParse(Console.ReadLine(), out novaHodnota); // Pokud nová hodnota je větší než maximum, nebo menší než 1 ... if ((novaHodnota > max) || (novaHodnota < 1)) { /* Přiřazení maximální velikosti matice do lokální proměnné určující * velikost matice v ose */ novaHodnota = max; // Vypsání nové velikosti matice v ose Console.WriteLine("Redukce počtu " + text + " matice: {0}", novaHodnota); } // Pokud nová velikost matice není stejná jako stávající velikost v ose ... if (novaHodnota != velikost) { // Uložení nové velikosti matice do proměnné velikost = novaHodnota; } // Návrat metody return velikost; }
Kód 1: Deklarace statické metody s celočíselným návratem s názvem RozmerPole
3.3. Dolní a horní mez prvků
Dalšími deklarovanými metodami v regionu Nastavení atributů pole jsou statické metody s celočíselným návratem DolniMez a HorniMez. Metody mohou být volány ve statické metodě Inicializace. Pomocí těchto metod může uživatel nastavit dolní a horní mez prvků matice, tj. minimální a maximální hodnotu, které mohou prvky matice nabývat - viz Obrázek 1.

Obrázek 1: Naplněné dvourozměrné pole - dolní a horní mez prvků matice
Metody DolniMez a HorniMez využívají dva formální parametry:
- minHodnota - představuje hodnotu stávající dolní meze prvků matice
- maxHodnota - představuje hodnotu stávající horní meze prvků matice
/// <summary> /// Metoda s celočíselným návratem - návrat dolní meze pro všechny prvky matice /// </summary> /// <param name="minHodnota"> dolní mez prvků matice </param> /// <param name="maxHodnota"> horní mez prvků matice </param> /// <returns> Dolní mez pro všechny prvky matice </returns> public static int DolniMez(int minHodnota, int maxHodnota) { // Deklarace: 'novaHodnota' ... nová dolní mez prvků matice int novaHodnota; // Výpis stávající hodnoty dolní meze Console.WriteLine("Dolní mez prvků pole: {0} (horní mez = {1})", minHodnota, maxHodnota); // Výzva k zadání nové dolní meze prvků matice Console.Write("Zadejte dolní mez prvků pole: "); // Načtení nové dolní meze prvků matice int.TryParse(Console.ReadLine(), out novaHodnota); // Pokud nová hodnota dolní meze je větší než horní mez, pak... if (novaHodnota > maxHodnota) { // Přiřazení horní meze do lokální proměnné určující dolní mez (horní a dolní mez budou stejné) novaHodnota = maxHodnota; // Výpis nové redukované dolní meze pro prvky matice Console.WriteLine("Redukce dolní meze prvků pole: {0}", novaHodnota); } // Pokud nová dolní mez prvků matice není stejná jako stávající dolní mez prvků matice, pak... if (novaHodnota != minHodnota) { // Přepsání stávající dolní meze prvků matice novou hodnotou minHodnota = novaHodnota; } // Návrat metody return minHodnota; }
Kód 1: Deklarace statické metody s celočíselným návratem s názvem DolniMez
Následující zdrojový kód obsahuje deklaraci metody s celočíselným návratem HorniMez - viz Kód 2. Tato metoda umožňuje uživateli nastavit horní mez pro hodnoty prvků celočíselné matice. Princip metody je téměř totožný s předcházející metodou DolniMez.
/// <summary> /// Metoda s celočíselným návratem - návrat horní meze pro všechny prvky matice /// </summary> /// <param name="minHodnota"> dolní mez prvků matice </param> /// <param name="maxHodnota"> horní mez prvků matice </param> /// <returns> Horní mez pro všechny prvky matice </returns> static int HorniMez(int minHodnota, int maxHodnota) { // Deklarace: 'novaHodnota' ... nová horní mez prvků matice int novaHodnota; // Výpis stávající hodnoty horní meze Console.WriteLine("Horní mez prvků pole: {0} (dolní mez = {1})", maxHodnota, minHodnota); // Výzva k zadání nové horní meze prvků matice Console.Write("Zadejte horní mez prvků pole: "); // Načtení nové horní meze prvků matice int.TryParse(Console.ReadLine(), out novaHodnota); // Pokud nová hodnota horní meze je menší než dolní mez, pak... if (novaHodnota < minHodnota) { // Přiřazení dolní meze do lokální proměnné určující horní mez (horní a dolní mez budou stejné) novaHodnota = minHodnota; // Výpis nové redukované horní meze pro prvky matice Console.WriteLine("Redukce horní meze prvků pole: {0}", novaHodnota); } // Pokud nová horní mez prvků matice není stejná jako stávající horní mez prvků matice, pak... if (novaHodnota != maxHodnota) { // Přepsání stávající horní meze prvků matice novou hodnotou maxHodnota = novaHodnota; } // Návrat metody return maxHodnota; }
Kód 2: Deklarace statické metody s celočíselným návratem s názvem HorniMez
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
3.5. Zobrazení pole
V předchozí metodě PlnitJednotlive jsme volali různé metody pro plnění dvourozměrného pole - matice. Pro zobrazení naplněné matice budeme deklarovat metodu s textovým návratem s názvem PoleJakoText, kterou umístíme do regionu Zobrazení pole - viz Kód 1. Tuto metodu budeme využívat pro výpis prvků matice, kde jednotlivé prvky jsou od sebe odděleny čárkami (kvůli lepší čitelnosti). Metoda přijímá tři parametry, kde první celočíselný parametr představuje aktuální počet řádků matice, druhý parametr představuje počet sloupců matice a poslední třetí parametr je matice, kterou budeme vypisovat. Metoda využívá následující lokální proměnné:
- i - index řádku matice v němž je uložen prvek, který má být vypsán (deklarován přímo v cyklu)
- j - index sloupce matice v němž je uložen prvek, který má být vypsán (deklarován přímo v cyklu)
- vystup - výstupní textový řetězec obsahující prvky řádku oddělené čárkou
Po nezbytné deklaraci proměnných je provedena inicializace výstupního textového řetězce vystup prázdným textem.
Pro procházení jednotlivých prvků uvnitř matice jsou použit dva cykly s krokem. Vnější cyklus s rozhodovací proměnnou i (proměnná je deklarována přímo v cyklu) zajistí procházení všech řádků matice. Druhý vnitřní (vnořený) cyklus zajistí procházení všech sloupců matice. V těle vnitřního cyklu budeme do výsledného textového řetězce připojovat (pomocí operátoru +=) hodnotu jednotlivých prvků na pozici, která je určena pomocí indexu řádku a sloupce v hranaté závorce. Konverzi celočíselné hodnoty prvku provedeme pomocí metody Format datového typu (třídy) string a využijeme u převáděného hodnoty formátovou specifikaci D3, tj. tři číslice. Do výsledného textového řetězce za každý prvek umístíme čárku. Pro provedení zápisu všech prvků v řádku do proměnné vystup připojíme nový řádek pomocí vlastnosti NewLine třídy Environment (jedná se o systémovou třídu System.Environment). Další možností jak vložit řádek je např. vložení řídícího znaku \n , nebo pomocí stejného znaku v Unicode \u000A.
/// <summary> /// Prvky v sloupcích matice jsou převedeny na text a odděleny čárkou, kde každá řádka /// matice je umístěna na novém řádku ve výstupním textovém řetězci /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> matice </param> /// <returns> výstupní textový řetezec s prvky matice </returns> static string PoleJakoText(int m, int n, int[,] pole) { /* Lokální proměnná: 'vystup' - výsledek převodu na text - inicializace * a vložení nového řádku */ string vystup = ""; // Procházení řádků matice for (int i = 0; i < m; i++) { // Procházení sloupců matice for (int j = 0; j < n; j++) { // Převod hodnoty prvku na text včetně připojení čárky vystup += string.Format("{0:D3}, ", pole[i, j]); } // Přidání odstavce na konci každého řádku (také možnost vložení "\n") vystup += Environment.NewLine; } // Návrat výsledného textového řetězce return vystup; }
Kód 1: Deklarace statické metody s textovým návratem s názvem PoleJakoText
Další deklarovanou metodou v regionu Zobrazení pole je metoda bez návratu s názvem ZobrazitPole - viz Kód 2. V metodě v příkazu výpisu využijeme volání předchozí deklarované metody PoleJakoText, která navrátí textový řetězec se všemi prvky matice.
/// <summary> /// Volání metody pro výpis prvků matice do textového řetězce /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> vypisovaná matice </param> static void ZobrazitPole(int m, int n, int[,] pole) { // Zavolání metody pro výpis matice do textového řetězce Console.Write(PoleJakoText(m, n, pole)); }
Kód 2: Deklarace statické metody bez návratu s názvem ZobrazitPole
3.6. Minimum a maximum pole
Nalezení nejmenší, nebo největší hodnoty (minima, nebo maxima) v dvourozměrném poli je založené na stejném principu, jako hledání těchto prvků v jednorozměrném poli. Mějme např. čtvercovou matici s názvem pole o rozměrech m x n, tj. 3 x 3 (matice je symetrická, tzn. m = n) a v níž chceme nalézt minimum (prvek označen zelenou barvou) a maximum (prvek je označen modrou barvou) - viz Obrázek 1. Abychom nalezli minimum, je zapotřebí nejprve přiřadit minimu počáteční hodnotu. V našem případě minimu přiřadíme hodnotu počátečního prvku matice (tj. prvek, jehož oba indexy jsou rovny nule).

Obrázek 1: Minimum a maximum dvourozměrného pole
Pro procházení všech prvků matice použijeme dva cykly s krokem. První vnější cyklus pro procházení jednotlivých řádků matice a druhý vnitřní cyklus pro procházení sloupců matice. Každý prvek pak porovnáváme s dosud nejlepším nalezeným prvkem (v případě minima s nejmenší nalezenou hodnotou a v případě maxima s největší nalezenou hodnotou). Toto porovnání tedy proběhne celkem m*n-krát - viz Obrázek 2. Samozřejmě je také možné procházet prvky opačným směrem, tj. od posledního prvku směrem k počátečnímu prvku a porovnávat tyto prvky s minimem, nebo maximem.

Obrázek 2: Hledání minima dvourozměrného pole
Zkusme si popsat metodu MinimumVPoli umístěnou v regionu Operace s polem. Tato metoda navrací minimum matice - viz Kód 1. Tato metoda přijímá tři vstupní parametry - první definuje počet řádků matice, druhý počet sloupců matice a do třetího parametru je uložena matice, ve které hledáme nejmenší hodnotu. Dále metoda obsahuje výstupní parametry indexRadku a indexSloupce. První výstupní parametr naplněný v metodě představuje index řádku nalezeného minima matice. Druhý výstupní parametr představuje index sloupce nalezeného minima matice. V metodě jsou deklarovány následující proměnné:
- minimum - nalezená minimální hodnota v matici
- i - index řádku matice, ve které se nachází prvek (deklarace přímo v cyklu)
- j - index sloupce matice, ve které se nachází prvek (deklarace přímo v cyklu)
Jako první krok je zapotřebí přiřadit proměnné minimum hodnotu počátečního prvku matice. V dalším kroku je nastavena pozice, která zahrnuje index řádku a sloupce minima. Vzhledem k tomu, že jsme počáteční prvek prohlásili minimem, nastavíme index řádku a sloupce minima na hodnotu 0. Následně pro procházení dalších prvků využijeme dva cykly s krokem (první pro procházení řádků a vnitřní pro procházení sloupců matice), pomocí kterých budeme procházet jednotlivé prvky matice.
Je vhodné podotknout, že bychom nemuseli předávat parametry vyjadřující rozměry pole v každé ose, tj. počet řádků, nebo počet sloupců. Namísto toho bychom mohli předat pouze matici. Ve třídě pro pole je totiž implementována metoda GetUpperBound. Tato metoda přidružená k poli, která lze vyvolat pomocí tečkové notace, tj. pole.GetUpperBound, navrací velikost pole pro jednotlivé osy. Index osy je předán jako parametr (v případě dvourozměrného pole jsou osy dvě - vertikální - řádky, tj. index 0 a horizontální - sloupce, tj. index 1).
Uvnitř vnitřního cyklu je provedeno porovnání hodnoty aktuálního prvku s dosud nalezeným minimem. Pokud je nalezen prvek, jehož hodnota je menší než minimum, je tato hodnota prohlášena novým minimem, tj. hodnota prvku je přiřazena do proměnné minimum. Musí být také zaznamenán index řádku minima do výstupního parametru indexRadku (tj. indexRadku = i;). V dalším příkazu je zaznamenán index sloupce minima do výstupního parametru indexSloupce (indexSloupce = j;). Návratu metody je přiřazeno nalezené minimum ze všech prvků matice - viz Kód 1.
/// <summary> /// Návrat hodnoty minima matice - nejmenší prvek /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> prohledávaná matice </param> /// <param name="indexRadku"> index řádku minima </param> /// <param name="indexSloupce"> index sloupce minima </param> /// <returns> Minimum matice </returns> static int MinimumVPoli(int m, int n, int[,] pole, out int indexRadku, out int indexSloupce) { /* Deklarace: 'minimum' ... nalezená minimální hodnota v matici; 'i' ... index řádku * matice; 'j' ... index sloupce matice */ int minimum; // Hodnotu počátečního prvku prohlásíme minimem minimum = pole[0, 0]; // Přiřazení hodnoty 0 do indexu řádku minima indexRadku = 0; // Přiřazení hodnoty 0 do indexu sloupce minima indexSloupce = 0; // Pro všechny řádky matice for (int i = 0; i < m; i++) { // Pro všechny sloupce matice for (int j = 0; j < n; j++) { // Pokud je aktuálně procházený prvek menší než minimum, pak... if (pole[i, j] < minimum) { // Uložené aktuálního prvku do minima minimum = pole[i, j]; // Přiřazení indexu aktuálního řádku do indexu řádku minima indexRadku = i; //přiřazení indexu aktuálního sloupce do indexu sloupce minima indexSloupce = j; } } } // Přiřazení minima návratu metody return minimum; }
Kód 1: Deklarace statické metody s celočíselným návratem s názvem MinimumVPoli
Stejnou podstatu používá metoda MaximumVPoli, která však porovnává všechny prvky s dosud nejvyšší nalezenou hodnotu v matici uloženou do proměnné s názvem maximum - viz Kód 2. Pokud je aktuálně procházený prvek větší, než dosud nalezené maximum, pak přiřadíme tuto hodnotu do maxima.
/// <summary> /// Návrat hodnoty maxima matice - největší prvek /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> prohledávaná matice </param> /// <param name="indexRadku"> index řádku maxima </param> /// <param name="indexSloupce"> index sloupce maxima </param> /// <returns> Maximum matice </returns> static int MaximumVPoli(int m, int n, int[,] pole, out int indexRadku, out int indexSloupce) { /* Deklarace: 'maximum' ... nalezená maximální hodnota v matici; 'i' ... index řádku *matice; 'j'... index sloupce matice */ int maximum; // Hodnotu prvního prvku prohlásíme maximem maximum = pole[0, 0]; // Přiřazení hodnoty 0 do indexu řádku maxima indexRadku = 0; // Přiřazení hodnoty 0 do indexu sloupce maxima indexSloupce = 0; // Pro všechny řádky matice for (int i = 0; i < m; i++) { // Pro všechny sloupce matice for (int j = 0; j < n; j++) { // Pokud je aktuálně procházený prvek menší než maximum, pak... if (pole[i, j] > maximum) { // Uložené aktuálního prvku do maxima maximum = pole[i, j]; // Přiřazení indexu aktuálního řádku do indexu řádku maxima indexRadku = i; //přiřazení indexu aktuálního sloupce do indexu sloupce maxima indexSloupce = j; } } } // Přiřazení maxima návratu metody return maximum; }
Kód 2: Deklarace statické metody s celočíselným návratem s názvem MaximumVPoli
3.7. Průměr pole
Další aritmetickou operací prováděnou nad prvky dvourozměrného pole, je výpočet aritmetického průměru ze všech prvků pole. Na následujícím obrázku vidíme, že se jedná o součet hodnot všech prvků pole podělený celkovým počtem prvků v poli, tj. m x n - viz Obrázek 1.

Obrázek 1: Průměr prvků dvourozměrného pole
Metoda PrumerPole, která je deklarována v regionu Operace s polem, navrací reálné číslo reprezentující vypočtený průměr. Metoda pro výpočet potřebuje tři parametry ve formě počtu řádků a sloupců matice a také samotnou matici obsahující jednotlivé prvky. Ve funkci jsou deklarovány následující lokální proměnné:
- prumer - průměrná reálná hodnota ze všech prvků vektoru
- suma - suma hodnot všech prvků vektoru
- i - index řádku matice (deklarace přímo v cyklu)
- j - index sloupce matice (deklarace přímo v cyklu)
Počátečním krokem metody je inicializace lokální celočíselné proměnné suma, která nám slouží pro uložení součtu všech dosud procházených prvků. Pro průchod všemi prvky matice jsou použity dva cykly s krokem - první pro procházení řádků a druhý pro sloupce. Po ukončení průchodu všemi prvky matice je tato suma přetypována na reálné číslo (na typ double), abychom mohli provést podíl sumy a počtu prvků matice, který je vyjádřen součinem počtu řádků a sloupců matice (jinak bychom prováděli celočíselné dělení). Výsledek této operace je přiřazen výstupu metody - viz Kód 1.
/// <summary> /// Návrat aritmetického průměru prvků matice /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> matice </param> /// <returns> Průměr matice </returns> static double PrumerPole(int m, int n, int[,] pole) { /* Deklarace: 'prumer' ... průměrná reálná hodnota ze všech prvků matice; * 'suma' ... suma hodnot všech prvků matice; i' ... index řádku matice; * 'j' ... index sloupce matice */ double prumer; int suma; // Inicializace - suma prvků je 0 suma = 0; // Pro všechny řádky matice for (int i = 0; i < m; i++) { // Pro všechny sloupce matice for (int j = 0; j < n; j++) { // Přičtení dalšího prvku vektoru do sumy suma += pole[i, j]; } } // Výpočet reálného průměru včetně přetypování prumer = (double)suma / (m * n); // Přiřazení vypočteného průměru návratu metody return prumer; }
Kód 1: Deklarace statické metody s reálným návratem s názvem PrumerPole
3.8. Seřazení prvků pole
Pro seřazení prvků v jednotlivých řádcích naplněného dvourozměrného pole budeme, jako u předchozího jednorozměrného pole, využívat algoritmus bublinkového řazení (anglicky "Bubble Sort"). Algoritmus funguje na principu průchodů prvky v řádku matice (řádka ve své podstatě představuje vektor). Vždy jsou porovnávány dva prvky. U vzestupného řazení prvků řádku je testována podmínka, pokud je aktuální prvek větší než následující, dojde k prohození těchto prvků (jedná se o vzestupné řazení). Po každém průchodu se dostaneme do určité fáze seřazení. Řádek je seřazen, pokud při průchodu prvků řádku nedošlo k žádnému prohození prvků. Tímto způsobem seřadíme všechny řádky matice - viz Obrázek 1.

Obrázek 1: Bublinkové řazení prvků dvourozměrného pole
Následující obrázek ilustruje, jak prohodit dva prvky např. v počátečním řádku matice - viz Obrázek 2.

Obrázek 2: Prohození dvou prvků v řádku matice
Metoda SeraditPole, deklarovaná v regionu Operace s polem, je bez návratu. Metoda přijímá tři parametry - v prvním parametru je uložen počet řádků matice, druhý obsahuje počet sloupců matice a třetí parametr obsahuje matici, jejíž prvky v jednotlivých řádcích mají být seřazeny vzestupně - viz Kód 1. Metoda obsahuje následující lokální proměnné:
- pom - pomocná proměnná pro dočasné uložení prvku
- i - index řádku matice (deklarace přímo v cyklu)
- j - index sloupce matice (deklarace přímo v cyklu)
- b - logická proměnná obsahující informaci, zda došlo k prohození některých sousedních prvků (tj. zda je již řádek seřazen, pokud b == false)
Uvnitř metody jsou umístěny tři cykly. První vnější cyklus s krokem slouží pro procházení jednotlivých řádků matice. Další cyklus s podmínkou na konci, se stará o kontrolu, zda jsou již všechny prvky v řádku kompletně seřazeny. Před proběhnutím navazujícího vnitřního vnořeného cyklu s krokem pro průchod jednotlivých sloupců matice, v nichž jsou umístěny prvky, je zapotřebí provést nastavení proměnné b na hodnotu false, tj. b = false. Tím je řečeno, že ještě před proběhnutím porovnání dvojic prvků v řádku neproběhlo žádné prohození dvou sousedních prvků. Uvnitř těla třetího cyklu s krokem je potřeba vždy porovnávat dva sousední prvky. U řídící proměnné j třetího cyklu s krokem je potřeba se při procházení sloupců zastavit na předposledním sloupci (horní mez intervalu hodnot indexu řídící proměnné j), protože porovnáme pouze předposlední a poslední prvek v řádku. Pokud bychom nechali řídící proměnnou j cyklu zastavit až na posledním sloupci v řádku, porovnávali bychom uvnitř těla cyklu poslední prvek s dalším prvkem, který však neexistuje. Pokud je aktuálně procházený prvek při vzestupném řazení větší než následující prvek (s indexem o 1 větší), je zapotřebí tyto prvky prohodit na základě principu, který jsme již probírali v předchozím textu. V opačném případě, není zapotřebí prvky prohazovat. Pokud došlo alespoň k jednomu vzájemnému prohození prvků, je do proměnné b přiřazena hodnota true a díky tomu bude v cyklu s podmínkou na konci provedena další iterace. V případě, že úvodní předpoklad (b == true) stále platí i na konci průchodu prvky v řádku, dojde k přechodu na nový řádek matice - viz Kód 1.
/// <summary> /// Vzestupné řazení prvků řádků matice /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> matice, kde prvky v každém řádku mají být setříděny vzestupně </param> static void SeraditPole(int m, int n, int[,] pole) { /* Deklarace: 'pom' ... pomocná proměnná pro dočasné uložení prvku; 'b' ... logická proměnná * obsahující informaci, zda došlo k prohození některých sousedních prvků; 'i' ... index řádku * matice; 'j' ... index sloupce matice */ int pom; bool b; // Pro všechny řádky matice for (int i = 0; i < m; i++) { // Opakuj tak dlouho u každé řádky, dokud bude docházet k prohození prvků do { // Nedošlo k prohození sousedních prvků b = false; // Pro všechny sloupce matice for (int j = 0; j < n - 1; j++) { /* Pokud je hodnota sousedícího prvku větší než hodnota aktuálně * testovaného prvku, pak... */ if (pole[i, j] > pole[i, j + 1]) { // Ulož hodnotu aktuálního prvku do pomocné proměnné pom = pole[i, j]; // Ulož hodnotu sousedícího prvku do aktuálního prvku pole[i, j] = pole[i, j + 1]; // Ulož hodnotu z pomocné proměnné do sousedícího prvku pole[i, j + 1] = pom; // Došlo k prohození sousedních prvků b = true; } } } // Testování, zda došlo k prohození některých sousedních prvků while (b == true); } }
Kód 1: Deklarace statické metody bez návratu s názvem SeraditPole
3.9. Transpozice
Pokud je matice symetrická , označujeme úhlopříčnou spojnici protilehlých míst (počátečního prvku a posledního prvku matice) jako hlavní diagonálu. Pro prvky na hlavní diagonále platí, že jejich index řádku je roven indexu sloupce , tj. Pro případ matice o rozměru např. 3 x 3 jsou prvky umístěné na hlavní diagonále označeny zeleně - viz Obrázek 1.

Obrázek 1: Prvky na hlavní diagonále ve dvourozměrném poli
Transpozice prvků podle hlavní diagonály znamená prohození osově souměrných prvků, kde osu otáčení představuje hlavní diagonála - viz Obrázek 2.

Obrázek 2: Transpozice prvků podle hlavní diagonály ve dvourozměrném poli
Abychom prohodili jednotlivé prvky podle hlavní diagonály, stačí nám pouze procházet jednotlivé prvky v oranžové oblasti, které jsou umístěny nad hlavní diagonálou (pokud bychom také procházeli i prvky pod hlavní diagonálou, znovu bychom prohazovali nazpátek již jednou prohozené prvky a matice by zůstala nezměněna) - viz Obrázek 3. Prvky na hlavní diagonále není zapotřebí prohazovat.

Obrázek 3: Průchod prvky nad hlavní diagonálou ve dvourozměrném poli při transpozici prvků podle hlavní diagonály
V následující metodě bez výstupu s názvem HlavniTranspozice, která je také umístěna v regionu Operace s polem, je zachycena podstata transpozice prvků podle hlavní diagonály. Metoda přijímá tři parametry: počet řádků, počet sloupců matice a matici, jejíž prvky chceme transponovat podle hlavní diagonály. Dále metoda obsahuje tři proměnné:
- pom - pomocná proměnná pro přesun osově souměrných prvků matice podle hlavní diagonály
- i - index řádku matice aktuálně procházeného prvku (deklarace přímo v cyklu)
- j - index sloupce matice aktuálně procházeného prvku (deklarace přímo v cyklu)
První rozhodovací příkaz zajišťuje, že pokud počet řádků není roven počtu sloupců (nejedná se o symetrickou matici), je metoda ukončena včetně výpisu varovného hlášení. Pokud je matice symetrická, využijeme pro procházení jednotlivých prvků nad hlavní diagonálou dva cykly s krokem. První vnější cyklus bude probíhat od prvního do předposledního řádku matice. Jedná se totiž o oranžovou oblast prvků nad hlavní diagonálou. Pro procházení sloupců v jednotlivých řádcích matice slouží další vnitřní cyklus s krokem. Jak si můžeme všimnout, je zapotřebí procházet pouze ty prvky, jejichž index sloupce je o 1 vyšší, než index řádku aktuálně procházeného prvku (do průchodu chceme zahrnout pouze oranžovou oblast). V těle cyklu provádíme vzájemné prohození prvků pomocí uložení hodnoty prvků z oranžové oblasti do pomocné proměnné. Tento princip jsme již využili dříve, např. při vzestupném řazení prvků v řádcích pomocí metody Bubble Sort. Prvek v oranžové oblasti je přepsán osově souměrným prvkem podle hlavní diagonály umístěným pod hlavní diagonálou pomocí příkazu pole[i, j] = pole[j, i];. Do osově souměrného prvku pod hlavní diagonálou je následně uložena hodnota z pomocné proměnné.
/// <summary> /// Transpozice prvků matice podle hlavní diagonály /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> matice, kde jsou prvky otočeny podle hlavní diagonály </param> static void HlavniTranspozice(int m, int n, int[,] pole) { /* Deklarace: 'pom' ... pomocná proměnná pro přesun osově souměrných prvků matice podle * hlavní diagonály; 'i' ... index řádku matice; 'j' ... index sloupce matice */ int pom; // Pokud počet řádek není roven počtu sloupců (matice není symetrická), pak... if (m != n) { // Výpis varovného upozornění Console.WriteLine("Nelze transponovat obdélníkovou matici"); // Ukončení metody return; } // Jinak ... else { // Od počátečního až předposledního řádku matice for (int i = 0; i < m - 1; i++) { // Od i + 1-tého sloupce do posledního sloupce matice for (int j = i + 1; j < m; j++) { // Uložení aktuálního prvku matice na pozici [i,j] do pomocné proměnné pom = pole[i, j]; /* Přepsání aktuálního prvku matice na pozici [i,j] osově souměrným prvkem * podle hlavní diagonály, tj. na pozici [j,i] */ pole[i, j] = pole[j, i]; /* Přepsání osově souměrného prvku na pozici [j,i] prvkem uloženým * v pomocné proměnné */ pole[j, i] = pom; } } } }
Kód 1: Deklarace statické metody bez návratu s názvem HlavniTranspozice
Pokud je matice symetrická označujeme protilehlou úhlopříčnou spojnici protilehlých míst (posledního prvku prvního řádku a prvního prvku posledního řádku) jako vedlejší diagonálu. Pro prvky na vedlejší diagonále platí, že jejich index řádku i je roven indexu sloupce pokud . Pro případ matice o rozměru 3 x 3 jsou prvky umístěné na vedlejší diagonále označeny modře - viz Obrázek 4.

Obrázek 4: Prvky na vedlejší diagonále ve dvourozměrném poli
Transpozice prvků podle vedlejší diagonály znamená prohození osově souměrných prvků, kde osu otáčení představuje vedlejší diagonála - viz Obrázek 5.

Obrázek 2: Transpozice prvků podle vedlejší diagonály ve dvourozměrném poli
V následující metodě bez výstupu s názvem VedlejšíTranspozice je zachycena podstata transpozice prvků podle vedlejší diagonály - viz Kód 2. Metoda přijímá tři parametry: počet řádku, počet sloupců matice a matici, jejíž prvky chceme transponovat. Dále metoda obsahuje tři proměnné:
- pom - pomocná proměnná pro přesun osově souměrných prvků matice podle vedlejší diagonály
- i - index řádku matice aktuálně procházeného prvku (deklarace přímo v cyklu)
- j - index sloupce matice aktuálně procházeného prvku (deklarace přímo v cyklu)
První rozhodovací příkaz zajišťuje, že pokud počet řádků není roven počtu sloupců (nejedná se o symetrickou matici), je metoda ukončena včetně výpisu varovného hlášení. Pokud je matice symetrická, využijeme pro procházení jednotlivých prvků nad vedlejší diagonálou dva cykly s krokem. První vnější cyklus bude probíhat od prvního do předposledního řádku matice. Jedná se totiž o oranžovou oblast prvků nad vedlejší diagonálou. Pro procházení sloupců v jednotlivých řádcích matice slouží další vnitřní cyklus s krokem. Jak si můžeme všimnout, je zapotřebí procházet pouze ty prvky, jejichž index sloupce je menší než rozdíl počtu řádků a indexu řádku aktuálně procházeného prvku (do průchodu chceme zahrnout pouze oranžovou oblast). Matice je symetrická m = n, takže nezáleží zda menšenec představuje počet řádků, nebo počet sloupců. V těle cyklu provádíme vzájemné prohození prvků pomocí uložení hodnoty prvků z oranžové oblasti do pomocné proměnné. Prvek v oranžové oblasti na pozici [i, j] je přepsán osově souměrným prvkem podle vedlejší diagonály umístěným pod vedlejší diagonálou na pozici [m - j - 1, m - i - 1]. Do osově souměrného prvku pod vedlejší diagonálou je následně uložena hodnota z pomocné proměnné.
/// <summary> /// Transpozice prvků matice podle vedlejší diagonály /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> matice, kde jsou prvky otočeny podle vedlejší diagonály </param> static void VedlejsiTranspozice(int m, int n, int[,] pole) { /* Deklarace: 'pom' ... pomocná proměnná pro přesun osově souměrných prvků matice podle * vedlejší diagonály; 'i' ... index řádku matice; 'j' ... index sloupce matice */ int pom; // Pokud počet řádek není roven počtu sloupců (matice není symetrická), pak... if (m != n) { // Výpis varovného upozornění Console.WriteLine("Nelze transponovat obdélníkovou matici"); // Ukončení metody return; } // Jinak ... else { // Od počátečního až předposledního řádku matice for (int i = 0; i < m - 1; i++) { // Od i + 1-tého sloupce do posledního sloupce matice for (int j = 0; j < m - i; j++) { // Uložení aktuálního prvku matice na pozici [i,j] do pomocné proměnné pom = pole[i, j]; /* Přepsání aktuálního prvku matice na pozici [i,j] osově souměrným prvkem * podle vedlejší diagonály, tj. na pozici [m-j-1,m-i-1] */ pole[i, j] = pole[m - j - 1, m - i - 1]; /* Přepsání osově souměrného prvku na pozici [m-j-1, m-i-1] prvkem uloženým * v pomocné proměnné */ pole[m - j - 1, m - i - 1] = pom; } } } }
Kód 2: Deklarace statické metody bez návratu s názvem VedlejsiTranspozice
4. Výsledný kód
Následující zdrojový kód je kompletací předešlých kódů programu DvourozmernePole, 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 DvourozmernePole { class Program { static void Main(string[] args) { /* Deklarace: 'pocetRadku' ... počet řádků matice; 'pocetSloupcu' ... počet sloupců matice; * 'Max' ... konstantní hodnota maximální velikosti matice pro každou osu (pro 1. vertikální osu * představuje maximální počet řádků matice, pro 2. osu představuje maximální počet sloupců matice; * 'minHodnota' ... přípustná minimální hodnota (dolní mez) prvků matice; 'maxHodnota' ... přípustná * maximální hodnota (horní mez) prvků matice; 'poradiRadku' ... pořadí řádku prvku (využití pro * vyhledání minima a maxima matice); 'poradiSloupce' ... pořadí sloupce prvku */ // Maximální velikost matice pro každou osu, tj. řádky, nebo sloupce const int Max = 10; // Metoda pro inicializaci atributů matice a jejich případnou změnu Inicializace(Max, out int minHodnota, out int maxHodnota, out int pocetRadku, out int pocetSloupcu, out int[,] pole); /* Zavolání metody pro plnění matice (náhodnými čísly, jednotlivě zadanými hodnotami, * plnění nulami) */ PlnitPole(pocetRadku, pocetSloupcu, minHodnota, maxHodnota, pole); // Výpis matice po jednotlivých řádcích, kde jednotlivé prvky jsou odděleny čárkami Console.WriteLine("Výpis matice: "); ZobrazitPole(pocetRadku, pocetSloupcu, pole); // Výpis hodnoty minima matice, včetně jeho pozice v matici Console.WriteLine("Minimum v matici: {0} na pozici [{1},{2}] ", MinimumVPoli(pocetRadku, pocetSloupcu, pole, out int indexRadku, out int indexSloupce), indexRadku, indexSloupce); // Výpis hodnoty maxima matice, včetně jeho pozice v matici Console.WriteLine("Maximum v matici: {0} na pozici [{1},{2}] ", MaximumVPoli(pocetRadku, pocetSloupcu, pole, out indexRadku, out indexSloupce), indexRadku, indexSloupce); // Výpis průměru všech prvků matice Console.WriteLine("Průměr prvků matice: " + PrumerPole(pocetRadku, pocetSloupcu, pole)); // Vzestupné řazení prvků v jednotlivých řádcích matice podle metody Bubble Sort SeraditPole(pocetRadku, pocetSloupcu, pole); // Výpis seřazené matice Console.WriteLine("Seřazená matice: "); ZobrazitPole(pocetRadku, pocetSloupcu, pole); // Transpozice matice podle hlavní diagonály HlavniTranspozice(pocetRadku, pocetSloupcu, pole); // Výpis transponované matice podle hlavní diagonály Console.WriteLine("Transpozice matice podle hlavní diagonály: "); ZobrazitPole(pocetRadku, pocetSloupcu, pole); // Transpozice matice podle vedlejší diagonály VedlejsiTranspozice(pocetRadku, pocetSloupcu, pole); // Výpis transponované matice podle vedlejší diagonály Console.WriteLine("Transpozice matice podle vedlejší diagonály: "); ZobrazitPole(pocetRadku, pocetSloupcu, pole); // Čekání na stisk klávesy -> ukončení programu Console.ReadKey(); } #region Nastavení atributů pole /// <summary> /// Metoda pro inicializaci a změnu atributů pole /// </summary> static void Inicializace(int Max, out int minHodnota, out int maxHodnota, out int pocetRadku, out int pocetSloupcu, out int[,] pole) { // Dolní mez, které může nabýt prvek matice minHodnota = 1; // Horní mez, které může nabýt prvek matice maxHodnota = 100; // Počet řádků je roven horní mezi přípustného počtu řádků pocetRadku = Max; // Počet sloupců je roven horní mezi přípustného počtu sloupců pocetSloupcu = Max; // Výpis stávajících atributů matice Console.WriteLine("Matice je nastavena:" + Environment.NewLine + " Počet řádků: {0} \n Počet sloupců: {1} \n Dolní mez: {2} \n Horní mez: {3}", pocetRadku, pocetSloupcu, minHodnota, maxHodnota); // Index pro změnu atributů matice int zmena; do { // Výzva ke změně atributů matice Console.Write("Změnit nastavení atributů matice? (0...Ne, 1...Ano): "); // Načtení hodnoty, zda má dojít ke změně int.TryParse(Console.ReadLine(), out zmena); // Pokud má být atribut matice změněn, pak prováděj... while (zmena == 1) { // Index atributu ke změně int atribut; do { // Výzva k zadání indexu změny atributu matice Console.Write("Zvolte změnu atributu matice " + "(0...Počet řádků, 1...Počet sloupců, 2...Dolní mez, 3...Horní mez): "); // Načtení indexu změny atributu int.TryParse(Console.ReadLine(), out atribut); } /* Načtení indexu změny atributu matice proběhne znovu, pokud nebyl * zadán validní index změny atributu */ while ((atribut != 0) && (atribut != 1) && (atribut != 2) && (atribut != 3)); // Přepnutí do změny příslušného atributu matice switch (atribut) { // Změna počtu řádků matice case 0: // Zavolání metody s celočíselným návratem pro změnu počtu řádků pocetRadku = RozmerPole(pocetRadku, Max, "řádků"); break; // Změna počtu sloupců matice case 1: // Zavolání metody s celočíselným návratem pro změnu počtu sloupců pocetSloupcu = RozmerPole(pocetSloupcu, Max, "sloupců"); break; // Změna dolní meze prvků matice case 2: /* Zavolání metody s celočíselný návratem pro změnu dolní meze, které * mohou nabývat prvky matice */ minHodnota = DolniMez(minHodnota, maxHodnota); break; // Změna horní meze prvků matice case 3: /* Zavolání metody s celočíselným návratem pro změnu horní meze, které * mohou nabývat prvky matice */ maxHodnota = HorniMez(minHodnota, maxHodnota); break; } // Výzva ke změně atributů matice Console.Write("Změnit další nastavení atributů matice? (0...Ne, 1...Ano): "); // Načtení hodnoty, zda má dojít k další změně int.TryParse(Console.ReadLine(), out zmena); } } // Pokud načtená hodnota nebyla validní, cyklus zadání je znovu opakován while ((zmena < 0) || (zmena > 1)); // Deklarace a vytvoření instance matice se zadanými rozměry (počtem prvků pro každou osu) pole = new int[pocetRadku, pocetSloupcu]; } /// <summary> /// Metoda navracející velikost pole v ose /// </summary> /// <param name="velikost"> aktuální velikost matice v ose </param> /// <param name="max"> maximální velikost matice v ose </param> /// <returns> Velikost matice v ose </returns> static int RozmerPole(int velikost, int max, string text) { // Deklarace: 'novaHodnota' ... nová velikost matice v ose int novaHodnota; // Vypsání stávající velikosti matice v ose Console.WriteLine("Stávající počet " + text + " matice {0}:", velikost); // Výzva k zadání velikosti matice v ose Console.Write("Zadejte počet " + text + " matice (1 - {0}): ", max); // Načtení velikosti matice int.TryParse(Console.ReadLine(), out novaHodnota); // Pokud nová hodnota je větší než maximum, nebo menší než 1 ... if ((novaHodnota > max) || (novaHodnota < 1)) { /* Přiřazení maximální velikosti matice do lokální proměnné určující * velikost matice v ose */ novaHodnota = max; // Vypsání nové velikosti matice v ose Console.WriteLine("Redukce počtu " + text + " matice: {0}", novaHodnota); } // Pokud nová velikost matice není stejná jako stávající velikost v ose ... if (novaHodnota != velikost) { // Uložení nové velikosti matice do proměnné velikost = novaHodnota; } // Návrat metody return velikost; } /// <summary> /// Metoda navracející dolní mez intervalu přípustných hodnot prvků matice /// </summary> /// <param name="minHodnota"> dolní mez prvků matice </param> /// <param name="maxHodnota"> horní mez prvků matice </param> /// <returns> Dolní mez pro všechny prvky matice </returns> public static int DolniMez(int minHodnota, int maxHodnota) { // Deklarace: 'novaHodnota' ... nová dolní mez prvků matice int novaHodnota; // Výpis stávající hodnoty dolní meze Console.WriteLine("Dolní mez prvků pole: {0} (horní mez = {1})", minHodnota, maxHodnota); // Výzva k zadání nové dolní meze prvků matice Console.Write("Zadejte dolní mez prvků pole: "); // Načtení nové dolní meze prvků matice int.TryParse(Console.ReadLine(), out novaHodnota); // Pokud nová hodnota dolní meze je větší než horní mez, pak... if (novaHodnota > maxHodnota) { // Přiřazení horní meze do lokální proměnné určující dolní mez (horní a dolní mez budou stejné) novaHodnota = maxHodnota; // Výpis nové redukované dolní meze pro prvky matice Console.WriteLine("Redukce dolní meze prvků pole: {0}", novaHodnota); } // Pokud nová dolní mez prvků matice není stejná jako stávající dolní mez prvků matice, pak... if (novaHodnota != minHodnota) { // Přepsání stávající dolní meze prvků matice novou hodnotou minHodnota = novaHodnota; } // Návrat metody return minHodnota; } /// <summary> /// Metoda navracející horní mez intervalu přípustných hodnot prvků matice /// </summary> /// <param name="minHodnota"> dolní mez prvků matice </param> /// <param name="maxHodnota"> horní mez prvků matice </param> /// <returns> Horní mez pro všechny prvky matice </returns> static int HorniMez(int minHodnota, int maxHodnota) { // Deklarace: 'novaHodnota' ... nová horní mez prvků matice int novaHodnota; // Výpis stávající hodnoty horní meze Console.WriteLine("Horní mez prvků pole: {0} (dolní mez = {1})", maxHodnota, minHodnota); // Výzva k zadání nové horní meze prvků matice Console.Write("Zadejte horní mez prvků pole: "); // Načtení nové horní meze prvků matice int.TryParse(Console.ReadLine(), out novaHodnota); // Pokud nová hodnota horní meze je menší než dolní mez, pak... if (novaHodnota < minHodnota) { // Přiřazení dolní meze do lokální proměnné určující horní mez (horní a dolní mez budou stejné) novaHodnota = minHodnota; // Výpis nové redukované horní meze pro prvky matice Console.WriteLine("Redukce horní meze prvků pole: {0}", novaHodnota); } // Pokud nová horní mez prvků matice není stejná jako stávající horní mez prvků matice, pak... if (novaHodnota != maxHodnota) { // Přepsání stávající horní meze prvků matice novou hodnotou maxHodnota = novaHodnota; } // Návrat metody return maxHodnota; } #endregion Nastavení atributů pole #region Plnění pole /// <summary> /// Metoda volající některou z metod 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) { /* Deklarace: 'zpusobPlneni' ... způsob plnění matice('0'...Náhodně, '1'...Jednotlivě, * '2'...Nulovat) */ int zpusobPlneni; do { // Výzva k zadání způsobu plnění matice Console.Write("Zvolte způsob plnění pole (0...Náhodně, 1...Jednotlivě, 2...Nulovat): "); // Načtení způsobu plnění int.TryParse(Console.ReadLine(), out zpusobPlneni); } // 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) { // Plnění matice náhodnými čísly case 0: // Zavolání metody pro plnění matice náhodnými čísly NahodnePole(m, n, minHodnota, maxHodnota, pole); break; // Plnění matice jednotlivými zadanými hodnotami uživatelem case 1: // Volání metody pro plnění matice uživatelem zadanými čísly PlnitJednotlive(m, n, minHodnota, maxHodnota, pole); break; case 2: // Volání metody, kdy všem prvkům matice je přiřazena hodnotu nula NulovatPole(m, n, pole); break; } } /// <summary> /// Metoda pro 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) { /* Deklarace: 'rnd' ... náhodné číslo (generované na základě rovnoměrného rozdělení); * 'i' ... index řádku prvku matice, 'j' ... index sloupce prvku matice */ // Deklarace náhodného čísla (objektu) včetně inicializace Random rnd = new Random(); // Pro všechny řádky matice od '0' (počátečního) do 'm-1'-tého (posledního) řádku for (int i = 0; i < m; i++) { // Pro všechny sloupce matice od '0' (počátečního) do 'n-1'-tého (posledního) sloupce for (int j = 0; j < n; j++) /* 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 */ pole[i, j] = rnd.Next(minHodnota, maxHodnota + 1); } } /// <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) { // Informace, že předaná hodnota je validní bool validni = true; // Test, zda načtená hodnota je mimo interval povolených hodnot ... if ((hodnota < dolniMez) || (hodnota > horniMez)) { // Výpis o chybě Console.WriteLine("Zadaná hodnota je mimo povolené meze <{0}, {1}>", dolniMez, horniMez); // Hodnota není validní validni = false; } // Návrat metody return validni; } /// <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) { /* 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) */ int indexRadku, indexSloupce, hodnota; bool plnit; /* 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 */ do { // Výzva k zadání indexu řádku plněného prvku Console.Write("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 { // Výzva k zadání pořadového čísla sloupce plněného prvku Console.Write("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 { // Cyklus s podmínkou na konci - validace zadané hodnoty zda je hodnota mimo rozsah intervalu do { /* 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 */ Console.Write("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) { //zvýšení indexu sloupce o 1 indexSloupce++; } // Jinak ... else { // Pokud index řádku je menší než celkový počet řádků - 1, pak... if (indexRadku < m - 1) { // Zvýšení indexu řádku o 1 indexRadku++; // Přiřazení 0 do indexu sloupce indexSloupce = 0; } } } /* Podmínka cyklu, zda má být provedeno další načtení prvku. Pokud ano (hodnota 'true'), * opakovaní načtení hodnoty */ while (plnit == true); } /// <summary> /// Metoda pro 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) { /* Pro všechny řádky od počátečního do posledního řádku matice; * 'i' ... index (pozice) řádku matice */ for (int i = 0; i < m; i++) { // Pro všechny sloupce for (int j = 0; j < n; j++) { // Přiřazení nuly prvku na pozici [i,j] pole[i, j] = 0; } } } #endregion Plnění pole #region Zobrazení pole /// <summary> /// Prvky v sloupcích matice jsou převedeny na text a odděleny čárkou, kde každá řádka /// matice je umístěna na novém řádku ve výstupním textovém řetězci /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> matice </param> /// <returns> výstupní textový řetezec s prvky matice </returns> static string PoleJakoText(int m, int n, int[,] pole) { /* Lokální proměnná: 'vystup' - výsledek převodu na text - inicializace * a vložení nového řádku */ string vystup = ""; // Procházení řádků matice for (int i = 0; i < m; i++) { // Procházení sloupců matice for (int j = 0; j < n; j++) { // Převod hodnoty prvku na text včetně připojení čárky vystup += string.Format("{0:D3}, ", pole[i, j]); } // Přidání odstavce na konci každého řádku (také možnost vložení "\n") vystup += Environment.NewLine; } // Návrat výsledného textového řetězce return vystup; } /// <summary> /// Volání metody pro výpis prvků matice do textového řetězce /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> vypisovaná matice </param> static void ZobrazitPole(int m, int n, int[,] pole) { // Zavolání metody pro výpis matice do textového řetězce Console.Write(PoleJakoText(m, n, pole)); } #endregion Zobrazení pole #region Operace s polem /// <summary> /// Návrat hodnoty minima matice - nejmenší prvek /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> prohledávaná matice </param> /// <param name="indexRadku"> index řádku minima </param> /// <param name="indexSloupce"> index sloupce minima </param> /// <returns> Minimum matice </returns> static int MinimumVPoli(int m, int n, int[,] pole, out int indexRadku, out int indexSloupce) { /* Deklarace: 'minimum' ... nalezená minimální hodnota v matici; 'i' ... index řádku * matice; 'j' ... index sloupce matice */ int minimum; // Hodnotu počátečního prvku prohlásíme minimem minimum = pole[0, 0]; // Přiřazení hodnoty 0 do indexu řádku minima indexRadku = 0; // Přiřazení hodnoty 0 do indexu sloupce minima indexSloupce = 0; // Pro všechny řádky matice for (int i = 0; i < m; i++) { // Pro všechny sloupce matice for (int j = 0; j < n; j++) { // Pokud je aktuálně procházený prvek menší než minimum, pak... if (pole[i, j] < minimum) { // Uložené aktuálního prvku do minima minimum = pole[i, j]; // Přiřazení indexu aktuálního řádku do indexu řádku minima indexRadku = i; //přiřazení indexu aktuálního sloupce do indexu sloupce minima indexSloupce = j; } } } // Přiřazení minima návratu metody return minimum; } /// <summary> /// Návrat hodnoty maxima matice - největší prvek /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> prohledávaná matice </param> /// <param name="indexRadku"> index řádku maxima </param> /// <param name="indexSloupce"> index sloupce maxima </param> /// <returns> Maximum matice </returns> static int MaximumVPoli(int m, int n, int[,] pole, out int indexRadku, out int indexSloupce) { /* Deklarace: 'maximum' ... nalezená maximální hodnota v matici; 'i' ... index řádku *matice; 'j'... index sloupce matice */ int maximum; // Hodnotu prvního prvku prohlásíme maximem maximum = pole[0, 0]; // Přiřazení hodnoty 0 do indexu řádku maxima indexRadku = 0; // Přiřazení hodnoty 0 do indexu sloupce maxima indexSloupce = 0; // Pro všechny řádky matice for (int i = 0; i < m; i++) { // Pro všechny sloupce matice for (int j = 0; j < n; j++) { // Pokud je aktuálně procházený prvek menší než maximum, pak... if (pole[i, j] > maximum) { // Uložené aktuálního prvku do maxima maximum = pole[i, j]; // Přiřazení indexu aktuálního řádku do indexu řádku maxima indexRadku = i; //přiřazení indexu aktuálního sloupce do indexu sloupce maxima indexSloupce = j; } } } // Přiřazení maxima návratu metody return maximum; } /// <summary> /// Návrat aritmetického průměru prvků matice /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> matice </param> /// <returns> Průměr matice </returns> static double PrumerPole(int m, int n, int[,] pole) { /* Deklarace: 'prumer' ... průměrná reálná hodnota ze všech prvků matice; * 'suma' ... suma hodnot všech prvků matice; i' ... index řádku matice; * 'j' ... index sloupce matice */ double prumer; int suma; // Inicializace - suma prvků je 0 suma = 0; // Pro všechny řádky matice for (int i = 0; i < m; i++) { // Pro všechny sloupce matice for (int j = 0; j < n; j++) { // Přičtení dalšího prvku vektoru do sumy suma += pole[i, j]; } } // Výpočet reálného průměru včetně přetypování prumer = (double)suma / (m * n); // Přiřazení vypočteného průměru návratu metody return prumer; } /// <summary> /// Vzestupné řazení prvků řádků matice /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> matice, kde prvky v každém řádku mají být setříděny vzestupně </param> static void SeraditPole(int m, int n, int[,] pole) { /* Deklarace: 'pom' ... pomocná proměnná pro dočasné uložení prvku; 'b' ... logická proměnná * obsahující informaci, zda došlo k prohození některých sousedních prvků; 'i' ... index řádku * matice; 'j' ... index sloupce matice */ int pom; bool b; // Pro všechny řádky matice for (int i = 0; i < m; i++) { // Opakuj tak dlouho u každé řádky, dokud bude docházet k prohození prvků do { // Nedošlo k prohození sousedních prvků b = false; // Pro všechny sloupce matice for (int j = 0; j < n - 1; j++) { /* Pokud je hodnota sousedícího prvku větší než hodnota aktuálně * testovaného prvku, pak... */ if (pole[i, j] > pole[i, j + 1]) { // Ulož hodnotu aktuálního prvku do pomocné proměnné pom = pole[i, j]; // Ulož hodnotu sousedícího prvku do aktuálního prvku pole[i, j] = pole[i, j + 1]; // Ulož hodnotu z pomocné proměnné do sousedícího prvku pole[i, j + 1] = pom; // Došlo k prohození sousedních prvků b = true; } } } // Testování, zda došlo k prohození některých sousedních prvků while (b == true); } } /// <summary> /// Transpozice prvků matice podle hlavní diagonály /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> matice, kde jsou prvky otočeny podle hlavní diagonály </param> static void HlavniTranspozice(int m, int n, int[,] pole) { /* Deklarace: 'pom' ... pomocná proměnná pro přesun osově souměrných prvků matice podle * hlavní diagonály; 'i' ... index řádku matice; 'j' ... index sloupce matice */ int pom; // Pokud počet řádek není roven počtu sloupců (matice není symetrická), pak... if (m != n) { // Výpis varovného upozornění Console.WriteLine("Nelze transponovat obdélníkovou matici"); // Ukončení metody return; } // Jinak ... else { // Od počátečního až předposledního řádku matice for (int i = 0; i < m - 1; i++) { // Od i + 1-tého sloupce do posledního sloupce matice for (int j = i + 1; j < m; j++) { // Uložení aktuálního prvku matice na pozici [i,j] do pomocné proměnné pom = pole[i, j]; /* Přepsání aktuálního prvku matice na pozici [i,j] osově souměrným prvkem * podle hlavní diagonály, tj. na pozici [j,i] */ pole[i, j] = pole[j, i]; /* Přepsání osově souměrného prvku na pozici [j,i] prvkem uloženým * v pomocné proměnné */ pole[j, i] = pom; } } } } /// <summary> /// Transpozice prvků matice podle vedlejší diagonály /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> matice, kde jsou prvky otočeny podle vedlejší diagonály </param> static void VedlejsiTranspozice(int m, int n, int[,] pole) { /* Deklarace: 'pom' ... pomocná proměnná pro přesun osově souměrných prvků matice podle * vedlejší diagonály; 'i' ... index řádku matice; 'j' ... index sloupce matice */ int pom; // Pokud počet řádek není roven počtu sloupců (matice není symetrická), pak... if (m != n) { // Výpis varovného upozornění Console.WriteLine("Nelze transponovat obdélníkovou matici"); // Ukončení metody return; } // Jinak ... else { // Od počátečního až předposledního řádku matice for (int i = 0; i < m - 1; i++) { // Od i + 1-tého sloupce do posledního sloupce matice for (int j = 0; j < m - i; j++) { // Uložení aktuálního prvku matice na pozici [i,j] do pomocné proměnné pom = pole[i, j]; /* Přepsání aktuálního prvku matice na pozici [i,j] osově souměrným prvkem * podle vedlejší diagonály, tj. na pozici [m-j-1,m-i-1] */ pole[i, j] = pole[m - j - 1, m - i - 1]; /* Přepsání osově souměrného prvku na pozici [m-j-1, m-i-1] prvkem uloženým * v pomocné proměnné */ pole[m - j - 1, m - i - 1] = pom; } } } } #endregion Operace s polem } }
Kód 1: Program DvourozmernePole - deklarace hlavní statické metody Main včetně deklarací dalších metod
5. Výstup programu
Na následujících výstupech týkajících se programu DvourozmernePole (viz kapitola 2 Program - Kód 1: Program DvourozmernePole) budou zobrazeny jednotlivé výstupy konzolové aplikace pro různá nastavení atributů matice a případy plnění dvourozměrného pole včetně jednotlivých operací prováděných s prvky tohoto pole. Pro změnu jednotlivých atributů pole uživatel zvolí index 1 - viz Výstup programu 1. Pokud by uživatel bez zadání hodnoty číselného indexu operace, která má být provedena, stiskl klávesu Enter, je provedena operace s indexem 0, tzn. nemá být provedena žádná operace pro nastavení atributů pole. Index změny je totiž výstupní parametr a ten by nabyl v případě nemožnosti konverze přednastavené hodnoty pro příslušný datový typ, v tomto případě pro int je to 0.
Výstup programu 1 - Kód 1 (viz kapitola 4 Program DvourozmernePole): Změna atributů pole
V následujících výstupech programu budou pouze uváděny výřezy výstupů jednotlivých metod.
Rozměr pole
V následujícím výstupu programu DvourozmernePole vidíme změnu velikosti (rozměru) ve vertikální ose dvourozměrného pole reprezentující počet řádků matice - viz Výstup programu 2. Pro nastavení počtu řádků byla z metody Inicializace volána metoda RozmerPole. Tato metoda byla volána na základě uživatelem zadané hodnoty indexu příslušné operace, tj. 0 (uložené do výstupního parametru atribut).
Výstup programu 2 - Kód 1 (viz kapitola 4 Program DvourozmernePole): Změna počtu řádků
Metoda RozmerPole je také využita pro změnu přednastaveného počtu sloupců matice, protože se jedná o stejný princip změny hodnoty uvnitř intervalu definovaného pomocí předaných mezí jako parametrů. Aby uživatel rozlišil mezi zadáváním počtu řádků, nebo sloupců, je do metody předán textový parametr ve formě: "řádků", nebo "sloupců", který je uveden ve výpisu u zadávané velikosti - viz Výstup programu 3.
Výstup programu 3 - Kód 1 (viz kapitola 4 Program DvourozmernePole): Změna počtu sloupců
Dolní a horní mez prvků
Dolní a horní mez prvků
V následujícím výřezu výstupu programu vidíme změnu dolní meze specifikované pro všechny prvky dvourozměrného pole - viz Výstup programu 4.
Výstup programu 4 - Kód 1 (viz kapitola 4 Program DvourozmernePole): Změna dolní meze prvků pole
V následujícím výřezu výstupu programu vidíme změnu horní meze specifikované pro všechny prvky dvourozměrného pole - viz Výstup programu 5.
Výstup programu 5 - Kód 1 (viz kapitola 4 Program DvourozmernePole): Změna horní meze prvků pole
Plnění pole
Vzhledem k možnosti plnění pole různými způsoby jsou v následujících odstavcích zobrazeny různé výřezy výstupů programu týkající se plnění matice na základě zvoleného indexu plnění v metodě PlnitPole. Matice je zobrazena pomocí metody ZobrazitPole (pro výpis jednotlivých prvků matice byla použita metoda PoleJakoText volaná v metodě ZobrazitPole).
Náhodná čísla
V následujícím výřezu výstupu programu vidíme variantu plnění dvourozměrného pole o velikosti 10 řádků a 10 sloupců náhodnými celými čísly - viz Výstup programu 6. Dolní mez prvků pole je nastavena na hodnotu 1 a horní mez na hodnotu 100.
Výstup programu 6 - Kód 1 (viz kapitola 4 Program DvourozmernePole): Plnění pole náhodnými čísly
Plnění jednotlivých prvků pole
Další možností plnění pole je plnění prvku v matici s určitým indexem řádku a sloupce pomocí hodnoty zadané uživatelem - viz Výstup programu 7. Prvky, u nichž není zadána hodnota uživatelem, jsou inicializovány počáteční hodnotou v závislosti na příslušném datovém typu (např. pro datový typ int je přednastavená hodnota 0). Na výřezu výstupu programu vidíme postupné plnění celočíselného dvourozměrného pole o 3 řádcích a 3 sloupcích (kde dolní mez hodnot prvků je rovna 1 a horní mez je rovna 9). Při dalším plnění prvku je automaticky přenastavena pozice prvku na pozici dalšího prvku.
Pokud nebyla zadána hodnota prvku a uživatel stiskl klávesu Enter, je sice provedena konverze zadaného prázdného textu na hodnotu, ale ta neproběhne. Protože je ale použit v této konverzi výstupní parametr (out), je použita výchozí hodnota datového typu int, tedy 0. Protože je ale následně provedena validace hodnoty, zda hodnota prvku splňuje podmínku, že náleží intervalu přípustných hodnot prvků matice. Hodnota 0 však nesplňuje tuto podmínku (dolní mez v tomto případě byla nastavena na hodnotu 1) a je znovu provedena výzva k zadání prvku.
Pokud uživatel naplní prvek v posledním řádku a sloupci, plnění prvků matice je ukončeno.
Výstup programu 7 - Kód 1 (viz kapitola 4 Program DvourozmernePole): Plnění jednotlivých prvků pole
Plnění nulami
Třetí možností plnění pole je všem prvkům přiřadit hodnotu 0. Následující výřez výstupu programu znázorňuje výpis matice o velikosti 3 x 3 prvků, kde jsou všechny prvky naplněny nulami - viz Výstup programu 8.
Výstup programu 8 - Kód 1 (viz kapitola 4 Program DvourozmernePole): Plnění prvků pole nulami
Minimum a maximum pole
Následující výřez výstup programu konzolové aplikace ilustruje nalezení minima a maxima v matici o rozměrech 3 x 3 (řádky x sloupce), která byla zadána při plnění uživatelem. Ve výpisu jsou uvedeny indexy řádků a sloupců pozic těchto dvou nalezených prvků. Pole bylo plněno jednotlivě uživatelem zadanými čísly v rozmezí celočíselných hodnot 1 ÷ 9 - viz Výstup programu 9.
Výstup programu 9 - Kód 1 (viz kapitola 4 Program DvourozmernePole): Nalezené minimum a maximum v poli včetně jejich pozice v poli (index řádku a sloupce)
Průměr pole
Následující výřez výstupu programu konzolové aplikace ilustruje výpočet aritmetického průměru pole o 9 prvcích, které byly zadány při plnění jednotlivých prvků matice - viz Výstup programu 10.
Výstup programu 10 - Kód 1 (viz kapitola 4 Program DvourozmernePole): Výpočet aritmetického průměru ze všech prvků pole
Seřazení prvků pole
Následující výřez výstupu programu ilustruje vzestupné seřazení prvků v jednotlivých řádcích pole o 9 prvcích, které byly zadány při plnění jednotlivých prvků matice - viz Výstup programu 11.
Výstup programu 11 - Kód 1 (viz kapitola 2 Program DvourozmernePole): Vzestupné seřazení všech prvků v jednotlivých řádcích pole
Transpozice prvků
Předposlední výřez výstupu programu ilustruje transpozici prvků pole podle hlavní diagonály již seřazených prvků ve všech řádcích matice - viz Výstup programu 12.
Výstup programu 12 - Kód 1 (viz kapitola 4 Program DvourozmernePole): Transpozice prvků pole podle hlavní diagonály
Poslední výřez výstupu programu ilustruje transpozici prvků pole podle vedlejší diagonály již transponovaných prvků pole podle hlavní diagonály - viz Výstup programu 13.
Výstup programu 13 - Kód 1 (viz kapitola 4 Program DvourozmernePole): Transpozice prvků pole podle vedlejší diagonály