Diskuze: Sudoku - Algoritmus
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Tvůrce
Zobrazeno 34 zpráv z 34.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
A čeho chceš docílit? Chceš jen naplnit prázdné pole tak, aby to bylo tohle sudoku?
Pardon, špatně jsme vyjádřil co požaduji. Program vygnereuje pole 9x9, kde v každém řádků budou čísla od 1-9. Zároveň se nesmí opakovat ve sloupcích dvě stejná čísla. Poté některá čísla zakryje a uživatel bude muset dořešit. Jedná se tedy o zjednodušené sudoku.
Ano google jsem použít mohl, v tom případě by devbook neměl smysl . Většina problémů se dá prakticky "vygůglit". Co tu ale nechat i komentáře pro jiné ? Každopádně jsem už možná přišel jak to vyřešit. Ještě sem psát nebudu ani nápad, nejsem si jistý jestli je vůbec použitelný.
Přijde mi lepší napsat o nějakém algoritmu článek, než se na něj ptát - jak jsi napsal - vygooglit to dokáže každý... Problém je, že mnoho alogritmů jen těžko seženeš Česky popsané, a nebo jsou hodně složité - což tento rozhodně není nejjednodušší - takže si článek zaslouží... Čily až jej pochopíš, tak jej můžeš pěkně popsat - aby jej mohl pochopit i nějaký začátečník...
To je pravda . Každopdáně nehledám algoritmus na to pravé sudoku. Hledám na to velmi zjednodušené. Stačí "nějak lehce" proházet několik čísel. Jak jsem psal, nápad už mám. Pokud budu úspěšný, určitě nezapomenu informovat.
Některé algoritmy na http://www.algoritmy.net/ jsou skutečně hezky česky popsané. Dokonce jsem tam našel i pár algoritmů pro řazení.
Ano, algoritmy.net nejsou špatné. Také jsem už tam našel jednou co jsem hledal a pomohlo to.
Nechápu, co chceš na tom zjednodušovat - dělá to, to co popisuješ... Zjednodušením to spíš ztížíš řekl bych - spíše bych si s tím dal tu práci a právě se snažil pochopit ten algoritmus...
Sudoku bude ulehčený, že nemusíš řešit čtverce, tedy řešíš pouze sloupce a řádky, tudíž podle mě bude i jednodušší algoritmus. Ano, až naleznu čas podvám se na ten "složitější". Bohužel teď kvůli škole moc nestíhám, mám dělat aplikaci pro Windows 8 -> Prvouka 1,2 třída pro základní školy a další. No málo času, mnoho věcí
Zplodil jsem toto:
List<int[]> sudokuArea = new List<int[]>() { new int[9], new int[9], new int[9], new int[9], new int[9], new int[9], new int[9], new int[9], new int[9] };
for (int x = 0; x < 9; x++)
{
List<int> column = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }.OrderBy(emp => Guid.NewGuid()).ToList();
for (int y = 0; y < 9; y++)
foreach (int i in column)
if (!sudokuArea[y].Contains(i))
{
sudokuArea[y][x] = i;
column.Remove(i);
break;
}
}
Má to ale nějakou díru - zítra ji opravím - nepředběhneš-li mne...
Možná jsem šťoura, ale sudoku mi nepřipadá jako seznam, ale spíš jako pole. Dokonce dvojrozměrné.
Matesax zásadně používá seznamy místo dvourozměrného pole, dělal přes ně i šachovnici, už jsem mu to říkal asi stokrát
int[][] sudokuArea = new int[9][] { new int[9], new int[9], new int[9], new int[9], new int[9], new int[9], new int[9], new int[9], new int[9] };
Random r = new Random();
for (int x = 0; x < 9; x++)
{
int[] column = new int[9];
for (int y = 0; y < 9; y++)
{
List<int> rough = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }.OrderBy(emp => Guid.NewGuid()).ToList();
rough.RemoveAll(t => sudokuArea[y].Contains(t) || column.Contains(t));
column[y] = rough[r.Next(rough.Count - 1)];
sudokuArea[y][x] = column[y];
}
}
Myslel jsem si, že v C# se dvourozměrné pole deklaruje jednodušeji:
int[,] sudokuArea = new int[9,9];
Právě proto jsem měl list - jak se dostanu k jednotlivým řádkům? Snížil jsem to na pole polí, ale jak dostat z více dimenzí řádek jsem nikde nenašel - a další cyklus opravdu nechci...
S vícerozměrným polem se obvykle pracuje s vícenásobným cyklem. Tedy pokud neděláš ve Fortranu nebo Octave.
A ten já nechci ("a další cyklus opravdu nechci") - přeci je lepší toto, než další cyklus - ne?
Popravdě mi opravdu přijde lepší dvourozěmrné pole. Přistupuje se k němu přes dva for cykly, tedy ve stylu
int[,]pole=new int[9,9];
for(int x=0;x<pole.GetLength(0);x++)
{
for(int y=0;y<pole.GetLength(1);y++)
{
pole[x,y]=1;
}
}
OK - 4 cykly lepší, než 2? Proč ze mě oba děláte blbce - vím, jak pracovat s xrozměrnými poli - a mnohem lépe to jde přes LINQ - ovšem jak jsem napsal - dostaň mi z toho bez cyklu řádek - u toho pole polí jen zadám index...
Máš ještě další možnost: Udělat 81 objektů, které naskládáš do 18 seznamů (9 vodorovně a 9 svisle) a těchto 18 seznamů (případně ještě dalších 9 pro čtverce 3×3 v úplném sudoku) si dáš do jednoho nadřazeného seznamu. Vystačíš si pak i bez cyklů.
To by také mohla být odpověď na tvou otázku kolem "jak dostat z více dimenzí řádek". Navíc můžeš získat i sloupec.
OK - čím více cyklů, tím více programátor? - OK...
Prostě proč bych jako idiot zadával jen index, když mohu použít 2 cykly (ještě k tomu druhý je vnořený) - že?
Momentálně přesně nevím pointu dohadování. Jak je to s rychlostmi, v tom zkušený nejsem, ale pro mě je přehlednější použít dva cykly, a tím pádem napsat dva indexy.
A co tím tvým získám? Já jsem to pochopil - je mnohem lepší si celý řádek postavit 2 cykly, než ho rovnou mít pod indexem v poli... Vůbec nejlepší by bylo, mít takových 10 cyklů a 120 vnořených - aby se mi ta aplikace vůbec nespustila...
Jasně - čím více cyklů, tím bude větší přehlednost - můj kód je absolutně nepřehledný - vůbec není jasné, co dělá... Takže si to celé roztahej nejlépe ještě tak do 10 souborů...
No, už jen chci dodat , to řešení na sudoku. Jak jsem psal, hledal jsem řešení pro zjednodušenou variantu. Nakonec, jsem tedy náhodně vybral dva sloupce v poli a ty mezi sebou prohodil. Takto se to prohodí několiklikrát. Poté náhodně zakryju několik polí a ejhle máme tu jednoduché sudoku. Pokud jich zakryju mnohem více, dokonce už se u toho musí začít i přemýšlet . Ale ano, není to řešení algoritmu pro tvorbu Sudoku jako takového.
Pointa dohadování je v tom, že matesax nechce vnořené cykly. Tak jsem mu navrhl řešení bez cyklů, ale myslí si, že si jen z něho dělám srandu. Přitom jsem to myslel vážně, v Lispu bych to tak určitě udělal.
Z hlediska sudoku jsou totiž řádky a sloupce (příp. i čtverce 3×3) z hlediska kontroly jedinečnosti symbolu rovnocenné.
Co je na tom k nepochoení?
int[][] sudokuArea = new int[9][] { new int[9], new int[9], new int[9], new int[9], new int[9], new int[9], new int[9], new int[9], new int[9] };
Random r = new Random();
for (int x = 0; x < 9; x++)
{
int[] column = new int[9];
for (int y = 0; y < 9; y++)
{
List<int> rough = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }.OrderBy(emp => Guid.NewGuid()).ToList();
rough.RemoveAll(t => sudokuArea[y].Contains(t) || column.Contains(t));
column[y] = rough[r.Next(rough.Count - 1)];
sudokuArea[y][x] = column[y];
}
}
Jen to musíš dotáhnout do konce - chybí tomu nějaké(á) pravidlo(a) - na to už by jsis musel přijít sám... (Nějaké modely kombinací - zde nejsou a algoritmus brzy dojde do místa, kde nic neprojde přes podmínku...)
Kit:
To už je lepší napsat to do TXT - a randomizovat přesouváním bloků...
A proč tam máš ten dvojitý cyklus? Myslel jsem si, že ho nechceš.
Já neřekl, že tam není nic k nepochopení . Ale dělat pole polí a potom ještě list, mi přijde horší způsob. Holt, asi kažý jsme zvyklí psát programy jinak. Neříkám, že se v tom vyznám extra. C# se věnuju přes rok.
Nechci - ale myslel jsem, že mě s mým hlavním nápadem pošlete do pryč. Takže jsem jej napsal - vytvoř sudoku model do TXT. A vytvoř model bloků - tak, aby se jejich přesouváním nenarušily stanovené vztahy - jejich mícháním pak budeš randomizovat...
Zobrazeno 34 zpráv z 34.