Advertisement
Razali

Sudoku Solver by Razali

Aug 7th, 2015
262
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.50 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3.  
  4. namespace Sudoku_Solver
  5. {
  6.     public  class Constraint
  7.     {
  8.         public Constraint(int row, int col, List<int> possibleValues)
  9.         {
  10.             Row = row;
  11.             Column = col;
  12.             PossibleValues = possibleValues;
  13.         }
  14.         public int Row { get; set;}
  15.         public int Column { get; set;}
  16.  
  17.         public List<int> PossibleValues { get; set; }
  18.  
  19.         public int Count() { return PossibleValues.Count;}
  20.  
  21.     }
  22.  
  23.     static class Program
  24.     {
  25.         #region Variables
  26.         //Hard Difficulty Sudoku Puzzle
  27.         private static int[,] grid = new int[,]{
  28.                 {0,0,0,0,0,0,0,0,0},
  29.                 {0,0,0,0,0,3,0,8,5},
  30.                 {0,0,1,0,2,0,0,0,0},
  31.                 {0,0,0,5,0,7,0,0,0},
  32.                 {0,0,4,0,0,0,1,0,0},
  33.                 {0,9,0,0,0,0,0,0,0},
  34.                 {5,0,0,0,0,0,0,7,3},
  35.                 {0,0,2,0,1,0,0,0,0},
  36.                 {0,0,0,0,4,0,0,0,9}
  37.             };
  38.  
  39.  
  40.  
  41.         private static List<Constraint> constraints;
  42.  
  43.         #endregion
  44.  
  45.  
  46.         static void Main(string[] args)
  47.         {
  48.             Console.WriteLine("Solving Sudoku...");
  49.             DateTime start = DateTime.UtcNow;
  50.  
  51.             GetConstraints();
  52.             SolveSudokuGrid(0);
  53.  
  54.             DateTime end = DateTime.UtcNow;
  55.  
  56.             DisplayGrid();
  57.            
  58.             Console.WriteLine("\nTook a total of " + end.Subtract(start).TotalSeconds.ToString() + " seconds to solve");
  59.             Console.Read();
  60.  
  61.         }
  62.  
  63.  
  64.         #region Methods
  65.         private static bool SolveSudokuGrid(int constraintIndex)
  66.         {
  67.  
  68.             if (IsGameOver() == true)
  69.                 return true;
  70.  
  71.             //Get constraint
  72.             Constraint constraint = constraints[constraintIndex];
  73.  
  74.  
  75.             for (int i = 0; i < constraint.Count(); i++)
  76.             {
  77.                 if (HasConflicts(constraint.Row, constraint.Column, constraint.PossibleValues[i]))
  78.                     continue;
  79.                 //Assume correct number by adding a constraint
  80.                 grid[constraint.Row, constraint.Column] = constraint.PossibleValues[i];
  81.  
  82.                 if (SolveSudokuGrid(constraintIndex + 1) == true)
  83.                     return true;
  84.  
  85.                 //Cant solve. Backtrack
  86.                 grid[constraint.Row, constraint.Column] = 0;
  87.             }
  88.  
  89.             return false;
  90.         }
  91.  
  92.  
  93.         private static void DisplayGrid()
  94.         {
  95.             Console.WriteLine("-------------------------");
  96.             for (int row = 0; row < 9; row++)
  97.             {
  98.                 for (int col = 0; col < 9; col++)
  99.                 {
  100.                     if (col == 0 || col % 3 == 0)
  101.                         Console.Write("| ");
  102.  
  103.                     if (grid[row,col] == 0)
  104.                         Console.Write("- ");
  105.                     else
  106.                         Console.Write(grid[row,col] +" ");
  107.                 }
  108.                 Console.WriteLine("|");
  109.  
  110.                 if ((row + 1) % 3 == 0 && row != 0)
  111.                     Console.WriteLine("-------------------------");
  112.             }
  113.  
  114.         }
  115.  
  116.  
  117.         /// <summary>
  118.         /// Determines if sudoku is solved by finding for
  119.         /// '0' zeroes in the grid
  120.         /// </summary>
  121.         /// <returns>
  122.         /// True if Sudoku is solved
  123.         /// False otherwise
  124.         /// </returns>
  125.         private static bool IsGameOver()
  126.         {
  127.             for(int r = 0; r < 9; r++)
  128.                for(int c = 0; c < 9; c++)
  129.                  if (grid[r, c] == 0)
  130.                     return false;
  131.              
  132.             return true;
  133.         }
  134.  
  135.         /// <summary>
  136.         /// Determines all valid values that can be put
  137.         /// into the unfilled squares
  138.         /// </summary>
  139.         private static void GetConstraints()
  140.         {
  141.             constraints = new List<Constraint>();
  142.  
  143.             for(int row = 0; row < 9; row++)
  144.                 for(int col = 0; col < 9; col++)
  145.                     if(grid[row,col] == 0)
  146.                         constraints.Add(ComputeConstraint(row, col));
  147.  
  148.             constraints.Sort(delegate(Constraint c1, Constraint c2) { return c1.Count().CompareTo(c2.Count()); });
  149.         }
  150.  
  151.         /// <summary>
  152.         /// Given an unsolved square in a puzzle,
  153.         /// determines all possible valid values
  154.         /// from 1 to 9
  155.         /// </summary>
  156.         /// <param name="row">Row of square</param>
  157.         /// <param name="col">Col of square</param>
  158.         /// <returns>List of valid values</returns>
  159.  
  160.        
  161.         private static Constraint ComputeConstraint(int row, int col)
  162.         {
  163.             List<int> possibleValues = new List<int>();
  164.            
  165.             for (int i = 1; i <= 9; i++)
  166.                 if (HasConflicts(row, col, i) == false)
  167.                     possibleValues.Add(i);
  168.  
  169.             Constraint constraint = new Constraint(row, col, possibleValues);
  170.             return constraint;
  171.         }
  172.  
  173.  
  174.         private static bool usedInRow(int row, int num)
  175.         {
  176.             /*
  177.             * Scans through that "row" till a match is found.
  178.             */
  179.             for (int col = 0; col < 9; col++)
  180.                 if (grid[row,col] == num)
  181.                    return true;
  182.                            
  183.             return false;
  184.         }
  185.  
  186.         private static bool usedInCol(int col, int num)
  187.         {
  188.             /*
  189.             * Scans through that "col" till a match is found.
  190.             */
  191.             for (int row = 0; row < 9; row++)
  192.                if (grid[row,col] == num)
  193.                    return true;                
  194.            
  195.             return false;
  196.         }
  197.  
  198.         private static bool usedInBox(int boxStartRow, int boxStartCol, int num)
  199.         {
  200.             /*
  201.             * Scans through the mini 3x3 box, looking for a duplicate number
  202.             */
  203.             for (int row = boxStartRow; row < boxStartRow + 3; row++)
  204.                   for (int col = boxStartCol; col < boxStartCol + 3; col++)
  205.                      if (grid[row,col] == num)
  206.                         return true;
  207.                
  208.             return false;
  209.         }
  210.  
  211.         private static bool HasConflicts(int row, int col, int num)
  212.         {            
  213.             int startRow = (row / 3) * 3;
  214.             int startCol = (col / 3) * 3;
  215.          
  216.  
  217.             return (usedInRow(row, num) || usedInCol(col, num) || usedInBox(startRow, startCol, num));
  218.         }
  219.  
  220.         #endregion
  221.     }
  222. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement