I've been asked to attach a C++ code sample to my application for an entry-level C++ programmer position in a videogame company.  I've created a simple, yet complete console application to solve Sudoku problems. How can I improve the code that I have?Please do comment on the algorithm, the code practices, presentation, or anything else.  It's one of my first attempts to also set up unit tests with my code.Also, I am interested in whether you think this would work well as a code sample in particular  i.e. does it show what people who look at the code samples want to see?Complete code#include <set>#include <string>#include <fstream>#include <iostream>#include <cassert>// ======================================================================================enum SolutionResult {    // The position has been solved OK.    SR_SOLVED,    // The current position in invalid.    // For that reason, it is useless to even attempt to solve it.    SR_INVALID,    // The current position is valid in its current state, but there     // exists no complete solution that would uphold the sudoku rules.    SR_UNSOLVABLE};// ======================================================================================class Sudoku {protected:    // 0 = Empty cell    short values[9][9];    // Returns whether all the rows are currently valid,     // i.e. whether no rows contain any duplicate values.    bool checkValidRows() {        for (short row = 0; row < 9; row++) {            std::set<short> valuesInRow;            for (short col = 0; col < 9; col++) {                short val = this->values[row][col];                if (!val) continue;                if (valuesInRow.find(val) != valuesInRow.end()) {                    return false;                }                valuesInRow.insert(val);            }        }        return true;    }    // Returns whether all the columns are currently valid,     // i.e. whether no columns contain any duplicate values.    bool checkValidCols() {        for (short col = 0; col < 9; col++) {            std::set<short> valuesInCol;            for (short row = 0; row < 9; row++) {                short val = this->values[row][col];                if (!val) continue;                if (valuesInCol.find(val) != valuesInCol.end()) {                    return false;                }                valuesInCol.insert(val);            }        }        return true;    }    // Returns whether all the partial squares are currently valid,     // i.e. whether no 3x3 square contains a duplicate value.    bool checkValidSquares() {        for (short squareX = 0; squareX < 3; squareX++) {        for (short squareY = 0; squareY < 3; squareY++) {            std::set<short> valuesInSquare;            for (short m = 0; m < 3; m++) {                for (short n = 0; n < 3; n++) {                    short val = this->values[squareX*3+m][squareY*3+n];                    if (val == 0) continue;                    if (valuesInSquare.find(val) != valuesInSquare.end()) {                        return false;                    }                    valuesInSquare.insert(val);                }            }        }        }        return true;    }    // Returns whether the current position is valid, i.e., whether its rows, columns,     // and squares are all valid and do not contain a duplicate value.    bool checkValid() {        return this->checkValidRows() && this->checkValidCols() && this->checkValidSquares();    }public:    Sudoku() {        // Start with a blank position.        for (short row = 0; row < 9; row++) {        for (short col = 0; col < 9; col++) {            this->values[row][col] = 0;        }        }    }    Sudoku (const short values[9][9]) {        for (short row = 0; row < 9; row++) {        for (short col = 0; col < 9; col++) {            // Values that are not between [0 .. 9]             // are discarded and replaced with zeroes.            short val = values[row][col];            if (val >= 0 && val <= 9) {                this->values[row][col] = val;            }             else {                this->values[row][col] = 0;            }        }        }    }    // This is the solver method.    // The way to solution is a standard backtrack exercise.    //     // For the next empty space, we put the lowest possible value in, and recursively call the solver    // to see whether it can complete all the other spaces in a valid manner  in which case, we are done.    // In case that no possible value in the chosen space leads to a valid and complete solution, we clear     // the space entirely and declare the position as unsolvable. In recursion terms, this means that     // we need to attempt to put another value to the previous space, and so on.    SolutionResult solve() {        // Check that the situation is valid.        if (!this->checkValid()) return SR_INVALID;        // For the next empty space:        for (short row = 0; row < 9; row++) {        for (short col = 0; col < 9; col++) {            if (this->values[row][col] > 0) continue;            // Put an arbitrary value into the space:            for (short val = 1; val <= 9; val++) {                this->values[row][col] = val;                // Recursively call the solver and see whether it can complete all                 // the other spaces in the same manner. In case that it can, we're done.                if (this->solve() == SR_SOLVED) {                    return SR_SOLVED;                }            }            // We tried all the possible values, and none has lead to a complete and             // valid solution. Clear the space, and return that the position is unsolvable.            this->values[row][col] = 0;            return SR_UNSOLVABLE;        }        }        // There are no more empty spaces.         // We're done.        return SR_SOLVED;    }    // Formatted output.    friend std::ostream& operator<< (std::ostream &os, const Sudoku& s) {        for (short row = 0; row < 9; row++) {            os << std::endl;            for (short col = 0; col < 9; col++) {                os << ' ';                if (s.values[row][col] > 0) {                    os << s.values[row][col];                } else {                    os << '.';                }                if (col == 2 || col == 5) {                    os <<  |;                }            }            if (row == 2 || row == 5) {                os << std::endl <<  ------+-------+------;            }        }        os << std::endl;        return os;    }    //    static void runUnitTests();};// ======================================================================================int main (int argc, char* argv[]){    short pos[9][9] = {        {0, 0, 4, 0, 0, 0, 0, 0, 0},        {6, 0, 2, 1, 0, 0, 0, 0, 0},        {1, 0, 8, 3, 4, 2, 5, 6, 7},        {0, 0, 9, 7, 0, 0, 4, 2, 3},        {4, 0, 6, 8, 0, 0, 0, 0, 1},        {7, 1, 3, 9, 2, 0, 8, 0, 0},        {0, 0, 0, 5, 3, 0, 2, 8, 4},        {0, 0, 0, 4, 1, 0, 6, 0, 0},        {3, 0, 0, 0, 0, 6, 1, 0, 0}    };    // Let's test the entire unit.    Sudoku::runUnitTests();    // Let's solve the particular position above:    Sudoku s (pos);    std::cout << s << std::endl;    std::cout << Solver starts, please wait... << std::endl;    switch (s.solve()) {    case SR_SOLVED:        std::cout << Solution:  << std:: endl;        std::cout << s << std::endl;        break;    case SR_INVALID:        std::cout << The position is not valid. << std:: endl;        break;    case SR_UNSOLVABLE:        std::cout << The position cannot be solved. << std:: endl;        break;    }    std::cout << Press any key to exit...;    getchar();    return 0;}// ======================================================================================void Sudoku::runUnitTests() {    short dataZeroes[9][9] = {        {0, 0, 0, 0, 0, 0, 0, 0, 0},        {0, 0, 0, 0, 0, 0, 0, 0, 0},        {0, 0, 0, 0, 0, 0, 0, 0, 0},        {0, 0, 0, 0, 0, 0, 0, 0, 0},        {0, 0, 0, 0, 0, 0, 0, 0, 0},        {0, 0, 0, 0, 0, 0, 0, 0, 0},        {0, 0, 0, 0, 0, 0, 0, 0, 0},        {0, 0, 0, 0, 0, 0, 0, 0, 0},        {0, 0, 0, 0, 0, 0, 0, 0, 0}    };    short dataValidPos1[9][9] = {        {5, 3, 4, 6, 7, 8, 9, 1, 2},        {6, 7, 2, 1, 9, 5, 3, 4, 8},        {1, 9, 8, 3, 4, 2, 5, 6, 7},        {8, 5, 9, 7, 6, 1, 4, 2, 3},        {4, 2, 6, 8, 5, 3, 7, 9, 1},        {7, 1, 3, 9, 2, 4, 8, 5, 6},        {9, 6, 1, 5, 3, 7, 2, 8, 4},        {2, 8, 7, 4, 1, 9, 6, 3, 5},        {3, 4, 5, 2, 8, 6, 1, 7, 9}    };    short dataValidPos2[9][9] = {        {0, 0, 0, 0, 0, 0, 0, 0, 0},        {6, 0, 2, 1, 0, 0, 0, 0, 0},        {1, 0, 8, 3, 4, 2, 5, 6, 7},        {0, 0, 9, 7, 0, 0, 4, 2, 3},        {4, 0, 6, 8, 0, 0, 0, 0, 1},        {7, 1, 3, 9, 2, 0, 8, 0, 0},        {0, 0, 0, 5, 3, 0, 2, 8, 4},        {0, 0, 0, 4, 1, 0, 6, 0, 0},        {3, 0, 0, 0, 0, 6, 1, 0, 0}    };    short dataInvalidRows[9][9] = {        {5, 3, 4, 6, 7, 8, 9, 1, 5},        {6, 7, 2, 1, 9, 5, 3, 4, 8},        {1, 9, 8, 3, 4, 2, 0, 6, 7},        {8, 5, 9, 7, 6, 1, 4, 2, 3},        {4, 2, 6, 8, 5, 3, 7, 9, 1},        {7, 1, 3, 9, 2, 4, 8, 5, 6},        {9, 6, 1, 5, 3, 7, 2, 8, 4},        {2, 8, 7, 4, 1, 9, 6, 3, 0},        {3, 4, 5, 2, 8, 6, 1, 7, 9}    };    short dataInvalidCols[9][9] = {        {5, 3, 4, 6, 7, 8, 9, 1, 2},        {6, 7, 2, 1, 9, 0, 3, 4, 8},        {1, 9, 8, 3, 4, 2, 5, 6, 7},        {8, 5, 9, 7, 6, 1, 4, 2, 3},        {4, 2, 6, 8, 5, 3, 7, 9, 1},        {7, 1, 3, 9, 2, 4, 8, 5, 6},        {9, 6, 1, 5, 3, 7, 2, 8, 4},        {2, 8, 7, 4, 1, 9, 6, 3, 5},        {5, 4, 0, 2, 8, 6, 1, 7, 9}    };    short dataInvalidSquares[9][9] = {        {5, 3, 4, 6, 7, 8, 9, 1, 2},        {6, 5, 2, 1, 9, 0, 3, 4, 8},        {1, 9, 8, 3, 4, 2, 5, 6, 7},        {8, 0, 9, 7, 6, 1, 4, 2, 3},        {4, 2, 6, 8, 5, 3, 7, 9, 1},        {7, 1, 3, 9, 2, 4, 8, 5, 6},        {9, 6, 1, 5, 3, 7, 2, 8, 4},        {2, 8, 7, 4, 1, 9, 6, 3, 5},        {3, 4, 5, 2, 8, 6, 1, 7, 9}    };    Sudoku zeroes (dataZeroes);    Sudoku validPos1 (dataValidPos1);    Sudoku validPos2 (dataValidPos2);    Sudoku invalidRows (dataInvalidRows);    Sudoku invalidCols (dataInvalidCols);    Sudoku invalidSquares (dataInvalidSquares);    std::cout << Unit tests start... << std::endl;    assert(zeroes.checkValidRows());    assert(zeroes.checkValidCols());    assert(zeroes.checkValidSquares());    assert(zeroes.checkValid());    assert(zeroes.solve() == SR_SOLVED);    assert(validPos1.checkValidRows());    assert(validPos1.checkValidCols());    assert(validPos1.checkValidSquares());    assert(validPos1.checkValid());    assert(validPos1.solve() == SR_SOLVED);    assert(validPos2.checkValidRows());    assert(validPos2.checkValidCols());    assert(validPos2.checkValidSquares());    assert(validPos2.checkValid());    assert(validPos2.solve() == SR_SOLVED);    assert(validPos2.values[0][0] == 5);    assert(validPos2.values[0][1] == 3);    assert(validPos2.values[0][2] == 4);    assert(validPos2.values[0][3] == 6);    assert(validPos2.values[0][4] == 7);    assert(validPos2.values[0][5] == 8);    assert(validPos2.values[0][6] == 9);    assert(validPos2.values[0][7] == 1);    assert(validPos2.values[0][8] == 2);    assert(!invalidRows.checkValidRows());    assert( invalidRows.checkValidCols());    assert( invalidRows.checkValidSquares());    assert(!invalidRows.checkValid());    assert( invalidRows.solve() == SR_INVALID);    assert( invalidCols.checkValidRows());    assert(!invalidCols.checkValidCols());    assert( invalidCols.checkValidSquares());    assert(!invalidCols.checkValid());    assert( invalidCols.solve() == SR_INVALID);    assert( invalidSquares.checkValidRows());    assert( invalidSquares.checkValidCols());    assert(!invalidSquares.checkValidSquares());    assert(!invalidSquares.checkValid());    assert( invalidSquares.solve() == SR_INVALID);    std::cout << All unit tests OK. << std::endl;}
Entry-level recursive Sudoku solver
c++;recursion;sudoku
From a brief glance, I can see a number of issues with the code. I'm sorry if I am overly blunt, but it's better that you hear it from me than a recruiter.In no particular order:Use the language. Structure your code better. Consider using more classes to represent the board. Don't write a sudoku-solving program. Make it a tiny sudoku-solver library, and include a driver program to use that library. Write reusable code.You have protected members of the class. This usually means the class is designed to be a base class. However, base classes should have a virtual destructor, but yours isn't. You probably want to change protected to private.Make your solver handle boards with multiple solutions.Your explicit use of this just creates clutter, in my opinion.Your code is not exception safe. There is no way to test the state of the solver if solve() throws an exception, for example. You should have a function in the public interface to query the state of the solver.Avoid excessive whitespace and comments.Make member functions that don't mutate state const.For example:bool checkValidCols() const { /* ... */ }Don't hard code sizes. Read your game board from a file. Accept variable-sized boards.Prefer pre-increment to post-increment when pre-increment is what you want. You want to say increment i by one, not make a copy of i and then increment the original value by one. This is a good habit in general, because post-increment for user-defined types does make an extra, unnecessary copy.Don't repeat yourself. checkValidRows and checkValidCols is more or less the same function. If you make a bit of an abstraction, the same goes for the square checking.Consider using a one-dimensional array, and/or using one-dimensional or two-dimensional std::array or std::vector.There are indentation issues in the code you have posted.Your solving algorithm is possibly the slowest one I can think of. Do a quick google search and do something smarter.You have very long functions defined inline. It gives the impression that you only know Java, but happen to be writing in C++. Move the implementation code out of the class definition, and structure your code into files.Use a separate unit test library, for example googletest. Don't always run unit tests when the program runs.Drop the Press any key to exit part. It looks very unprofessional.Consider adding read-only access to your board tiles, so that your class can be used as a back-end for a GUI later.Don't pass parameters to main if you are not going to use them.Put a default in your switch to catch errors.Use assertions to ensure pre- and post-conditions and invariants of functions during debugging.Perform error handling, preferably using exceptions. Make your program very robust; you don't want CTD in a game.Have many small unit tests that test exactly a single thing. If a test fails, you should know from its name what has failed. Look at an example of unit tests online.Sort your #includes alphabetically.Consider making your solver multi-threaded.Remember to include the other important parts. Primarily: Documentation, and use a proper build system (make is enough for such a simple application). In the documentation, you can include a discussion of your solving algorithm, including analysis of its efficiency (asymptotic complexity/Big-O as a minimum.)