Пример #1
0
        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());
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
 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();
 }
Пример #5
0
 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);
 }
Пример #6
0
        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]++;
        }
Пример #7
0
 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;
     });
 }
Пример #8
0
        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);
            }
        }
Пример #9
0
        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);
        }
Пример #10
0
        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);
        }
Пример #11
0
 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));
 }
Пример #12
0
 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);
 }
Пример #13
0
        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();
        }
Пример #14
0
 public void SetPencil(SudokuCandidate sc, Hint.Kind v)
 {
     SetPencil(sc.x, sc.y, sc.n, v);
 }
Пример #15
0
        /*
         * 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);
             *  }
             * }
             */
        }