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
Entry
za typEntrySudoku
, - vytvorenie nového objektu typu
Entry
za 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:
0
pre neutrálnu hodnotu,1
-9
pre 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.