I am trying to create a sudoku solver by first
- calculating the possible values that can be put in the square.
- Then using these constraints to backtrack
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sudoku_Solver
{
static class Program
{
private static int[,] grid = new int[,]{
{ 3, 0, 6, 5, 0, 8, 4, 0, 0 },
{ 5, 2, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 8, 7, 0, 0, 0, 0, 3, 1 },
{ 0, 0, 3, 0, 1, 0, 0, 8, 0 },
{ 9, 0, 0, 8, 6, 3, 0, 0, 5 },
{ 0, 5, 0, 0, 9, 0, 0, 6, 0 },
{ 1, 3, 0, 0, 0, 0, 2, 5, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 7, 4 },
{ 0, 0, 5, 2, 0, 6, 3, 0, 0 }
};
private static List<int>[,] constraints;
static void Main(string[] args)
{
GetConstraints();
SolveSudokuGrid();
PrintGrid();
Console.Read();
}
static bool SolveSudokuGrid()
{
int row = -1 , col = -1;
if (IsGameOver(ref row, ref col) == true)
return true;
//Get constraint
List<int> constraint = constraints[row, col];
for (int i = 0; i < constraint.Count; i++)
{
//Assume correct number by adding a constraint
grid[row, col] = constraint[i];
if (SolveSudokuGrid() == true)
return true;
//Cant solve. Backtrack
grid[row, col] = 0;
}
return false;
}
static void PrintGrid()
{
for (int row = 0; row < 9; row++)
{
for (int col = 0; col < 9; col++)
Console.Write(grid[row,col]);
Console.WriteLine();
}
}
static bool IsGameOver(ref int row, ref int col)
{
for(int r = 0; r < 9; r++)
{
for(int c = 0; c < 9; c++)
{
if (grid[r, c] == 0)
{
row = r;
col = c;
return false;
}
}
}
return true;
}
static void GetConstraints()
{
constraints = new List<int>[9, 9];
for(int row = 0; row < 9; row++)
{
for(int col = 0; col < 9; col++)
{
if(grid[row,col] == 0)
{
constraints[row, col] = ComputeConstraint(row, col);
continue;
}
constraints[row, col] = null;
}
}
}
static List<int> ComputeConstraint(int row, int col)
{
List<int> constraint = new List<int>();
for (int i = 1; i <= 9; i++)
if (HasConflicts(row, col, i) == false)
constraint.Add(i);
return constraint;
}
static bool usedInRow(int row, int num)
{
/*
* Scans through that "row" till a match is found.
* So "row" will be the same, but "col" will keep changing as we scan
*/
for (int col = 0; col < 9; col++)
{
if (grid[row,col] == num)
{
return true;
}
}
return false;
}
static bool usedInCol(int col, int num)
{
/*
* Scans through that "col" till a match is found.
* So "col" will be the same, but "row" will keep changing as we scan
*/
for (int row = 0; row < 9; row++)
{
if (grid[row,col] == num)
{
return true;
}
}
return false;
}
static bool usedInBox(int boxStartRow, int boxStartCol, int num)
{
/*
* Scans through the mini 3x3 box, looking for a duplicate number
*/
for (int row = boxStartRow; row < boxStartRow + 3; row++)
{
for (int col = boxStartCol; col < boxStartCol + 3; col++)
{
if (grid[row,col] == num)
return true;
}
}
return false;
}
static bool HasConflicts(int row, int col, int num)
{
bool isInRow, isInCol, isInBox, hasConflicts = false;
isInRow = usedInRow(row, num);
isInCol = usedInCol(col, num);
int startRow = (row / 3) * 3;
int startCol = (col / 3) * 3;
isInBox = usedInBox(startRow, startCol, num);
if (isInRow)
{
hasConflicts = true;
}
if (isInCol)
{
hasConflicts = true;
}
if (isInBox)
{
hasConflicts = true;
}
return hasConflicts;
}
}
}