Beispiel #1
0
 public Difficulty GetDifficulty(CellsGrid inputGrid)
 {
     Grid = inputGrid.TrueClone();
     if (!IsValid())
     {
         return(Difficulty.Unsolvable);
     }
     Grid = inputGrid.TrueClone();
     if (!SolveEasy())
     {
         Grid = inputGrid.TrueClone();
         if (!SolveMedium())
         {
             Grid = inputGrid.TrueClone();
             if (!SolveHard())
             {
                 return(Difficulty.Unsolvable);
             }
             else
             {
                 return(Difficulty.Hard);
             }
         }
         else
         {
             return(Difficulty.Medium);
         }
     }
     else
     {
         return(Difficulty.Easy);
     }
 }
Beispiel #2
0
        private void GenerateEasy()
        {
            CellsGrid tempGrid   = new CellsGrid();
            int       iterations = 0;
            int       tests      = 0;

            for (; ;)
            {
                grid     = new CellsGrid();
                tempGrid = new CellsGrid();
                while (tempGrid.Count < 20)
                {
                    DebugGridPrint();
                    iterations++;
                    tempGrid = grid.Clone();
                    tempGrid[random.Next(0, 9), random.Next(0, 9)] = random.Next(1, 9);
                    if (new Validator(tempGrid).IsValid())
                    {
                        grid = tempGrid.Clone();
                    }
                }
                if (new Solver(grid).SolveHard())
                {
                    break;
                }
                tests++;
                Debug.Print(tests.ToString());
            }
            Generated = grid.Clone();
        }
Beispiel #3
0
        private void DebugGridPrintMain(CellsGrid cells, string message = "", bool print = false)
        {
            if (!print)
            {
                return;
            }
            string helper = "";

            Debug.Print(message);
            for (int x = 0; x < 9; x++)
            {
                helper = "";
                for (int y = 0; y < 9; y++)
                {
                    if (y % 3 == 0)
                    {
                        helper += "| ";
                    }
                    if (cells[x, y] == 0)
                    {
                        helper += "  ";
                    }
                    else
                    {
                        helper += cells[x, y].ToString() + " ";
                    }
                }
                if (x % 3 == 0)
                {
                    Debug.Print("------------------------");
                }
                Debug.Print(helper);
            }
            Debug.Print("");
        }
Beispiel #4
0
        public Generator()
        {
            Generated = new CellsGrid();
            grid      = new CellsGrid();
            random    = new Random();

            XElement element;

            using (Stream reader = new FileStream(".\\Data\\solved.xml", FileMode.Open))
            {
                element = XElement.Load(reader);
            }

            var tempList = element.Descendants("sudoku").ToList().Select(d => { d.Value.Trim(); return(d.Value.Split("\n").Select(x => x.Trim()).Where(x => !string.IsNullOrEmpty(x.ToString()))); })
                           .ToArray().Select(x => x.Select(y => y.Split(" ").Select(d => int.Parse(d)))).ToArray();

            int tempIndex = random.Next(tempList.Length);
            //Debug.Print("Starting: " + tempIndex);
            var temp = tempList[tempIndex];

            int x = 0;
            int y = 0;

            foreach (var item in temp)
            {
                if (x > 8)
                {
                    x = 0;
                }
                foreach (var num in item)
                {
                    if (y > 8)
                    {
                        y = 0;
                    }
                    grid[x, y] = num;
                    y++;
                }
                x++;
            }

            Generated = grid.TrueClone();

            //Switches random numbers
            for (int i = 0; i < 9; i++)
            {
                int num1 = Next();
                int num2 = Next();
                while (num1 == num2)
                {
                    num2 = Next();
                }
                NumberSwitch(num1, num2);
            }
        }
Beispiel #5
0
        public List <int[]> GetInvalid(CellsGrid inputGrid)
        {
            List <int[]> output = new List <int[]>();

            if (new Validator(inputGrid).IsValid())
            {
                return(output);
            }
            Grid = inputGrid;
            for (int num = 1; num < 10; num++)
            {
                for (int i = 0; i < 9; i++)
                {
                    int subX = (i / 3) * 3;
                    int subY = (i % 3) * 3;
                    if (CountRow(i, num) > 1)
                    {
                        int[] row = GetRow(i);
                        for (int y = 0; y < 9; y++)
                        {
                            if (row[y] == num)
                            {
                                output.Add(new int[] { i, y });
                            }
                        }
                    }
                    if (CountColumn(i, num) > 1)
                    {
                        int[] col = GetColumn(i);
                        for (int x = 0; x < 9; x++)
                        {
                            if (col[x] == num)
                            {
                                output.Add(new int[] { x, i });
                            }
                        }
                    }
                    if (CountSubgrid(subX, subY, num) > 1)
                    {
                        for (int x = subX; x < subX + 3; x++)
                        {
                            for (int y = subY; y < subY + 3; y++)
                            {
                                if (inputGrid[x, y] == num)
                                {
                                    output.Add(new int[] { x, y });
                                }
                            }
                        }
                    }
                }
            }
            return(output);
        }
Beispiel #6
0
        /// <summary>
        /// Returns copy of inputCells.
        /// </summary>
        /// <returns>New copy of inputCells</returns>
        public CellsGrid TrueClone()
        {
            CellsGrid cells = new CellsGrid();

            for (int x = 0; x < 9; x++)
            {
                for (int y = 0; y < 9; y++)
                {
                    cells[x, y] = grid[x, y];
                }
            }
            return(cells);
        }
Beispiel #7
0
        public Solver(CellsGrid inputGrid) : base(inputGrid)
        {
            Grid     = inputGrid.TrueClone();
            possible = new List <List <List <int> > >();
            for (int i = 0; i < 9; i++)
            {
                possible.Add(new List <List <int> >());
                for (int j = 0; j < 9; j++)
                {
                    possible[i].Add(new List <int>());
                }
            }

            Steps = new List <CellsGrid>();
            Steps.Add(Grid.TrueClone());
        }
Beispiel #8
0
        //Hints ----------------------------------

        /// <summary>
        /// Returns List of x and y indexes, where is difference from inputGrid.
        /// </summary>
        /// <param name="inputGrid">InputGrid will be compared to SolvedGrid</param>
        /// <returns>List of indexes, where are differences.</returns>
        public List <int[]> IsCorrect(CellsGrid inputGrid)
        {
            List <int[]> output = new List <int[]>();

            SolveHard();
            for (int x = 0; x < 9; x++)
            {
                for (int y = 0; y < 9; y++)
                {
                    if (inputGrid[x, y] != 0 && SolvedGrid[x, y] != inputGrid[x, y])
                    {
                        output.Add(new int[] { x, y });
                    }
                }
            }
            return(output);
        }
Beispiel #9
0
        /// <summary>
        /// Returns list of indexes of input grid, where is not a zero.
        /// </summary>
        /// <param name="grid">Input CellsGrid</param>
        /// <returns>List of Lists with x and y indexes.</returns>
        private List <List <int> > NotNull(CellsGrid grid)
        {
            List <List <int> > tempList = new List <List <int> >();

            for (int x = 0; x < 9; x++)
            {
                for (int y = 0; y < 9; y++)
                {
                    if (grid[x, y] != 0)
                    {
                        tempList.Add(new List <int> {
                            x, y
                        });
                    }
                }
            }
            return(tempList);
        }
Beispiel #10
0
        public Generator()
        {
            grid   = new CellsGrid();
            solver = new Solver(grid);
            random = new Random();

            XElement element;

            using (Stream reader = new FileStream("..\\..\\..\\Data\\solved.xml", FileMode.Open))
            {
                element = XElement.Load(reader);
            }

            var tempList = element.Descendants("sudoku").ToList().Select(d => { d.Value.Trim(); return(d.Value.Split("\n").Select(x => x.Trim()).Where(x => !string.IsNullOrEmpty(x.ToString()))); })
                           .ToArray().Select(x => x.Select(y => y.Split(" ").Select(d => int.Parse(d)))).ToArray();

            var temp = tempList[random.Next(tempList.Length)];

            int x = 0;
            int y = 0;

            foreach (var item in temp)
            {
                if (x > 8)
                {
                    x = 0;
                }
                foreach (var num in item)
                {
                    if (y > 8)
                    {
                        y = 0;
                    }
                    grid[x, y] = num;
                    y++;
                }
                x++;
            }

            DebugGridPrint();
        }
