Dvourozměrné pole - WPF
| Website: | Moodle ZČU |
| Kurs: | KPV/TI Technická informatika ve strojírenství - cvičení |
| Buch: | Dvourozměrné pole - WPF |
| Gedruckt von: | Nepřihlášený host |
| Datum: | Sonntag, 8. November 2026, 16:33 |
1. DvourozmernePoleWPF
Úkolem je vytvořit aplikaci, která by dovedla pro dvourozměrné pole celých čísel, tj. matici:
- Naplnit matici automaticky nulami
- Naplnit matici automaticky náhodnými hodnotami v zadaném rozsahu
- Naplnit matici cyklem jednotlivě zadávanými hodnotami pro zadaný index
- Zobrazit matici jako text oddělený čárkami
- Zobrazit matici do seznamu o velikosti MxN
- Vypočítat minimum z hodnot matice
- Vypočítat maximum z hodnot matice
- Vypočítat průměr z hodnot matice
- Seřadit každý řádek matice vzestupně
- Transponovat matici podle hlavní diagonály
- Transponovat matici podle vedlejší diagonály
Účel příkladu
- Práce s jednorozměrným polem
Typ aplikace
- WPF aplikace
Popis úkolu
- Základní operace s dvourozměrným polem
Funkčnosti
- Při stisku tlačítka Náhodně se naplní matice automaticky náhodnými hodnotami v zadaném rozsahu
- Při stisku tlačítka Jednotlivě se naplní matice pomocí jednotlivě zadávaných hodnot pro zadanou pozici (pomocí indexu řádku a sloupce prvku v matici) v rámci cyklu
- Při stisku tlačítka Nulovat se naplní matice automaticky nulami
- Při stisku tlačítka Jako text se zobrazí matice jako text oddělený čárkami
- Při stisku tlačítka Do mřížky se zobrazí matice do seznamu
- Při stisku tlačítka Minimum se zjistí minimum z hodnot matice a zobrazí se pozice minima (index řádku a sloupce prvku)
- Při stisku tlačítka Maximum se zjistí maximum z hodnot matice a zobrazí se pozice maxima
- Při stisku tlačítka Průměr se vypočítá průměr z hodnot matice
- Při stisku tlačítka Seřadit se každý řádek matice seřadí vzestupně na základě hodnot prvků v řádce
- Při stisku tlačítka Transpozice - hlavní diagonála se provede transpozice prvků matice podle hlavní diagonály
- Při stisku tlačítka Transpozice - vedlejší diagonála se provede transpozice prvků matice podle vedlejší diagonály
- Při stisku tlačítka Konec se provede zavření formuláře
Výstup programu
Výstup programu 1: Ukázka GUI při počátečním spuštění programu DvourozmernePoleWPF
Výsledek:
Výstup programu 2: Ukázka dvourozměrného pole s náhodnými čísly v programu DvourozmernePoleWPF
2. Analýza a návrh řešení
V příkladu budou využity stejné principy vytvoření, plnění, zobrazení a operace s dvourozměrným polem jako v předchozím příkladu DvourozmernePole, proto již není zapotřebí provádět detailní analýzu.
Pro rozložení jednotlivých prvků na formuláři použijeme Grid vložený do formuláře, který rozdělíme na 3 řádky - viz Obrázek 1. V dalších kapitolách si postupně popíšeme jednotlivé řádky mřížky.
Obrázek 1: Návrh GUI - Základní rozdělení mřížky formuláře na 3 řádky (DvourozmernePoleWPF)
2.1. Nastavení atributů pole
Do prvního řádku Grid (s indexem 0) umístíme objekt typu GroupBox s titulkem Nastavení matice (matice je synonymum pro dvourozměrné pole) - viz Obrázek 1. Do tohoto objektu vložíme další mřížku Grid, pomocí které rozdělíme vnitřní prostor na dvě řádky. Do prvního řádku tohoto Grid umístíme popisek (Label) s textem "Matice". Do druhé řádky umístíme další mřížku Grid, pomocí níž rozdělíme vnitřní prostor tohoto řádku na tři sloupce. Do každého sloupce umístíme GroupBox pro nastavení rozměru matice, hodnot dolní a horní meze intervalu přípustných hodnot prvků matice a poslední sloupec bude obsahovat atributy pro možnosti plnění matice po jednotlivých prvcích, nebo pro změnu hodnoty určitého prvku matice.
GroupBox pro nastavení rozměru, umístěný v prvním sloupci Grid, bude obsahovat další mřížku se dvěma řádky a dvěma sloupci. Do prvního řádku a prvního sloupce umístíme popisek (Label) s textem "Počet řádků". Do druhého sloupce ve stejném řádku vložíme vstupní pole (TextBox), ve kterém bude uživatel specifikovat počet řádků matice. Stejně budeme postupovat i v případu druhého řádku kde bude specifikován vertikální rozměr matice, tj. do prvního sloupce druhého řádku umístíme popisek (Label) s textem "Počet sloupců" a do druhého sloupce vstupní pole (TextBox) pro specifikaci počtu sloupců.
GroupBox pro nastavení dolní a horní meze hodnot prvků matice, umístěného ve druhém sloupci Grid, bude obsahovat další mřížku (Grid), kterou rozdělíme na dva řádky a dva sloupce. Do prvního řádku prvního sloupce této mřížky umístíme popisek (Label) "Minimum:". Tento popisek je popiskem pro vstupní pole (TextBox), kde uživatel specifikuje dolní mez hodnot prvků matice. Toto vstupní pole umístíme do druhého sloupce prvního řádku této mřížky. Stejným způsobem vyřešíme zadávání horní meze prvků matice, kde objekty typu Label a TextBox umístíme do prvního a druhého sloupce následujícího druhého řádku této mřížky.
Další sloupec Grid necháme volný. Tento prostor bude vyplňovat zbývající místo při roztáhnutí, nebo zmenšení formuláře.
GroupBox pro plnění matice po jednotlivých prvcích, umístíme do posledního sloupce mřížky (Grid). V tomto GroupBox opět využijeme rozdělení prostoru na 2 řádky a 4 sloupce pomocí další vložené mřížky (Grid). Do prvního řádku a prvního sloupce mřížky umístíme popisek (Label) s textem "Index řádku:". Do dalšího sloupce ve stejném řádku umístíme vstupní pole (TextBox) pro specifikaci indexu řádku, kde se bude prvek v matici nacházet. V dalším řádku prvního sloupce umístíme popisek (Label) s textem "Index sloupce:". Do dalšího sloupce ve stejném řádku umístíme vstupní pole (TextBox) pro specifikaci indexu sloupce prvku matice.
Do prvního řádku do předposledního sloupce této mřížky umístíme popisek (Label) s textem "Hodnota:". Do posledního sloupce ve stejném řádku umístíme vstupní pole (TextBox) pro specifikaci hodnoty prvku s pozici (pomocí indexu řádku a sloupce), kterou uživatel zadal v druhém sloupci této mřížky.
První řádek základní mřížky formuláře bude obsahovat objekty (kontrolky), které budou vnořeny následujícím způsobem:
- Grid (první řádek základní mřížky formuláře)
- GroupBox
- Grid
- Label
- Grid
- GroupBox
- Grid
- Label
- TextBox: TxtPocetRadku
- Label
- TextBox: TxtPocetSloupcu
- GroupBox
- Grid
- Label
- TextBox: TxtMinHodnota
- Label
- TextBox: TxtMaxHodnota
- GroupBox
- Grid
- Label
- TextBox: TxtPrvekIndexRadku
- Label
- TextBox: TxtPrvekIndexSloupce
- Label
- TextBox: TxtHodnota
Formulář bude obsahovat následující prvky - viz Obrázek 2.
Obrázek 2: Návrh GUI - nastavení atributů pole - účel jednotlivých objektů v prvním řádku mřížky formuláře (DvourozmernePoleWPF)
2.2. Zobrazení pole
Do druhého řádku základní mřížky formuláře (s indexem 1) umístíme objekt typu GroupBox se záhlavím "Zobrazení matice", který bude obsahovat další mřížku (Grid), kterou rozdělíme na dva sloupce - viz Obrázek 1.
Do prvního sloupce mřížky umístíme GroupBox, jehož záhlaví bude obsahovat text "Matice". V tomto GroupBox bude umístěn objekt typu ListView, pomocí něhož budeme zobrazovat jednotlivé řádky matice pod sebou. Ve druhém sloupci mřížky se bude nacházet také objekt GroupBox. V tomto GroupBox budeme zobrazovat výslednou matici např. po provedení operace setřídění. Prvky matice budou vypisovány do jednotlivých řádku umístěných pod sebou. Prvku v řádku budou mezi sebou odděleny čárkou - viz Obrázek 2.
Formulář bude obsahovat následující objekty (kontrolky), které budou vnořeny následujícím způsobem:
- Grid (druhý řádek základní mřížky formuláře)
- GroupBox
- Grid
- GroupBox
- ListView: LstMatice
- GroupBox
- TextBox: TxtVysledek
Obrázek 1: Návrh GUI - rozložení prvků v mřížce formuláře (DvourozmernePoleWPF)
Formulář bude obsahovat následující prvky - viz Obrázek 2.
Obrázek 2: Návrh GUI a účel jednotlivých objektů (DvourozmernePoleWPF)
2.3. Operace s polem
Do třetího řádku základní mřížky formuláře (s indexem 2) umístíme další mřížku (Grid). Tuto mřížku rozdělíme do 3 sloupců, které využijeme jako oddělené sekce Plnit, Výstup a Výpočet s jednotlivými tlačítky - viz Obrázek 1.
Do prvního sloupce této vložené mřížky umístíme objekt typu StackPanel. Do tohoto objektu jako první umístíme popisek (Label) "Plnit", který bude tvořit záhlaví sekce. Pod popisek umístíme 3 tlačítka:
- Náhodně - plnění matice prvky, jenž každý obsahuje náhodně vygenerovanou hodnotu na základě rovnoměrného rozdělení v intervalu, jehož dolní mez představuje hodnota, která je načtena z prvního řádku základní mřížky, tj. hodnota vstupního pole Minimum umístěného na formuláři a hodnota horní meze, která je načtena ze vstupního pole Maximum na formuláři
- Jednotlivě - plnění matice na základě hodnoty uvedené ve vstupním poli Hodnota u prvku s definovanou pozicí. Pozice se skládá z indexu řádku a indexu sloupce načtených ze vstupních polí umístěných v objektu GroupBox se záhlavím "Prvek v matici" nacházejícím se vpravo prvním řádku základní mřížky
- Nulovat - plnění matice prvky s hodnotou 0
Do druhého sloupce umístíme objekt typu StackPanel. Do tohoto objektu jako první umístíme popisek (Label) "Výstup", který bude tvořit záhlaví sekce. Pod popisek umístíme 2 tlačítka:
- Jako text - výpis prvků matice. Prvky jsou umístěny do řádků umístěných pod sebou v objektu typu TextBox, kde jednotlivé prvky jsou odděleny čárkou
- Do mřížky - výpis jednotlivých řádků matice umístěných do jednotlivých řádků v objektu typu ListView (jednotlivé prvky jsou odděleny čárkou)
Do třetího sloupce mřížky umístíme objekt typu StackPanel. Do tohoto objektu jako první umístíme popisek (Label) "Výpočet", který bude tvořit záhlaví sekce. Pod popisek umístíme 4 tlačítka:
- Minimum - hledání prvku matice s nejmenší hodnotou, včetně vypsání pozice minima (index řádku a sloupce umístěných v hranatých závorkách)
- Maximum - hledání prvku matice s největší hodnotou, včetně vypsání pozice maxima
- Průměr - výpočet aritmetického průměru ze všech prvků matice
- Seřadit - vzestupné třídění všech prvků matice
- Transpozice - hlavní diagonála - transpozice prvků matice podle hlavní diagonály
- Transpozice - vedlejší diagonála - transpozice prvků matice podle vedlejší diagonály
Formulář bude obsahovat následující objekty (kontrolky), které budou vnořeny následujícím způsobem:
- Grid (třetí řádek základní mřížky formuláře)
- StackPanel
- Grid
- StackPanel
- Label
- Button: BtnNahodne
- Button: BtnJednotlive
- Button: Nulovat
- StackPanel
- Label
- Button: BtnJakoText
- Button: BtnDoMrizky
- StackPanel
- Label
- Button: BtnMinimum
- Button: BtnMaximum
- Button: BtnPrumer
- Button: BtnSeradit
- Button: BtnTranspoziceHlavni
- Button: BtnTranspoziceVedlejsi
- WrapPanel
- Button: BtnKonec
Obrázek 1: Návrh GUI - tlačítka pro operace s polem (DvourozmernePoleWPF)
Formulář bude obsahovat následující prvky - viz Obrázek 2.
Obrázek 2: Návrh GUI - operace s polem - účel jednotlivých objektů v prvním řádku mřížky formuláře (DvourozmernePoleWPF)
3. XAML
Na základě našich zkušeností s XAML bude již stručně popsán postup tvorby formuláře. Základní atributy (titulek, výšku a šířku) formuláře nastavíme následujícím způsobem. Budeme také definovat minimální výšku a šířku, na kterou lze formulář zmenšit - viz Kód 1.
Title="Základní práce s maticí" Height="850" Width="850" MinHeight="800" MinWidth="800">
Kód 1: Nastavení atributů formuláře
Objekt typu Grid umístěného na formuláři rozdělíme na tři řádky. První a poslední řádek se přizpůsobí obsahu vložených prvků. Výška druhého řádku se bude přizpůsobovat roztažení okna - viz Kód 2.
Abychom následující XAML kód zjednodušili pro čtení a pochopení podstaty, využijeme komentáře v kódu XAML pomocí nichž rozdělíme XAML kód na určité sekce, které budou v kapitolách postupně doplněny - viz Kód 2.
<Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <!-- Nastavení matice --> <!-- Zobrazení matice --> <!-- Tlačítka - sekce: Plnit, Výstup, Výpočet -->
Kód 2: Rozdělení Grid na řádky a komentáře jednotlivých sekcí
Formulář
Navržené rozložení prvků na formuláři, včetně formuláře samotného v této části etapy, je vidět na následujícím obrázku - viz Obrázek 1.
Obrázek 1: Rozpracovaný formulář WPF aplikace
Objekty na formuláři:
Formulář v této fázi obsahuje pouze jeden objekt (kontrolku):
- Grid
který je umístěn následujícím způsobem - viz Obrázek 2.
Obrázek 2: VS - okno Document Outline - seznam objektů
3.1. Nastavení atributů pole
V úvodu začněme nejprve popisem vytvářeného XAML kódu v první řádce základní mřížky formuláře. Tato řádka bude obsahovat objekty, které slouží k nastavení atributů dvourozměrného pole - matice. Prvním vloženým objektem seskupujícím jednotlivé objekty je GroupBox. Do záhlaví (vlastnost Header) tohoto objektu vložíme text "Nastavení matice". Do objektu vložíme další mřížku, která nám rozdělí prostor na dva řádky (rozměry se budou přizpůsobovat vloženému obsahu). Do prvního řádku vložíme vložíme zvětšený (FontSize) tučný (FontWeight) vystředěný (HorizontalAlignment) popisek "Matice" (Label), který bude uživatelem vnímám jako nadpis celého formuláře. Pod tento popisek vložíme další mřížku, která nám rozdělí zbývající prostor na čtyři sloupce, do nichž umístíme sekce pro specifikaci rozměru matice, meze intervalu hodnot prvků matice a prvku matice, který je definován konkrétní pozicí, tj. indexem řádku a sloupce - viz Kód 1. V kódu budeme dále doplňovat pod komentáře zbývající části XAML kódu jednotlivých objektů formuláře.
<!-- Nastavení matice --> <GroupBox Header="Nastavení matice"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Label Content="Matice" FontSize="18" FontWeight="Bold" HorizontalAlignment="Center" /> <Grid Grid.Row="1"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <!-- Rozměry matice --> <!-- Hodnoty - meze --> <!-- Prvek v matici --> </Grid> </Grid> </GroupBox>
Kód 1: GroupBox - nastavení matice (dvourozměrného pole)
Pod komentář Rozměry matice vložíme do prvního sloupce mřížky objekt GroupBox se záhlavím "Rozměry matice".
Do tohoto objektu vložíme další mřížku se dvěma řádky a dvěma sloupci, jejichž výšky a šířky se budou automaticky přizpůsobovat vloženému obsahu. Do prvního řádku a prvního sloupce umístíme popisek (Label) s textem "Počet řádků". U tohoto objektu nastavíme vertikální zarovnání na střed (vlastnost VerticalAlignment). Do druhého sloupce ve stejném řádku vložíme vstupní pole (TextBox), ve kterém bude uživatel specifikovat počet řádků matice. U tohoto objektu TextBox nastavíme vnitřní okraje (vlastnost Padding), vnější okraje (vlastnost Margin) na 5 pixelů a šířku (Width) na 100 pixelů.
Stejně budeme postupovat i v případu druhého řádku (Grid.Row="1"), kde bude specifikován vertikální rozměr matice, tj. do prvního sloupce druhého řádku umístíme popisek (Label) s textem "Počet sloupců" a do druhého sloupce (Grid.Column="1") umístíme vstupní pole (TextBox) pro specifikaci počtu sloupců. Pro oba objekty typu TextBox vygenerujeme obsluhu události při opuštění tohoto objektu (událost LostFocus) pomocí nastavení vlastnosti LostFocus a zvolení položky <New Event Handler> - viz Kód 2.
<!-- Rozměry matice --> <GroupBox Header="Rozměry matice"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Label Content="Počet řádků:" VerticalAlignment="Center"/> <TextBox Name="TxtPocetRadku" Grid.Column="1" Width="100" Margin="5" Padding="5" LostFocus="TxtPocetRadku_LostFocus"/> <Label Content="Počet sloupců:" Grid.Row="1" VerticalAlignment="Center"/> <TextBox Name="TxtPocetSloupcu" Grid.Row="1" Grid.Column="1" Width="100" Margin="5" Padding="5" LostFocus="TxtPocetSloupcu_LostFocus"/> </Grid> </GroupBox>
Kód 2: GroupBox - rozměr matice
Pod komentář Hodnoty - meze vložíme do druhého sloupce mřížky znovu objekt GroupBox, nyní však se záhlavím "Hodnoty - meze". Do tohoto objektu vložíme Grid, který rozdělíme na 2 řádky a 2 sloupce. Do prvního řádku prvního sloupce této mřížky umístíme popisek (Label) "Minimum:". Tento popisek je popiskem pro vstupní pole (TextBox), kde uživatel specifikuje dolní mez hodnot prvků matice. Toto vstupní pole umístíme do druhého sloupce prvního řádku této mřížky (Grid.Column). Stejným způsobem vyřešíme zadávání horní meze prvků matice v dalším řádku (Grid.Row), kde objekty typu Label a TextBox umístíme do prvního a druhého sloupce (Grid.Column) následujícího druhého řádku této mřížky. U těchto objektů nastavíme jejich další vlastnosti - viz Kód 3. U obou objektů typu TextBox vygenerujeme obsluhu události při opuštění tohoto objektu (událost LostFocus) pomocí nastavení vlastnosti LostFocus a zvolení položky <New Event Handler> .
<!-- Hodnoty - meze --> <GroupBox Header="Hodnoty - meze" Grid.Column="1"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Label Content="Minimum:" VerticalAlignment="Center"/> <TextBox Name="TxtMinHodnota" Grid.Column="1" Width="100" Margin="5" Padding="5" LostFocus="TxtMinHodnota_LostFocus"/> <Label Content="Maximum:" Grid.Row="1" VerticalAlignment="Center"/> <TextBox Name="TxtMaxHodnota" Grid.Row="1" Grid.Column="1" Width="100" Margin="5" Padding="5" LostFocus="TxtMaxHodnota_LostFocus"/> </Grid> </GroupBox>
Kód 3: GroupBox - hodnoty mezí intervalu přípustných hodnot prvků matice
Další sloupec mřížky v první řádku formuláře necháme volný. Tento prostor bude vyplňovat zbývající místo při roztáhnutí, nebo zmenšení formuláře.
Do posledního sloupce mřížky, tj. pod komentář Prvek v matice umístíme GroupBox pro plnění matice po jednotlivých prvcích. V tomto GroupBox opět využijeme rozdělení prostoru na 2 řádky a 4 sloupce pomocí další vložené mřížky (Grid).
Do prvního řádku a prvního sloupce této mřížky umístíme popisek (Label) s textem "Index řádku:". Do dalšího sloupce ve stejném řádku umístíme vstupní pole (TextBox) pro specifikaci indexu řádku, kde se bude prvek v matici nacházet. Šířka tohoto TextBox a i všech dalších objektů typu TextBox, umístěných v této sekci, bude nastavena na fixní hodnotou 100 pixelů (vlastnost Width) a vnitřní okraje (vlastnost Padding) a vnější okraje (vlastnost Margin) budou nastaveny na 5 pixelů.
Do dalšího řádku (Grid.Row = "1") prvního sloupce (Grid.Column="0") vložíme popisek (Label) s textem "Index sloupce:". Do dalšího sloupce ve stejném řádku umístíme vstupní pole (TextBox) pro specifikaci indexu sloupce prvku matice.
Do prvního řádku řádku třetího sloupce této mřížky umístíme popisek (Label) s textem "Hodnota:". Do dalšího sloupce ve stejném řádku umístíme vstupní pole (TextBox) o fixní délce pro specifikaci hodnoty prvku na pozici reprezentovanou pomocí indexů, které uživatel zadal ve druhém sloupci mřížky. Pro všechny objekty typu TextBox vygenerujeme obsluhu události při opuštění tohoto objektu (událost LostFocus) pomocí nastavení vlastnosti LostFocus a zvolení položky <New Event Handler> - viz Kód 4.
<!-- Prvek v matici --> <GroupBox Header="Prvek v matici" Grid.Column="3"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Label Content="Index řádku:" Grid.Row="0" Grid.Column="0"/> <TextBox Name="TxtPrvekIndexRadku" Grid.Row="0" Grid.Column="1" Width="100" Margin="5" Padding="5" LostFocus="TxtPrvekIndexRadku_LostFocus"/> <Label Content="Index sloupce:" Grid.Row = "1" Grid.Column="0"/> <TextBox Name="TxtPrvekIndexSloupce" Grid.Row="1" Grid.Column="1" Width="100" Margin="5" Padding="5" LostFocus="TxtPrvekIndexSloupce_LostFocus"/> <Label Content="Hodnota:" Grid.Row="0" Grid.Column="2"/> <TextBox Name="TxtHodnota" Grid.Row="0" Grid.Column="3" Width="100" Margin="5" Padding="5" LostFocus="TxtHodnota_LostFocus"/> </Grid> </GroupBox>
Kód 4: GroupBox - prvek v matici
Formulář
Navržené rozložení prvků v prvním řádku základní mřížky na formuláři v této části etapy, je vidět na následujícím obrázku - viz Obrázek 1.
Obrázek 1: Rozpracovaný formulář WPF aplikace - první řádek základní mřížky
Objekty na formuláři:
Formulář v prvním řádku základní mřížky formuláře obsahuje následující objekty (kontrolky):
- Grid (5x)
- GroupBox (4x)
- Label (8x)
- TextBox: TxtPocetRadku, TxtPocetSloupcu, TxtMinHodnota, TxtMaxHodnota, TxtPrvekIndexRadku, TxtPrvekIndexSloupce, TxtHodnota
které jsou umístěny následujícím způsobem - viz Obrázek 2.
Obrázek 2: VS - okno Document Outline - seznam objektů - první řádek základní mřížky
3.2. Zobrazení pole
Do druhého řádku základní mřížky formuláře (s indexem 1) umístíme objekt typu GroupBox se záhlavím "Zobrazení matice", který bude obsahovat další mřížku (Grid), kterou rozdělíme na dva sloupce - viz Kód 1. V kódu budeme dále doplňovat pod komentáře zbývající části XAML kódu jednotlivých objektů formuláře.
<!-- Zobrazení matice --> <GroupBox Header="Zobrazení matice" Grid.Row="1"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <!-- Matice --> <!-- Výsledek --> </Grid> </GroupBox>
Kód 1: GroupBox - zobrazení matice
Pod komentář Matice vložíme do prvního sloupce mřížky GroupBox, jehož záhlaví bude obsahovat text "Mřížka". V tomto GroupBox bude umístěn objekt typu ListView, pomocí něhož budeme zobrazovat jednotlivé řádky matice pod sebou. U tohoto objektu zobrazíme svislý posuvník, který umožňuje vertikálně posouvat vložený obsah do tohoto objektu (vlastnost ScrollViewer.VerticalScrollBarVisibility). Nastavení této vlastnosti na hodnotu "Auto" zajistí, že pokud obsah nebude zobrazen v tomto objektu celý, je automaticky zpřístupněn (zviditelněn) posuvník - viz Kód 2.
<!-- Matice --> <GroupBox Header="Mřížka" Margin="5" MinHeight="100"> <ListView Name="LstMatice" ScrollViewer.VerticalScrollBarVisibility="Auto"/> </GroupBox>
Kód 2: GroupBox - zobrazení prvků matice v jednotlivých řádcích v objektu ListView
Pod komentář Výsledek vložíme do druhého sloupce mřížky ve stejném řádku objekt GroupBox. V tomto GroupBox budeme zobrazovat výslednou matici např. po provedení operace setřídění. Prvky matice budou vypisovány za sebou a budou mezi sebou odděleny čárkou (provedeme pomocí CodeBehind). Jednotlivé prvky v umístíme do příslušných řádků. U objektu typu TextBox jsme zapnuly (zviditelnily, tj. hodnota "Visible") oba posuvníky jak horizontální (ScrollViewer.HorizontalScrollBarVisibility), tak i vertikální (ScrollViewer.VerticalScrollBarVisibility). Objekt TextBox bude určen pouze pro výpis (IsReadOnly) a nastavíme modré pozadí (BackGround) - viz Kód 3.
<!-- Výsledek --> <GroupBox Header="Jako text (nebo výpis výsledku)" Grid.Column="2" Margin="5"> <TextBox Name="TxtVysledek" Margin="5" ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollBarVisibility="Visible" IsReadOnly="True" Background="AliceBlue"/> </GroupBox>
Kód 3: GroupBox - zobrazení prvků matice za sebou v objektu TextBox
Navržené rozložení prvků ve druhém řádku základní mřížky na formuláři v této části etapy je vidět na následujícím obrázku - viz Obrázek 1.Formulář
Obrázek 1: Rozpracovaný formulář WPF aplikace - druhý řádek základní mřížky
Formulář v druhém řádku základní mřížky formuláře obsahuje následující objekty (kontrolky): které jsou umístěny následujícím způsobem - viz Obrázek 2.Objekty na formuláři:
Obrázek 2: VS - okno Document Outline - seznam objektů - druhý řádek základní mřížky
3.3. Operace s polem
V posledním řádku základní mřížky formuláře (s indexem 2) se bude nacházet další mřížka (Grid). Tuto mřížku rozdělíme do 3 sloupců, které využijeme jako oddělené sekce Plnit, Výstup a Výpočet s jednotlivými tlačítky - viz Kód 1.
<!-- Tlačítka - sekce: Plnit, Výstup, Výpočet --> <StackPanel Grid.Row="4"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <!-- Plnit --> <!-- Výstup --> <!-- Výpočet --> </Grid> <!-- Konec --> </StackPanel>
Kód 1: StackPanel - tlačítka pro operace s maticí
Pod komentář Plnit vložíme do prvního sloupce této mřížky objekt typu StackPanel. Do tohoto objektu jako první umístíme popisek (Label) "Plnit", který bude tvořit záhlaví sekce. Pod popisek umístíme 3 tlačítka:
- Náhodně (objekt BtnNahodne)- plnění matice prvky, kde každý prvek obsahuje náhodně vygenerovanou hodnotu na základě rovnoměrného rozdělení v intervalu, jehož dolní mez představuje hodnotu, která je načtena z prvního řádku základní mřížky, tj. hodnota ve vstupním poli (objekt TxtMinHodnota) umístěného vpravo vedle popisku Minimum a hodnota horní meze, která je načtena ze vstupního pole (objekt TxtMaxHodnota) umístěného vpravo vedle popisku Maximum
- Jednotlivě (objekt BtnJednotlive) - plnění matice hodnotou uvedenou ve vstupním poli (objekt TxtHodnota) umístěného vpravo vedle popisku Hodnota. Prvek je umístěn v matici v řádku a sloupci, kde index řádku je určen pomocí hodnoty zadané ve vstupním poli (objekt TxtPrvekIndexRadku) umístěného vpravo vedle popisku Index řádku: a index sloupce je načten ze vstupního pole (objekt TxtPrvekIndexSloupce) umístěného vpravo od popisku Index sloupce:. Všechna tři vstupní pole jsou umístěna v prvním řádku základní mřížky
- Nulovat (objekt BtnNulovat) - plnění prvků matice hodnotou 0
U všech tlačítek nastavíme vnitřní okraje (vlastnost Padding) a také vnější okraje (vlastnost Margin). Pro všechna tlačítka vygenerujeme obsluhu události stisknutí tlačítka (událost Click) pomocí nastavení vlastnosti Click a zvolení položky <New Event Handler> - viz Kód 2.
<!-- Plnit --> <StackPanel > <Label Content="Plnit:" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center"/> <Button Name="BtnNahodne" Content="Náhodně" Margin="5" Padding="10,5" Click="BtnNahodne_Click"/> <Button Name="BtnJednotlive" Content="Jednotlivě" Margin="5" Padding="10,5" Click="BtnJednotlive_Click"/> <Button Name="BtnNulovat" Content="Nulovat" Margin="5" Padding="10,5" Click="BtnNulovat_Click"/> </StackPanel>
Kód 2: StackPanel - tlačítka pro plnění matice
Pod komentář Výstup vložíme do druhého sloupce objekt typu StackPanel. Do tohoto objektu jako první umístíme popisek (Label) "Výstup", který bude tvořit záhlaví sekce. Pod popisek umístíme 2 tlačítka:
- Jako text (objekt BtnJakoText) - výpis prvků matice (prvky oddělené čárkou jsou umístěny do příslušných řádků a sloupců) v objektu typu TextBox (objekt TxtVysledek)
- Do mřížky (objekt BtnDoMrizky) - výpis prvků matice do jednotlivých řádků v objektu typu ListView (objekt LstMatice)
U všech tlačítek nastavíme vnitřní okraje (vlastnost Padding) a také vnější okraje (vlastnost Margin). Pro všechna tlačítka vygenerujeme obsluhu události stisknutí tlačítka (událost Click) pomocí nastavení vlastnosti Click a zvolení položky <New Event Handler> - viz Kód 3.
<!-- Výstup --> <StackPanel Grid.Column="1"> <Label Content="Výstup:" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center"/> <Button Name="BtnJakoText" Content="Jako text" Margin="5" Padding="10,5" Click="BtnJakoText_Click"/> <Button Name="BtnDoMrizky" Content="Do mřížky" Margin="5" Padding="10,5" Click="BtnDoMrizky_Click"/> </StackPanel>
Kód 3: StackPanel - tlačítka pro výpis prvků matice
Pod komentář Výpočet vložíme do třetího sloupce mřížky objekt typu StackPanel. Do tohoto objektu jako první umístíme popisek (Label) "Výpočet", který bude tvořit záhlaví sekce. Pod popisek umístíme 6 tlačítek:
- Minimum (objekt BtnMinimum) - hledání prvku matice s nejmenší hodnotou, včetně vypsání pozice minima (index řádku a sloupce uvedených v hranatých závorkách)
- Maximum (objekt BtnMaximum)- hledání prvku matice s největší hodnotou, včetně vypsání pozice maxima
- Průměr (objekt BtnPrumer) - výpočet aritmetického průměru ze všech prvků matice
- Seřadit (objekt BtnSeradit)- vzestupné třídění prvků v řádku matice
- Transpozice - hlavní diagonála (objekt BtnTranspoziceHlavni) - transpozice prvků matice podle hlavní diagonály
- Transpozice - vedlejší diagonála (objekt BtnTranspoziceVedlejsi) - transpozice prvků matice podle vedlejší diagonály
U všech tlačítek nastavíme vnitřní okraje (vlastnost Padding) a také vnější okraje (vlastnost Margin). Pro všechna tlačítka vygenerujeme obsluhu události stisknutí tlačítka (událost Click) pomocí nastavení vlastnosti Click a zvolení položky <New Event Handler> - viz Kód 4.
<StackPanel Grid.Column="2"> <Label Content="Výpočet:" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center"/> <Button Name="BtnMinimum" Content="Minimum" Margin="5" Padding="10,5" Click="BtnMinimum_Click"/> <Button Name="BtnMaximum" Content="Maximum" Margin="5" Padding="10,5" Click="BtnMaximum_Click"/> <Button Name="BtnPrumer" Content="Průměr" Margin="5" Padding="10,5" Click="BtnPrumer_Click"/> <Button Name="BtnSeradit" Content="Seřadit" Margin="5" Padding="10,5" Click="BtnSeradit_Click"/> <Button Name="BtnTranspoziceHlavni" Content="Transpozice - hlavní diagonála" Margin="5" Padding="10,5" Click="BtnTranspoziceHlavni_Click"/> <Button Name="BtnTranspoziceVedlejsi" Content="Transpozice - vedlejší diagonála" Margin="5" Padding="10,5" Click="BtnTranspoziceVedlejsi_Click"/> </StackPanel>
Kód 4: StackPanel - tlačítka pro operace s prvky matice
Pod komentář Konec umístíme objekt typu WrapPanel, který zarovnáme k pravému okraji. Do tohoto objektu umístíme tlačítko Konec, pomocí kterého uživatel zavře formulář. Nastavíme velikost vnějšího okraje (vlastnost Margin) a šířku tlačítka nastavíme na 100 pixelů - viz Kód 5.
<!-- Konec --> <WrapPanel HorizontalAlignment="Right"> <Button Name="BtnKonec" Content="Konec" Margin="5" Width="100" Padding="5" Click="BtnKonec_Click"/> </WrapPanel>
Kód 5: WrapPanel - tlačítko pro zavření formuláře
Formulář
Navržené rozložení prvků ve třetím řádku základní mřížky na formuláři v této části etapy je vidět na následujícím obrázku - viz Obrázek 1.
Obrázek 1: Rozpracovaný formulář WPF aplikace - třetí řádek základní mřížky
Objekty na formuláři:
Formulář v třetím řádku základní mřížky formuláře obsahuje následující objekty (kontrolky):
- StackPanel (4x)
- Grid
- Label (3x)
- WrapPanel
- Button: BtnNahodne, BtnJednotlive, BtnNulovat, BtnJakoText, BtnDoMrizky, BtnMinimum, BtnMaximum, BtnPrumer, BtnSeradit, BtnKonec, BtnTranspoziceHlavni, BtnTranspoziceVedlejsi
které jsou umístěny následujícím způsobem - viz Obrázek 2.
Obrázek 2: VS - okno Document Outline - seznam objektů - třetí řádek základní mřížky
3.4. XAML - prvky formuláře
Následující XAML kód obsahuje nastavení formuláře - viz Kód 1. Pokud je zapotřebí zkopírujte XAML kód a vložte jej namísto řádky s nastavením vlastností okna (řádek začíná Title=....).
Title="Základní práce s maticí" Height="850" Width="850" MinHeight="800" MinWidth="800">
Kód 1: Nastavení vlastností formuláře
Grid
Následující zdrojový kód XAML obsahuje potřebné prvky na formuláři pro řešení úlohy, bez nastavení událostí - viz Kód 2. Pokud je zapotřebí, zkopírujte XAML kód a vložte jej mezi počáteční a koncovou značku prvku Grid.<Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <!-- Nastavení matice --> <GroupBox Header="Nastavení matice"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Label Content="Matice" FontSize="18" FontWeight="Bold" HorizontalAlignment="Center" /> <Grid Grid.Row="1"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <!-- Rozměry matice --> <GroupBox Header="Rozměry matice"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Label Content="Počet řádků:" VerticalAlignment="Center"/> <TextBox Name="TxtPocetRadku" Grid.Column="1" Width="100" Margin="5" Padding="5"/> <Label Content="Počet sloupců:" Grid.Row="1" VerticalAlignment="Center"/> <TextBox Name="TxtPocetSloupcu" Grid.Row="1" Grid.Column="1" Width="100" Margin="5" Padding="5"/> </Grid> </GroupBox> <!-- Hodnoty - meze --> <GroupBox Header="Hodnoty - meze" Grid.Column="1"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Label Content="Minimum:" VerticalAlignment="Center"/> <TextBox Name="TxtMinHodnota" Grid.Column="1" Width="100" Margin="5" Padding="5"/> <Label Content="Maximum:" Grid.Row="1" VerticalAlignment="Center"/> <TextBox Name="TxtMaxHodnota" Grid.Row="1" Grid.Column="1" Width="100" Margin="5" Padding="5"/> </Grid> </GroupBox> <!-- Prvek v matici --> <GroupBox Header="Prvek v matici" Grid.Column="3"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Label Content="Index řádku:" Grid.Row="0" Grid.Column="0"/> <TextBox Name="TxtPrvekIndexRadku" Grid.Row="0" Grid.Column="1" Width="100" Margin="5" Padding="5"/> <Label Content="Index sloupce:" Grid.Row = "1" Grid.Column="0"/> <TextBox Name="TxtPrvekIndexSloupce" Grid.Row="1" Grid.Column="1" Width="100" Margin="5" Padding="5"/> <Label Content="Hodnota:" Grid.Row="0" Grid.Column="2"/> <TextBox Name="TxtHodnota" Grid.Row="0" Grid.Column="3" Width="100" Margin="5" Padding="5"/> </Grid> </GroupBox> </Grid> </Grid> </GroupBox> <!-- Zobrazení matice --> <GroupBox Header="Zobrazení matice" Grid.Row="1"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <!-- Matice --> <GroupBox Header="Mřížka" Margin="5" MinHeight="100"> <ListView Name="LstMatice" ScrollViewer.VerticalScrollBarVisibility="Auto"/> </GroupBox> <!-- Výsledek --> <GroupBox Header="Jako text (nebo výpis výsledku)" Grid.Column="2" Margin="5"> <TextBox Name="TxtVysledek" Margin="5" ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollBarVisibility="Visible" IsReadOnly="True" Background="AliceBlue"/> </GroupBox> </Grid> </GroupBox> <!-- Tlačítka - sekce: Plnit, Výstup, Výpočet --> <StackPanel Grid.Row="4"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <!-- Plnit --> <StackPanel > <Label Content="Plnit:" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center"/> <Button Name="BtnNahodne" Content="Náhodně" Margin="5" Padding="10,5"/> <Button Name="BtnJednotlive" Content="Jednotlivě" Margin="5" Padding="10,5"/> <Button Name="BtnNulovat" Content="Nulovat" Margin="5" Padding="10,5"/> </StackPanel> <!-- Výstup --> <StackPanel Grid.Column="1"> <Label Content="Výstup:" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center"/> <Button Name="BtnJakoText" Content="Jako text" Margin="5" Padding="10,5"/> <Button Name="BtnDoMrizky" Content="Do mřížky" Margin="5" Padding="10,5"/> </StackPanel> <!-- Výpočet --> <StackPanel Grid.Column="2"> <Label Content="Výpočet:" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center"/> <Button Name="BtnMinimum" Content="Minimum" Margin="5" Padding="10,5"/> <Button Name="BtnMaximum" Content="Maximum" Margin="5" Padding="10,5"/> <Button Name="BtnPrumer" Content="Průměr" Margin="5" Padding="10,5"/> <Button Name="BtnSeradit" Content="Seřadit" Margin="5" Padding="10,5"/> <Button Name="BtnTranspoziceHlavni" Content="Transpozice - hlavní diagonála" Margin="5" Padding="10,5"/> <Button Name="BtnTranspoziceVedlejsi" Content="Transpozice - vedlejší diagonála" Margin="5" Padding="10,5"/> </StackPanel> </Grid> <!-- Konec --> <WrapPanel HorizontalAlignment="Right"> <Button Name="BtnKonec" Content="Konec" Margin="5" Width="100" Padding="5"/> </WrapPanel> </StackPanel>
Kód 2: Prvky v Grid
4. C#
V souboru MainWindow.xaml.cs obsahující kód na pozadí (Code Behind) byla vygenerována základní struktura našeho programu v C#. Vedle konstruktoru MainWindow této třídy byly také vygenerovány soukromé (private) metody bez návratu, které umístíme do oblasti Události:
- TxtPocetRadku_LostFocus
- TxtPocetSloupcu_LostFocus
- TxtMinHodnota_LostFocus
- TxtMaxHodnota_LostFocus
- TxtPrvekIndexRadku_LostFocus
- TxtPrvekIndexSloupce_LostFocus
- TxtHodnota_LostFocus
- BtnNahodne_Click
- BtnJednotlive_Click
- BtnNulovat_Click
- BtnJakoText_Click
- BtnDoMrizky_Click
- BtnMinimum_Click
- BtnMaximum_Click
- BtnPrumer_Click
- BtnSeradit_Click
- BtnTranspoziceHlavni_Click
- BtnTranspoziceVedlejsi_Click
- BtnKonec_Click
Vzhledem k tomu, že C# kód bude rozsáhlejší, bude vhodné použít značky regionů, kde pro větší přehlednost uvedeme název regionu jak za počáteční značkou regionu (#region), tak i za koncovou značkou (#endregion). Vytvoříme si následující regiony, které budou obsahovat další vnořené regiony. U již vygenerovaných metod si také uvedeme, do kterého regionu budou patřit:
- Datové složky třídy
- Pomocné metody
- Nastavení atributů pole
- Zobrazení pole
- Plnění pole
- Operace s polem
- Události
- Nastavení atributů pole - region bude obsahovat následující metody:
- TxtPocetRadku_LostFocus
- TxtPocetSloupcu_LostFocus
- TxtMinHodnota_LostFocus
- TxtMaxHodnota_LostFocus
- TxtPrvekIndexRadku_LostFocus
- TxtPrvekIndexSloupce_LostFocus
- TxtHodnota_LostFocus
- Plnění pole - region bude obsahovat následující metody:
- BtnNahodne_Click
- BtnJednotlive_Click
- BtnNulovat_Click
- Zobrazení pole - region bude obsahovat následující metody:
- BtnJakoText_Click
- BtnDoMrizky_Click
- Operace s polem - region bude obsahovat následující metody:
- BtnMinimum_Click
- BtnMaximum_Click
- BtnPrumer_Click
- BtnSeradit_Click
- BtnTranspoziceHlavni_Click
- BtnTranspoziceVedlejsi_Click
- BtnKonec_Click
Takto vytvořené regiony lze sbalit, nebo rozbalit a přehledně si tak můžeme zobrazit pouze ty metody, které nás zajímají.
Do regionu Datové složky třídy si umístíme seznam jednotlivých datových složek složek třídy (atributů částečné třídy MainWindow), do nichž budeme ukládat a nebo načítat hodnoty. V podstatě se jedná o proměnné, které lze využívat v rámci celé třídy (globální proměnné) - viz Kód 1. Hodnoty v datových složkách využijeme pro specifikaci atributů matice - rozměru a intervalu přípustných hodnot prvků matice. Uveďme pro úplnost, že datové složky jsou přístupné pouze uvnitř třídy (modifikátor přístupu private). Jedna z datových složek s názvem Max je konstantní (klíčové slovo const), tzn. se nebude v průběhu programu měnit. V tomto regionu budeme také deklarovat samotné dvourozměrné pole (matici) obsahující celá čísla.
Oproti minulému příkladu JednorozmernePoleWPF umístíme do konstruktoru MainWindow volání metody Inicializace, která nám zajistí vyplnění hodnot v příslušných objektech na formuláři na základě hodnot jednotlivých datových složek třídy - viz Kód 1. Tato metoda bude popsána v následující kapitole.
namespace DvourozmernePoleWPF { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { #region Datové složky třídy (globální proměnné) /* Specifikace konstanty pro maximální vertikální (počet řádků) a horizontální * (počet sloupců) rozměr matice - inicializace */ const int Max = 10; // Aktuální rozměr pole - počet řádků private int pocetRadku; // Aktuální rozměr pole - počet sloupců private int pocetSloupcu; // Přípustná minimální hodnota (dolní mez) prvku - inicializace private int minHodnota = 1; // Přípustná maximální hodnota (horní mez) prvku - inicializace private int maxHodnota = 100; // Deklarace dvourozměrného pole - matice private int[,] pole; #endregion Datové složky třídy public MainWindow() { InitializeComponent(); //Inicializace atributů pole a prvků na formuláři Inicializace(); } } }
Kód 1: Deklarace datových složek třídy a volání metody Inicializace v konstruktoru
4.1. Nastavení atributů pole
Metodu Inicializace umístíme do regionu Nastavení atributů pole, který bude součástí regionu Pomocné metody. Jak již bylo řečeno, tato metoda nám zajistí potřebnou inicializaci datových složek třídy a také vyplnění hodnot v objektech na formuláři pomocí těchto hodnot - viz Kód 1. K přístupu k jednotlivým datovým složkám třídy využijeme klíčové slovo this spolu s tečkou za tímto slovem (tečková notace).
Budeme také muset vytvořit instanci třídy - objekt - dvourozměrného pole (matice) s definovanou délkou. Do této matice budeme ukládat hodnoty, vypisovat hodnoty a nebo s ní budeme provádět různé operace. Vytvoření matice provedeme pomocí implicitního konstruktoru (VS ho vytvořil za nás), který přijímá parametr (hodnotu v datové složce pocetRadku a pocetSloupcu) určující velikosti v každé ose naší celočíselné matice. Tyto parametry jsou umístěny v hranatých závorkách, kde první parametr určuje počet řádků a druhý počet sloupců vytvořené matice. Konstruktor matice voláme pomocí klíčového slova new. Vytvořenou instanci přiřadíme do datové složky pole v naší třídě.
#region Nastavení atributů pole /// <summary> /// Inicializace atributů pole a prvků na formuláři /// </summary> private void Inicializace() { // Přiřazení maximálního počtu řádků matice do datové složky this.pocetRadku = Max; // Přiřazení maximálního počtu sloupců matice do datové složky this.pocetSloupcu = Max; // Vytvoření instance (objektu) matice s definovanými rozměry this.pole = new int[this.pocetRadku, this.pocetSloupcu]; // Přiřazení počtu řádků matice do objektu na formuláři this.TxtPocetRadku.Text = this.pocetRadku.ToString(); // Přiřazení počtu sloupců matice do objektu na formuláři this.TxtPocetSloupcu.Text = this.pocetSloupcu.ToString(); /* Přiřazení přípustné minimální hodnoty prvku v matici do objektu * na formuláři určujícího mezní hodnotu */ this.TxtMinHodnota.Text = this.minHodnota.ToString(); /* Přiřazení přípustné maximální hodnoty prvku v matici do objektu (pole) * na formuláři určujícího mezní hodnotu */ this.TxtMaxHodnota.Text = this.maxHodnota.ToString(); } #endregion Nastavení atributů pole
Kód 1: Deklarace metody bez návratu s názvem Inicializace
Pojďme se nyní podívat na metody umístěné v regionu Události, tj. metody pro obsluhu událostí objektů formuláře. Tento region obsahuje další regiony, ale my se nyní zaměříme na region Nastavení atributů pole, který bude obsahovat následující metody:
- TxtPocetRadku_LostFocus
- TxtPocetSloupcu_LostFocus
- TxtMinHodnota_LostFocus
- TxtMaxHodnota_LostFocus
- TxtPrvekIndexRadku_LostFocus
- TxtPrvekIndexSloupce_LostFocus
- TxtHodnota_LostFocus
První metodou, kterou budeme muset upravit je metoda obsluhy události opuštění objektu TxtPocetRadku pro specifikaci počtu řádků matice, tj. vertikální rozměr dvourozměrného pole - viz Kód 2. Pro popis metody využijeme trojitého lomítka, po jehož zadání nad název metody Visual Studio vygeneruje poznámky k dokumentaci ve formě XML prvků přidaných do zdrojového kódu. U těchto prvků budeme specifikovat pouze popis účelu metody. Parametr sender u metody představuje objekt, ke kterému je přidružena metoda obsluhy události v tomto případě TxtPocetRadku. Další formální parametr e představuje data o události. Tyto popisy jsou u metod obsluhy události přidružených k objektům stejné, proto je již v dalších XML značkách nebudeme popisovat.
V metodě deklarujeme lokální proměnnou novaHodnota, do níž budeme ukládat načtenou hodnotu z objektu na formuláři pro specifikaci počtu řádků matice. Po načtení textu z objektu na formuláři (vlastnost Text) provedeme test, zda lze text převést na celé číslo pomocí metody TryParse přidružené k třídě (datovému typu) int. Metoda navrací logickou hodnotu (true nebo false), zda lze konverzi provést, či nikoliv. U metody využijeme výstupní parametr (klíčové slovo out) novaHodnota. Znamená to, že pokud nebude provedena konverze, do parametru bude uložena předdefinovaná hodnota pro typ int, tj. hodnota 0. V následující podmínce testujeme, zda hodnota náleží intervalu 1 až maximální rozměr matice (hodnota je uložena v konstantě Max). Pokud není, přiřadíme do lokální proměnné novaHodnota maximální rozměru ve vertikální směru, tj. počtu řádků matice. Pokud uživatel provedl chybné nastavení rozměru matice, je vhodné ho o této situaci informovat. To provedeme pomocí dialogového okna (třída MessageBox metoda Show). Pro konverzi číselné hodnoty na text uvedené ve výpisu můžeme použít metodu Format třídy String (pokud Vám tento přístup nevyhovuje, můžete místo něho využít metodu ToString). Výhodou této metody je, že ve výpisu využijeme indexaci proměnných pomocí složené závorky, do níž uvedeme index proměnné, jejíž hodnotu chceme v textu vypsat. Chybu vyřešíme nastavením rozměru matice na maximální povolený rozměr, tj. konstanta Max. Musíme zároveň vypsat tento nový rozměr do objektu pro specifikaci počtu řádků matice umístěného na formuláři.
Pokud nový počet řádků matice není stejný jako stávající počet řádků matice, pak touto novou hodnotou musíme přepsat stávající počet řádků matice uložený v datové složce třídy s názvem pocetRadku. S tím také souvisí vytvoření nové instance pole s novým rozměrem (v podstatě staré pole je odstraněno tak, že je vytvořeno nové pole a datová složka pole nyní odkazuje na toto nové pole. Nová matice obsahuje samé 0, což je předefinovaná hodnota pro datový typ int). Pro zobrazení hodnot nové matice použijeme dvě metody. První metoda ZobrazitPoleJakoText zobrazí prvky nové matice (které budou odděleny čárkou) v objektu TextBox umístěného na formuláři. Další volání metody ZobrazitPoleVListView zobrazí prvky jednotlivé řádky matice v objektu LstMatice typu ListView. Parametrem je samotná matice. Obě metody si budeme deklarovat později v kapitole Zobrazení pole.
/// <summary> /// Validace počtu řádků matice /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TxtPocetRadku_LostFocus(object sender, RoutedEventArgs e) { // Lokální proměnná: 'novaHodnota' - nový počet řádků matice int novaHodnota; /* Přiřazení počtu řádků z objektu na formuláři do lokální proměnné * určující počet řádků matice */ int.TryParse(this.TxtPocetRadku.Text, out novaHodnota); /* Pokud počet řádků je větší než maximální počet řádků matice, nebo počet * řádků matice je menší než 1, pak... */ if ((novaHodnota > Max) || (novaHodnota < 1)) { // Zobrazení dialogového okna s textem a hodnotou max. počtu řádků matice MessageBox.Show(String.Format("Chyba rozměru matice, nastavení na max. počet řádků: {0}", Max)); /* Přiřazení maximálního rozměru matice do lokální proměnné určující * počet řádků matice */ novaHodnota = Max; // Přiřazení maximálního počtu řádků matice do objektu na formuláři this.TxtPocetRadku.Text = Max.ToString(); } // Pokud nový počet řádků matice není stejný jako stávající počet řádků matice, pak... if (novaHodnota != this.pocetRadku) { // Uložení nového počtu řádků matice do datové složky třídy this.pocetRadku = novaHodnota; // Vytvoření nové instance matice s novým počtem řádků this.pole = new int[this.pocetRadku, this.pocetSloupcu]; // Zavolání metody pro zobrazení matice do objektu TextBox na formuláři this.ZobrazitPoleJakoText(this.pocetRadku, this.pocetSloupcu, this.pole); // Zavolání metody pro zobrazení matice do objektu ListView na formuláři this.ZobrazitPoleVListView(this.pocetRadku, this.pocetSloupcu, this.pole); }
Kód 2: Deklarace metody při opuštění objektu pro specifikaci počtu řádků matice (TxtPocetRadku_LostFocus)
/// <summary> /// Validace počtu sloupců matice /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TxtPocetSloupcu_LostFocus(object sender, RoutedEventArgs e) { // Lokální proměnná: 'novaHodnota' - nový počet sloupců matice int novaHodnota; /* Přiřazení počtu sloupců z objektu na formuláři do lokální proměnné * určující počet sloupců matice */ int.TryParse(this.TxtPocetSloupcu.Text, out novaHodnota); /* Pokud počet sloupců je větší než maximální počet sloupců matice, nebo počet * řádků sloupců je menší než 1, pak... */ if ((novaHodnota > Max) || (novaHodnota < 1)) { // Zobrazení dialogového okna s textem a hodnotou max. počtu sloupců matice MessageBox.Show(String.Format("Chyba rozměru matice, nastavení na max. počet sloupců: {0}", Max)); /* Přiřazení maximálního rozměru matice do lokální proměnné určující * počet sloupců matice */ novaHodnota = Max; // Přiřazení maximálního počtu sloupců matice do objektu na formuláři this.TxtPocetSloupcu.Text = Max.ToString(); } // Pokud nový počet sloupců matice není stejný jako stávající počet sloupců matice, pak... if (novaHodnota != this.pocetSloupcu) { // Uložení nového počtu sloupců matice do datové složky třídy this.pocetSloupcu = novaHodnota; // Vytvoření nové instance matice s novým počtem sloupců this.pole = new int[this.pocetRadku, this.pocetSloupcu]; // Zavolání metody pro zobrazení matice do objektu TextBox na formuláři this.ZobrazitPoleJakoText(this.pocetRadku, this.pocetSloupcu, this.pole); // Zavolání metody pro zobrazení matice do objektu ListView na formuláři this.ZobrazitPoleVListView(this.pocetRadku, this.pocetSloupcu, this.pole); } }
Kód 3: Deklarace metody při opuštění objektu pro specifikaci počtu sloupců matice (TxtPocetSloupcu_LostFocus)
Další metodou v regionu je metoda obsluhy události opuštění objektu TxtMinHodnota pro specifikaci dolní meze intervalu přípustných hodnot prvků matice - viz Kód 4. Po provedení konverze (v případě neprovedení konverze je do dolní meze uložena předdefinovaná hodnota pro typ int, tedy 0 - využití výstupního parametru out) je dolní mez testována, zda nepřekračuje hodnotu horní meze. Pokud ano, je dolní mez nastavena na hodnotu horní meze včetně zobrazení informace pro uživatele o této chybě pomocí dialogového okna. Hodnota dolní meze je také přepsána v objektu na formuláři.
/// <summary> /// Validace dolní meze intervalu přípustných hodnot prvků matice /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TxtMinHodnota_LostFocus(object sender, RoutedEventArgs e) { /* Přiřazení dolní meze z objektu na formuláři do datové složky třídy určující * dolní mez intervalu přípustných hodnot */ int.TryParse(this.TxtMinHodnota.Text, out this.minHodnota); // Pokud nová dolní mez je větší než stávající horní mez, pak... if (this.minHodnota > this.maxHodnota) { // Zobrazení dialogového okna s chybou a nastavení dolní meze na horní mez MessageBox.Show(String.Format("Chyba hodnoty dolní meze - dolní mez nastavena na horní mez: {0}", this.maxHodnota)); // Dolní mez je nastavena na hodnotu horní meze this.minHodnota = this.maxHodnota; // Zobrazení hodnoty dolní meze na formuláři this.TxtMinHodnota.Text = minHodnota.ToString(); } }
Kód 4: Deklarace metody při opuštění objektu pro dolní mez intervalu přístupných hodnot prvků matice (TxtMinHodnota_LostFocus)
Další obdobnou metodou je metoda obsluhy události opuštění objektu TxtMaxHodnota pro specifikaci horní meze intervalu přípustných hodnot prvků matice - viz Kód 5. Princip metody je obdobný jako v předchozí metodě.
/// <summary> /// Validace horní meze intervalu přípustných hodnot prvků matice /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TxtMaxHodnota_LostFocus(object sender, RoutedEventArgs e) { /* Přiřazení horní meze z objektu na formuláři do datové složky třídy určující * horní mez intervalu hodnot, kterých mohou nabývat prvky v matici */ int.TryParse(this.TxtMaxHodnota.Text, out this.maxHodnota); // Pokud nová horní mez je menší než stávající dolní mez, pak... if (this.maxHodnota < this.minHodnota) { // Zobrazení dialogového okna s chybou a nastavení horní meze na dolní mez MessageBox.Show(String.Format("Chyba hodnoty horní meze - horní mez nastavena na dolní mez: {0}", this.minHodnota)); // Horní mez je nastavena na hodnotu dolní meze this.maxHodnota = this.minHodnota; // Zobrazení hodnoty horní meze na formuláři this.TxtMaxHodnota.Text = maxHodnota.ToString(); } }
Kód 5: Deklarace metody při opuštění objektu pro horní mez intervalu přístupných hodnot prvků matice (TxtMaxHodnota_LostFocus)
Další metodou v regionu je metoda obsluhy události opuštění objektu TxtPrvekIndexRadku pro specifikaci indexu řádku u prvku při ručním plnění matice- viz Kód 6. Po provedení konverze (v případě neprovedení konverze je do indexu uložena předdefinovaná hodnota pro typ int, tedy 0 - využití výstupního parametru out) je index testován, zda nepřekračuje počet řádků matice - 1, nebo zda není menší než 0 (index počátečního prvku je 0). Pokud ano, je index nastaven na horní přípustnou mez, tj. počet řádků matice - 1 a tato hodnota je vypsána do objektu na formuláři. Zároveň je provedeno zobrazení informace pro uživatele o této chybě pomocí dialogového okna.
/// <summary> /// Validace indexu řádku prvku matice při ručním plnění /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TxtPrvekIndexRadku_LostFocus(object sender, RoutedEventArgs e) { // Lokální proměnná: 'index' - index řádku prvku matice int index; // Uložení indexu řádku prvku do lokální proměnné (konverze textu na celé číslo) int.TryParse(this.TxtPrvekIndexRadku.Text, out index); /* Pokud index řádku prvku je větší než počet řádků matice - 1, nebo index řádku prvku je * menší než 0, pak... */ if ((index > this.pocetRadku - 1) || (index < 0)) { // Zobrazení dialogového okna s chybou a nastavení indexu na počet řádků matice - 1 MessageBox.Show(String.Format("Chybný index řádku prvku. Index nastaven na horní mez: {0}", this.pocetRadku - 1)); // Přiřazení horní meze indexu do objektu na formuláři určujícího index řádku prvku matice this.TxtPrvekIndexRadku.Text = String.Format("{0}", this.pocetRadku - 1); } }
Kód 6: Deklarace metody při opuštění objektu pro specifikaci indexu řádku prvku matice při ručním plnění (TxtPrvekIndexRadku_LostFocus)
Další obdobnou metodou je metoda obsluhy události opuštění objektu TxtPrvekIndexSloupce pro specifikaci indexu sloupce prvku matice při ručním plnění - viz Kód 7. Princip metody je obdobný jako v předchozí metodě.
/// <summary> /// Validace indexu sloupce prvku matice při ručním plnění /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TxtPrvekIndexSloupce_LostFocus(object sender, RoutedEventArgs e) { // Lokální proměnná: 'index' - index sloupce prvku matice int index; // Uložení indexu sloupce prvku do lokální proměnné (konverze textu na celé číslo) int.TryParse(this.TxtPrvekIndexSloupce.Text, out index); /* Pokud index sloupce prvku je větší než počet sloupců matice - 1, nebo index sloupce prvku je * menší než 0, pak... */ if ((index > this.pocetSloupcu - 1) || (index < 0)) { // Zobrazení dialogového okna s chybou a nastavení indexu na počet sloupců matice - 1 MessageBox.Show(String.Format("Chybný index sloupce prvku. Index nastaven na horní mez: {0}", this.pocetSloupcu - 1)); // Přiřazení horní meze indexu do objektu na formuláři určujícího index sloupce prvku matice this.TxtPrvekIndexSloupce.Text = String.Format("{0}", this.pocetSloupcu - 1); } }
Kód 6: Deklarace metody při opuštění objektu pro specifikaci indexu sloupce prvku matice při ručním plnění (TxtPrvekIndexSloupce_LostFocus)
Poslední metodou v regionu je metoda obsluhy události opuštění objektu TxtHodnota pro specifikaci hodnoty prvku na určené pozici (index řádku a sloupce) při ručním plnění matice- viz Kód 7. Po provedení konverze je hodnota prvku testována, zda nepřekračuje horní mez intervalu přípustných hodnot prvků, nebo zda není menší než dolní mez intervalu přípustných hodnot prvků matice. Pokud ano, je zadaná hodnota prvku v objektu na formuláři vymazána pomocí metody Clear objektu TxtHodnota. Zároveň uživateli v dialogovém okně zobrazena tato chyba, včetně výpisu dolní a horní meze intervalu přípustných hodnot prvků matice.
/// <summary> /// Validace hodnoty prvku matice při ručním plnění /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TxtHodnota_LostFocus(object sender, RoutedEventArgs e) { // Lokální proměnná: 't' - hodnota prvku int t; // Uložení hodnoty prvku do lokální proměnné (konverze textu na celé číslo) int.TryParse(this.TxtHodnota.Text, out t); /* Pokud hodnota prvku je větší než horní mez, nebo hodnota prvku je * menší než dolní mez intervalu hodnot v matici, pak... */ if ((t > this.maxHodnota) || (t < this.minHodnota)) { // Zobrazení dialogového okna s textem chyby a hodnotami mezí MessageBox.Show(String.Format("Hodnota prvku není v intervalu: {0} až {1}", this.minHodnota, this.maxHodnota)); // Vymázání obsahu objektu na formuláři s hodnotou prvku this.TxtHodnota.Clear(); } }
Kód 7: Deklarace metody při opuštění objektu pro specifikaci hodnoty prvku při ručním plnění prvku matice (TxtHodnota_LostFocus)
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)
4.3. Zobrazení pole
Pojďme se nyní podívat na metody umístěné v regionu Zobrazení pole, který je součástí regionu Události, ve kterém jsou umístěny metody pro obsluhu událostí objektů formuláře. Tento region obsahuje následující metody:
- BtnJakoText_Click
- BtnDoMrizky_Click
Abychom mohli matici zobrazit jako text v objektu typu TextBox, je zapotřebí převést její obsah na text. V regionu Zobrazení pole, který je součástí regionu Pomocné metody, budeme deklarovat metodu PoleJakoText, která navrací textový řetězec, který bude obsahovat hodnoty jednotlivých prvků matice, které budou vypsány v jednotlivých řádcích a sloupcích - viz Kód 1. Hodnoty budou od sebe odděleny čárkou.
V metodě deklarujeme pomocnou lokální proměnnou vystup, do níž budeme ukládat výstupní řetězec. Lokální proměnnou budeme inicializovat prázdným textem. V cyklech s krokem (vnější cyklus bude použit pro procházení řádků a vnější pro procházení sloupců) budeme procházet prvky matice. V těle cyklu použijeme konverzi třídy string, kde za každé vypsané číslo do výstupního řetězce umístíme čárku. K tomu použijeme metodu Format, která nám převede číslo uložené v prvku na pozici [i, j]. Hodnota čísla prvku (je indexována 0 ve složené závorce) je převedena do specifikovaného formátu, tj. na 3 číslice (formát D3). Tato metoda je součástí třídy (datového typu) string.
Pokud byly vypsány prvky ve všech sloupcích v řádku, umístíme do výsledného výpisu nový odstavec pomocí vlastnosti NewLine třídy Environment.
Návratem metody je výsledný textový řetězec obsahující vypsané prvky matice.
/// <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 v objektu /// </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> private 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 metody pro převod prvků předané matice do textového řetězce - oddělení prvků čárkami (PoleJakoText)
Další metodou, kterou budeme muset přidat do stejného regionu, je metoda bez návratu s názvem ZobrazitPoleJakoText, která zajistí zobrazení matice v objektu typu TextBox s názvem TxtVysledek, který je umístěn na formuláři - viz Kód 2. V těle metody budeme volat předchozí deklarovanou metodu PoleJakoText, které předáme hodnotou počet prvků a vektor. Výstupní řetězec, obdržený jako návrat volané metody, přiřadíme do vlastnosti Text objektu TxtVysledek.
/// <summary> /// Zobrazení matice na formuláři jako text v objektu typu TextBox /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> matice </param> private void ZobrazitPoleJakoText(int m, int n, int[,] pole) { // Výpis matice v objektu typu TextBox na formuláři this.TxtVysledek.Text = this.PoleJakoText(m, n, pole); }
Kód 2: Deklarace metody pro zavolání metody pro převod prvků matice na textový řetězec (ZobrazitPoleJakoText)
Abychom přiřadili akci tlačítku, které spustí zobrazení matice jako text, přemístíme se do regionu Události a jeho části Zobrazení pole. V tomto regionu upravíme metodu obsluhy události stisknutí tlačítka BtnJakoText, která bude volat předchozí metodu ZobrazitPoleJakoText - viz Kód 3. Této metodě předáme předáme parametry, kterými jsou počet řádků matice, počet sloupců matice a samotná matice.
/// <summary> /// Volání metody pro zobrazení matice jako text v objektu typu TextBox na formuláři /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnJakoText_Click(object sender, RoutedEventArgs e) { // Zavolání metody pro zobrazení matice jako text v objektu na formuláři this.ZobrazitPoleJakoText(this.pocetRadku, this.pocetSloupcu, this.pole); }
Kód 3: Deklarace metody pro zavolání metody pro zobrazení matice jako text v objektu na formuláři (BtnJakoText_Click)
Další metodou, kterou budeme deklarovat v regionu Pomocné metody v regionu Zobrazení pole, je soukromá metoda bez návratu s názvem ZobrazitPoleVListView - viz Kód 4. V tomto případě jsou metodě předány parametry vyjadřující počet řádků matice, počet sloupců matice a matice samotná. Na začátku metody deklarujeme textovou proměnnou radka, do níž budeme ukládat obsah řádku matice, který budeme vypisovat do řádku v objektu LstMatice, který je typu ListView. Proto nejprve vymažeme předchozí obsah zobrazený v tomto objektu pomocí metody Clear. To provedeme pomocí tečkové notace u objektu. Pomocí dvou cyklů s krokem (vnější - procházení řádků, vnitřní - procházení sloupců) budeme procházet jednotlivé prvky matice. Ve vnitřním cyklu budeme jednotlivé prvky řádky matice umísťovat do proměnné radka a po ukončení tohoto cyklu proměnnou vypíšeme do objektu LstMatice pomocí vlastnosti Items (kolekce prvků objektu), kterou vyvoláme pomocí tečkové notace. U této vlastnosti lze volat metodu s návratem Add, pomocí které přidáme (vypíšeme) řádek matice (uložený v proměnné radek) do objektu LstMatice. Návrat metody Add vyjadřuje zda byl předaný objekt přidán (hodnota 0), nebo zda nešel přidat (hodnota -1) do objektu LstMatice.
/// <summary> /// Zobrazení prvků matice na formuláři v objektu typu ListView /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> matice </param> private void ZobrazitPoleVListView(int m, int n, int[,] pole) { // Lokální proměnná: 'radka' - řádka matice převedená na text string radka; // Vymazání předchozí obsahu (přidaných prvků) this.LstMatice.Items.Clear(); // Procházení řádků matice for (int i = 0; i < m; i++) { // Vymazání předchozího obsahu řádky (textového řetězce) radka = ""; // Procházení sloupců matice for (int j = 0; j < n; j++) { // Převod hodnoty prvku na text včetně připojení čárky radka += string.Format("{0:D3}, ", pole[i, j]); } // Přidání textového řetězce (řádky matice) do obsahu objektu this.LstMatice.Items.Add(radka); } }
Kód 4: Deklarace metody pro zobrazení prvků předané matice v objektu typu ListView (ZobrazitPoleVListView)
Kvůli úpravě metody pro obsluhy události stisknutí tlačítka BtnDoMrizky se přemístíme se zpět do regionu Události a jeho části Zobrazení pole. V rámci těla metody budeme volat předchozí deklarovanou metodu ZobrazitPoleVListView, které předáme jako parametry počet řádků a sloupců matice a matici - viz Kód 5.
/// <summary> /// Volání metody pro zobrazení prvků matice v objektu typu ListView na formuláři /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnDoMrizky_Click(object sender, RoutedEventArgs e) { // Zavolání metody pro zobrazení prvků matice do mřížky na formuláři this.ZobrazitPoleVListView(this.pocetRadku, this.pocetSloupcu, this.pole); }
Kód 5: Deklarace metody pro zavolání metody pro zobrazení matice v objektu typu ListView na formuláři (BtnDoMrizky_Click)
4.4. Operace s polem
V následujících kapitolách se zaměříme na metody pro obsluhu událostí objektů formuláře umístěné v regionu Operace s polem, který je součástí regionu Události. Tento region obsahuje následující metody:
- BtnMinimum_Click
- BtnMaximum_Click
- BtnPrumer_Click
- BtnSeradit_Click
- BtnTranspoziceHlavni_Click
- BtnTranspoziceVedlejsi_Click
Nezapomínejme také na metodu pro zavření formuláře. Tato metoda obsluhy stisknutí tlačítka BtnKonec bude vypadat následovně - viz Kód 1. Metoda je taktéž umístěna v regionu Události.
/// <summary> /// Metoda pro zavření formuláře /// </summary> private void BtnKonec_Click(object sender, RoutedEventArgs e) { // Zavření formuláře this.Close(); }
Kód 1: Deklarace metody bez návratu pro zavření formuláře (BtnKonec_Click)
4.5. Minimum a maximum pole
Abychom mohli nalézt ve matici její nejmenší prvek, tj. minimum, musíme nejprve deklarovat metodu, která bude prohledávat a porovnávat prvky matice s dosud nejmenším nalezeným prvkem. Proto v regionu Operace s polem, která je součástí regionu Pomocné metody, budeme deklarovat metodu MinimumVPoli, která navrací celočíselnou hodnotu minima, a zároveň má tato metoda výstupní parametry (uvozený klíčovým slovem out), které představují index řádku a sloupce nalezeného minima - viz Kód 1.
V metodě je deklarována lokální proměnná minimum, do níž je uložena hodnota nejmenšího prvku matice. My však oproti hledání minima v jednorozměrném poli nyní využijeme jiný princip. Na začátku do proměnné minimum uložíme co nejvyšší hodnotu, tj. maximální hodnotu příslušného datového typu int. Je tedy zřejmé, že jakýkoliv prvek v matici může být stejný, nebo menší (což je vysoce pravděpodobné). Jako další krok provedeme inicializaci hodnotou -1 výstupních parametrů metody, které představují pozici minima v matici.
V metodě tradičně použijeme pro procházení prvků matice dva cykly s krokem. První pro procházení řádků, druhý pro procházení sloupců. Ve vnitřním cyklu je porovnán aktuální prvek s nejmenším dosud nalezeným prvkem, jehož hodnota je uložena v proměnné minimum. Podstata metody tkví v podmínce, že pokud aktuálně procházený prvek je menší než minimum, je hodnota tohoto prvku uložena do proměnné minimum. Zároveň musí být uložen index řádku a sloupce tohoto prvku matice.
Po ukončení průchodu všemi prvky matice je hodnota minima přiřazena výstupu metody.
/// <summary> /// Metoda pro hledání nejmenšího prvku v matici /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> matice </param> /// <param name="indexRadkuMinima"> index řádku minima </param> /// <param name="indexSloupceMinima"> index sloupce minima </param> /// <returns> celočíselná hodnota minima </returns> private int MinimumVPoli(int m, int n, int[,] pole, out int indexRadkuMinima, out int indexSloupceMinima) { // Lokální proměnné: 'i' - index řádku; 'j' - index sloupce; 'minimum' - hodnota minima int minimum; // Přiřazení maximální možné hodnoty datového typu int minimum = int.MaxValue; // Přiřazení hodnoty 0 do indexu řádku a sloupce minima - nutná inicializace indexRadkuMinima = indexSloupceMinima = -1; // Procházení řádků matice for (int i = 0; i < m; i++) { // Procházení sloupců matice for (int j = 0; j < n; j++) { // Pokud je nalezen prvek v matici, jehož hodnota je menší než minimum... if (pole[i, j] < minimum) { // Uložení hodnoty nalezeného prvku do minima minimum = pole[i, j]; // Přiřazení indexu řádku aktuálního prvku do indexu řádku minima indexRadkuMinima = i; // Přiřazení indexu sloupce aktuálního prvku do indexu sloupce minima indexSloupceMinima = j; } } } // Přiřazení hodnoty nalezeného minima do výstupu metody return minimum; }
Kód 1: Deklarace metody s návratem pro hledání minima matice včetně jeho pozice (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. V tomto případě však do proměnné maximum na začátku metody uložíme nejmenší možnou hodnotu datového typu int.
/// <summary> /// Metoda pro hledání největšího prvku v matici /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> matice </param> /// <param name="indRadkuMaxima"> index řádku maxima </param> /// <param name="indexSloupceMaxima"> index sloupce maxima </param> /// <returns> celočíselná hodnota maxima </returns> private int MaximumVPoli(int m, int n, int[,] pole, out int indRadkuMaxima, out int indexSloupceMaxima) { // Lokální proměnné: 'i' - index řádku; 'j' - index sloupce; 'maximum' - hodnota maxima int maximum; // Přiřazení nejmenší možné hodnoty datového typu int maximum = (-int.MaxValue - 1); // Přiřazení hodnoty 0 do indexu řádku a sloupce maxima - nutná inicializace indRadkuMaxima = indexSloupceMaxima = -1; // Procházení řádků matice for (int i = 0; i < m; i++) { // Procházení sloupců matice for (int j = 0; j < n; j++) { // Pokud je nalezen prvek v matici, jehož hodnota je větší než maximum... if (pole[i, j] > maximum) { // Uložení hodnoty nalezeného prvku do minima maximum = pole[i, j]; // Přiřazení indexu řádku aktuálního prvku do indexu řádku maxima indRadkuMaxima = i; // Přiřazení indexu sloupce aktuálního prvku do indexu sloupce maxima indexSloupceMaxima = j; } } } // Přiřazení hodnoty nalezeného maxima do výstupu metody return maximum; }
Kód 2: Deklarace metody s návratem pro hledání maxima matice včetně jeho pozice (MaximumVPoli)
Přemístíme se zpět do regionu Události a jeho části Operace s polem. V tomto regionu upravíme metodu obsluhy události stisknutí tlačítka BtnMinimum - viz Kód 3. V rámci těla metody budeme deklarovat lokální proměnnou minimum, do které uložíme návrat volané metody MinimumVPoli, které bude obsahovat pět parametrů. První a druhý parametr je počet řádků a počet sloupců matice, které jsou uloženy v datové složce třídy. Jako třetí parametr předáme matici. Čtvrtý výstupní parametr uvozený klíčovým slovem out představuje index řádku nalezeného minima v matici. Pátý výstupní parametr obsahuje index sloupce nalezeného minima. Obdržené celočíselné hodnoty hodnoty nalezeného minima a jeho pozice (uzavřené do hranatých závorek a oddělené čárkou) konvertujeme na text pomocí metody Format třídy string. Pro výpis hodnot použijeme indexaci prvků ve složených závorkách.
/// <summary> /// Volání metody pro určení minima a jeho pozice v matici /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnMinimum_Click(object sender, RoutedEventArgs e) { /* Lokální proměnné: 'minimum' - hodnota minima v matici; 'indexRadkuMinima' - * index řádku minima; 'indexSloupceMinima' - index sloupce minima */ int minimum; /* Přiřazení výstupu metody pro určení minima do lokální proměnné a výstupní parametry * určující index řádku ('indexRadkuMinima') a sloupce ('indexSloupceMinima') minima */ minimum = this.MinimumVPoli(this.pocetRadku, this.pocetSloupcu, this.pole, out int indexRadkuMinima, out int indexSloupceMinima); /* Zobrazení textu spolu s hodnotou minima a indexu řádku a sloupce minima * do objektu (TextBox) na formuláři */ this.TxtVysledek.Text = string.Format("Minimum = {0} (na pozici [{1}, {2}])", minimum, indexRadkuMinima, indexSloupceMinima); }
Kód 3: Deklarace metody pro zavolání metody pro hledání minima a jeho pozice - výpis na formuláři (BtnMinimum_Click)
Stejně jako u předchozí metody postupujeme v metodě BtnMaximum_Click umístěné ve stejném regionu - viz Kód 4.
/// <summary> /// Volání metody pro určení maxima a jeho pozice v matici /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnMaximum_Click(object sender, RoutedEventArgs e) { /* Lokální proměnné: 'maximum' - hodnota maxima v matici; 'indexRadkuMaxima' - * index řádku maxima; 'indexSloupceMaxima' - index sloupce maxima */ int maximum; /* Přiřazení výstupu metody pro určení maxima do lokální proměnné a výstupní parametry * určující index řádku ('indexRadkuMaxima') a sloupce ('indexSloupceMaxima') maxima */ maximum = this.MaximumVPoli(this.pocetRadku, this.pocetSloupcu, this.pole, out int indexRadkuMaxima, out int indexSloupceMaxima); /* Zobrazení textu spolu s hodnotou maxima a indexu řádku a sloupce maxima * do objektu (TextBox) na formuláři */ this.TxtVysledek.Text = string.Format("Maximum = {0} (na pozici [{1}, {2}])", maximum, indexRadkuMaxima, indexSloupceMaxima); }
Kód 4: Deklarace metody pro zavolání metody pro hledání maxima a jeho pozice - výpis na formuláři (BtnMaximum_Click)
4.6. Průměr pole
Pro výpočet aritmetického průměru ze všech prvků v matici je použita soukromá metoda PrumerPole, která je deklarována v regionu Operace s polem, která je součástí regionu Pomocné metody. Tato metoda navrací reálné číslo reprezentující vypočtený průměr. 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ů. 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 (pokud by byla suma celé číslo, bylo by provedeno celočíselné dělení). Počet prvků matice je roven součinu hodnoty počtu řádků a počtu sloupců uložených ve formálních parametrech m a n. Výsledek podílu sumy a počtu prvků je desetinné číslo, které je přiřazeno výstupu metody - viz Kód 1.
/// <summary> /// Metoda pro výpočet aritmetického průměru 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> /// <returns> hodnota aritmetického průměru (reálné číslo) </returns> private double PrumerPole(int m, int n, int[,] pole) { /* Lokální proměnné: 'i' ... index řádku matice; 'j'... index sloupce matice; * 'suma' - suma prvků matice */ int suma; // Nastavení počáteční hodnoty u sumy suma = 0; // Procházení řádků matice for (int i = 0; i < m; i++) { // Procházení sloupců matice for (int j = 0; j < n; j++) { // Přičtení dalšího prvku matice do sumy suma += pole[i, j]; } } /* Výpočet průměru (suma/počet prvků) a přiřazení hodnoty do výstupu metody * nutné přetypovat sumu na double, aby nedošlo k celočíselnému dělení */ return (double)suma / (m * n); }
Kód 1: Deklarace metody pro výpočet aritmetického průměru prvků matice (PrumerPole)
Přemístíme se zpět do regionu Události a jeho části Operace s polem. V tomto regionu upravíme metodu obsluhy události stisknutí tlačítka BtnPrumer - viz Kód 2. V rámci těla metody budeme deklarovat reálnou lokální proměnnou prumer, do které uložíme návrat volané metody PrumerPole, které předáme tři parametry. První předaný parametr hodnotou je počet řádků matice, druhý je počet sloupců matice (uložené v datové složce třídy). Jako třetí parametr předáme matici. Navrácený průměr zobrazíme v na formuláři v objektu typu TextBox spolu s textem. Pro konverzi reálného čísla na textový řetězec využijeme metody Format třídy string, kde použijeme indexaci prvků ve složených závorkách včetně uvedení formátu výpisu reálného čísla na dvě desetinná místa (N2).
/// <summary> /// Volání metody pro výpočet aritmetického průměru z prvků matice /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnPrumer_Click(object sender, RoutedEventArgs e) { // Lokální proměnná: 'prumer' - průměr prvků v matici double prumer; // Přiřazení výstupu metody pro výpočet průměru z prvků pole do lokální proměnné prumer = this.PrumerPole(this.pocetRadku, this.pocetSloupcu, this.pole); /* Zobrazení textu 'Průměr = ' spolu s vypočteným průměrem (konverze reálného čísla * na text, zobrazného na 2 desetinná místa) do objektu (TextBox) na formuláři */ this.TxtVysledek.Text = string.Format("Průměr = {0:N2}", prumer); }
Kód 2: Deklarace metody pro zavolání metody pro výpočet aritmetického průměru prvků matice - výpis na formuláři (BtnPrumer_Click)
4.7. Seřazení prvků pole
Pro seřazení prvků v každém řádku matice vzestupně (přístup je obdobný, jako v případu jednorozměrného pole, kde každý řádek matice v podstatě představuje vektor) je v regionu Operace s polem, která je součástí regionu Pomocné metody, volána soukromá metoda bez návratu s názvem SeraditPole. V metodě jsou použit tři cykly. První cyklus s krokem slouží pro procházení řádků matice. U prvků v řádku matice totiž budeme znovu využívat pro třídění prvků v řádce algoritmus typu Bubble Sort, kde jsou porovnány jednotlivé dvojice sousedních prvků. Toto porovnání je prováděno ve třetím (druhém vnořeném) cyklu s krokem. Pokud je aktuálně procházený prvek větší než následující prvek, jsou tyto prvky vzájemně prohozeny. Pokud došlo alespoň k jednomu prohození sousedních prvků, celý vnitřní cyklus s krokem pro procházení od prvního do předposledního prvku je znovu opakován. Toto opakování zajistí druhý (vnořený) cyklus s podmínkou na konci. Pokud nedošlo k prohození ani v jedné porovnávané dvojici sousedních prvků není již cyklus s podmínkou na konci prováděn. Následující zdrojový kód obsahuje deklaraci metody SeraditPole - viz Kód 1.
/// <summary> /// Metoda pro vzestupné třídě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 SeraditPole(int m, int n, int[,] pole) { /* Lokální proměnné: '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 hodnota sousedícího prvku je 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 metody s návratem pro vzestupné seřazení prvků v jednotlivých řádcích matice (SeraditPole)
Přemístíme se zpět do regionu Události a jeho části Operace s polem. V tomto regionu upravíme metodu obsluhy události stisknutí tlačítka BtnSeradit - viz Kód 2. V rámci těla metody budeme volat předchozí deklarovanou metodu SeraditPole, které předáme tři parametry - počet řádků matice, počet sloupců matice a matici (uložené v datových složkách třídy). Vzhledem k tomu, že v metodě bude upravena matice, je vhodné tuto změněnou matici uživateli zobrazit. Proto matici zobrazíme jak do objektu typu TextBox, tak i do objektu typu ListView umístěných na formuláři.
/// <summary> /// Volání metody pro vzestupné třídění prvků v řádcích matice /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnSeradit_Click(object sender, RoutedEventArgs e) { // Zavolání metody pro vzestupné třídění prvků v matici this.SeraditPole(this.pocetRadku, this.pocetSloupcu, this.pole); // Zavolání metody pro zobrazení matice do objektu (TextBox) na formuláři this.ZobrazitPoleJakoText(this.pocetRadku, this.pocetSloupcu, this.pole); // Zavolání metody pro zobrazení matice v objektu (ListView) na formuláři this.ZobrazitPoleVListView(this.pocetRadku, this.pocetSloupcu, this.pole); }
Kód 2: Deklarace metody pro zavolání metody vzestupného třídění v jednotlivých řádcích matice - výpis na formuláři (BtnSeradit_Click)
4.8. Transpozice
Pro transpozici prvků matice podle hlavní diagonály je v regionu Operace s polem, která je součástí regionu Pomocné metody, volána soukromá metoda bez návratu s názvem HlavniTranspozice. Metoda přijímá tři parametry: počet řádků, počet sloupců matice a matici. Metoda obsahuje tři lokální proměnné. Proměnná pom reprezentuje pomocnou proměnnou pro přesun osově souměrných prvků matice podle hlavní diagonály. Ostatní dvě lokální proměnné i - index řádku matice aktuálně procházeného prvku a j - index sloupce matice aktuálně procházeného prvku jsou deklarovány 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í v dialogovém oknu. 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 oblast prvků umístěných 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 oblast nad hlavní diagonálou). V těle cyklu provádíme vzájemné prohození prvků pomocí uložení hodnoty prvků z oblasti nad diagonálou 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 oblasti nad diagonálou 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é.
Následující zdrojový kód obsahuje deklaraci metody HlavniTranspozice- viz Kód 1.
/// <summary> /// Metoda pro transpozici 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 </param> private 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í MessageBox.Show("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 metody pro transpozici prvků podle hlavní diagonály (HlavniTranspozice)
Přemístíme se zpět do regionu Události a jeho části Operace s polem. V tomto regionu upravíme metodu obsluhy události stisknutí tlačítka BtnTranspoziceHlavni_Click - viz Kód 2. V rámci těla metody budeme volat předchozí deklarovanou metodu HlavniTranspozice, které předáme tři parametry - počet řádků matice, počet sloupců matice a matici (uložené v datových složkách třídy). Vzhledem k tomu, že v metodě bude upravena matice, je vhodné tuto změněnou matici uživateli zobrazit. Proto matici zobrazíme jak do objektu typu TextBox, tak i do objektu typu ListView umístěných na formuláři.
/// <summary> /// Volání metody pro transpozici prvků matice podle hlavní diagonály /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnTranspoziceHlavni_Click(object sender, RoutedEventArgs e) { // Zavolání metody pro transpozici prvků matice podle hlavní diagonály this.HlavniTranspozice(this.pocetRadku, this.pocetSloupcu, this.pole); // Zavolání metody pro zobrazení matice do objektu (TextBox) na formuláři this.ZobrazitPoleJakoText(this.pocetRadku, this.pocetSloupcu, this.pole); // Zavolání metody pro zobrazení matice v objektu (ListView) na formuláři this.ZobrazitPoleVListView(this.pocetRadku, this.pocetSloupcu, this.pole); }
Kód 2: Deklarace metody pro zavolání metody pro transpozici prvků matice podle hlavní diagonály - výpis na formuláři (BtnTranspoziceHlavni_Click)
Pro transpozici prvků matice podle hlavní diagonály je v regionu Operace s polem, která je součástí regionu Pomocné metody, volána soukromá metoda bez návratu s názvem VedlejsiTranspozice - viz Kód 3. Metoda přijímá tři parametry: počet řádků, počet sloupců matice a matici. Metoda obsahuje tři lokální proměnné. Proměnná pom reprezentuje pomocnou proměnnou pro přesun osově souměrných prvků matice podle hlavní diagonály. Ostatní dvě lokální proměnné i - index řádku matice aktuálně procházeného prvku a j - index sloupce matice aktuálně procházeného prvku jsou deklarovány přímo v cyklu.Stejně jako v předchozím případu transpozice podle hlavní diagonály, první rozhodovací příkaz metody zajišťuje, že pokud počet řádků není roven počtu sloupců, je metoda ukončena včetně výpisu varovného hlášení v dialogovém oknu. 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 o 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 oblast nad vedlejší diagonálou). 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 oblasti nad vedlejší diagonálou do pomocné proměnné. Prvek v oblasti nad diagonálou 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> /// Metoda pro transpozici 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 </param> private 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á) ... if (m != n) { // Výpis varovného upozornění MessageBox.Show("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 3: Deklarace metody pro transpozici prvků podle vedlejší diagonály (VedlejsiTranspozice)
Přemístíme se zpět do regionu Události a jeho části Operace s polem. V tomto regionu upravíme metodu obsluhy události stisknutí tlačítka BtnTranspoziceVedlejsi_Click - viz Kód 4. V rámci těla metody budeme volat předchozí deklarovanou metodu VedlejsiTranspozice, které předáme tři parametry - počet řádků matice, počet sloupců matice a matici (uložené v datových složkách třídy). Vzhledem k tomu, že v metodě bude upravena matice, je vhodné tuto změněnou matici uživateli zobrazit. Proto matici zobrazíme jak do objektu typu TextBox, tak i do objektu typu ListView umístěných na formuláři.
/// <summary> /// Volání metody pro transpozici prvků matice podle vedlejší diagonály /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnTranspoziceVedlejsi_Click(object sender, RoutedEventArgs e) { // Zavolání metody pro transpozici prvků matice podle vedlejsi diagonály this.VedlejsiTranspozice(this.pocetRadku, this.pocetSloupcu, this.pole); // Zavolání metody pro zobrazení matice do objektu (TextBox) na formuláři this.ZobrazitPoleJakoText(this.pocetRadku, this.pocetSloupcu, this.pole); // Zavolání metody pro zobrazení matice v objektu (ListView) na formuláři this.ZobrazitPoleVListView(this.pocetRadku, this.pocetSloupcu, this.pole); }
Kód 4: Deklarace metody pro zavolání metody pro transpozici prvků matice podle vedlejší diagonály - výpis na formuláři (BtnTranspoziceVedlejsi_Click)
5. Výsledný kód
XAML kód
Výsledný XAML kód formuláře (MainWindow.xaml) - viz Kód 1.
<Window x:Class="DvourozmernePoleWPF.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:DvourozmernePoleWPF" mc:Ignorable="d" Title="Základní práce s maticí" Height="850" Width="850" MinHeight="800" MinWidth="800"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <!-- Nastavení matice --> <GroupBox Header="Nastavení matice"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Label Content="Matice" FontSize="18" FontWeight="Bold" HorizontalAlignment="Center" /> <Grid Grid.Row="1"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <!-- Rozměry matice --> <GroupBox Header="Rozměry matice"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Label Content="Počet řádků:" VerticalAlignment="Center"/> <TextBox Name="TxtPocetRadku" Grid.Column="1" Width="100" Margin="5" Padding="5" LostFocus="TxtPocetRadku_LostFocus"/> <Label Content="Počet sloupců:" Grid.Row="1" VerticalAlignment="Center"/> <TextBox Name="TxtPocetSloupcu" Grid.Row="1" Grid.Column="1" Width="100" Margin="5" Padding="5" LostFocus="TxtPocetSloupcu_LostFocus"/> </Grid> </GroupBox> <!-- Hodnoty - meze --> <GroupBox Header="Hodnoty - meze" Grid.Column="1"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Label Content="Minimum:" VerticalAlignment="Center"/> <TextBox Name="TxtMinHodnota" Grid.Column="1" Width="100" Margin="5" Padding="5" LostFocus="TxtMinHodnota_LostFocus"/> <Label Content="Maximum:" Grid.Row="1" VerticalAlignment="Center"/> <TextBox Name="TxtMaxHodnota" Grid.Row="1" Grid.Column="1" Width="100" Margin="5" Padding="5" LostFocus="TxtMaxHodnota_LostFocus"/> </Grid> </GroupBox> <!-- Prvek v matici --> <GroupBox Header="Prvek v matici" Grid.Column="3"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Label Content="Index řádku:" Grid.Row="0" Grid.Column="0"/> <TextBox Name="TxtPrvekIndexRadku" Grid.Row="0" Grid.Column="1" Width="100" Margin="5" Padding="5" LostFocus="TxtPrvekIndexRadku_LostFocus"/> <Label Content="Index sloupce:" Grid.Row = "1" Grid.Column="0"/> <TextBox Name="TxtPrvekIndexSloupce" Grid.Row="1" Grid.Column="1" Width="100" Margin="5" Padding="5" LostFocus="TxtPrvekIndexSloupce_LostFocus"/> <Label Content="Hodnota:" Grid.Row="0" Grid.Column="2"/> <TextBox Name="TxtHodnota" Grid.Row="0" Grid.Column="3" Width="100" Margin="5" Padding="5" LostFocus="TxtHodnota_LostFocus"/> </Grid> </GroupBox> </Grid> </Grid> </GroupBox> <!-- Zobrazení matice --> <GroupBox Header="Zobrazení matice" Grid.Row="1"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <!-- Matice --> <GroupBox Header="Mřížka" Margin="5" MinHeight="100"> <ListView Name="LstMatice" ScrollViewer.VerticalScrollBarVisibility="Auto"/> </GroupBox> <!-- Výsledek --> <GroupBox Header="Jako text (nebo výpis výsledku)" Grid.Column="2" Margin="5"> <TextBox Name="TxtVysledek" Margin="5" ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollBarVisibility="Visible" IsReadOnly="True" Background="AliceBlue"/> </GroupBox> </Grid> </GroupBox> <!-- Tlačítka - sekce: Plnit, Výstup, Výpočet --> <StackPanel Grid.Row="4"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <!-- Plnit --> <StackPanel > <Label Content="Plnit:" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center"/> <Button Name="BtnNahodne" Content="Náhodně" Margin="5" Padding="10,5" Click="BtnNahodne_Click"/> <Button Name="BtnJednotlive" Content="Jednotlivě" Margin="5" Padding="10,5" Click="BtnJednotlive_Click"/> <Button Name="BtnNulovat" Content="Nulovat" Margin="5" Padding="10,5" Click="BtnNulovat_Click"/> </StackPanel> <!-- Výstup --> <StackPanel Grid.Column="1"> <Label Content="Výstup:" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center"/> <Button Name="BtnJakoText" Content="Jako text" Margin="5" Padding="10,5" Click="BtnJakoText_Click"/> <Button Name="BtnDoMrizky" Content="Do mřížky" Margin="5" Padding="10,5" Click="BtnDoMrizky_Click"/> </StackPanel> <!-- Výpočet --> <StackPanel Grid.Column="2"> <Label Content="Výpočet:" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center"/> <Button Name="BtnMinimum" Content="Minimum" Margin="5" Padding="10,5" Click="BtnMinimum_Click"/> <Button Name="BtnMaximum" Content="Maximum" Margin="5" Padding="10,5" Click="BtnMaximum_Click"/> <Button Name="BtnPrumer" Content="Průměr" Margin="5" Padding="10,5" Click="BtnPrumer_Click"/> <Button Name="BtnSeradit" Content="Seřadit" Margin="5" Padding="10,5" Click="BtnSeradit_Click"/> <Button Name="BtnTranspoziceHlavni" Content="Transpozice - hlavní diagonála" Margin="5" Padding="10,5" Click="BtnTranspoziceHlavni_Click"/> <Button Name="BtnTranspoziceVedlejsi" Content="Transpozice - vedlejší diagonála" Margin="5" Padding="10,5" Click="BtnTranspoziceVedlejsi_Click"/> </StackPanel> </Grid> <!-- Konec --> <WrapPanel HorizontalAlignment="Right"> <Button Name="BtnKonec" Content="Konec" Margin="5" Width="100" Padding="5" Click="BtnKonec_Click"/> </WrapPanel> </StackPanel> </Grid> </Window>
Kód 1: Výsledný XAML kód vytvořeného formuláře
C# kód
Code Behind - C# kód pro veškeré události vyvolané uživatelem při manipulaci s aplikací (MainWindow.xaml.cs) - viz Kód 2.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace DvourozmernePoleWPF { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { #region Datové složky třídy (globální proměnné) /* Specifikace konstanty pro maximální vertikální (počet řádků) a horizontální * (počet sloupců) rozměr matice - inicializace */ const int Max = 10; // Aktuální rozměr pole - počet řádků private int pocetRadku; // Aktuální rozměr pole - počet sloupců private int pocetSloupcu; // Přípustná minimální hodnota (dolní mez) prvku - inicializace private int minHodnota = 1; // Přípustná maximální hodnota (horní mez) prvku - inicializace private int maxHodnota = 100; // Deklarace dvourozměrného pole - matice private int[,] pole; #endregion Datové složky třídy public MainWindow() { InitializeComponent(); //Inicializace atributů pole a prvků na formuláři Inicializace(); } #region Pomocné metody #region Nastavení atributů pole /// <summary> /// Inicializace atributů pole a prvků na formuláři /// </summary> private void Inicializace() { // Přiřazení maximálního počtu řádků matice do datové složky this.pocetRadku = Max; // Přiřazení maximálního počtu sloupců matice do datové složky this.pocetSloupcu = Max; // Vytvoření instance (objektu) matice s definovanými rozměry this.pole = new int[this.pocetRadku, this.pocetSloupcu]; // Přiřazení počtu řádků matice do objektu na formuláři this.TxtPocetRadku.Text = this.pocetRadku.ToString(); // Přiřazení počtu sloupců matice do objektu na formuláři this.TxtPocetSloupcu.Text = this.pocetSloupcu.ToString(); /* Přiřazení přípustné minimální hodnoty prvku v matici do objektu * na formuláři určujícího mezní hodnotu */ this.TxtMinHodnota.Text = this.minHodnota.ToString(); /* Přiřazení přípustné maximální hodnoty prvku v matici do objektu (pole) * na formuláři určujícího mezní hodnotu */ this.TxtMaxHodnota.Text = this.maxHodnota.ToString(); } #endregion Nastavení atributů pole #region Plnění pole /// <summary> /// Metoda pro plnění prvků matice náhodnými čísly /// </summary> /// <param name="n"> počet prvků pole </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); } } } /// <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; } } } #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 v objektu /// </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> private 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> /// Zobrazení matice na formuláři jako text v objektu typu TextBox /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> matice </param> private void ZobrazitPoleJakoText(int m, int n, int[,] pole) { // Výpis matice v objektu typu TextBox na formuláři this.TxtVysledek.Text = this.PoleJakoText(m, n, pole); } /// <summary> /// Zobrazení prvků matice na formuláři v objektu typu ListView /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> matice </param> private void ZobrazitPoleVListView(int m, int n, int[,] pole) { // Lokální proměnná: 'radka' - řádka matice převedená na text string radka; // Vymazání předchozí obsahu (přidaných prvků) this.LstMatice.Items.Clear(); // Procházení řádků matice for (int i = 0; i < m; i++) { // Vymazání předchozího obsahu řádky (textového řetězce) radka = ""; // Procházení sloupců matice for (int j = 0; j < n; j++) { // Převod hodnoty prvku na text včetně připojení čárky radka += string.Format("{0:D3}, ", pole[i, j]); } // Přidání textového řetězce (řádky matice) do obsahu objektu this.LstMatice.Items.Add(radka); } } #endregion Zobrazení pole #region Operace s polem /// <summary> /// Metoda pro hledání nejmenšího prvku v matici /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> matice </param> /// <param name="indexRadkuMinima"> index řádku minima </param> /// <param name="indexSloupceMinima"> index sloupce minima </param> /// <returns> celočíselná hodnota minima </returns> private int MinimumVPoli(int m, int n, int[,] pole, out int indexRadkuMinima, out int indexSloupceMinima) { // Lokální proměnné: 'i' - index řádku; 'j' - index sloupce; 'minimum' - hodnota minima int minimum; // Přiřazení maximální možné hodnoty datového typu int minimum = int.MaxValue; // Přiřazení hodnoty 0 do indexu řádku a sloupce minima - nutná inicializace indexRadkuMinima = indexSloupceMinima = -1; // Procházení řádků matice for (int i = 0; i < m; i++) { // Procházení sloupců matice for (int j = 0; j < n; j++) { // Pokud je nalezen prvek v matici, jehož hodnota je menší než minimum... if (pole[i, j] < minimum) { // Uložení hodnoty nalezeného prvku do minima minimum = pole[i, j]; // Přiřazení indexu řádku aktuálního prvku do indexu řádku minima indexRadkuMinima = i; // Přiřazení indexu sloupce aktuálního prvku do indexu sloupce minima indexSloupceMinima = j; } } } // Přiřazení hodnoty nalezeného minima do výstupu metody return minimum; } /// <summary> /// Metoda pro hledání největšího prvku v matici /// </summary> /// <param name="m"> počet řádků matice </param> /// <param name="n"> počet sloupců matice </param> /// <param name="pole"> matice </param> /// <param name="indRadkuMaxima"> index řádku maxima </param> /// <param name="indexSloupceMaxima"> index sloupce maxima </param> /// <returns> celočíselná hodnota maxima </returns> private int MaximumVPoli(int m, int n, int[,] pole, out int indRadkuMaxima, out int indexSloupceMaxima) { // Lokální proměnné: 'i' - index řádku; 'j' - index sloupce; 'maximum' - hodnota maxima int maximum; // Přiřazení nejmenší možné hodnoty datového typu int maximum = (-int.MaxValue - 1); // Přiřazení hodnoty 0 do indexu řádku a sloupce maxima - nutná inicializace indRadkuMaxima = indexSloupceMaxima = -1; // Procházení řádků matice for (int i = 0; i < m; i++) { // Procházení sloupců matice for (int j = 0; j < n; j++) { // Pokud je nalezen prvek v matici, jehož hodnota je větší než maximum... if (pole[i, j] > maximum) { // Uložení hodnoty nalezeného prvku do minima maximum = pole[i, j]; // Přiřazení indexu řádku aktuálního prvku do indexu řádku maxima indRadkuMaxima = i; // Přiřazení indexu sloupce aktuálního prvku do indexu sloupce maxima indexSloupceMaxima = j; } } } // Přiřazení hodnoty nalezeného maxima do výstupu metody return maximum; } /// <summary> /// Metoda pro výpočet aritmetického průměru 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> /// <returns> hodnota aritmetického průměru (reálné číslo) </returns> private double PrumerPole(int m, int n, int[,] pole) { /* Lokální proměnné: 'i' ... index řádku matice; 'j'... index sloupce matice; * 'suma' - suma prvků matice */ int suma; // Nastavení počáteční hodnoty u sumy suma = 0; // Procházení řádků matice for (int i = 0; i < m; i++) { // Procházení sloupců matice for (int j = 0; j < n; j++) { // Přičtení dalšího prvku matice do sumy suma += pole[i, j]; } } /* Výpočet průměru (suma/počet prvků) a přiřazení hodnoty do výstupu metody * nutné přetypovat sumu na double, aby nedošlo k celočíselnému dělení */ return (double)suma / (m * n); } /// <summary> /// Metoda pro vzestupné třídě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 SeraditPole(int m, int n, int[,] pole) { /* Lokální proměnné: '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 hodnota sousedícího prvku je 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> /// Metoda pro transpozici 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 </param> private 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í MessageBox.Show("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> /// Metoda pro transpozici 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 </param> private 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á) ... if (m != n) { // Výpis varovného upozornění MessageBox.Show("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 #endregion Pomocné metody #region Události #region Nastavení atributů pole /// <summary> /// Validace počtu řádků matice /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TxtPocetRadku_LostFocus(object sender, RoutedEventArgs e) { // Lokální proměnná: 'novaHodnota' - nový počet řádků matice int novaHodnota; /* Přiřazení počtu řádků z objektu na formuláři do lokální proměnné * určující počet řádků matice */ int.TryParse(this.TxtPocetRadku.Text, out novaHodnota); /* Pokud počet řádků je větší než maximální počet řádků matice, nebo počet * řádků matice je menší než 1, pak... */ if ((novaHodnota > Max) || (novaHodnota < 1)) { // Zobrazení dialogového okna s textem a hodnotou max. počtu řádků matice MessageBox.Show(String.Format("Chyba rozměru matice, nastavení na max. počet řádků: {0}", Max)); /* Přiřazení maximálního rozměru matice do lokální proměnné určující * počet řádků matice */ novaHodnota = Max; // Přiřazení maximálního počtu řádků matice do objektu na formuláři this.TxtPocetRadku.Text = Max.ToString(); } // Pokud nový počet řádků matice není stejný jako stávající počet řádků matice, pak... if (novaHodnota != this.pocetRadku) { // Uložení nového počtu řádků matice do datové složky třídy this.pocetRadku = novaHodnota; // Vytvoření nové instance matice s novým počtem řádků this.pole = new int[this.pocetRadku, this.pocetSloupcu]; // Zavolání metody pro zobrazení matice do objektu TextBox na formuláři this.ZobrazitPoleJakoText(this.pocetRadku, this.pocetSloupcu, this.pole); // Zavolání metody pro zobrazení matice do objektu ListView na formuláři this.ZobrazitPoleVListView(this.pocetRadku, this.pocetSloupcu, this.pole); } } /// <summary> /// Validace počtu sloupců matice /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TxtPocetSloupcu_LostFocus(object sender, RoutedEventArgs e) { // Lokální proměnná: 'novaHodnota' - nový počet sloupců matice int novaHodnota; /* Přiřazení počtu sloupců z objektu na formuláři do lokální proměnné * určující počet sloupců matice */ int.TryParse(this.TxtPocetSloupcu.Text, out novaHodnota); /* Pokud počet sloupců je větší než maximální počet sloupců matice, nebo počet * řádků sloupců je menší než 1, pak... */ if ((novaHodnota > Max) || (novaHodnota < 1)) { // Zobrazení dialogového okna s textem a hodnotou max. počtu sloupců matice MessageBox.Show(String.Format("Chyba rozměru matice, nastavení na max. počet sloupců: {0}", Max)); /* Přiřazení maximálního rozměru matice do lokální proměnné určující * počet sloupců matice */ novaHodnota = Max; // Přiřazení maximálního počtu sloupců matice do objektu na formuláři this.TxtPocetSloupcu.Text = Max.ToString(); } // Pokud nový počet sloupců matice není stejný jako stávající počet sloupců matice, pak... if (novaHodnota != this.pocetSloupcu) { // Uložení nového počtu sloupců matice do datové složky třídy this.pocetSloupcu = novaHodnota; // Vytvoření nové instance matice s novým počtem sloupců this.pole = new int[this.pocetRadku, this.pocetSloupcu]; // Zavolání metody pro zobrazení matice do objektu TextBox na formuláři this.ZobrazitPoleJakoText(this.pocetRadku, this.pocetSloupcu, this.pole); // Zavolání metody pro zobrazení matice do objektu ListView na formuláři this.ZobrazitPoleVListView(this.pocetRadku, this.pocetSloupcu, this.pole); } } /// <summary> /// Validace dolní meze intervalu přípustných hodnot prvků matice /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TxtMinHodnota_LostFocus(object sender, RoutedEventArgs e) { /* Přiřazení dolní meze z objektu na formuláři do datové složky třídy určující * dolní mez intervalu přípustných hodnot */ int.TryParse(this.TxtMinHodnota.Text, out this.minHodnota); // Pokud nová dolní mez je větší než stávající horní mez, pak... if (this.minHodnota > this.maxHodnota) { // Zobrazení dialogového okna s chybou a nastavení dolní meze na horní mez MessageBox.Show(String.Format("Chyba hodnoty dolní meze - dolní mez nastavena na horní mez: {0}", this.maxHodnota)); // Dolní mez je nastavena na hodnotu horní meze this.minHodnota = this.maxHodnota; // Zobrazení hodnoty dolní meze na formuláři this.TxtMinHodnota.Text = minHodnota.ToString(); } } /// <summary> /// Validace horní meze intervalu přípustných hodnot prvků matice /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TxtMaxHodnota_LostFocus(object sender, RoutedEventArgs e) { /* Přiřazení horní meze z objektu na formuláři do datové složky třídy určující * horní mez intervalu hodnot, kterých mohou nabývat prvky v matici */ int.TryParse(this.TxtMaxHodnota.Text, out this.maxHodnota); // Pokud nová horní mez je menší než stávající dolní mez, pak... if (this.maxHodnota < this.minHodnota) { // Zobrazení dialogového okna s chybou a nastavení horní meze na dolní mez MessageBox.Show(String.Format("Chyba hodnoty horní meze - horní mez nastavena na dolní mez: {0}", this.minHodnota)); // Horní mez je nastavena na hodnotu dolní meze this.maxHodnota = this.minHodnota; // Zobrazení hodnoty horní meze na formuláři this.TxtMaxHodnota.Text = maxHodnota.ToString(); } } /// <summary> /// Validace indexu řádku prvku matice při ručním plnění /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TxtPrvekIndexRadku_LostFocus(object sender, RoutedEventArgs e) { // Lokální proměnná: 'index' - index řádku prvku matice int index; // Uložení indexu řádku prvku do lokální proměnné (konverze textu na celé číslo) int.TryParse(this.TxtPrvekIndexRadku.Text, out index); /* Pokud index řádku prvku je větší než počet řádků matice - 1, nebo index řádku prvku je * menší než 0, pak... */ if ((index > this.pocetRadku - 1) || (index < 0)) { // Zobrazení dialogového okna s chybou a nastavení indexu na počet řádků matice - 1 MessageBox.Show(String.Format("Chybný index řádku prvku. Index nastaven na horní mez: {0}", this.pocetRadku - 1)); // Přiřazení horní meze indexu do objektu na formuláři určujícího index řádku prvku matice this.TxtPrvekIndexRadku.Text = String.Format("{0}", this.pocetRadku - 1); } } /// <summary> /// Validace indexu sloupce prvku matice při ručním plnění /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TxtPrvekIndexSloupce_LostFocus(object sender, RoutedEventArgs e) { // Lokální proměnná: 'index' - index sloupce prvku matice int index; // Uložení indexu sloupce prvku do lokální proměnné (konverze textu na celé číslo) int.TryParse(this.TxtPrvekIndexSloupce.Text, out index); /* Pokud index sloupce prvku je větší než počet sloupců matice - 1, nebo index sloupce prvku je * menší než 0, pak... */ if ((index > this.pocetSloupcu - 1) || (index < 0)) { // Zobrazení dialogového okna s chybou a nastavení indexu na počet sloupců matice - 1 MessageBox.Show(String.Format("Chybný index sloupce prvku. Index nastaven na horní mez: {0}", this.pocetSloupcu - 1)); // Přiřazení horní meze indexu do objektu na formuláři určujícího index sloupce prvku matice this.TxtPrvekIndexSloupce.Text = String.Format("{0}", this.pocetSloupcu - 1); } } /// <summary> /// Validace hodnoty prvku matice při ručním plnění /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TxtHodnota_LostFocus(object sender, RoutedEventArgs e) { // Lokální proměnná: 't' - hodnota prvku int t; // Uložení hodnoty prvku do lokální proměnné (konverze textu na celé číslo) int.TryParse(this.TxtHodnota.Text, out t); /* Pokud hodnota prvku je větší než horní mez, nebo hodnota prvku je * menší než dolní mez intervalu hodnot v matici, pak... */ if ((t > this.maxHodnota) || (t < this.minHodnota)) { // Zobrazení dialogového okna s textem chyby a hodnotami mezí MessageBox.Show(String.Format("Hodnota prvku není v intervalu: {0} až {1}", this.minHodnota, this.maxHodnota)); // Vymázání obsahu objektu na formuláři s hodnotou prvku this.TxtHodnota.Clear(); } } #endregion Nastavení atributů pole #region Plnění pole /// <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(); } } } /// <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); } #endregion Plnění pole #region Zobrazení pole /// <summary> /// Volání metody pro zobrazení matice jako text v objektu typu TextBox na formuláři /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnJakoText_Click(object sender, RoutedEventArgs e) { // Zavolání metody pro zobrazení matice jako text v objektu na formuláři this.ZobrazitPoleJakoText(this.pocetRadku, this.pocetSloupcu, this.pole); } /// <summary> /// Volání metody pro zobrazení prvků matice v objektu typu ListView na formuláři /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnDoMrizky_Click(object sender, RoutedEventArgs e) { // Zavolání metody pro zobrazení prvků matice do mřížky na formuláři this.ZobrazitPoleVListView(this.pocetRadku, this.pocetSloupcu, this.pole); } #endregion Zobrazení pole #region Operace s polem /// <summary> /// Volání metody pro určení minima a jeho pozice v matici /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnMinimum_Click(object sender, RoutedEventArgs e) { /* Lokální proměnné: 'minimum' - hodnota minima v matici; 'indexRadkuMinima' - * index řádku minima; 'indexSloupceMinima' - index sloupce minima */ int minimum; /* Přiřazení výstupu metody pro určení minima do lokální proměnné a výstupní parametry * určující index řádku ('indexRadkuMinima') a sloupce ('indexSloupceMinima') minima */ minimum = this.MinimumVPoli(this.pocetRadku, this.pocetSloupcu, this.pole, out int indexRadkuMinima, out int indexSloupceMinima); /* Zobrazení textu spolu s hodnotou minima a indexu řádku a sloupce minima * do objektu (TextBox) na formuláři */ this.TxtVysledek.Text = string.Format("Minimum = {0} (na pozici [{1}, {2}])", minimum, indexRadkuMinima, indexSloupceMinima); } /// <summary> /// Volání metody pro určení maxima a jeho pozice v matici /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnMaximum_Click(object sender, RoutedEventArgs e) { /* Lokální proměnné: 'maximum' - hodnota maxima v matici; 'indexRadkuMaxima' - * index řádku maxima; 'indexSloupceMaxima' - index sloupce maxima */ int maximum; /* Přiřazení výstupu metody pro určení maxima do lokální proměnné a výstupní parametry * určující index řádku ('indexRadkuMaxima') a sloupce ('indexSloupceMaxima') maxima */ maximum = this.MaximumVPoli(this.pocetRadku, this.pocetSloupcu, this.pole, out int indexRadkuMaxima, out int indexSloupceMaxima); /* Zobrazení textu spolu s hodnotou maxima a indexu řádku a sloupce maxima * do objektu (TextBox) na formuláři */ this.TxtVysledek.Text = string.Format("Maximum = {0} (na pozici [{1}, {2}])", maximum, indexRadkuMaxima, indexSloupceMaxima); } /// <summary> /// Volání metody pro výpočet aritmetického průměru z prvků matice /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnPrumer_Click(object sender, RoutedEventArgs e) { // Lokální proměnná: 'prumer' - průměr prvků v matici double prumer; // Přiřazení výstupu metody pro výpočet průměru z prvků pole do lokální proměnné prumer = this.PrumerPole(this.pocetRadku, this.pocetSloupcu, this.pole); /* Zobrazení textu 'Průměr = ' spolu s vypočteným průměrem (konverze reálného čísla * na text, zobrazného na 2 desetinná místa) do objektu (TextBox) na formuláři */ this.TxtVysledek.Text = string.Format("Průměr = {0:N2}", prumer); } /// <summary> /// Volání metody pro vzestupné třídění prvků v řádcích matice /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnSeradit_Click(object sender, RoutedEventArgs e) { // Zavolání metody pro vzestupné třídění prvků v matici this.SeraditPole(this.pocetRadku, this.pocetSloupcu, this.pole); // Zavolání metody pro zobrazení matice do objektu (TextBox) na formuláři this.ZobrazitPoleJakoText(this.pocetRadku, this.pocetSloupcu, this.pole); // Zavolání metody pro zobrazení matice v objektu (ListView) na formuláři this.ZobrazitPoleVListView(this.pocetRadku, this.pocetSloupcu, this.pole); } /// <summary> /// Volání metody pro transpozici prvků matice podle hlavní diagonály /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnTranspoziceHlavni_Click(object sender, RoutedEventArgs e) { // Zavolání metody pro transpozici prvků matice podle hlavní diagonály this.HlavniTranspozice(this.pocetRadku, this.pocetSloupcu, this.pole); // Zavolání metody pro zobrazení matice do objektu (TextBox) na formuláři this.ZobrazitPoleJakoText(this.pocetRadku, this.pocetSloupcu, this.pole); // Zavolání metody pro zobrazení matice v objektu (ListView) na formuláři this.ZobrazitPoleVListView(this.pocetRadku, this.pocetSloupcu, this.pole); } /// <summary> /// Volání metody pro transpozici prvků matice podle vedlejší diagonály /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnTranspoziceVedlejsi_Click(object sender, RoutedEventArgs e) { // Zavolání metody pro transpozici prvků matice podle vedlejsi diagonály this.VedlejsiTranspozice(this.pocetRadku, this.pocetSloupcu, this.pole); // Zavolání metody pro zobrazení matice do objektu (TextBox) na formuláři this.ZobrazitPoleJakoText(this.pocetRadku, this.pocetSloupcu, this.pole); // Zavolání metody pro zobrazení matice v objektu (ListView) na formuláři this.ZobrazitPoleVListView(this.pocetRadku, this.pocetSloupcu, this.pole); } #endregion Operace s polem /// <summary> /// Metoda pro zavření formuláře /// </summary> private void BtnKonec_Click(object sender, RoutedEventArgs e) { // Zavření formuláře this.Close(); } #endregion Události } }
Kód 2: Výsledný C# kód vytvořeného formuláře a metod jeho prvků
6. Výstup programu
Na následujících výstupech týkajících se programu DvourozmernePoleWPF budou zobrazeny jednotlivé výstupy aplikace pro různá nastavení atributů dvourozměrného pole (matice) a případy plnění tohoto pole včetně jednotlivých operací prováděných s prvky pole.
Rozměr pole
Pokud uživatel nastavil některý z rozměrů pole mimo povolené hranice, je o této chybě informován pomocí dialogového okna a rozměr je nastaven na maximální rozměr, tj. na konstantu Max - viz Výstup programu 1.
Výstup programu 1 - Kód 1 a 2 (viz kapitola 5 Výsledný kód): Překročení maximálního počtu řádků pole
Dolní a horní mez prvků
Pokud uživatel zadal dolní mez větší než horní mez, dolní mez bude nastavena na hodnotu horní meze - viz Výstup programu 2. V opačném případu, pokud uživatel zadal horní mez menší než dolní mez, bude horní mez nastavena no dolní mez.
Výstup programu 2 - Kód 1 a 2 (viz kapitola 5 Výsledný kód): Změna velikosti dolní meze, která je větší než horní mez
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é varianty týkající se plnění dvourozměrného pole. Pole je vypsáno jak v objektu typu TextBox s titulkem Jako text (nebo výpis výsledku), tak i do objektu typu ListView s titulkem Mřížka.
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 3. Dolní mez prvků pole je nastavena na hodnotu 1 a horní mez na hodnotu 100.Výstup programu 3 - Kód 1 a 2 (viz kapitola 5 Výsledný kód): 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 4. 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.
Výstup programu 4 - Kód 1 a 2 (viz kapitola 5 Výsledný kód): Ruční plnění pomocí specifikace pozice a hodnoty prvku
Pokud nebyla zadána hodnota prvku, uživateli je zobrazeno dialogové okno s popisem chyby - viz Výstup programu 5.
Výstup programu 5 - Kód 1 a 2 (viz kapitola 5 Výsledný kód): Nezadání hodnoty prvku při ručním plnění 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 10 x 10 prvků, kde jsou všechny prvky naplněny nulami - viz Výstup programu 6.
Výstup programu 6 - Kód 1 a 2 (viz kapitola 5 Výsledný kód): Plnění všech prvků nulami
Minimum a maximum pole
Následující výstup programu aplikace ilustruje nalezení minima v poli o rozměrech 3 x 3 (řádky x sloupce). Ve výpisu jsou uvedeny indexy řádku a sloupce nalezeného minima. Pole bylo plněno jednotlivě uživatelem zadanými čísly v rozmezí celočíselných hodnot 1 ÷ 9 (viz Výstup programu 4 - nadpis Plnění jednotlivých prvků pole) - viz Výstup programu 7.
Výstup programu 7 - Kód 1 a 2 (viz kapitola 5 Výsledný kód): Nalezené minimum v poli včetně jeho pozice v poli (index řádku a sloupce)
Další výstup programu ilustruje nalezení maxima pole o rozměrech 3 x 3 (jedná se o stejné pole naplněné ručně viz Výstup programu 4 - nadpis Plnění jednotlivých prvků pole) a výpisu jeho hodnoty včetně pozice - viz Výstup programu 8.
Výstup programu 8 - Kód 1 a 2 (viz kapitola 5 Výsledný kód): Nalezené maximum v poli včetně jeho pozice v poli (index řádku a sloupce)
Průměr pole
Následující výstup programu aplikace ilustruje výpočet aritmetického průměru prvků pole o rozměrech 3 x 3, které byly zadány při plnění jednotlivých prvků pole (jedná se o stejné pole naplněné ručně viz Výstup programu 4 - nadpis Plnění jednotlivých prvků pole) - viz Výstup programu 9.
Výstup programu 9 - Kód 1 a 2 (viz kapitola 5 Výsledný kód): Výpočet aritmetického průměru ze všech prvků pole
Seřazení prvků pole
Následující výstup programu ilustruje vzestupné seřazení prvků v jednotlivých řádcích pole o rozměrech 3 x 3, které bylo zadáno pomocí plnění jednotlivých prvků pole (jedná se o stejné pole naplněné ručně viz Výstup programu 4 - nadpis Plnění jednotlivých prvků pole) - viz Výstup programu 10.
Výstup programu 10 - Kód 1 a 2 (viz kapitola 5 Výsledný kód): Vzestupné seřazení všech prvků v jednotlivých řádcích pole
Transpozice prvků
Předposlední výstup programu ilustruje transpozici prvků pole podle hlavní diagonály již seřazených prvků ve všech řádcích matice (viz Výstup programu 10 - nadpis Seřazení prvků pole) - viz Výstup programu 11.
Výstup programu 11 - Kód 1 a 2 (viz kapitola 5 Výsledný kód): Transpozice prvků pole podle hlavní diagonály
Poslední výstup programu ilustruje transpozici prvků pole podle vedlejší diagonály již transponovaných prvků pole (viz Výstup programu 11 - nadpis Transpozice prvků) podle hlavní diagonály - viz Výstup programu 12.
Výstup programu 12 - Kód 1 a 2 (viz kapitola 5 Výsledný kód): Transpozice prvků pole podle vedlejší diagonály