/// <summary> /// Delete's a slot's text out of all it's row/column/box's possibleEntries. /// </summary> /// <param name="senderControl"></param> public static void RemoveNeighbors(SudokuSlot senderControl, List<SudokuSlot> slotList, SolveHistory history, Queue<SudokuSlot> queueToClean) { foreach (SudokuSlot slot in slotList) { if (slot.row == senderControl.row & slot != senderControl) { if (slot.RemovePossibleEntry(senderControl.Text) == true) queueToClean.Enqueue(slot); } else if (slot.column == senderControl.column & slot != senderControl) { if (slot.RemovePossibleEntry(senderControl.Text) == true) queueToClean.Enqueue(slot); } else if (slot.box == senderControl.box & slot != senderControl) { if (slot.RemovePossibleEntry(senderControl.Text) == true) queueToClean.Enqueue(slot); } history.AddSnapshot(slotList); } if (queueToClean.Count > 0) RemoveNeighbors(queueToClean.Dequeue(), slotList, history, queueToClean); }
// Find slots with identical possibleEntries and remove them from // other slots public void SearchNakeds(SolveHistory history, Queue <SudokuSlot> queueToClean) { byte counter = 0; foreach (SudokuSlot slot in paredList) { foreach (SudokuSlot slot_2 in paredList) { if (slot_2.possibleEntries == slot.possibleEntries && slot_2 != slot) { counter++; } } if (counter == slot.possibleEntries.Count) { foreach (SudokuSlot slot_2 in paredList) { if (slot_2.possibleEntries != slot.possibleEntries) { foreach (string entry in slot.possibleEntries) { if (slot_2.RemovePossibleEntry(entry) == true) { Solver.RemoveNeighbors(slot, allSlots, history, queueToClean); } } } } } } }
// If 2 possible Entries are spread across 2 slots in the collection, remove those slots' // other possibleEntries. public void SearchHiddenDoubles(SolveHistory history, Queue<SudokuSlot> queueToClean) { this.UpdatePossibleEntries(); foreach (string entry in this.collPossibleEntries) { foreach (string entry_2 in this.collPossibleEntries) { List<SudokuSlot> slotsWithPossHiddens = new List<SudokuSlot>(); if (entry_2 != entry) foreach (SudokuSlot slot in this.paredList) if (slot.possibleEntries.Contains(entry) || slot.possibleEntries.Contains(entry_2)) if (!slotsWithPossHiddens.Contains(slot)) { slotsWithPossHiddens.Add(slot); if (slotsWithPossHiddens.Count > 2) break; // If spread across more than 2 slots, save CPU cycles } if (slotsWithPossHiddens.Count == 2) { List<string> allPossibles = new List<string>(); foreach (SudokuSlot slot in slotsWithPossHiddens) { foreach (string possEntry in slot.possibleEntries) allPossibles.Add(possEntry); } if (allPossibles.Contains(entry) && allPossibles.Contains(entry_2)) { foreach (SudokuSlot slot in slotsWithPossHiddens) { if (!(slot.possibleEntries.Count == 2 && slot.possibleEntries.Contains(entry) && slot.possibleEntries.Contains(entry_2))) { List<string> tempPossibleEntries = new List<string>(); foreach (string possEntry in slot.possibleEntries) tempPossibleEntries.Add(possEntry); foreach (string possEntry in tempPossibleEntries) if (possEntry != entry && possEntry != entry_2) { if (slot.RemovePossibleEntry(possEntry) == true) Solver.RemoveNeighbors(slot, allSlots, history, queueToClean); } } } } } } } }
//byte unsuccessfulRuns = 0; //byte unsolvedSlots = 0; // Constructor //public Solver(List<SudokuSlot> slotList) //{ // //this.slotList = slotList; // //history.AddSnapshot(slotList); //} public static void solve(List<SlotCollection> CollectionList, List<SudokuSlot> slotList, SolveHistory history, Queue<SudokuSlot> queueToClean, byte unsuccessfulCounter) { byte unsuccessfulRuns = unsuccessfulCounter; while (CheckForWin(CollectionList, unsuccessfulRuns, 0, slotList) == false) { foreach(SudokuSlot slot in slotList) RemoveNeighbors(slot, slotList, history, queueToClean); foreach (SlotCollection collection in CollectionList) { collection.SearchHiddenSingles(history, queueToClean); collection.SearchNakeds(history, queueToClean); collection.SearchHiddenDoubles(history, queueToClean); collection.SearchHiddenTriples(history, queueToClean); collection.SearchHiddenQuads(history, queueToClean); } } }
// Main Solve button private void btnSolve_Click(object sender, EventArgs e) { foreach(SudokuSlot slot in allSlots) { slot.LockValues(); slot.BackColor = System.Drawing.Color.Empty; } List<SlotCollection> CollectionList = new List<SlotCollection>(); for (int i = 1; i <= 3; i++) for (int j = 1; j <= 9; j++) { CollectionList.Add(new SlotCollection(allSlots, j.ToString(), i)); } Queue<SudokuSlot> queueToClean = new Queue<SudokuSlot>(); SolveHistory history = new SolveHistory(); Solver.solve(CollectionList, allSlots, history, queueToClean, 0); }
// If a slot has the only instance of an PossibleEntry in its row/column/box, remove // all its other possible entries public void SearchHiddenSingles(SolveHistory history, Queue <SudokuSlot> queueToClean) { for (int entry = 1; entry <= 9; entry++) { int counter = 0; foreach (SudokuSlot slot in paredList) { if (slot.possibleEntries.Contains(entry.ToString())) { counter++; } if (counter > 1) { break; } } if (counter == 1) { foreach (SudokuSlot slot in paredList) { if (slot.possibleEntries.Contains(entry.ToString())) { for (int i = 1; i <= 9; i++) { if (slot.possibleEntries.Contains(i.ToString())) { if (i != entry) { if (slot.RemovePossibleEntry(i.ToString()) == true) { Solver.RemoveNeighbors(slot, allSlots, history, queueToClean); } } } } } } } } }
// Main Solve button private void btnSolve_Click(object sender, EventArgs e) { foreach (SudokuSlot slot in allSlots) { slot.LockValues(); slot.BackColor = System.Drawing.Color.Empty; } List <SlotCollection> CollectionList = new List <SlotCollection>(); for (int i = 1; i <= 3; i++) { for (int j = 1; j <= 9; j++) { CollectionList.Add(new SlotCollection(allSlots, j.ToString(), i)); } } Queue <SudokuSlot> queueToClean = new Queue <SudokuSlot>(); SolveHistory history = new SolveHistory(); Solver.solve(CollectionList, allSlots, history, queueToClean, 0); }
//byte unsuccessfulRuns = 0; //byte unsolvedSlots = 0; // Constructor //public Solver(List<SudokuSlot> slotList) //{ // //this.slotList = slotList; // //history.AddSnapshot(slotList); //} static public void solve(List <SlotCollection> CollectionList, List <SudokuSlot> slotList, SolveHistory history, Queue <SudokuSlot> queueToClean, byte unsuccessfulCounter) { byte unsuccessfulRuns = unsuccessfulCounter; while (CheckForWin(CollectionList, unsuccessfulRuns, 0, slotList) == false) { foreach (SudokuSlot slot in slotList) { RemoveNeighbors(slot, slotList, history, queueToClean); } foreach (SlotCollection collection in CollectionList) { collection.SearchHiddenSingles(history, queueToClean); collection.SearchNakeds(history, queueToClean); collection.SearchHiddenDoubles(history, queueToClean); collection.SearchHiddenTriples(history, queueToClean); collection.SearchHiddenQuads(history, queueToClean); } } }
/// <summary> /// Delete's a slot's text out of all it's row/column/box's possibleEntries. /// </summary> /// <param name="senderControl"></param> static public void RemoveNeighbors(SudokuSlot senderControl, List <SudokuSlot> slotList, SolveHistory history, Queue <SudokuSlot> queueToClean) { foreach (SudokuSlot slot in slotList) { if (slot.row == senderControl.row & slot != senderControl) { if (slot.RemovePossibleEntry(senderControl.Text) == true) { queueToClean.Enqueue(slot); } } else if (slot.column == senderControl.column & slot != senderControl) { if (slot.RemovePossibleEntry(senderControl.Text) == true) { queueToClean.Enqueue(slot); } } else if (slot.box == senderControl.box & slot != senderControl) { if (slot.RemovePossibleEntry(senderControl.Text) == true) { queueToClean.Enqueue(slot); } } history.AddSnapshot(slotList); } if (queueToClean.Count > 0) { RemoveNeighbors(queueToClean.Dequeue(), slotList, history, queueToClean); } }
// If 4 possible Entries are spread across 4 slots in the collection, remove those slots' // other possibleEntries. public void SearchHiddenQuads(SolveHistory history, Queue <SudokuSlot> queueToClean) { this.UpdatePossibleEntries(); foreach (string entry in this.collPossibleEntries) { foreach (string entry_2 in this.collPossibleEntries) { foreach (string entry_3 in this.collPossibleEntries) { foreach (string entry_4 in this.collPossibleEntries) { List <SudokuSlot> slotsWithPossHiddens = new List <SudokuSlot>(); if (entry_4 != entry_3 && entry_4 != entry_2 && entry_4 != entry && entry_3 != entry_2 && entry_3 != entry && entry_2 != entry) { foreach (SudokuSlot slot in this.paredList) { if (slot.possibleEntries.Contains(entry) || slot.possibleEntries.Contains(entry_2) || slot.possibleEntries.Contains(entry_3) || slot.possibleEntries.Contains(entry_4)) { if (!slotsWithPossHiddens.Contains(slot)) { slotsWithPossHiddens.Add(slot); if (slotsWithPossHiddens.Count > 4) { break; // If spread across more than 2 slots, save CPU cycles } } } } } if (slotsWithPossHiddens.Count == 4) { List <string> allPossibles = new List <string>(); foreach (SudokuSlot slot in slotsWithPossHiddens) { foreach (string possEntry in slot.possibleEntries) { allPossibles.Add(possEntry); } } if (allPossibles.Contains(entry) && allPossibles.Contains(entry_2) && allPossibles.Contains(entry_3) && allPossibles.Contains(entry_4)) { foreach (SudokuSlot slot in slotsWithPossHiddens) { if (!(slot.possibleEntries.Count == 4 && slot.possibleEntries.Contains(entry) && slot.possibleEntries.Contains(entry_2) && slot.possibleEntries.Contains(entry_3) && slot.possibleEntries.Contains(entry_4))) { List <string> tempPossibleEntries = new List <string>(); foreach (string possEntry in slot.possibleEntries) { tempPossibleEntries.Add(possEntry); } foreach (string possEntry in tempPossibleEntries) { if (possEntry != entry && possEntry != entry_2 && possEntry != entry_3 && possEntry != entry_4) { if (slot.RemovePossibleEntry(possEntry) == true) { Solver.RemoveNeighbors(slot, allSlots, history, queueToClean); } } } } } } } } } } } }
// Find slots with identical possibleEntries and remove them from // other slots public void SearchNakeds(SolveHistory history, Queue<SudokuSlot> queueToClean) { byte counter = 0; foreach (SudokuSlot slot in paredList) { foreach (SudokuSlot slot_2 in paredList) { if (slot_2.possibleEntries == slot.possibleEntries && slot_2 != slot) counter++; } if (counter == slot.possibleEntries.Count) { foreach (SudokuSlot slot_2 in paredList) if (slot_2.possibleEntries != slot.possibleEntries) foreach (string entry in slot.possibleEntries) { if (slot_2.RemovePossibleEntry(entry) == true) Solver.RemoveNeighbors(slot, allSlots, history, queueToClean); } } } }
// If a slot has the only instance of an PossibleEntry in its row/column/box, remove // all its other possible entries public void SearchHiddenSingles(SolveHistory history, Queue<SudokuSlot> queueToClean) { for (int entry = 1; entry <= 9; entry++) { int counter = 0; foreach (SudokuSlot slot in paredList) { if (slot.possibleEntries.Contains(entry.ToString())) counter++; if (counter > 1) break; } if (counter == 1) { foreach (SudokuSlot slot in paredList) if (slot.possibleEntries.Contains(entry.ToString())) { for (int i = 1; i<=9;i++) if (slot.possibleEntries.Contains(i.ToString())) if (i != entry) { if (slot.RemovePossibleEntry(i.ToString()) == true) { Solver.RemoveNeighbors(slot, allSlots, history, queueToClean); } } } } } }