Dvourozměrné pole - WPF
4. C#
4.2. Plnění pole
Jak již název podkapitoly napovídá, nyní je zapotřebí definovat těla metod, která budou matici plnit čísly. Region Události obsahuje další region s názvem Plnění pole, který obsahuje následující metody:
- BtnNahodne_Click
- BtnJednotlive_Click
- BtnNulovat_Click
Abychom mohli matici naplnit náhodnými čísly pomocí stisku tlačítka, je zapotřebí nejprve deklarovat metodu, která bude v těle metody obsluhy stisknutí tlačítka volána. Tuto metodu deklarujeme v regionu Plnění pole, který je součástí regionu Pomocné metody.
Takovou základní metodou je soukromá (private) metoda bez návratu (void) s názvem NahodnePole - viz Kód 1. Tato metoda přijímá 5 formálních parametrů. Prvním parametrem je počet řádků matice (parametry jsou v metodě ponechány zejména z didaktických důvodů, protože např. počet řádků matice lze získat pomocí vlastnosti GetLength(0), vyvolané pomocí tečkové notace, kde 0 určuje dimenzi, v tomto případě počet řádků, atd.). Druhým parametrem je počet sloupců matice. Dalšími parametry je dolní a horní mez intervalu přípustných hodnot prvků. Posledním formálním parametrem je matice. Je nutné si uvědomit, že ač se matice jeví jako předávaná hodnotou, ve skutečnosti je předáván odkaz, protože matice není hodnotový typ, ale referenční typ. Tato matice je zpočátku naplněna 0. My však budeme chtít, aby matice obsahovala náhodná čísla z intervalu přípustných hodnot. To zajistíme pomocí vytvoření instance generátoru náhodného čísla s názvem rnd, pomocí zavolání konstruktoru s využitím klíčového slova new. Pomocí dvou cyklů s pevným krokem zajistíme procházení řádků (vnější cyklus) a sloupců matice (vnitřní cyklus). Ve vnitřní cyklu budeme každému prvku na pozici [i, j] přiřazovat náhodné číslo v intervalu dolní a horní meze, které jsou metodě Next předány jako parametry. Nezapomeňte, že metoda generuje náhodné číslo ve zleva uzavřeném intervalu (může generovat náhodné číslo rovné dolní mezi) a zprava otevřeném (nemůže generovat číslo rovné horní mezi). Proto je zapotřebí přičíst k horní mezi 1, aby mohlo být generováno náhodné číslo rovné horní mezi - jedná se o celá čísla, protože matice obsahuje pouze celá čísla, tj. typ int.
/// <summary> /// Metoda pro plnění prvků matice náhodnými čísly /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="minh"> minimální celočíselná hodnota prvku </param> /// <param name="maxh"> maximální celočíselná hodnota prvku </param> /// <param name="pole"> matice </param> private void NahodnePole(int m, int n, int minh, int maxh, int[,] pole) { // Vytvoření instance generátoru náhodného čísla Random rnd = new Random(); // Cyklus s pevným krokem - pro procházení řádků matice for (int i = 0; i < m; i++) { // Cyklus s pevným krokem - pro procházení sloupců matice for (int j = 0; j < n; j++) { // Přiřazení náhodného čísla v rozmezí intervalu u prvku na pozici [i, j] pole[i, j] = rnd.Next(minh, maxh + 1); } } }
Kód 1: Deklarace metody pro plnění matice náhodnými čísly (NahodnePole)
Vzhledem k tomu, že již máme deklarovánu metodu pro plnění, přejděme do regionu Události a dále do regionu Plnění pole, ve kterém nalezneme metodu BtnNahodne_Click, jejíž tělo budeme plnit - viz Kód 2. Tato metoda obsluhy události stisknutí tlačítka BtnNahodne, zajistí plnění matice náhodnými čísly v intervalu přípustných hodnot, jehož dolní a horní mez je specifikována na formuláři. Tyto hodnoty byly v těle hlavní metody naplněny do datových složek třídy minHodnota a maxHodnota. Jak vidíme v následujícím kódu v těle metody je volána soukromá metoda bez návratu s názvem NahodnePole, kterou jsme deklarovali v předchozím zdrojovém kódu. Skutečné parametry volané metody jsou počet řádků a sloupců matice, již zmiňované meze a samotná matice, která bude ve volané metodě změněna, ale vzhledem k referenčnímu typu nemusíme používat předávání parametru odkazem.
/// <summary> /// Volání metody pro plnění matice náhodnými čísly /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnNahodne_Click(object sender, RoutedEventArgs e) { // Zavolání metody bez návratu pro plnění matice náhodnými čísly this.NahodnePole(this.pocetRadku, this.pocetSloupcu, this.minHodnota, this.maxHodnota, this.pole); }
Kód 2: Deklarace metody pro zavolání metody pro plnění matice náhodnými čísly (BtnNahodne_Click)
V regionu Plnění pole, který je součástí regionu Události, také nalezneme metodu BtnJednotlive_Click, jejíž tělo nyní budeme doplňovat - viz Kód 3. Tato metoda obsluhy události stisknutí tlačítka BtnJednotlive, zajistí ruční plnění matice, tzn., že jednotlivé prvky bude definovat uživatel na formuláři a po stisknutí tlačítka bude prvek na definované pozici přepsán hodnotou načtenou z objektu na formuláři. Jak vidíme v následujícím kódu těla metody je nejprve provedena konverze textu na celé číslo z objektu na formuláři určeného pro specifikaci indexu řádku a sloupce prvku matice (počáteční řádek a sloupec jsou indexovány hodnotou 0). Načtenou hodnotu indexu řádku uložíme do lokální proměnné indexRadku a načtenou hodnotu indexu sloupce do lokální proměnné indexSloupce. Dále je zapotřebí načíst hodnotu, která má být umístěna do prvku matice. Mohlo by se stát, že uživatel by stiskl tlačítko pro ruční plnění, aniž by vyplnil hodnoty indexu řádku, nebo sloupce prvku, nebo hodnotu prvku. Proto v metodě provedeme načtení hodnot z těchto objektů na formuláři a sestavíme podmínky, které budou testovat, zda byly zadány validní hodnoty (mohli bychom také namísto tohoto druhu testování např. pouze testovat, zda objekty na formuláři nejsou prázdné, atd.). Pokud index řádku prvku je mimo interval povolených hodnot (je menší než 0, nebo větší než počet řádků - 1), je zobrazeno dialogové okno s textem popisujícím chybu. Pro validaci indexu sloupce použijeme princip kaskádování (vnoření if do if), kde v podmínce budeme testovat, zda zadaný index je mimo povolené meze (je menší než 0, nebo větší než počet sloupců - 1). Třetí podmínkou je testování zadané hodnoty, zda je v intervalu přípustných hodnot prvků matice. Pokud byl v některé podmínce je hodnota mimo interval, je pomocí metody Show zobrazeno dialogové okno, ve kterém můžeme pomocí specifikace parametrů definovat, jaká tlačítka mají být v okně zobrazena (v našem případě pouze tlačítko OK) a jaký obrázek má být zobrazen vedle vypsaného textu (v našem případě chyba, tj. kříž v červeném kruhu).
Pokud byly definované podmínky splněny (byl zadán validní index řádku, sloupce a hodnota prvku matice), provedou se příkazy v poslední větvi else. V prvním příkazu této větve vidíme, že hodnota uložená v lokální proměnné hodnota, je uložena do prvku, který je na pozici specifikované indexem řádku a sloupce. Protože byl přepsán prvek matice novou hodnotou, je vhodné změněnou matici zobrazit uživateli. To zajistíme pomocí volání metody ZobrazitPoleJakoText, která zobrazí prvky matice v objektu typu TextBox na formuláři. Dále pomocí metody ZobrazitPoleVListView zobrazíme matici v objektu typu ListView. Popis zdrojového kódu v C# obou těchto metod naleznete v kapitole Zobrazení pole.
V dalším bloku rozhodování je umístěna podmínka, že pokud je index sloupce je menší než celkový počet sloupců - 1, bude provedena inkrementace (zvýšení o 1) u indexu sloupce. Tím uživateli odpadá povinnost vždy specifikovat index následujícího prvku (které je o 1 vyšší než předchozí), protože se tak stane po stisku tlačítka. Zvýšený Index sloupce vypíšeme v objektu na formuláři.
Pokud index roven počtu sloupců, bude automaticky zvýšen index řádku prvku matice. To je provedeno pomocí vnořeného rozhodování do prvního příkazu if. Do podmínky tohoto rozhodování umístíme podmínku, zda je index řádku prvku matice menší než celkový počet řádků matice - 1. Pokud ano, zvýšíme index řádku prvku matice, vypíšeme index řádku prvku matice na formulář a nastavíme index sloupce prvku matice na počáteční sloupec, tj. na hodnotu 0. Index počátečního sloupce prvku matice vypíšeme též na formulář.
/// <summary> /// Volání metody pro plnění matice náhodnými čísly /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnNahodne_Click(object sender, RoutedEventArgs e) { // Zavolání metody bez návratu pro plnění matice náhodnými čísly this.NahodnePole(this.pocetRadku, this.pocetSloupcu, this.minHodnota, this.maxHodnota, this.pole); } /// <summary> /// Metoda pro ruční plnění jednotlivých prvků matice /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnJednotlive_Click(object sender, RoutedEventArgs e) { /* Přiřazení indexu řádku prvku z objektu na formuláři (konverze textu na celé * číslo) do lokální proměnné */ int.TryParse(this.TxtPrvekIndexRadku.Text, out int indexRadku); /* Přiřazení indexu sloupce prvku z objektu na formuláři (konverze textu na celé * číslo) do lokální proměnné */ int.TryParse(this.TxtPrvekIndexSloupce.Text, out int indexSloupce); // Přiřazení hodnoty prvku z objektu na formuláři do lokální proměnné int.TryParse(this.TxtHodnota.Text, out int hodnota); /* Přiřazení dolní meze intervalu hodnoty prvku z objektu na formuláři * do lokální proměnné */ int.TryParse(this.TxtMinHodnota.Text, out int minh); /* Přiřazení horní meze intervalu hodnoty prvku z objektu na formuláři * do lokální proměnné */ int.TryParse(this.TxtMaxHodnota.Text, out int maxh); /* Pokud index řádku prvku je mimo interval hodnot, tj. je menší než 0, * nebo je větší než počet řádků - 1, pak... */ if ((indexRadku < 0) || (indexRadku > this.pocetRadku - 1)) { // Zobrazení varovného dialogového okna MessageBox.Show("Zadaná hodnota indexu řádku prvku je mimo meze", "Chyba v zadání", MessageBoxButton.OK, MessageBoxImage.Error); } /* Pokud index sloupce prvku je mimo interval hodnot, tj. je menší než 0, * nebo je větší než počet sloupců - 1, pak... */ else if ((indexSloupce < 0) || (indexSloupce > this.pocetSloupcu - 1)) { // Zobrazení varovného dialogového okna MessageBox.Show("Zadaná hodnota indexu sloupce prvku je mimo meze", "Chyba v zadání", MessageBoxButton.OK, MessageBoxImage.Error); } /* Pokud hodnota prvku je větší, než horní mez intervalu povolené hodnoty prvku, nebo * je menší než dolní mez intervalu hodnot prvku, pak... */ else if ((hodnota > maxh) || (hodnota < minh)) { // Zobrazení varovného dialogového okna MessageBox.Show("Zadaná hodnota prvku je mimo meze", "Chyba v zadání", MessageBoxButton.OK, MessageBoxImage.Error); } // Jinak... else { // Přiřazení hodnoty z lokální proměnné do prvku matice na pozici [indexRadku, indexSloupce] this.pole[indexRadku, indexSloupce] = hodnota; // Zavolání metody pro zobrazení matice v objektu (typu TextBox) na formuláři this.ZobrazitPoleJakoText(this.pocetRadku, pocetSloupcu, this.pole); // Zavolání metody pro zobrazení matice v objektu (typu ListView) na formuláři this.ZobrazitPoleVListView(this.pocetRadku, this.pocetSloupcu, this.pole); // Pokud index sloupce prvku je menší než celkový počet sloupců matice - 1, pak... if (indexSloupce < this.pocetSloupcu - 1) { // Zvýšení indexu sloupce prvku o 1 indexSloupce++; // Přiřazení indexu sloupce prvku do objektu na formuláři this.TxtPrvekIndexSloupce.Text = indexSloupce.ToString(); } // Pokud index řádku prvku je menší než celkový počet řádků matice - 1, pak... else if (indexRadku < this.pocetRadku - 1) { // Zvýšení indexu řádku prvku o 1 indexRadku++; // Přiřazení indexu řádku prvku do objektu na formuláři this.TxtPrvekIndexRadku.Text = indexRadku.ToString(); // Přiřazení 0 do indexu sloupce indexSloupce = 0; // Přiřazení indexu sloupce prvku do objektu na formuláři this.TxtPrvekIndexSloupce.Text = indexSloupce.ToString(); } } }
Kód 3: Deklarace metody pro ruční plnění matice definovanými hodnotami uživatelem (BntJednotlive_Click)
Nyní budeme deklarovat poslední metodu v regionu Plnění pole, umístněného v regionu Pomocné metody. Jedná se o soukromou metodu bez návratu s názvem NulovatPole - viz Kód 4. Tato metoda pomocí cyklu s krokem bude procházet všechny prvky předané matice a zajistí přepsání stávající hodnoty prvků hodnotou 0.
/// <summary> /// Metoda pro nulování prvků v matici /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> matice </param> private void NulovatPole(int m, int n, int[,] pole) { // Cyklus s pevným krokem - pro procházení řádků matice for (int i = 0; i < m; i++) { // Cyklus s pevným krokem - pro procházení sloupců matice for (int j = 0; j < n; j++) { // Přiřazení nuly prvku na pozici [i, j] pole[i, j] = 0; } } }
Kód 4: Deklarace metody pro přepsaní hodnot prvků hodnotou 0 u předané matice (NulovatPole)
Po deklaraci metody pro plnění matice hodnotou 0, se přemístíme do regionu Události a dále do regionu Plnění pole, ve kterém nalezneme metodu BtnNulovat_Click, jejíž tělo budeme plnit - viz Kód 5. Tato metoda obsluhy události stisknutí tlačítka BtnNulovat, zajistí plnění matice nulami. Jak vidíme, v následujícím kódu v těle metody je volána soukromá metoda bez návratu s názvem NulovatPole, kterou jsme deklarovali v předchozím zdrojovém kódu. Skutečné parametry volané metody jsou počet řádků matice, počet sloupců matice a samotná matice.
/// <summary> /// Metoda pro zavolání metody pro nulování matice /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnNulovat_Click(object sender, RoutedEventArgs e) { //Zavolání metody pro nulování matice this.NulovatPole(this.pocetRadku, this.pocetSloupcu, this.pole); }
Kód 5: Deklarace metody pro zavolání metody pro nulování matice (BntNulovat_Click)