예제 #1
0
    public void SolveBoard()
    {
        solver.Initialise(sudoku);
        solver.settings.bruteForce = false;
        var result = solver.Solve();

        Debug.Log(result);
        for (int i = 0; i < sudoku.settings.numHorizontal; i++)
        {
            for (int j = 0; j < sudoku.settings.numVertical; j++)
            {
                if (solver.GetValue(i, j) != "")
                {
                    SetFull(i, j, solver.GetValue(i, j).ToString(), false);
                }
                else
                {
                    boxes[i, j].Clear(false);
                    foreach (string x in solver.final.possible_values[i, j])
                    {
                        boxes[i, j].ToggleCentre(x, false);
                    }
                }
            }
        }
    }
예제 #2
0
    public override void PropogateChange(int i, int j, BoardSolver bs)
    {
        for (int k = 0; k < bs.final.sudoku.settings.numHorizontal; k++)
        {
            if (k != i)
            {
                bs.EnsureNotPossible(k, j, bs.GetValue(i, j));
            }
        }
        for (int k = 0; k < bs.final.sudoku.settings.numVertical; k++)
        {
            if (k != j)
            {
                bs.EnsureNotPossible(i, k, bs.GetValue(i, j));
            }
        }
        // Locate the box we are in
        int boxX = (int)((i / (bs.final.sudoku.settings.numHorizontalThins + 1)) * (bs.final.sudoku.settings.numHorizontalThins + 1));
        int boxY = (int)((j / (bs.final.sudoku.settings.numVerticalThins + 1)) * (bs.final.sudoku.settings.numVerticalThins + 1));

        for (int a = 0; a < (bs.final.sudoku.settings.numHorizontalThins + 1); a++)
        {
            for (int b = 0; b < (bs.final.sudoku.settings.numVerticalThins + 1); b++)
            {
                if ((a + boxX != i) || (b + boxY != j))
                {
                    bs.EnsureNotPossible(a + boxX, b + boxY, bs.GetValue(i, j));
                }
            }
        }
    }
예제 #3
0
    public override List <BoardNotifications.BoardError> GetErrors(BoardSolver bs)
    {
        List <BoardNotifications.BoardError> errors = new List <BoardNotifications.BoardError>();
        var ts = bs.final.sudoku.GetVariant(VariantList.VariantType.Thermo.ToString()).serializer as ThermoSerializer;

        for (int i = 0; i < bs.final.sudoku.settings.numHorizontal; i++)
        {
            for (int j = 0; j < bs.final.sudoku.settings.numVertical; j++)
            {
                for (int k = 0; k < 4; k++)
                {
                    (int x, int y)newPos = (i + ThermoSerializer.directions[k, 0], j + ThermoSerializer.directions[k, 1]);
                    if (bs.GetValue(i, j) != "" && bs.GetValue(newPos.x, newPos.y) != "")
                    {
                        int res1, res2;
                        if (!int.TryParse(bs.GetValue(i, j), out res1))
                        {
                            List <(int x, int y)> boxes = new List <(int x, int y)>();
                            boxes.Add((i, j));
                            errors.Add(new BoardNotifications.BoardError(
                                           BoardNotifications.ErrorType.SELECTION_INVALID,
                                           boxes,
                                           "This box must be numeric."
                                           ));
                        }
                        else if (!int.TryParse(bs.GetValue(newPos.x, newPos.y), out res2))
                        {
                            List <(int x, int y)> boxes = new List <(int x, int y)>();
                            boxes.Add((newPos.x, newPos.y));
                            errors.Add(new BoardNotifications.BoardError(
                                           BoardNotifications.ErrorType.SELECTION_INVALID,
                                           boxes,
                                           "This box must be numeric."
                                           ));
                        }
                        else if (ts.incoming[i, j, k] && res1 <= res2)
                        {
                            List <(int x, int y)> affected = new List <(int x, int y)>();
                            affected.Add((i, j));
                            affected.Add((newPos.x, newPos.y));
                            errors.Add(new BoardNotifications.BoardError(
                                           BoardNotifications.ErrorType.SELECTION_INVALID,
                                           affected,
                                           "Thermo rules require that numbers increase along lines, meaning we require " + bs.GetValue(i, j) + " > " + bs.GetValue(newPos.x, newPos.y)
                                           ));
                        }
                    }
                }
            }
        }
        return(errors);
    }
