Esempio n. 1
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));
                }
            }
        }
    }
Esempio n. 2
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);
    }
Esempio n. 3
0
    public override BoardSolver.SolveResult RestrictGrid(BoardSolver bs)
    {
        BoardSolver.SolveResult r = BoardSolver.SolveResult.Unchanged;
        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++)
                {
                    if (ts.incoming[i, j, k])
                    {
                        r = bs.Combine(r, bs.EnsureLarger(i, j, i + ThermoSerializer.directions[k, 0], j + ThermoSerializer.directions[k, 1]));
                    }
                    if (ts.outgoing[i, j, k])
                    {
                        r = bs.Combine(r, bs.EnsureLarger(i + ThermoSerializer.directions[k, 0], j + ThermoSerializer.directions[k, 1], i, j));
                    }
                }
            }
        }
        return(r);
    }
Esempio n. 4
0
 public static BoardSolver.SolveResult RestrictSum(BoardSolver boardSolver, List <(int x, int y)> points, int sum)
 public BoardSolverShould()
 {
     _gameBoard   = new GameBoard();
     _humanPlayer = new HumanPlayer(Symbol.Cross, new InputChecker());
     _boardSolver = new BoardSolver();
 }
Esempio n. 6
0
    public override BoardSolver.SolveResult RestrictGrid(BoardSolver bs)
    {
        var  ss      = bs.final.sudoku.GetVariant(VariantList.VariantType.Sandwich.ToString()).serializer as SandwichSerializer;
        bool changed = false;

        foreach (var box in ss.serializedObject.boxes)
        {
            var points = new List <(int x, int y)>();
            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.Allows(box.posy, i, 1.ToString()))
                    {
                        oneCounts++; oneIndex = i;
                    }
                    if (bs.Allows(box.posy, i, 9.ToString()))
                    {
                        nineCounts++; nineIndex = i;
                    }
                }
                if (oneCounts == 1 && nineCounts == 1)
                {
                    for (int i = Mathf.Min(oneIndex, nineIndex) + 1; i < Mathf.Max(oneIndex, nineIndex); i++)
                    {
                        points.Add((box.posy, i));
                    }
                }
            }
            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.Allows(j, box.posx, 1.ToString()))
                    {
                        oneCounts++; oneIndex = j;
                    }
                    if (bs.Allows(j, box.posx, 9.ToString()))
                    {
                        nineCounts++; nineIndex = j;
                    }
                }
                if (oneCounts == 1 && nineCounts == 1)
                {
                    for (int j = Mathf.Min(oneIndex, nineIndex) + 1; j < Mathf.Max(oneIndex, nineIndex); j++)
                    {
                        points.Add((j, box.posx));
                    }
                }
            }
            else
            {
                continue;
            }
            var r = SumUtility.RestrictSum(bs, points, int.Parse(box.answer));
            if (r == BoardSolver.SolveResult.Impossible)
            {
                return(r);
            }
            if (r == BoardSolver.SolveResult.Solved)
            {
                changed = true;
            }
        }
        if (changed)
        {
            return(BoardSolver.SolveResult.Solved);
        }
        return(BoardSolver.SolveResult.Unchanged);
    }
Esempio n. 7
0
 public override void PropogateChange(int i, int j, BoardSolver bs)
 {
 }
Esempio n. 8
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);
    }
