The solver can only solve when at least one cell can be solved with certainty at each step of the process until repeating this eventually results in a solved board. The next step here is to allow exploration/trail of possible solutions. Presumably, would want to keep a copy of the board just before each "guess" that's taken to be able to easily roll back if failure. This would probably work really nicely as a recursive call: board = get_fresh_board(board) solve_all_certainties(board) for each possible board as cand_board: solution = solve_all_certainties(cand_board) if complete(solution) success /* we should have solution presuming board was solvable */