Lekce 5 - Tvorba sudoku v Xamarin - Kontrolní mechanismy
V minulé lekci, Tvorba sudoku v Xamarin - Nahrání aplikace do mobilu, jsme nahráli aplikaci na iPhone a Android a nastavili mobil pro vývoj, abychom mohli aplikaci debugovat.
V dnešním Xamarin tutoriálu implementujeme kontrolní mechanismy pro zadání a řešení Sudoku. Základem bude kontrola dvou buněk, kterou zavoláme při kontrole stejných čísel ve sloupcích, řádcích, mřížce a nakonec v celém Sudoku.
Budeme rozšiřovat naši aplikaci z lekce Nahrání
aplikace do mobilu. Všechen kód budeme psát do souboru
MainPage.xaml.cs.
Třída EntrySudoku
Jelikož máme 81 Entry, které umí reagovat na uživatelský
vstup, ale nevědí, kde v mřížce se nacházejí, musíme určit
souřadnice. Tyto souřadnice budeme definovat při vytvoření
nového objektu třídy EntrySudoku, kterou si teď vložíme na
začátek souboru MainPage.xaml.cs:
public class EntrySudoku : Entry { int row; int column; public int getRow() => row; public int getColumn() => column; public EntrySudoku(int r, int c) : base() { row = r; column = c; } }
Třídu využijeme pro testování implementovaných funkcionalit z uživatelského rozhraní.
V proměnných row a column budeme ukládat
umístění mřížky. Umístění pak definujeme v
konstruktoru.
Změny stávajícího kódu
Na základě vytvoření třídy EntrySudoku změníme:
- všechny výskyty typu
Entryza typEntrySudoku, - vytvoření nového objektu typu
Entryza nový objekt typuEntrySudoku.
Struktura Bunka
Pod třídu EntrySudoku si vložíme novou strukturu
Bunka, do které umístíme proměnné hodnota a
konstanta:
public struct Bunka { public int hodnota; public bool konstanta; };
Proměnná hodnota bude moci nabývat hodnot:
0pro neutrální hodnotu,1-9pro povolené hodnoty,- ostatní pro nepovolené hodnoty.
Pomocí proměnné konstanta budeme zjišťovat, zda daná
hodnota nabývá hodnoty true a jedná se tedy o zadání
sudoku, nebo hodnoty false a jedná se o buňku kterou
musí vyplnit řešitel úlohy.
Následující metody si napíšeme například na konec souboru
MainPage.xaml.cs.
Kontrola buněk
Jako první si napíšeme metodu pro kontrolu, zda hodnoty obou přijatých buněk jsou stejné:
static public bool SuRovnake(Bunka bunka1, Bunka bunka2) { if ((bunka1.hodnota < 1) || (bunka1.hodnota > 9)) return false; if ((bunka2.hodnota < 1) || (bunka2.hodnota > 9)) return false; return bunka1.hodnota == bunka2.hodnota; }
V metodě porovnáváme buňky bunka1 a bunka2,
které jsme přijali v parametrech metody. Pokud se hodnoty buněk v intervalu
1 až 9 shodují, vrátíme hodnotu true.
Pokud se hodnoty buněk v tomto intervalu neshodují, nebo máme v buňce
neutrální hodnotu 0, vrátíme hodnotu false.
Kontrola sloupce
Nyní v nové metodě zkontrolujeme, zda ve sloupci se vyskytují stejné hodnoty:
static public bool SkontrolujStlpec(int row) { for (int column = 0; column < 8; column++) { for (int i = column + 1; i < 9; i++) { if (SuRovnake(sudoku_grid[row, column], sudoku_grid[row, i])) return false; } } return true; }
V prvním cyklu načítáme číslo. V druhém cyklu načteme další
číslo. Načtená dvě čísla porovnáme pomocí metody
SuRovnake() a vrátíme hodnotu false nebo
true. Takto následně porovnáme číslo z prvního cyklu se
zbývajícími čísly z druhého cyklu. Nakonec načteme další číslo v
prvním cyklu a pokračujeme v porovnávání.
Kontrola řádku
Obdobně v další metodě zkontrolujeme, zda se v řádku vyskytují stejné hodnoty:
static public bool SkontrolujRiadok(int column) { for (int row = 0; row < 8; row++) { for (int i = row + 1; i < 9; i++) { if (SuRovnake(sudoku_grid[row, column], sudoku_grid[i, column])) return false; } } return true; }
Stejně tak zkontrolujeme čísla v řádku. Tedy opět
načteme číslo v prvním cyklu. V druhém cyklu načteme další číslo.
Načtená dvě čísla porovnáme pomocí metody SuRovnake() a
vrátíme hodnotu false nebo true. Takto následně
porovnáme číslo z prvního cyklu se zbývajícími čísly z druhého cyklu.
Nakonec načteme další číslo v prvním cyklu a pokračujeme v
porovnávání.
Kontrola mřížky
Nyní implementujeme metodu pro kontrolu čísel v mřížce 3x3:
static public bool SkontrolujMriezku(int row_in, int column_in) { int zaciatok_mriezky_row = 0; int zaciatok_mriezky_column = 0; int row, column, i, j; Bunka[] pole = new Bunka[9]; zaciatok_mriezky_row = row_in / 3 * 3; // bude to 0 nebo 3 nebo 6 zaciatok_mriezky_column = column_in / 3 * 3; // bude to 0 nebo 3 nebo 6 i = 0; for (row = zaciatok_mriezky_row; row < zaciatok_mriezky_row + 3; row++) { for (column = zaciatok_mriezky_column; column < zaciatok_mriezky_column + 3; column++) { pole[i++] = sudoku_grid[row, column]; } } for (i = 0; i < 8; i++) { for (j = i + 1; j < 9; j++) { if (SuRovnake(pole[i], pole[j])) return false; } } return true; }
V metodě jsme převedli mřížku na řádek a použili stejný algoritmus.
U výpočtu počátečního řádku a sloupce mřížky používáme
celočíselnou aritmetiku. Takže například u kontroly
pátého řádku, počáteční řádek mřížky je 5/3=1 a
1*3=3, tedy třetí řádek. Pokud je vše v
pořádku, vrátíme hodnotu true. V případě dvou stejných
čísel v mřížce vrátíme hodnotu false.
Kontrola Sudoku
Poslední metodou zkontrolujeme celé Sudoku:
static public bool SkontrolujSudoku() { int riadok, stlpec; // kontrola řádků for (riadok = 0; riadok < 9; riadok++) { if (!SkontrolujRiadok(riadok)) return false; } // kontrola sloupců for (stlpec = 0; stlpec < 9; stlpec++) { if (!SkontrolujStlpec(stlpec)) return false; } // kontrola mřížky for (riadok = 0; riadok < 9; riadok += 3) { for (stlpec = 0; stlpec < 9; stlpec += 3) { if (!SkontrolujMriezku(riadok, stlpec)) return false; } } return true; }
Zkontrolujeme postupně všechny řádky, sloupce a mřížku. Pokud
nalezneme chybu, z metody vyskočíme a vrátíme hodnotu false.
Pokud dojdeme až na konec bez chyby, vrátíme hodnotu true.
V příští lekci, Tvorba sudoku v Xamarin - Test kontrolních mechanismů, si ukážeme, jak můžeme graficky otestovat naše kontrolní mechanismy a zobrazit počet zadaných čísel a číslic.
Měl jsi s čímkoli problém? Zdrojový kód vzorové aplikace je ke stažení každých pár lekcí. Zatím pokračuj dál, a pak si svou aplikaci porovnej se vzorem a snadno oprav.