Esempio n. 9
0
    // Use this for initialization
    public void init(int w, int h, SpriteRenderer bgRender)
    {
        Vector3 dim = 1.6f * Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, 0));

        if (Screen.width < Screen.height)
        {
            boardSize = (float)dim.x / (float)w;
        }
        else
        {
            boardSize = (float)dim.y / (float)h;
        }
        Vector3 center = new Vector3((float)w / 2.0f - .5f, (float)h / 2.0f - .5f, 0) * boardSize;

        transform.localPosition = -center;
        transform.localScale    = new Vector3(boardSize, boardSize, 1);

        width  = w;
        height = h;
        blocks = new Block[w, h];

        background = bgRender;
        bgSize     = new Vector3((float)width / 4f, (float)height / 4f, 1);
        background.transform.localScale = new Vector3(bgSize.x, bgSize.y, bgSize.z);
        background.transform.parent     = transform;
        oldBG = background.color;
        newBG = background.color;


        name                                     = "Board";
        emptyBlockFolder                         = new GameObject();
        emptyBlockFolder.name                    = "Empty Blocks";
        emptyBlockFolder.transform.parent        = transform;
        emptyBlockFolder.transform.localPosition = new Vector3(0, 0, 0);
        emptyBlockFolder.transform.localScale    = new Vector3(1, 1, 1);
        blockFolder                              = new GameObject();
        blockFolder.name                         = "Blocks";
        blockFolder.transform.parent             = transform;
        blockFolder.transform.localPosition      = new Vector3(0, 0, 0);
        blockFolder.transform.localScale         = new Vector3(1, 1, 1);
        switchFolder                             = new GameObject();
        switchFolder.name                        = "Switches";
        switchFolder.transform.parent            = transform;
        switchFolder.transform.localPosition     = new Vector3(0, 0, 0);
        switchFolder.transform.localScale        = new Vector3(1, 1, 1);
        enemyFolder                              = new GameObject();
        enemyFolder.name                         = "Enemy Folder";
        enemyFolder.transform.parent             = transform;
        enemyFolder.transform.localScale         = new Vector3(1, 1, 1);

        solidBlocks = new List <Block>();
        enemyList   = new List <Enemy>();
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                addEmptyBlock(x, y);
            }
        }
        initPlayer();
        //Track_AI_List = new List<TrackerAI> ();
//		addTraversalAI();
        //addTrackerAI();
        initExit();

        solver = new BoardSolver(this);
    }
Esempio n. 10
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);
    }
Esempio n. 11
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);
    }
Esempio n. 12
0
 public abstract List <BoardNotifications.BoardError> GetErrors(BoardSolver bs);
Esempio n. 13
0
 // Only returns Impossible, Solved, or Unchanged
 public abstract BoardSolver.SolveResult RestrictGrid(BoardSolver bs);
Esempio n. 14
0
 public abstract void PropogateChange(int i, int j, BoardSolver bs);
Esempio n. 15
0
    public SolveResult Solve()
    {
        for (int i = 0; i < final.sudoku.settings.numHorizontal; i++)
        {
            for (int j = 0; j < final.sudoku.settings.numVertical; j++)
            {
                // Trigger the propogate for all already set vlaues.
                if (GetValue(i, j) != "")
                {
                    SetValue(i, j, GetValue(i, j));
                }
            }
        }
        SolveResult s = ApplyRules();

        if (s == SolveResult.Impossible)
        {
            return(s);
        }
        if (s == SolveResult.Solved)
        {
            return(s);
        }
        // In any other case, we can continue solving.
        if (!settings.bruteForce)
        {
            return(s);
        }
        // Find the smallest possible switch box
        (int x, int y)bestPoint = (-1, -1);
        int best = final.sudoku.AllValues().Count + 1;

        for (int i = 0; i < final.sudoku.settings.numHorizontal; i++)
        {
            for (int j = 0; j < final.sudoku.settings.numVertical; j++)
            {
                if ((final.possible_values[i, j].Count < best) && (final.possible_values[i, j].Count != 1))
                {
                    best      = final.possible_values[i, j].Count;
                    bestPoint = (i, j);
                }
            }
        }
        // Split on (i, j)
        int        amountSolved     = 0;
        int        amountIncomplete = 0;
        SolveState newFinal         = new SolveState();

        foreach (var k in final.possible_values[bestPoint.x, bestPoint.y])
        {
            BoardSolver bs = new BoardSolver();
            bs.Initialise(final, settings);
            var r = bs.Solve();
            if (r == SolveResult.Solved)
            {
                amountSolved++;
                newFinal = bs.final;
            }
            if (r == SolveResult.Incomplete)
            {
                amountIncomplete++;
                if (amountSolved == 0)
                {
                    newFinal = bs.final;
                }
            }
            if (r == SolveResult.MaybeMultiple)
            {
                newFinal = bs.final;
                amountSolved++;
                amountIncomplete++;
            }
            if (r == SolveResult.Multiple)
            {
                return(r);
            }
            if (r == SolveResult.Impossible)
            {
                continue;
            }
        }
        if ((amountSolved == 0) && (amountIncomplete == 0))
        {
            return(SolveResult.Impossible);
        }
        final = newFinal;
        if (amountSolved > 1)
        {
            return(SolveResult.Multiple);
        }
        if (amountIncomplete == 0)
        {
            return(SolveResult.Solved);
        }
        if (amountSolved == 0)
        {
            return(SolveResult.Incomplete);
        }
        return(SolveResult.MaybeMultiple);
    }