Beispiel #11
0
        /// <summary>
        /// Tries to generate random sudoku. Older algorithm.
        /// </summary>
        /// <param name="difficulty">Dificulty parameter</param>
        private void GenerateHelp2(int difficulty)
        {
            int left = 20;

            switch (difficulty)
            {
            case 0:
                left = 25;
                break;

            case 1:
                left = 24;
                break;

            case 2:
                left = 24;
                break;
            }
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();
            int       reset      = 0;
            CellsGrid gridTested = grid.TrueClone();
            Solver    solver     = new Solver(gridTested);

            while (reset < 100)
            {
                reset++;
                while (gridTested.Count > left)
                {
                    gridTested[Next(), Next()] = 0;
                }
                solver.Grid = gridTested.TrueClone();
                switch (difficulty)
                {
                case 0:
                    solver.SolveAll(true, true, 4, 4);
                    //solver.SolveEasy();
                    break;

                case 1:
                    solver.SolveAll(true, true, 0, 4);
                    //solver.SolveMedium();
                    break;

                case 2:
                    solver.SolveAll(true, true, 4, 0);
                    //solver.SolveHard();
                    break;
                }
                if (solver.IsSolved())
                {
                    break;
                }
                gridTested = grid.TrueClone();
                Debug.Print(reset.ToString() + "\t" + stopwatch.ElapsedMilliseconds.ToString());
            }
            Generated = gridTested.TrueClone();
            stopwatch.Stop();
            Debug.Print(reset.ToString() + "\t" + stopwatch.ElapsedMilliseconds.ToString());
        }
Beispiel #12
0
        /// <summary>
        /// Generates sudoku into Generated property.
        /// </summary>
        /// <param name="difficulty">Relative difficulty of generated sudoku</param>
        private void GenerateHelpTestingOnly(Difficulty difficulty, int left, int returning)
        {
            int resetsMax = 300;

            CellsGrid          gridTested = grid.TrueClone();
            CellsGrid          gridSolved = grid.TrueClone();
            List <List <int> > NotNullList;
            int    resets     = 1;
            int    iterations = 0;
            int    last       = 0;
            int    backDebug  = 0;
            Solver solver     = new Solver(gridTested);

            for (; ;)
            {
                if (Generated.Count <= left)
                {
                    return;                             //Stops generating if any other thread generated
                }
                if (gridSolved.Count <= left)
                {
                    if (new Solver(gridSolved).GetDifficulty() == difficulty)
                    {
                        break;
                    }
                }

                if (resets >= resetsMax)
                {
                    break;
                }

                iterations++;
                NotNullList = NotNull(gridTested);
                List <int> item = NotNullList[random.Next(NotNullList.Count)];
                gridTested[item[0], item[1]] = 0;

                solver.Grid = gridTested.TrueClone();

                switch (difficulty)
                {
                case Difficulty.Easy:
                    solver.SolveEasy();
                    break;

                case Difficulty.Medium:
                    solver.SolveMedium();
                    break;

                case Difficulty.Hard:
                    solver.SolveHard();
                    break;
                }


                if (solver.IsSolved())
                {
                    gridSolved = gridTested.TrueClone();
                    last       = 0;
                }
                else
                {
                    gridTested = gridSolved.TrueClone();
                    backDebug++;
                    last++;
                    if (last > gridSolved.Count / returning)
                    {
                        backDebug  = 0;
                        iterations = 0;

                        resets++;
                        gridTested = grid.TrueClone();
                        gridSolved = grid.TrueClone();
                    }
                }
            }
            Generated = gridSolved.TrueClone();
        }