예제 #4
0
    public override List <BoardNotifications.BoardError> GetErrors(BoardSolver bs)
    {
        List <BoardNotifications.BoardError> errors = new List <BoardNotifications.BoardError>();
        var ss = bs.final.sudoku.GetVariant(VariantList.VariantType.Sandwich.ToString()).serializer as SandwichSerializer;

        foreach (var box in ss.serializedObject.boxes)
        {
            if (box.posx == BoxController.topBox || box.posx == BoxController.botBox)
            {
                int oneIndex   = -1;
                int oneCounts  = 0;
                int nineIndex  = -1;
                int nineCounts = 0;
                for (int i = 0; i < bs.final.sudoku.settings.numHorizontal; i++)
                {
                    if (bs.GetValue(box.posy, i) == "1")
                    {
                        oneCounts++; oneIndex = i;
                    }
                    if (bs.GetValue(box.posy, i) == "9")
                    {
                        nineCounts++; nineIndex = i;
                    }
                }
                if (oneCounts == 1 && nineCounts == 1)
                {
                    List <(int x, int y)> points = new List <(int x, int y)>();
                    bool bad = false;
                    for (int i = Mathf.Min(oneIndex, nineIndex) + 1; i < Mathf.Max(oneIndex, nineIndex); i++)
                    {
                        points.Add((box.posy, i));
                        if (bs.GetValue(box.posy, i) == "")
                        {
                            bad = true;
                        }
                    }
                    if (!bad)
                    {
                        int s = 0;
                        foreach (var v in points)
                        {
                            int res;
                            if (int.TryParse(bs.GetValue(v.x, v.y), out res))
                            {
                                s += res;
                            }
                            else
                            {
                                List <(int x, int y)> p = new List <(int x, int y)>();
                                p.Add(v);
                                errors.Add(new BoardNotifications.BoardError(BoardNotifications.ErrorType.SELECTION_INVALID, p, "This box must be numeric."));
                            }
                        }
                        if (s != int.Parse(box.answer))
                        {
                            errors.Add(new BoardNotifications.BoardError(BoardNotifications.ErrorType.SUM_INVALID, points, "These boxes must sum to " + box.answer));
                        }
                    }
                }
            }
            else if (box.posy == BoxController.topBox || box.posy == BoxController.botBox)
            {
                int oneIndex   = -1;
                int oneCounts  = 0;
                int nineIndex  = -1;
                int nineCounts = 0;
                for (int j = 0; j < bs.final.sudoku.settings.numHorizontal; j++)
                {
                    if (bs.GetValue(j, box.posx) == "1")
                    {
                        oneCounts++; oneIndex = j;
                    }
                    if (bs.GetValue(j, box.posx) == "9")
                    {
                        nineCounts++; nineIndex = j;
                    }
                }
                if (oneCounts == 1 && nineCounts == 1)
                {
                    List <(int x, int y)> points = new List <(int x, int y)>();
                    bool bad = false;
                    for (int j = Mathf.Min(oneIndex, nineIndex) + 1; j < Mathf.Max(oneIndex, nineIndex); j++)
                    {
                        points.Add((j, box.posx));
                        if (bs.GetValue(j, box.posx) == "")
                        {
                            bad = true;
                        }
                    }
                    if (!bad)
                    {
                        int s = 0;
                        foreach (var v in points)
                        {
                            int res;
                            if (int.TryParse(bs.GetValue(v.x, v.y), out res))
                            {
                                s += res;
                            }
                            else
                            {
                                List <(int x, int y)> p = new List <(int x, int y)>();
                                p.Add(v);
                                errors.Add(new BoardNotifications.BoardError(BoardNotifications.ErrorType.SELECTION_INVALID, p, "This box must be numeric."));
                            }
                        }
                        if (s != int.Parse(box.answer))
                        {
                            errors.Add(new BoardNotifications.BoardError(BoardNotifications.ErrorType.SUM_INVALID, points, "These boxes must sum to " + box.answer));
                        }
                    }
                }
            }
        }
        return(errors);
    }
