static SudokuCandidate[] Filter(SudokuSolver ss, int cage, Func <int, bool> included) { int Cells = ss.Cells; List <SudokuCandidate> toRemove = new List <SudokuCandidate>(); for (int i = 0; i < Cells; ++i) { if (!included(i + 1)) { CageOptional co = ss.GetCageOptional(cage, i); if (co.Included) { foreach (SudokuCandidate sc in co.UnselectedCandidates) { if (!sc.IsMarked) { toRemove.Add(sc); sc.MarkCandidate(true); } } } } } SudokuCandidate[] removed = toRemove.ToArray(); for (int i = 0; i < removed.Length; ++i) { SudokuCandidate sc = removed[i]; ss.DiscardCandidate(sc); sc.MarkCandidate(false); } return(removed.ToArray()); }
public override void SelectCandidate(Candidate k) { SudokuCandidate sc = (SudokuCandidate)k; values[sc.x, sc.y] = sc.n; flags[sc.x, sc.y] = CellFlags.Solved; solver.SelectCandidate(k); }
public void OnCover(ExactCover ec, SudokuCandidate sc) { int cage = sc.c; int num = sc.n + 1; System.Diagnostics.Debug.Assert(info.sizes[cage] > 0); SudokuSolver ss = (SudokuSolver)ec; info.remaining_totals[cage] -= num; info.remaining_sizes[cage]--; removed = CheckRemains(ss, info, cage, num); }
public void Generate(HintSelections hints) { // Take any solution for a clear grid ClearGrid(); Candidate[] soln = solver.RandomSolution(); if (soln == null) { return; } int[,] ans = new int[Cells, Cells]; foreach (Candidate k in soln) { SudokuCandidate sc = (SudokuCandidate)k; ans[sc.x, sc.y] = sc.n; } // Add clues until soluable PlayMode = PlayModes.EditCell; while (true) { SolveResult sr = solver.DoLogicalSolve(this, hints); if (sr == SolveResult.SingleSolution) { break; } int x = Utils.Utils.Rnd(Cells); int y = Utils.Utils.Rnd(Cells); if (sr == SolveResult.NoSolutions) { ClearCell(x, y); ClearCell(8 - x, 8 - y); } else { SetCell(x, y, ans[x, y]); SetCell(Cells - x - 1, Cells - y - 1, ans[Cells - x - 1, Cells - y - 1]); } } // Remove any clues where it remains soluable for (int x = 0; x < Cells; ++x) { for (int y = 0; y < Cells; ++y) { ClearCell(x, y); if (solver.DoLogicalSolve(this, hints) != SolveResult.SingleSolution) { SetCell(x, y, ans[x, y]); } } } Setup(); }
bool PencilCell(int x, int y, int n) { foreach (Candidate k in solver.UnselectedCandidates) { SudokuCandidate sc = (SudokuCandidate)k; if (x == sc.x && y == sc.y && n == sc.n) { solver.DiscardCandidate(k); Updated(); return(true); } } return(false); }
public void OnUncover(ExactCover ec, SudokuCandidate sc) { if (removed != null) { for (int i = removed.Length - 1; i >= 0; --i) { ec.UndiscardCandidate(removed[i]); } } int num = sc.n + 1; info.remaining_totals[sc.c] += num; info.remaining_sizes[sc.c]++; }
Func <Hint, bool> HintIsAt(int selx, int sely) { return((Hint hint) => { SudokuRequirement r = (SudokuRequirement)hint.Requirement; if (r != null) { return r.AppliesAt(selx, sely, this); } SudokuCandidate c = (SudokuCandidate)hint.Candidate; if (c != null) { return c.x == selx && c.y == sely; } return false; }); }
bool AddClue(int x, int y, int n, CellFlags fx) { SudokuCandidate sc = (SudokuCandidate)solver.GetCandidate(x, y, n); if (solver.TrySelectCandidate(sc)) { // Add clue flags[x, y] = fx; values[x, y] = n; Updated(); return(true); } else { // Clue cannot be added return(false); } }
static bool AppliesAt(Hint hint, int x, int y, SudokuGrid grid) { if (!(hint is ForcedMoveHint)) { SudokuCandidate k = (SudokuCandidate)hint.Candidate; if (k != null) { return(k.x == x && k.y == y); } } SudokuRequirement c = (SudokuRequirement)hint.Requirement; if (c != null) { return(c.AppliesAt(x, y, grid)); } return(false); }
bool SelectForcedHint() { ForcedMoveHint hint = null; if (Grid.HintFlags.SelectForcedMoveHints && Grid.PaintedHints.Length > 0 && Grid.PaintedHints[0] is ForcedMoveHint) { hint = Grid.PaintedHints[0] as ForcedMoveHint; } if (hint != null) { SudokuCandidate sc = (SudokuCandidate)hint.Candidate; // MakeSelection(sc.x, sc.y); -- loses the hint if it was requested with "show hints" off selx = sc.x; sely = sc.y; return(true); } return(false); }
bool SetFreeCell(int x, int y, int n, CellFlags fx) { // Agree with any existing known for that cell foreach (Candidate k in solver.SelectedCandidates) { SudokuCandidate sc = (SudokuCandidate)k; if (x == sc.x && y == sc.y) { if (n == sc.n) { flags[x, y] = fx; values[x, y] = n; return(true); } else { return(false); } } } return(AddClue(x, y, n, fx)); }
public string[] SolutionStrings() { string[] ret = new string[Cells]; char[,] g = new char[Cells, Cells]; for (int x = 0; x < Cells; ++x) { for (int y = 0; y < Cells; ++y) { g[x, y] = '.'; } } for (int i = 0; i < tsc; ++i) { SudokuCandidate sc = (SudokuCandidate)ts[i].Candidate; g[sc.x, sc.y] = (char)('1' + sc.n); } for (int y = 0; y < Cells; ++y) { ret[y] = ""; for (int x = 0; x < Cells; ++x) { if (g[x, y] == '.') { ret[y] += "["; SudokuRequirement c = GetRequirement(x, y, Houses.Cell); foreach (SudokuCandidate k in c.UnselectedCandidates) { ret[y] += (char)('1' + k.n); } ret[y] += "]"; } else { ret[y] += g[x, y]; } } } return(ret); }
public void Paint(PaintContext context) { Graphics graphics = context.graphics; // Background Brush back = InEditMode ? Brushes.LightSalmon : (solver.UnfulfilledRequirements.Length == 0) ? Brushes.LightGreen : Brushes.White; context.FillBackground(back); // Coloured cages or boxes if (gridOptions.colours != null) { Color[] cage_colours = new Color[] { Color.FromArgb(255, 253, 152), Color.FromArgb(207, 231, 153), Color.FromArgb(203, 232, 250), Color.FromArgb(248, 207, 223) }; Brush[] cage_brushes = new Brush[4]; for (int i = 0; i < 4; ++i) { cage_brushes[i] = new SolidBrush(cage_colours[i]); } for (int x = 0; x < Cells; ++x) { for (int y = 0; y < Cells; ++y) { context.FillCell(x, y, cage_brushes[gridOptions.colours[x, y]]); } } for (int i = 0; i < 4; ++i) { cage_brushes[i].Dispose(); } } // Diagonals - brush previously Brushes.LightGray if (MajorDiagonal) { using (Brush br = new HatchBrush(HatchStyle.ForwardDiagonal, Color.DarkGray, Color.Transparent)) for (int x = 0; x < Cells; ++x) { context.FillCell(x, x, br); } } if (MinorDiagonal) { using (Brush br = new HatchBrush(HatchStyle.BackwardDiagonal, Color.DarkGray, Color.Transparent)) for (int x = 0; x < Cells; ++x) { context.FillCell(x, Cells - x - 1, br); } } // Cage totals if (IsKiller) { Point?[] cage_indicators = new Point?[NumCages]; for (int y = Cells - 1; y >= 0; --y) { for (int x = Cells - 1; x >= 0; --x) { if (flags[x, y] == CellFlags.Free) { cage_indicators[cageInfo.cages[x, y]] = new Point(x, y); } } } using (Pen inner = new Pen(Color.White, 5.0f)) PaintCages(context, inner); for (int i = 0; i < NumCages; ++i) { if (cage_indicators[i] != null) { context.DrawTotal(Brushes.Black, cage_indicators[i].Value.X, cage_indicators[i].Value.Y, cageInfo.remaining_totals[i].ToString()); } } } foreach (Hint hint in paintedHints) { hint.PaintBackground(context); } context.DrawSelection(); // Grid Dictionary <int, int> bs = new Dictionary <int, int>(); for (int x = 0; x < Cells; ++x) { for (int y = 0; y < Cells; ++y) { int b = BoxAt(x, y); if (bs.ContainsKey(b)) { ++bs[b]; } else { bs[b] = 1; } } } Func <int, int, int, int, int> border = (int x0, int y0, int x1, int y1) => { int b0 = BoxAt(x0, y0), b1 = BoxAt(x1, y1); if (b0 == b1) { return(0); } if (bs[b0] < Cells || bs[b1] < Cells) { return(2); } return(1); }; using (Pen thick = new Pen(Color.Black, 3.0f)) using (Pen wrong = new Pen(Color.Red, 3.0f)) { Pen[] pens = { Pens.Black, thick, wrong }; for (int x = 0; x < Cells - 1; ++x) { for (int y = 0; y < Cells; ++y) { context.DrawVerticalLine(x, y, pens[border(x, y, x + 1, y)]); } } for (int x = 0; x < Cells; ++x) { for (int y = 0; y < Cells - 1; ++y) { context.DrawHorizontalLine(x, y, pens[border(x, y, x, y + 1)]); } } } // Givens { for (int x = 0; x < Cells; ++x) { for (int y = 0; y < Cells; ++y) { if (flags[x, y] == CellFlags.Fixed) { context.DrawCell(Brushes.Black, x, y, values[x, y]); } else if (flags[x, y] == CellFlags.Play) { context.DrawCell(Brushes.Purple, x, y, values[x, y]); } else if (flags[x, y] == CellFlags.Solved) { context.DrawCell(Brushes.Green, x, y, values[x, y]); } } } } // Knowns of solver { foreach (Candidate k in solver.SelectedCandidates) { SudokuCandidate sc = (SudokuCandidate)k; if (flags[sc.x, sc.y] == CellFlags.Free) { context.DrawCell(Brushes.Green, sc.x, sc.y, sc.n); } } } // Unknowns as pencil marks if (HintFlags.PaintPencilMarks) { foreach (SudokuCandidate k in solver.UnselectedCandidates) { context.SetPencil(k, Hint.Kind.Maybe); } } foreach (Hint hint in paintedHints) { hint.PaintForeground(context); } context.PaintPencilMarksAndHints(); }
public void SetPencil(SudokuCandidate sc, Hint.Kind v) { SetPencil(sc.x, sc.y, sc.n, v); }
/* * public SudokuSolver(string[] lines) * { * CreateMatrix(); * Apply(lines); * } */ void CreateMatrix(SudokuGrid grid) { // Create requirements - columns of 0/1 matrix int num_cages = grid.NumCages; int diags = 0; if (grid.MajorDiagonal) { ++diags; } if (grid.MinorDiagonal) { ++diags; } int d = grid.MajorDiagonal ? 1 : 0; // Where minor diagonal is found CreateRequirements(grid, Cells * Cells * 4 + diags * Cells); CreateOptionals(grid, num_cages); Houses[] houses = new Houses[] { Houses.Cell, Houses.Column, Houses.Row, Houses.Box }; for (int i0 = 0; i0 < Cells; ++i0) { for (int i1 = 0; i1 < Cells; ++i1) { for (int type = 0; type < 4; ++type) { Houses house = houses[type]; SudokuRequirement c = GetRequirement(i0, i1, house); c.i0 = i0; c.i1 = i1; c.house = house; requirements.AddRequirement(c); } } } if (grid.MajorDiagonal) { for (int i0 = 0; i0 < Cells; ++i0) { SudokuRequirement c = GetDiagonalRequirement(0, i0); c.i0 = i0; c.i1 = -1; c.house = Houses.MajorDiagonal; requirements.AddRequirement(c); } } if (grid.MinorDiagonal) { for (int i0 = 0; i0 < Cells; ++i0) { SudokuRequirement c = GetDiagonalRequirement(d, i0); c.i0 = i0; c.i1 = -1; c.house = Houses.MinorDiagonal; requirements.AddRequirement(c); } } for (int i0 = 0; i0 < num_cages; ++i0) { for (int i1 = 0; i1 < Cells; ++i1) { CageOptional ca = GetCageOptional(i0, i1); ca.i0 = i0; ca.i1 = i1; ca.house = Houses.Cage; //optionals.AddRequirement(ca); ca.SetIncluded(); } } // Create candidates - rows of 0/1 matrix CreateCandidates(new SudokuCandidate[Cells * Cells * Cells]); CreateSolution(Cells * Cells); for (int x = 0; x < Cells; ++x) { for (int y = 0; y < Cells; ++y) { int cage = grid.CageAt(x, y); int box = grid.BoxAt(x, y); for (int n = 0; n < Cells; ++n) { SudokuCandidate k = new SudokuCandidate(x, y, n, box, cage); k.AddCandidate(GetRequirement(x, y, Houses.Cell)); k.AddCandidate(GetRequirement(x, n, Houses.Column)); k.AddCandidate(GetRequirement(y, n, Houses.Row)); k.AddCandidate(GetRequirement(box, n, Houses.Box)); if (grid.MajorDiagonal && x == y) { k.AddCandidate(GetDiagonalRequirement(0, n)); } if (grid.MinorDiagonal && x == Cells - y - 1) { k.AddCandidate(GetDiagonalRequirement(d, n)); } if (cage != -1) { k.AddCageOptional(GetCageOptional(cage, n)); } tr[trc++] = k; // Discard candidates where cage size already reached 1 //if (cage != -1 && grid.cageInfo.sizes[cage] == 1 && n + 1 != grid.cageInfo.totals[cage]) // DiscardCandidate(k); } } } // Discard candidates that do not meet cage total for (int i0 = 0; i0 < num_cages; ++i0) { CageOptional.CheckRemains(this, grid.cageInfo, i0, -1); } /* * if (grid.IsKiller) * { * SudokuGrid.CageInfo info = grid.cageInfo; * for (int ca = 0; ca < info.cages.Length; ++ca) * { * List<Point> pts = new List<Point>(); * for (int x = 0; x < Cells; ++x) * for (int y = 0; y < Cells-1; ++y) * if (info.cages[x, y] == ca) * pts.Add(new Point(x, y)); * int[] ns = new int[Cells]; * for (int i = 0; i < Cells; ++i) ns[i] = i; * Candidate k = new Candidate(); * KillerRequire(k, info.totals[ca], pts.ToArray(), ns); * } * } */ }