0

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.

Papriker
  • 77
  • 6
  • Are you against using ' ' in your code, or as a value? You could save the ' ' in a readonly variable somewhere, or use a struct/class to represent a cell with an `IsEmpty` field perhaps – rhughes May 13 '20 at 11:59
  • @rhughes I use ' ' to represent an empty cell. I don't mind using it for calculations to represent an empty cell. What I don't like is that after initializing my App, every textbox is of course filled with ' '. This means the user of the Sudoku Solver has to delete the Value inside the textbox and then enter a number. For coding this was the easiest way, but for using the application it's a little annoying. I also don't know how to initialize the SudokuTable without these for calculations. If I don't fill the textboxes I get a NullReferenceException. – Papriker May 13 '20 at 12:02
  • 1
    You can improve editing experience: select all text on focus (so user don't have to delete entry), make mouse support (by using numeric up/down controls, read-only comboxes, etc.). Consider to use `\0` (default `char` value), inside loop: `SudokuTable[i] = new char[9];` – Sinatr May 13 '20 at 12:15
  • @Sinatr I was already thinking about using \0 but thought it was misleading for the user, as he had to delete it before. So \0 was less recognizeable than ' ', but if you show me how to select all the Text on focus in an answer to the question and it works, I will mark you as the correct answer because it actually sounds good. Thank you! – Papriker May 13 '20 at 12:18
  • 1
    Check [this answer](https://stackoverflow.com/a/102095/1997232). – Sinatr May 13 '20 at 12:36
  • @Sinatr Looks like a WinForms only answer. I didn't state that I use WPF. That was my bad. – Papriker May 13 '20 at 13:11
  • Your SudokuTable needs to be `int?[][]`, not a `char` array. – Mat J May 13 '20 at 13:13
  • @MatJ How do I have empty array Elements in a int?[][]? – Papriker May 13 '20 at 13:26
  • You can have null in there `int?` is `Nullable` – Mat J May 13 '20 at 13:41

0 Answers0