예제 #5
0
    public override BoardSolver.SolveResult RestrictGrid(BoardSolver bs)
    {
        bool changed = false;

        for (int v = 1; v <= 9; v++)
        {
            for (int i = 0; i < bs.final.sudoku.settings.numHorizontal; i++)
            {
                int v_located = 0;
                for (int j = 0; j < bs.final.sudoku.settings.numVertical; j++)
                {
                    if (bs.Allows(i, j, v.ToString()))
                    {
                        v_located++;
                    }
                }
                if (v_located == 0)
                {
                    return(BoardSolver.SolveResult.Impossible);
                }
                if (v_located == 1)
                {
                    for (int j = 0; j < bs.final.sudoku.settings.numVertical; j++)
                    {
                        if (bs.Allows(i, j, v.ToString()) && bs.GetValue(i, j) != v.ToString())
                        {
                            changed = true;
                            bs.SetValue(i, j, v.ToString());
                        }
                    }
                }
            }
            for (int j = 0; j < bs.final.sudoku.settings.numVertical; j++)
            {
                int v_located = 0;
                for (int i = 0; i < bs.final.sudoku.settings.numHorizontal; i++)
                {
                    if (bs.Allows(i, j, v.ToString()))
                    {
                        v_located++;
                    }
                }
                if (v_located == 0)
                {
                    return(BoardSolver.SolveResult.Impossible);
                }
                if (v_located == 1)
                {
                    for (int i = 0; i < bs.final.sudoku.settings.numHorizontal; i++)
                    {
                        if (bs.Allows(i, j, v.ToString()) && bs.GetValue(i, j) != v.ToString())
                        {
                            changed = true;
                            bs.SetValue(i, j, v.ToString());
                        }
                    }
                }
            }
            for (int a = 0; a < bs.final.sudoku.settings.numHorizontal; a += (int)(bs.final.sudoku.settings.numHorizontalThins + 1))
            {
                for (int b = 0; b < bs.final.sudoku.settings.numVertical; b += (int)(bs.final.sudoku.settings.numVerticalThins + 1))
                {
                    // Check for box (a, b)
                    int v_located = 0;
                    for (int x = 0; x < (bs.final.sudoku.settings.numHorizontalThins + 1); x++)
                    {
                        for (int y = 0; y < (bs.final.sudoku.settings.numVerticalThins + 1); y++)
                        {
                            if (bs.Allows(a + x, b + y, v.ToString()))
                            {
                                v_located++;
                            }
                        }
                    }
                    if (v_located == 0)
                    {
                        return(BoardSolver.SolveResult.Impossible);
                    }
                    if (v_located == 1)
                    {
                        for (int x = 0; x < (bs.final.sudoku.settings.numHorizontalThins + 1); x++)
                        {
                            for (int y = 0; y < (bs.final.sudoku.settings.numVerticalThins + 1); y++)
                            {
                                if (bs.Allows(a + x, b + y, v.ToString()) && bs.GetValue(a + x, b + y) != v.ToString())
                                {
                                    changed = true;
                                    bs.SetValue(a + x, b + y, v.ToString());
                                }
                            }
                        }
                    }
                }
            }
        }
        if (changed)
        {
            return(BoardSolver.SolveResult.Solved);
        }
        return(BoardSolver.SolveResult.Unchanged);
    }
예제 #6
0
    public override List <BoardNotifications.BoardError> GetErrors(BoardSolver bs)
    {
        List <BoardNotifications.BoardError> errors = new List <BoardNotifications.BoardError>();

        for (int v = 1; v <= 9; v++)
        {
            for (int i = 0; i < bs.final.sudoku.settings.numHorizontal; i++)
            {
                List <(int x, int y)> boxes = new List <(int x, int y)>();
                for (int j = 0; j < bs.final.sudoku.settings.numVertical; j++)
                {
                    if (bs.GetValue(i, j) == v.ToString())
                    {
                        boxes.Add((i, j));
                    }
                }
                if (boxes.Count > 1)
                {
                    errors.Add(new BoardNotifications.BoardError(BoardNotifications.ErrorType.COL_INVALID, boxes, "This column can only have a single " + v));
                }
            }
            for (int j = 0; j < bs.final.sudoku.settings.numVertical; j++)
            {
                List <(int x, int y)> boxes = new List <(int x, int y)>();
                for (int i = 0; i < bs.final.sudoku.settings.numHorizontal; i++)
                {
                    if (bs.GetValue(i, j) == v.ToString())
                    {
                        boxes.Add((i, j));
                    }
                }
                if (boxes.Count > 1)
                {
                    errors.Add(new BoardNotifications.BoardError(BoardNotifications.ErrorType.ROW_INVALID, boxes, "This row can only have a single " + v));
                }
            }
            for (int a = 0; a < bs.final.sudoku.settings.numHorizontal; a += (int)(bs.final.sudoku.settings.numHorizontalThins + 1))
            {
                for (int b = 0; b < bs.final.sudoku.settings.numVertical; b += (int)(bs.final.sudoku.settings.numVerticalThins + 1))
                {
                    // Check for box (a, b)
                    List <(int x, int y)> boxes = new List <(int x, int y)>();
                    for (int x = 0; x < (bs.final.sudoku.settings.numHorizontalThins + 1); x++)
                    {
                        for (int y = 0; y < (bs.final.sudoku.settings.numVerticalThins + 1); y++)
                        {
                            if (bs.GetValue(a + x, b + y) == v.ToString())
                            {
                                boxes.Add((a + x, b + y));
                            }
                        }
                    }
                    if (boxes.Count > 1)
                    {
                        errors.Add(new BoardNotifications.BoardError(BoardNotifications.ErrorType.BOX_INVALID, boxes, "This box can only have a single " + v));
                    }
                }
            }
        }
        return(errors);
    }