I'm currently making a Sudoku Solver in C#. Since I have to initialize it before solving it, I bound the Cells of my char[][] SudokuTable to my view. Every cell has it's own textbox inside of my view. Example:
<TextBox Grid.Row = "0" Grid.Column = "0" Style = "{StaticResource GridTextBox}" Text = "{Binding Path=SudokuTable[0][0]}" />
So upon start of the Application, it will Initialize Sudokutable like this:.
public RelayCommand Solve { get; set; }
public RelayCommand Reset { get; set; }
public MainViewModel()
{
SudokuTable = new char[9][];
for (int i = 0; i < 9; i++)
{
SudokuTable[i] = new char[9]
{ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };
}
Solve = new RelayCommand(o => SudokuStart());
Reset = new RelayCommand(o => SudokuReset());
}
Because if I have it without the spacebars, I will get invisible char ('\0') which would have to be deleted before calculating. The RelacCommands are bound to Buttons in my View. The Logic of my Application looks like this:
private void SudokuReset()
{
var newTable = new char[9][];
for (int i = 0; i < 9; i++)
{
newTable[i] = new char[9]
{ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };
}
SudokuTable = newTable;
}
private void SudokuStart()
{
DateTime startTime = DateTime.Now;
char[][] sudokuTable = InitializeJaggedArray();
SudokuSolve(sudokuTable);
DateTime endTime = DateTime.Now;
TimeSpan solveTime = endTime - startTime;
SudokuTimer = $"Calculation time: \n{solveTime.TotalSeconds} seconds";
}
private char[][] InitializeJaggedArray()
{
char[][] jaggedArray = new char[9][];
for (int i = 0; i < 9; i++)
{
jaggedArray[i] = new char[9];
for (int j = 0; j < 9; j++)
{
if (SudokuTable[i][j] < '1' || SudokuTable[i][j] > '9')
{
jaggedArray[i][j] = ' ';
}
else
{
jaggedArray[i][j] = SudokuTable[i][j];
}
}
}
return jaggedArray;
}
private char[][] SudokuSolve(char[][] sudokuTable)
{
int row = -1;
int column = -1;
char[] possibleSolution = null;
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
if (sudokuTable[i][j] == ' ')
{
char[] solutions = GetSolution(sudokuTable, i, j);
if (row < 0 || solutions.Length < possibleSolution.Length)
{
row = i;
column = j;
possibleSolution = solutions;
}
}
}
}
if (row < 0)
{
SudokuTable = sudokuTable;
}
else
{
for (int i = 0; i < possibleSolution.Length; i++)
{
sudokuTable[row][column] = possibleSolution[i];
if (SudokuSolve(sudokuTable) == sudokuTable)
{
SudokuTable = sudokuTable;
break;
}
sudokuTable[row][column] = ' ';
}
}
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
if (SudokuTable[i][j] == ' ')
{
SudokuStatus = "Not able to solve this Sudoku";
}
else
{
SudokuStatus = "Able to solve this Sudoku";
}
}
}
return SudokuTable = sudokuTable;
}
private char[] GetSolution(char[][] sudokuTable, int row, int column)
{
string solution ="";
for (char c = '1'; c <= '9'; c++)
{
bool collision = false;
for (int i = 0; i < 9; i++)
{
if (sudokuTable[row][i] == c ||
sudokuTable[i][column] == c ||
sudokuTable[(row - row % 3) + i / 3][(column - column % 3) + i % 3] == c)
{
collision = true;
break;
}
}
if (!collision)
solution += c;
}
return solution.ToCharArray();
}
private string sudokuTimer;
public string SudokuTimer
{
get { return sudokuTimer; }
set
{
if (sudokuTimer != value)
{
sudokuTimer = value;
OnPropertyChanged("SudokuTimer");
}
}
}
private string sudokuStatus;
public string SudokuStatus
{
get { return sudokuStatus; }
set
{
if (sudokuStatus != value)
{
sudokuStatus = value;
OnPropertyChanged("SudokuStatus");
}
}
}
private char[][] sudokuTable;
public char[][] SudokuTable
{
get { return sudokuTable; }
set
{
if (sudokuTable != value)
{
sudokuTable = value;
OnPropertyChanged("SudokuTable");
}
}
}
}
}
I don't have a problem with changing the whole logic behind my programm (using string arrays or int arrays) if that helps you.
I'm thankful for every answer.