public bool VyresRekurzivne(Bunka dalsiBunka) //dalsiBunka je bunka s minimem vhodnych kandidatu { //Vyřešeno if (dalsiBunka.Equals(new Bunka(-1, -1))) { Console.WriteLine("Sudoku is solved, Huray!"); return(true); } foreach (int kandidat in omezeniBunek[dalsiBunka.Radek, dalsiBunka.Sloupec]) { ZvolKandidata(dalsiBunka, kandidat); //Backtracking if (VyresRekurzivne(DalsiBunka()) == false) { OdeberKandidata(dalsiBunka, kandidat); continue; } //Vyřešeno dříve else { return(true); } } //Nemůže pokračovat dále, postup neodpovídá řešení return(false); }
public Bunka DalsiBunka() { pocetKroku++; if (nevyresene.Count == 0) { return(new Bunka(-1, -1)); } Bunka min = nevyresene.First(); foreach (Bunka bunka in nevyresene) { min = (omezeniBunek[bunka.Radek, bunka.Sloupec].Pocet < omezeniBunek[min.Radek, min.Sloupec].Pocet) ? bunka : min; } return(min); }
public void OdeberKandidata(Bunka bunka, int kandidat) { sudokuResene[bunka.Radek, bunka.Sloupec] = 0; //Vypnout omezení Řádek, Sloupec, Region omezeniRadku[bunka.Radek][kandidat] = false; omezeniSloupce[bunka.Sloupec][kandidat] = false; omezeniRegionu[bunka.Radek / 3, bunka.Sloupec / 3][kandidat] = false; //Nastavi cislo zpet jako vhodneho kandidata pro zmenene bunky omezeniBunek[bunka.Radek, bunka.Sloupec][kandidat] = true; foreach (Bunka b in zmenene.Pop()) { omezeniBunek[b.Radek, b.Sloupec][kandidat] = true; } vyresene.Remove(bunka); nevyresene.Add(bunka); }
//Dosazeni omezeni do nevyresenych poli private void OmezitKandidaty() { for (int radek = 0; radek < 9; radek++) { for (int sloupec = 0; sloupec < 9; sloupec++) { //V případě, že pole je vyřešené if (sudokuResene[radek, sloupec] > 0) { //Vyřešené pole nepotřebuje kandidáty omezeniBunek[radek, sloupec].NastavVsechnyNaHodnotu(false); vyresene.Add(new Bunka(radek, sloupec)); } else { //Najdu nevyřešené číslo a chci mu přiřadit omezení na kandidáty //1) Podívám se jestli tam vůbec nějaké omezení je: //2) Pokud ano, překopíruji číslo z omezení a v kandidátu buňky ho nastavým jako neplatné foreach (int cislo in omezeniRadku[radek]) { omezeniBunek[radek, sloupec][cislo] = false; } foreach (int cislo in omezeniSloupce[sloupec]) { omezeniBunek[radek, sloupec][cislo] = false; } foreach (int cislo in omezeniRegionu[radek / 3, sloupec / 3]) { omezeniBunek[radek, sloupec][cislo] = false; } Bunka b = new Bunka(radek, sloupec); nevyresene.Add(b); } } } }
public void ZvolKandidata(Bunka bunka, int kandidat) { HashSet <Bunka> zmeneneBunky = new HashSet <Bunka>(); // Vybrat prvního kandidáta sudokuResene[bunka.Radek, bunka.Sloupec] = kandidat; omezeniBunek[bunka.Radek, bunka.Sloupec][kandidat] = false; omezeniRadku[bunka.Radek][kandidat] = true; omezeniSloupce[bunka.Sloupec][kandidat] = true; omezeniRegionu[bunka.Radek / 3, bunka.Sloupec / 3][kandidat] = true; // Odeberu kandidáty z polí souvisejici se zmenenou bunkou for (int i = 0; i < 9; i++) { if (sudokuResene[bunka.Radek, i] == 0) { // radek if (omezeniBunek[bunka.Radek, i][kandidat] == true) { omezeniBunek[bunka.Radek, i][kandidat] = false; zmeneneBunky.Add(new Bunka(bunka.Radek, i)); } } if (sudokuResene[i, bunka.Sloupec] == 0) { // sloupec if (omezeniBunek[i, bunka.Sloupec][kandidat] == true) { omezeniBunek[i, bunka.Sloupec][kandidat] = false; zmeneneBunky.Add(new Bunka(i, bunka.Sloupec)); } } } // region int pocatek_radkuR = bunka.Radek / 3 * 3; int pocatek_sloupceR = bunka.Sloupec / 3 * 3; for (int radek = pocatek_radkuR; radek < pocatek_radkuR + 3; radek++) { for (int sloupec = pocatek_sloupceR; sloupec < pocatek_sloupceR + 3; sloupec++) { // only change unsolved cells containing the candidate if (sudokuResene[radek, sloupec] == 0) { if (omezeniBunek[radek, sloupec][kandidat] == true) { //remove the candidate omezeniBunek[radek, sloupec][kandidat] = false; //update changed cells (for backtracking) zmeneneBunky.Add(new Bunka(radek, sloupec)); } } } } nevyresene.Remove(bunka); vyresene.Add(bunka); zmenene.Push(zmeneneBunky); }