5. diel - Tvorba sudoku v Xamarin - Kontrolné mechanizmy
V minulej lekcii, Tvorba sudoku v Xamarin - Nahranie aplikácie do mobilu , sme nahrali aplikáciu do iPhonu a Androidu a nastavili mobil pre vývoj, aby sme mohli aplikáciu debugovať.
V dnešnom Xamarin tutoriále implementujeme kontrolné mechanizmy na zadanie a riešenie Sudoku. Základom bude kontrola dvoch buniek, ktorú zavoláme pri kontrole rovnakých čísel v stĺpcoch, riadkoch, mriežke a nakoniec v celom Sudoku.
Budeme rozširovať našu aplikáciu z lekcie Nahranie
aplikácie do mobilu. Všetok kód budeme písať do súboru
MainPage.xaml.cs.
Trieda EntrySudoku
Keďže máme 81 Entry, ktoré vedia reagovať na
užívateľský vstup, ale nevedia, kde v mriežke sa nachádzajú, musíme
určiť súradnice. Tieto súradnice budeme definovať pri
vytvorení nového objektu triedy EntrySudoku, ktorú si teraz
vložíme na začiatok súboru 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; } }
Triedu využijeme na testovanie implementovaných funkcionalít z užívateľského rozhrania.
V premenných row a column budeme ukladať
umiestnenie mriežky. Umiestnenie potom definujeme v
konštruktore.
Zmeny existujúceho kódu
Na základe vytvorenia triedy EntrySudoku zmeníme:
- všetky výskyty typu
Entryza typEntrySudoku, - vytvorenie nového objektu typu
Entryza nový objekt typuEntrySudoku.
Bunka
Pod triedu EntrySudoku si vložíme novú štruktúru
Bunka, do ktorej umiestnime premenné hodnota a
konstanta:
public struct Bunka { public int hodnota; public bool konstanta; };
Premenná hodnota bude môcť nadobúdať hodnoty:
0pre neutrálnu hodnotu,1-9pre povolené hodnoty,- ostatné pre nepovolené hodnoty.
konstanta budeme zisťovať, či daná hodnota
nadobúda hodnotu true, a jedná sa teda o zadanie
sudoku, alebo hodnoty false, a jedná sa o bunku, ktorú
musí vyplniť riešiteľ úlohy.
Nasledujúce metódy si napíšeme napríklad na koniec súboru
MainPage.xaml.cs.
Kontrola buniek
Ako prvé si napíšeme metódu pre kontrolu, či hodnoty oboch prijatých buniek sú rovnaké.
static public bool JsouStejne(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 metóde porovnávame bunky bunka1 a bunka2,
ktoré sme prijali v parametroch metódy. Pokiaľ sa hodnoty buniek v intervale
1 až 9 zhodujú, vrátime hodnotu true.
Ak sa hodnoty buniek v tomto intervale nezhodujú, alebo máme v bunke
neutrálnu hodnotu 0, vrátime hodnotu false.
Kontrola stĺpca
Teraz v novej metóde skontrolujeme, či v stĺpci sa vyskytujú rovnaké hodnoty:
static public bool ZkontrolujSloupec(int row) { for (int column = 0; column < 8; column++) { for (int i = column + 1; i < 9; i++) { if (JsouStejne(sudoku_grid[row, column], sudoku_grid[row, i])) return false; } } return true; }
V prvom cykle načítame číslo. V druhom cykle načítame ďalšie číslo.
Načítané dva čísla porovnáme pomocou metódy JsouStejne() a
vrátime hodnotu false alebo true. Takto následne
porovnáme číslo z prvého cyklu so zvyšnými číslami z druhého cyklu.
Nakoniec načítame ďalšie číslo v prvom cykle a pokračujeme v
porovnávaní.
Kontrola riadku
Podobne, v ďalšej metóde, skontrolujeme, či v riadku sa vyskytujú rovnaké hodnoty:
static public bool ZkontrolujRadek(int column) { for (int row = 0; row < 8; row++) { for (int i = row + 1; i < 9; i++) { if (JsouStejne(sudoku_grid[row, column], sudoku_grid[i, column])) return false; } } return true; }
Podobne skontrolujeme čísla v riadku. Teda zase načítame
číslo v prvom cykle. V druhom cykle načítame ďalšie číslo. Načítané
dva čísla porovnáme pomocou metódy JsouStejne() a vrátime
hodnotu false alebo true. Takto následne porovnáme
číslo z prvého cyklu so zvyšnými číslami z druhého cyklu. Nakoniec
načítame ďalšie číslo v prvom cykle a pokračujeme v porovnávaní.
Kontrola mriežky
Teraz implementujeme metódu na kontrolu čísel v mriežke 3x3:
static public bool ZkontrolujMrizku(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 alebo 3 alebo 6 zaciatok_mriezky_column = column_in / 3 * 3; // bude to 0 alebo 3 alebo 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 (JsouStejne(pole[i], pole[j])) return false; } } return true; }
V metóde sme previedli mriežku na riadok a použili rovnaký algoritmus.
Pri výpočte počiatočného riadku a stĺpca mriežky používame
celočíselnú aritmetiku. Takže napríklad pri kontrole
piateho riadku, počiatočný riadok mriežky je 5/3=1 a
1*3=3, teda tretí riadok. Pokiaľ je všetko
v poriadku, vrátime hodnotu true, v prípade dvoch rovnakých
čísel v mriežke vrátime hodnotu false.
Kontrola Sudoku
Poslednou metódou skontrolujeme celé Sudoku:
static public bool ZkontrolujSudoku() { int riadok, stlpec; // kontrola riadkov for (riadok = 0; riadok < 9; riadok++) { if (!ZkontrolujRadek(riadok)) return false; } // kontrola stĺpcov for (stlpec = 0; stlpec < 9; stlpec++) { if (!ZkontrolujSloupec(stlpec)) return false; } // kontrola mriežky for (riadok = 0; riadok < 9; riadok += 3) { for (stlpec = 0; stlpec < 9; stlpec += 3) { if (!ZkontrolujMrizku(riadok, stlpec)) return false; } } return true; }
Skontrolujeme postupne všetky riadky, stĺpce a mriežku. Pokiaľ nájdeme
chybu, z metódy vyskočíme a vrátime hodnotu false. Pokiaľ
dôjdeme až na koniec bez chyby, vrátime hodnotu true.
V nasledujúcej lekcii, Tvorba sudoku v Xamarin - Test kontrolných mechanizmov , si ukážeme, ako môžeme graficky otestovať naše kontrolné mechanizmy a zobraziť počet zadaných čísel a číslic.