Beispiel #13
0
        /// <summary>
        /// Generates sudoku into Generated property.
        /// </summary>
        /// <param name="difficulty">Relative difficulty of generated sudoku</param>
        /// <param name="offset">Subtract from left numbers to create harder sudoku, CPU intensive</param>
        private void GenerateHelp(int difficulty, int offset = 0)
        {
            int left = 20;

            switch (difficulty)
            {
            case 0:
                left = 25 - offset;
                break;

            case 1:
                left = 24 - offset;
                break;

            case 2:
                left = 24 - offset;
                break;
            }
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();
            CellsGrid          gridTested = grid.TrueClone();
            CellsGrid          gridSolved = grid.TrueClone();
            List <List <int> > NotNullList;
            int    resets     = 1;
            int    iterations = 0;
            int    last       = 0;
            int    backDebug  = 0;
            Solver solver     = new Solver(gridTested);

            while (gridSolved.Count > left && resets < 30)
            {
                if (Generated.Count <= left)
                {
                    return;                             //Stops generating if any other thread generated
                }
                iterations++;
                NotNullList = NotNull(gridTested);
                List <int> item = NotNullList[random.Next(NotNullList.Count)];
                gridTested[item[0], item[1]] = 0;

                solver.Grid = gridTested.TrueClone();

                switch (difficulty)
                {
                case 0:
                    //solver.SolveAll(true, true, 4, 4);
                    solver.SolveEasy();
                    break;

                case 1:
                    //solver.SolveAll(true, true, 0, 4);
                    solver.SolveMedium();
                    break;

                case 2:
                    //solver.SolveAll(true, true, 2, 0);
                    solver.SolveHard();
                    break;
                }


                if (solver.IsSolved())
                {
                    gridSolved = gridTested.TrueClone();
                    last       = 0;
                }
                else
                {
                    gridTested = gridSolved.TrueClone();
                    backDebug++;
                    last++;
                    if (last > gridSolved.Count / 2)
                    {
                        Debug.Print(resets.ToString() + "\t" + backDebug.ToString() + "\t" + iterations.ToString() + "\t" + gridSolved.Count.ToString() + "\t" + stopwatch.ElapsedMilliseconds.ToString());
                        stopwatch.Restart();
                        backDebug  = 0;
                        iterations = 0;

                        resets++;
                        gridTested = grid.TrueClone();
                        gridSolved = grid.TrueClone();
                    }
                }
            }
            Generated = gridSolved.TrueClone();
            stopwatch.Stop();
            Debug.Print(resets.ToString() + "\t" + backDebug.ToString() + "\t" + iterations.ToString() + "\t" + gridSolved.Count.ToString() + "\t" + stopwatch.ElapsedMilliseconds.ToString());
        }
Beispiel #14
0
 public Validator(CellsGrid inputGrid)
 {
     grid = inputGrid;
 }
Beispiel #15
0
        public int[] ShowNext(CellsGrid inputGrid, Difficulty difficulty)
        {
            bool possiblePair = true;
            int  hidden       = 0;
            int  same         = 0;

            switch (difficulty)
            {
            case Difficulty.Easy:
                possiblePair = false;
                break;

            case Difficulty.Medium:
                same = 2;
                break;

            case Difficulty.Hard:
                hidden = 4;
                same   = 4;
                break;
            }

            Grid = inputGrid.TrueClone();
            //Adding numbers to possible.
            for (int x = 0; x < 9; x++)
            {
                for (int y = 0; y < 9; y++)
                {
                    if (Grid[x, y] == 0)
                    {
                        Intersect(x, y);
                    }
                }
            }

            //Removing numbers from possible.
            for (int x = 0; x < 9; x++)
            {
                for (int y = 0; y < 9; y++)
                {
                    if (Grid[x, y] != 0)
                    {
                        RemovePossible(x, y);
                    }
                }
            }

            if (possiblePair)
            {
                for (int x = 0; x < 9; x++)
                {
                    for (int y = 0; y < 9; y++)
                    {
                        if (Grid[x, y] == 0)
                        {
                            RemovePair(x, y);
                        }
                    }
                }
            }

            if (hidden != 0)
            {
                for (int x = 0; x < 9; x++)
                {
                    for (int y = 0; y < 9; y++)
                    {
                        if (Grid[x, y] == 0)
                        {
                            RemoveHidden(x, y);
                            if (hidden > 2)
                            {
                                RemoveHidden(x, y, 3);
                            }
                            if (hidden > 3)
                            {
                                RemoveHidden(x, y, 4);
                            }
                        }
                    }
                }
            }

            if (same != 0)
            {
                for (int x = 0; x < 9; x++)
                {
                    for (int y = 0; y < 9; y++)
                    {
                        if (Grid[x, y] == 0)
                        {
                            RemoveSame(x, y);
                            if (same > 2)
                            {
                                RemoveSame(x, y, 3);
                            }
                            if (same > 3)
                            {
                                RemoveSame(x, y, 4);
                            }
                        }
                    }
                }
            }
            //Adding numbers to grid.
            for (int x = 0; x < 9; x++)
            {
                for (int y = 0; y < 9; y++)
                {
                    if (Grid[x, y] == 0)
                    {
                        if (Count(x, y))
                        {
                            return(new int[] { x, y, Grid[x, y] });
                        }
                        else if (AlonePossible(x, y))
                        {
                            return(new int[] { x, y, Grid[x, y] });
                        }
                    }
                }
            }
            return(new int[] { -1, -1 });
        }
