What was the goal?

At this point in time I was a sophmore in college, and I was thinking of things that I knew were weaknesses for me so that I could focus on improving in those places. One of those topics for me was function recursion (i.e. when a function or method calls itself). It was a topic that myself and many others seemed to have a hard time wrapping our heads around. So I took to the internet like most college students do looking for inspiration on how I might be able to improve on this subject. I ended up coming across an interesting project that talked about making a sudoku solver with function recursion. Right then I decided I wanted to make one for myself too!

My approach

I knew that when approaching this project I would have to think a little outside of my comfort zone because I was working with concepts and practices that were foreign for me. I knew that the real bulk of work, when it came to the actual solving of the sudoku puzzle, would be contained in one function. Then that function would be what called itself recursively, ultimately solving the puzzle. But before I really tackled that function I knew I needed to lay some ground work. I needed something that represented my sudoku puzzle behind the scenes. I decided to go with an object oriented approach and make a "Board" class as well as a "Cell" class.

The Board object would be responsible for creating the sudoku puzzle via a two dimensional array of cell objects as well as managing the puzzle entirely. I wanted the end goal for solving a board to simply look like "Board.solve()". I also wanted some way to visualize the Board so I decided to go with what Pygame as the library I'd use to do that since it was what I knew the best at the time.

Finally after all the preliminary work was finish I could get to work on my solve function. Before I actually wrote any lines of code I wanted some kind of outline so I knew what the function needed. I landed on two core things the function needed to accomplish:
1. Keep track of the current row and column (i.e. "active cell") appropriately
2. Try placing a number into the active cell and see if that placement is valid
These two goals are definitely a bit broad, but, as an example, if the currently active cell was a cell that had a number given from the start then that cell would need to be skipped. Another example would be if we wanted to place, say, a number 5 into the active cell then the board would need to check to see if that was a valid placement based on the rules of sudoku. And if you're not familiar with the rules of sudoku there are three main criteria; a number cannot be repeated in a row, column, or the 3x3 subsection within the board. Eventually after a fair bit of trial and error I landed on these two function as my solve and validSpot. I ended up abstracting the constraint checking into its own function so that it didnt overly clutter the easy to read goal I had for the solve function.
valid
solve

Challenges Faced and Things Learned

For me the biggest challenge on this project was forcing myself to think differently thank I normally do. The whole idea of function recursion made sense to me practically, but in use it could get very confussing once a function has recurssed on itself hundreds of times. But taking the extra time to think about these concepts and how to work with them really helped. So much so that one of the most difficult pre-loaded sudoku boards that I have in my programe recursively calls the solve function over 35,000 times. All in all this project helped me as just a general programmer but also in specifically targeted areas as well.

How to check out the project?

The project with all the source code is up on my GitHub for you to download if you'd like to check it out!