Beispiel #16
0
        /// <summary>
        /// Solves a sudoku with different parameters.
        /// </summary>
        /// <param name="possibleAlone">Use possibleAlone method.</param>
        /// <param name="possiblePair">Use possiblePair method.</param>
        /// <param name="hidden">Use removeHidden method.</param>
        /// <param name="debug">Steps outputing into debugging console.</param>
        /// <returns></returns>
        public int SolveAll(bool possibleAlone = true, bool possiblePair = true, int hidden = 0, int same = 0, bool debug = false)
        {
            this.debug = debug;
            bool changed        = false;
            int  changedCounter = 0;
            int  iteration      = 0;

            DebugGridPrint();
            //for (int x = 0; x < 9; x++) for (int y = 0; y < 9; y++) if (Grid[x, y] != 0) possible[x][y].Add(Grid[x, y]);
            for (; ;)
            {
                //Adding numbers to possible.
                for (int x = 0; x < 9; x++)
                {
                    for (int y = 0; y < 9; y++)
                    {
                        if (Grid[x, y] == 0)
                        {
                            Intersect(x, y);
                        }
                    }
                }

                //Removing numbers from possible.
                for (int x = 0; x < 9; x++)
                {
                    for (int y = 0; y < 9; y++)
                    {
                        if (Grid[x, y] != 0)
                        {
                            RemovePossible(x, y);
                        }
                    }
                }

                if (possiblePair)
                {
                    for (int x = 0; x < 9; x++)
                    {
                        for (int y = 0; y < 9; y++)
                        {
                            if (Grid[x, y] == 0)
                            {
                                RemovePair(x, y);
                            }
                        }
                    }
                }

                if (hidden != 0)
                {
                    for (int x = 0; x < 9; x++)
                    {
                        for (int y = 0; y < 9; y++)
                        {
                            if (Grid[x, y] == 0)
                            {
                                RemoveHidden(x, y);
                                if (hidden > 2)
                                {
                                    RemoveHidden(x, y, 3);
                                }
                                if (hidden > 3)
                                {
                                    RemoveHidden(x, y, 4);
                                }
                            }
                        }
                    }
                }

                if (same != 0)
                {
                    for (int x = 0; x < 9; x++)
                    {
                        for (int y = 0; y < 9; y++)
                        {
                            if (Grid[x, y] == 0)
                            {
                                RemoveSame(x, y);
                                if (same > 2)
                                {
                                    RemoveSame(x, y, 3);
                                }
                                if (same > 3)
                                {
                                    RemoveSame(x, y, 4);
                                }
                            }
                        }
                    }
                }

                //Adding numbers to grid.
                for (int x = 0; x < 9; x++)
                {
                    for (int y = 0; y < 9; y++)
                    {
                        if (Grid[x, y] == 0)
                        {
                            if (Count(x, y))
                            {
                                changed = true;
                                DebugGridPrint("COUNT X: " + x + " Y: " + y + " NUM: " + Grid[x, y]);
                                Steps.Add(Grid.Clone());
                            }
                            else if (possibleAlone && AlonePossible(x, y))
                            {
                                changed = true;
                                Steps.Add(Grid.Clone());
                            }
                        }
                    }
                }

                //Ends loop if nothing is added 10 iterations in row.
                if (changed)
                {
                    changedCounter = 0;
                }
                else
                {
                    changedCounter++;
                }
                if (changedCounter >= 10)
                {
                    break;
                }
                changed = false;

                if (IsSolved())
                {
                    if (debug)
                    {
                        Debug.Print("Solved");
                        string helper = "";
                        for (int x = 0; x < 9; x++)
                        {
                            helper = "";
                            for (int y = 0; y < 9; y++)
                            {
                                helper += Grid[x, y].ToString() + " ";
                            }
                            Debug.Print(helper);
                        }
                        Debug.Print("");
                    }
                    break;
                }

                iteration++;
            }
            SolvedGrid = Grid.Clone();
            return(iteration);
        }
Beispiel #17
0
        /// <summary>
        /// Generates sudoku into Generated property.
        /// </summary>
        /// <param name="difficulty">Relative difficulty of generated sudoku</param>
        /// <param name="offset">Subtract from left numbers to create harder sudoku, CPU intensive</param>
        private void GenerateHelp3(Difficulty difficulty)
        {
            int resetsMax = 300;
            int left      = 30;
            int returning = 2;

            switch (difficulty)
            {
            case Difficulty.Easy:
                left      = 25;
                returning = 2;
                break;

            case Difficulty.Medium:
                left      = 26;
                returning = 3;
                break;

            case Difficulty.Hard:
                left      = 35;
                returning = 7;
                break;
            }
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();
            CellsGrid          gridTested = grid.TrueClone();
            CellsGrid          gridSolved = grid.TrueClone();
            List <List <int> > NotNullList;
            int    resets     = 1;
            int    iterations = 0;
            int    last       = 0;
            int    backDebug  = 0;
            Solver solver     = new Solver(gridTested);

            for (; ;)
            {
                if (Generated.Count <= left)
                {
                    return;                             //Stops generating if any other thread generated
                }
                if (gridSolved.Count <= left)
                {
                    if (new Solver(gridSolved).GetDifficulty() == difficulty)
                    {
                        break;
                    }
                }

                if (resets >= resetsMax)
                {
                    break;
                }

                iterations++;
                NotNullList = NotNull(gridTested);
                List <int> item = NotNullList[random.Next(NotNullList.Count)];
                gridTested[item[0], item[1]] = 0;

                solver.Grid = gridTested.TrueClone();

                switch (difficulty)
                {
                case Difficulty.Easy:
                    solver.SolveEasy();
                    break;

                case Difficulty.Medium:
                    solver.SolveMedium();
                    break;

                case Difficulty.Hard:
                    solver.SolveHard();
                    break;
                }


                if (solver.IsSolved())
                {
                    gridSolved = gridTested.TrueClone();
                    last       = 0;
                }
                else
                {
                    gridTested = gridSolved.TrueClone();
                    backDebug++;
                    last++;
                    if (last > gridSolved.Count / returning)
                    {
                        Debug.Print(resets.ToString() + "\t" + backDebug.ToString() + "\t" + iterations.ToString() + "\t" + gridSolved.Count.ToString() + "\t" + stopwatch.ElapsedMilliseconds.ToString());
                        stopwatch.Restart();
                        backDebug  = 0;
                        iterations = 0;

                        resets++;
                        gridTested = grid.TrueClone();
                        gridSolved = grid.TrueClone();
                    }
                }
            }
            Generated = gridSolved.TrueClone();
            stopwatch.Stop();
            Debug.Print(resets.ToString() + "\t" + backDebug.ToString() + "\t" + iterations.ToString() + "\t" + gridSolved.Count.ToString() + "\t" + stopwatch.ElapsedMilliseconds.ToString());
        }