I have this program http://ostermiller.org/qqwing/qqwing.cpp.html
I need run the program by code with parameters to do somehtin on interface.
So how i load the data that i need to my program without change it.
Note: I want make a program based on it http://ostermiller.org/qqwing/qqwing.cpp.html.

Recommended Answers

All 2 Replies

1.You haven't explained enough for you to get enough answers, although for basic file operations, use the fstream.
2. Please post the code on this forum.... putting a link to another site might discourage other members from even reading your post.
3. Where's config.h?

I not make the original program.
The program that i gona make is a interface to use with this in a separeted bin.
Of any way this is the code that i need:

int main(int argc, char *argv[]){
    try {
        // Start time for the application for timing
        long applicationStartTime = getMicroseconds();

        // The number of puzzles solved or generated.
        int puzzleCount = 0;

        enum Action {NONE, GENERATE, SOLVE};

        // defaults for options
        bool printPuzzle = false;
        bool printSolution = false;
        bool printHistory = false;
        bool printInstructions = false;
        bool timer = false;
        bool countSolutions = false;
        Action action = NONE;
        bool logHistory = false;
        SudokuBoard::PrintStyle printStyle = SudokuBoard::READABLE;
        int numberToGenerate = 1;
        bool printStats = false;
        SudokuBoard::Difficulty difficulty = SudokuBoard::UNKNOWN;

        // Read the arguments and set the options
        {for (int i=1; i<argc; i++){
            if (!strcmp(argv[i],"--puzzle")){
                printPuzzle = true;
            } else if (!strcmp(argv[i],"--nopuzzle")){
                printPuzzle = false;
            } else if (!strcmp(argv[i],"--solution")){
                printSolution = true;
            } else if (!strcmp(argv[i],"--nosolution")){
                printSolution = false;
            } else if (!strcmp(argv[i],"--history")){
                printHistory = true;
            } else if (!strcmp(argv[i],"--nohistory")){
                printHistory = false;
            } else if (!strcmp(argv[i],"--instructions")){
                printInstructions = true;
            } else if (!strcmp(argv[i],"--noinstructions")){
                printInstructions = false;
            } else if (!strcmp(argv[i],"--stats")){
                printStats = true;
            } else if (!strcmp(argv[i],"--nostats")){
                printStats = false;
            #if HAVE_GETTIMEOFDAY == 1
                } else if (!strcmp(argv[i],"--timer")){
                    timer = true;
                } else if (!strcmp(argv[i],"--notimer")){
                    timer = false;
            #endif
            } else if (!strcmp(argv[i],"--count-solutions")){
                countSolutions = true;
            } else if (!strcmp(argv[i],"--nocount-solutions")){
                countSolutions = false;
            } else if (!strcmp(argv[i],"--generate")){
                action = GENERATE;
                printPuzzle = true;
                if (i+1 < argc && argv[i+1][0] >= '1' && argv[i+1][0] <= '9'){
                    numberToGenerate = atoi(argv[i+1]);
                    i++;
                }
            } else if (!strcmp(argv[i],"--difficulty")){
                if (argc < i+1){
                    cout << "Please specify a difficulty." << endl;
                    return 1;
                } else if (!strcmp(argv[i+1],"simple")){
                    difficulty = SudokuBoard::SIMPLE;
                } else if (!strcmp(argv[i+1],"easy")){
                    difficulty = SudokuBoard::EASY;
                } else if (!strcmp(argv[i+1],"intermediate")){
                    difficulty = SudokuBoard::INTERMEDIATE;
                } else if (!strcmp(argv[i+1],"expert")){
                    difficulty = SudokuBoard::EXPERT;
                } else {
                    cout << "Difficulty expected to be simple, easy, intermediate, or expert, not " << argv[i+1] << endl;
                    return 1;
                }
                i++;
            } else if (!strcmp(argv[i],"--solve")){
                action = SOLVE;
                printSolution = true;
            } else if (!strcmp(argv[i],"--log-history")){
                logHistory = true;
            } else if (!strcmp(argv[i],"--nolog-history")){
                logHistory = false;
            } else if (!strcmp(argv[i],"--one-line")){
                printStyle=SudokuBoard::ONE_LINE;
            } else if (!strcmp(argv[i],"--compact")){
                printStyle=SudokuBoard::COMPACT;
            } else if (!strcmp(argv[i],"--readable")){
                printStyle=SudokuBoard::READABLE;
            } else if (!strcmp(argv[i],"--csv")){
                printStyle=SudokuBoard::CSV;
            } else if (!strcmp(argv[i],"-n") || !strcmp(argv[i],"--number")){
                if (i+1 < argc){
                    numberToGenerate = atoi(argv[i+1]);
                    i++;
                } else {
                    cout << "Please specify a number." << endl;
                    return 1;
                }
            } else if (!strcmp(argv[i],"-h") || !strcmp(argv[i],"--help") || !strcmp(argv[i],"help") || !strcmp(argv[i],"?")){
                printHelp(argv[0]);
                return 0;
            } else if (!strcmp(argv[i],"--version")){
                printVersion();
                return 0;
            } else if (!strcmp(argv[i],"--about")){
                printAbout();
                return 0;
            } else {
                cout << "Unknown argument: '" << argv[i] << "'" << endl;
                printHelp(argv[0]);
                return 1;
            }
        }}

        if (action == NONE){
            cout << "Either --solve or --generate must be specified." << endl;
            printHelp(argv[0]);
            return 1;
        }

        // Initialize the random number generator
        int timeSeed = time(NULL);
        srand(timeSeed);

        // If printing out CSV, print a header
        if (printStyle == SudokuBoard::CSV){
            if (printPuzzle) cout << "Puzzle,";
            if (printSolution) cout << "Solution,";
            if (printHistory) cout << "Solve History,";
            if (printInstructions) cout << "Solve Instructions,";
            if (countSolutions) cout << "Solution Count,";
            if (timer) cout << "Time (milliseconds),";
            if (printStats) cout << "Givens,Singles,Hidden Singles,Naked Pairs,Hidden Pairs,Pointing Pairs/Triples,Box/Line Intersections,Guesses,Backtracks,Difficulty";
            cout << "" << endl;
        }

        // Create a new puzzle board
        // and set the options
        SudokuBoard* ss = new SudokuBoard();
        ss->setRecordHistory(printHistory || printInstructions || printStats || difficulty!=SudokuBoard::UNKNOWN);
        ss->setLogHistory(logHistory);
        ss->setPrintStyle(printStyle);

        // Solve puzzle or generate puzzles
        // until end of input for solving, or
        // until we have generated the specified number.
        bool done = false;
        int numberGenerated = 0;
        while (!done){
            // record the start time for the timer.
            long puzzleStartTime = getMicroseconds();

            // iff something has been printed for this particular puzzle
            bool printedSomething = false;

            // Record whether the puzzle was possible or not,
            // so that we don't try to solve impossible givens.
            bool havePuzzle = false;
            if (action == GENERATE){
                // Generate a puzzle
                havePuzzle = ss->generatePuzzle();
                if (!havePuzzle && printPuzzle){
                    cout << "Could not generate puzzle.";
                    if (printStyle==SudokuBoard::CSV){
                        cout << ",";
                    } else {
                        cout << endl;
                    }
                    printedSomething = true;
                }
            } else {
                // Read the next puzzle on STDIN
                int* puzzle = new int[BOARD_SIZE];
                if (readPuzzleFromStdIn(puzzle)){
                    havePuzzle = ss->setPuzzle(puzzle);
                    if (!havePuzzle){
                        if (printPuzzle){
                            ss->printPuzzle();
                            printedSomething = true;
                        }
                        if (printSolution) {
                            cout << "Puzzle is not possible.";
                            if (printStyle==SudokuBoard::CSV){
                                cout << ",";
                            } else {
                                cout << endl;
                            }
                            printedSomething = true;
                        }
                    }
                } else {
                    // Set loop to terminate when nothing is left on STDIN
                    havePuzzle = false;
                    done = true;
                }
                delete puzzle;
            }

           int solutions = 0;

            if (havePuzzle){

                // Count the solutions if requested.
                // (Must be done before solving, as it would
                // mess up the stats.)
                if (countSolutions){
                    solutions = ss->countSolutions();
                }

                // Solve the puzzle
                if (printSolution || printHistory || printStats || printInstructions || difficulty!=SudokuBoard::UNKNOWN){
                    ss->solve();
                }

                // Bail out if it didn't meet the difficulty standards for generation
                if (action == GENERATE){
                    if (difficulty!=SudokuBoard::UNKNOWN && difficulty!=ss->getDifficulty()){
                        havePuzzle = false;
                    } else {
                        numberGenerated++;
                        // Set loop to terminate if enough have been generated.
                        if (numberGenerated >= numberToGenerate) done = true;
                    }
                }
            }

            if (havePuzzle){

                // With a puzzle now in hand and possibly solved
                // print out the solution, stats, etc.
                printedSomething = true;

                // Record the end time for the timer.
                long puzzleDoneTime = getMicroseconds();

                // Print the puzzle itself.
                if (printPuzzle) ss->printPuzzle();

                // Print the solution if there is one
                if (printSolution){
                    if (ss->isSolved()){
                        ss->printSolution();
                    } else {
                        cout << "Puzzle has no solution.";
                        if (printStyle==SudokuBoard::CSV){
                            cout << ",";
                        } else {
                            cout << endl;
                        }
                    }
                }

                // Print the steps taken to solve or attempt to solve the puzzle.
                if (printHistory) ss->printSolveHistory();
                // Print the instructions for solving the puzzle
                if (printInstructions) ss->printSolveInstructions();

                // Print the number of solutions to the puzzle.
                if (countSolutions){
                    if (printStyle == SudokuBoard::CSV){
                        cout << solutions << ",";
                    } else {
                        if (solutions == 0){
                            cout << "There are no solutions to the puzzle." << endl;
                        } else if (solutions == 1){
                            cout << "The solution to the puzzle is unique." << endl;
                        } else {
                            cout << "There are " << solutions << " solutions to the puzzle." << endl;
                        }
                    }
                }

                // Print out the time it took to solve the puzzle.
                if (timer){
                    double t = ((double)(puzzleDoneTime - puzzleStartTime))/1000.0;
                    if (printStyle == SudokuBoard::CSV){
                        cout << t << ",";
                    } else {
                        cout << "Time: " << t  << " milliseconds" << endl;
                    }
                }

                // Print any stats we were able to gather while solving the puzzle.
                if (printStats){
                    int givenCount = ss->getGivenCount();
                    int singleCount = ss->getSingleCount();
                    int hiddenSingleCount = ss->getHiddenSingleCount();
                    int nakedPairCount = ss->getNakedPairCount();
                    int hiddenPairCount = ss->getHiddenPairCount();
                    int pointingPairTripleCount = ss->getPointingPairTripleCount();
                    int boxReductionCount = ss->getBoxLineReductionCount();
                    int guessCount = ss->getGuessCount();
                    int backtrackCount = ss->getBacktrackCount();
                    char* difficultyString = ss->getDifficultyAsString();
                    if (printStyle == SudokuBoard::CSV){
                        cout << givenCount << ","  << singleCount << "," << hiddenSingleCount
                                << "," << nakedPairCount << "," << hiddenPairCount
                                << ","  << pointingPairTripleCount  << ","  << boxReductionCount
                                << "," << guessCount << "," << backtrackCount
                                << "," << difficultyString << ",";
                    } else {
                        cout << "Number of Givens: " << givenCount  << endl;
                        cout << "Number of Singles: " << singleCount << endl;
                        cout << "Number of Hidden Singles: " << hiddenSingleCount  << endl;
                        cout << "Number of Naked Pairs: " << nakedPairCount  << endl;
                        cout << "Number of Hidden Pairs: " << hiddenPairCount  << endl;
                        cout << "Number of Pointing Pairs/Triples: " << pointingPairTripleCount  << endl;
                        cout << "Number of Box/Line Intersections: " << boxReductionCount  << endl;
                        cout << "Number of Guesses: " << guessCount  << endl;
                        cout << "Number of Backtracks: " << backtrackCount  << endl;
                        cout << "Difficulty: " << difficultyString  << endl;
                    }
                }
                puzzleCount++;
            }
            if (printedSomething && printStyle == SudokuBoard::CSV){
                cout << endl;
            }
        }

        delete ss;

        long applicationDoneTime = getMicroseconds();
        // Print out the time it took to do everything
        if (timer){
            double t = ((double)(applicationDoneTime - applicationStartTime))/1000000.0;
            cout << puzzleCount << " puzzle" << ((puzzleCount==1)?"":"s") << " " << (action==GENERATE?"generated":"solved") << " in " << t << " seconds." << endl;
        }


    } catch (char const* s){
        cout << s <<  endl;
        return 1;
    }

    return 0;
}

void printVersion(){
    cout << PACKAGE_STRING << endl;
}

void printAbout(){
    cout << PACKAGE_NAME << " - Sudoku solver and generator." << endl;
    cout << "Written by Stephen Ostermiller copyright 2006." << endl;
    cout << "http://ostermiller.org/qqwing/" << endl;
    cout << "" << endl;
    cout << "This program is free software; you can redistribute it and/or modify" << endl;
    cout << "it under the terms of the GNU General Public License as published by" << endl;
    cout << "the Free Software Foundation; either version 2 of the License, or" << endl;
    cout << "(at your option) any later version." << endl;
    cout << "" << endl;
    cout << "This program is distributed in the hope that it will be useful," << endl;
    cout << "but WITHOUT ANY WARRANTY; without even the implied warranty of" << endl;
    cout << "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the" << endl;
    cout << "GNU General Public License for more details." << endl;
    cout << "" << endl;
    cout << "You should have received a copy of the GNU General Public License" << endl;
    cout << "along with this program; if not, write to the Free Software" << endl;
    cout << "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA" << endl;
}

void printHelp(char* programName){
    cout << programName << " <options>" << endl;
    cout << "Sudoku solver and generator." << endl;
    cout << "  --generate <num>     Generate new puzzles" << endl;
    cout << "  --solve              Solve all the puzzles from standard input" << endl;
    cout << "  --difficulty <diff>  Generate only simple,easy, intermediate, or expert" << endl;
    cout << "  --puzzle             Print the puzzle (default when generating)" << endl;
    cout << "  --nopuzzle           Do not print the puzzle (default when solving)" << endl;
    cout << "  --solution           Print the solution (default when solving)" << endl;
    cout << "  --nosolution         Do not print the solution (default when generating)" << endl;
    cout << "  --stats              Print statistics about moves used to solve the puzzle" << endl;
    cout << "  --nostats            Do not print statistics (default)" << endl;
    #if HAVE_GETTIMEOFDAY == 1
        cout << "  --timer              Print time to generate or solve each puzzle" << endl;
        cout << "  --notimer            Do not print solve or generation times (default)" << endl;
    #endif
    cout << "  --count-solutions    Count the number of solutions to puzzles" << endl;
    cout << "  --nocount-solutions  Do not count the number of solutions (default)" << endl;
    cout << "  --history            Print trial and error used when solving" << endl;
    cout << "  --nohistory          Do not print trial and error to solve (default)" << endl;
    cout << "  --instructions       Print the steps (at least 81) needed to solve the puzzle" << endl;
    cout << "  --noinstructions     Do not print steps to solve (default)" << endl;
    cout << "  --log-history        Print trial and error to solve as it happens" << endl;
    cout << "  --nolog-history      Do not print trial and error  to solve as it happens" << endl;
    cout << "  --one-line           Print puzzles on one line of 81 characters" << endl;
    cout << "  --compact            Print puzzles on 9 lines of 9 characters" << endl;
    cout << "  --readable           Print puzzles in human readable form (default)" << endl;
    cout << "  --csv                Ouput CSV format with one line puzzles" << endl;
    cout << "  --help               Print this message" << endl;
    cout << "  --about              Author and license information" << endl;
    cout << "  --version            Display current version number" << endl;
}

/**
 * Create a new Sudoku board
 */
SudokuBoard::SudokuBoard(){
    puzzle = new int[BOARD_SIZE];
    solution = new int[BOARD_SIZE];
    solutionRound = new int[BOARD_SIZE];
    possibilities = new int[POSSIBILITY_SIZE];
    recordHistory = false;
    printStyle = READABLE;
    randomBoardArray = new int[BOARD_SIZE];
    randomPossibilityArray = new int[NUM_POSS];
    solveHistory = new vector<LogItem*>();
    solveInstructions = new vector<LogItem*>();
    {for (int i=0; i<BOARD_SIZE; i++){
        randomBoardArray[i] = i;
    }}
    {for (int i=0; i<NUM_POSS; i++){
        randomPossibilityArray[i] = i;
    }}
}

/**
 * Get the number of cells that are
 * set in the puzzle (as opposed to
 * figured out in the solution
 */
int SudokuBoard::getGivenCount(){
    int count = 0;
    {for (int i=0; i<BOARD_SIZE; i++){
        if (puzzle[i] != 0) count++;
    }}
    return count;
}

/**
 * Set the board to the given puzzle.
 * The given puzzle must be an array of 81 integers.
 */
bool SudokuBoard::setPuzzle(int* initPuzzle){
    {for (int i=0; i<BOARD_SIZE; i++){
        puzzle[i] = (initPuzzle==NULL)?0:initPuzzle[i];
    }}
    return reset();
}

/**
 * Reset the board to its initial state with
 * only the givens.
 * This method clears any solution, resets statistics,
 * and clears any history messages.
 */
bool SudokuBoard::reset(){
    {for (int i=0; i<BOARD_SIZE; i++){
        solution[i] = 0;
    }}
    {for (int i=0; i<BOARD_SIZE; i++){
        solutionRound[i] = 0;
    }}
    {for (int i=0; i<POSSIBILITY_SIZE; i++){
        possibilities[i] = 0;
    }}

    {for (int i=0;i<solveHistory->size();i++){
        delete solveHistory->at(i);
    }}
    solveHistory->clear();
    solveInstructions->clear();

    int round = 1;
    for (int position=0; position<BOARD_SIZE; position++){
        if (puzzle[position] > 0){
            int valIndex = puzzle[position]-1;
            int valPos = getPossibilityIndex(valIndex,position);
            int value = puzzle[position];
            if (possibilities[valPos] != 0) return false;
            mark(position,round,value);
            if (logHistory || recordHistory) addHistoryItem(new LogItem(round, LogItem::GIVEN, value, position));
        }
    }

    return true;
}

/**
 * Get the difficulty rating.
 */
SudokuBoard::Difficulty SudokuBoard::getDifficulty(){
    if (getGuessCount() > 0) return SudokuBoard::EXPERT;
    if (getBoxLineReductionCount() > 0) return SudokuBoard::INTERMEDIATE;
    if (getPointingPairTripleCount() > 0) return SudokuBoard::INTERMEDIATE;
    if (getHiddenPairCount() > 0) return SudokuBoard::INTERMEDIATE;
    if (getNakedPairCount() > 0) return SudokuBoard::INTERMEDIATE;
    if (getHiddenSingleCount() > 0) return SudokuBoard::EASY;
    if (getSingleCount() > 0) return SudokuBoard::SIMPLE;
    return SudokuBoard::UNKNOWN;
}

/**
 * Get the difficulty rating.
 */
char* SudokuBoard::getDifficultyAsString(){
    SudokuBoard::Difficulty difficulty = getDifficulty();
    switch (difficulty){
        case SudokuBoard::EXPERT: return "Expert"; break;
        case SudokuBoard::INTERMEDIATE: return "Intermediate"; break;
        case SudokuBoard::EASY: return "Easy"; break;
        case SudokuBoard::SIMPLE: return "Simple"; break;
        default: return "Unknown"; break;
    }
}

/**
 * Get the number of cells for which the solution was determined
 * because there was only one possible value for that cell.
 */
int SudokuBoard::getSingleCount(){
    return getLogCount(solveInstructions, LogItem::SINGLE);
}

/**
 * Get the number of cells for which the solution was determined
 * because that cell had the only possibility for some value in
 * the row, column, or section.
 */
int SudokuBoard::getHiddenSingleCount(){
    return getLogCount(solveInstructions, LogItem::HIDDEN_SINGLE_ROW) +
            getLogCount(solveInstructions, LogItem::HIDDEN_SINGLE_COLUMN) +
            getLogCount(solveInstructions, LogItem::HIDDEN_SINGLE_SECTION);
}

/**
 * Get the number of naked pair reductions that were performed
 * in solving this puzzle.
 */
int SudokuBoard::getNakedPairCount(){
    return getLogCount(solveInstructions, LogItem::NAKED_PAIR_ROW) +
            getLogCount(solveInstructions, LogItem::NAKED_PAIR_COLUMN) +
            getLogCount(solveInstructions, LogItem::NAKED_PAIR_SECTION);
}

/**
 * Get the number of hidden pair reductions that were performed
 * in solving this puzzle.
 */
int SudokuBoard::getHiddenPairCount(){
    return getLogCount(solveInstructions, LogItem::HIDDEN_PAIR_ROW) +
            getLogCount(solveInstructions, LogItem::HIDDEN_PAIR_COLUMN) +
            getLogCount(solveInstructions, LogItem::HIDDEN_PAIR_SECTION);
}

/**
 * Get the number of pointing pair/triple reductions that were performed
 * in solving this puzzle.
 */
int SudokuBoard::getPointingPairTripleCount(){
    return getLogCount(solveInstructions, LogItem::POINTING_PAIR_TRIPLE_ROW)+
        getLogCount(solveInstructions, LogItem::POINTING_PAIR_TRIPLE_COLUMN);
}

/**
 * Get the number of box/line reductions that were performed
 * in solving this puzzle.
 */
int SudokuBoard::getBoxLineReductionCount(){
    return getLogCount(solveInstructions, LogItem::ROW_BOX)+
        getLogCount(solveInstructions, LogItem::COLUMN_BOX);
}

/**
 * Get the number lucky guesses in solving this puzzle.
 */
int SudokuBoard::getGuessCount(){
    return getLogCount(solveInstructions, LogItem::GUESS);
}

/**
 * Get the number of backtracks (unlucky guesses) required
 * when solving this puzzle.
 */
int SudokuBoard::getBacktrackCount(){
    return getLogCount(solveHistory, LogItem::ROLLBACK);
}

void SudokuBoard::markRandomPossibility(int round){
    int remainingPossibilities = 0;
    {for (int i=0; i<POSSIBILITY_SIZE; i++){
        if (possibilities[i] == 0) remainingPossibilities++;
    }}

    int randomPossibility = rand()%remainingPossibilities;

    int possibilityToMark = 0;
    {for (int i=0; i<POSSIBILITY_SIZE; i++){
        if (possibilities[i] == 0){
            if (possibilityToMark == randomPossibility){
                int position = i/NUM_POSS;
                int value = i%NUM_POSS+1;
                mark(position, round, value);
                return;
            }
            possibilityToMark++;
        }
    }}
}

void SudokuBoard::shuffleRandomArrays(){
    shuffleArray(randomBoardArray, BOARD_SIZE);
    shuffleArray(randomPossibilityArray, NUM_POSS);
}

void SudokuBoard::clearPuzzle(){
    // Clear any existing puzzle
    {for (int i=0; i<BOARD_SIZE; i++){
        puzzle[i] = 0;
    }}
    reset();
}

bool SudokuBoard::generatePuzzle(){

    // Don't record history while generating.
    bool recHistory = recordHistory;
    setRecordHistory(false);
    bool lHistory = logHistory;
    setLogHistory(false);

    clearPuzzle();

    // Start by getting the randomness in order so that
    // each puzzle will be different from the last.
    shuffleRandomArrays();

    // Now solve the puzzle the whole way.  The solve
    // uses random algorithms, so we should have a
    // really randomly totally filled sudoku
    // Even when starting from an empty grid
    solve();

    // Rollback any square for which it is obvious that
    // the square doesn't contribute to a unique solution
    // (ie, squares that were filled by logic rather
    // than by guess)
    rollbackNonGuesses();

    // Record all marked squares as the puzzle so
    // that we can call countSolutions without losing it.
    {for (int i=0; i<BOARD_SIZE; i++){
        puzzle[i] = solution[i];
    }}

    // Rerandomize everything so that we test squares
    // in a different order than they were added.
    shuffleRandomArrays();

    // Remove one value at a time and see if
    // the puzzle still has only one solution.
    // If it does, leave it0 out the point because
    // it is not needed.
    {for (int i=0; i<BOARD_SIZE; i++){
        // check all the positions, but in shuffled order
        int position = randomBoardArray[i];
        if (puzzle[position] > 0){
            // try backing out the value and
            // counting solutions to the puzzle
            int savedValue = puzzle[position];
            puzzle[position] = 0;
            reset();
            if (countSolutions(2, true) > 1){
                // Put it back in, it is needed
                puzzle[position] = savedValue;
            }
        }
    }}

    // Clear all solution info, leaving just the puzzle.
    reset();

    // Restore recording history.
    setRecordHistory(recHistory);
    setLogHistory(lHistory);

    return true;

}

void SudokuBoard::rollbackNonGuesses(){
    // Guesses are odd rounds
    // Non-guesses are even rounds
    {for (int i=2; i<=lastSolveRound; i+=2){
        rollbackRound(i);
    }}
}

void SudokuBoard::setPrintStyle(PrintStyle ps){
    printStyle = ps;
}

void SudokuBoard::setRecordHistory(bool recHistory){
    recordHistory = recHistory;
}

void SudokuBoard::setLogHistory(bool logHist){
    logHistory = logHist;
}

void SudokuBoard::addHistoryItem(LogItem* l){
    if (logHistory){
        l->print();
        cout << endl;
    }
    if (recordHistory){
        solveHistory->push_back(l);
        solveInstructions->push_back(l);
    } else {
        delete l;
    }
}

void SudokuBoard::printHistory(vector<LogItem*>* v){
    if (!recordHistory){
        cout << "History was not recorded.";
        if (printStyle == CSV){
            cout << " -- ";
        } else {
            cout << endl;
        }
    }
    {for (int i=0;i<v->size();i++){
        cout << i+1 << ". ";
        v->at(i)->print();
        if (printStyle == CSV){
            cout << " -- ";
        } else {
            cout << endl;
        }
    }}
    if (printStyle == CSV){
        cout << ",";
    } else {
        cout << endl;
    }
}

void SudokuBoard::printSolveInstructions(){
    if (isSolved()){
        printHistory(solveInstructions);
    } else {
        cout << "No solve instructions - Puzzle is not possible to solve." << endl;
    }
}

void SudokuBoard::printSolveHistory(){
    printHistory(solveHistory);
}

bool SudokuBoard::solve(){
    reset();
    shuffleRandomArrays();
    return solve(2);
}

bool SudokuBoard::solve(int round){
    lastSolveRound = round;

    while (singleSolveMove(round)){
        if (isSolved()) return true;
        if (isImpossible()) return false;
    }

    int nextGuessRound = round+1;
    int nextRound = round+2;
    for (int guessNumber=0; guess(nextGuessRound, guessNumber); guessNumber++){
        if (isImpossible() || !solve(nextRound)){
            rollbackRound(nextRound);
            rollbackRound(nextGuessRound);
        } else {
            return true;
        }
    }
    return false;
}

int SudokuBoard::countSolutions(){
    // Don't record history while generating.
    bool recHistory = recordHistory;
    setRecordHistory(false);
    bool lHistory = logHistory;
    setLogHistory(false);

    reset();
    int solutionCount = countSolutions(2, false);

    // Restore recording history.
    setRecordHistory(recHistory);
    setLogHistory(lHistory);

    return solutionCount;
}

int SudokuBoard::countSolutions(int round, bool limitToTwo){
    while (singleSolveMove(round)){
        if (isSolved()){
            rollbackRound(round);
            return 1;
        }
        if (isImpossible()){
            rollbackRound(round);
            return 0;
        }
    }

    int solutions = 0;
    int nextRound = round+1;
    for (int guessNumber=0; guess(nextRound, guessNumber); guessNumber++){
        solutions += countSolutions(nextRound, limitToTwo);
        if (limitToTwo && solutions >=2){
            rollbackRound(round);
            return solutions;
        }
    }
    rollbackRound(round);
    return solutions;
}

void SudokuBoard::rollbackRound(int round){
    if (logHistory || recordHistory) addHistoryItem(new LogItem(round, LogItem::ROLLBACK));
    {for (int i=0; i<BOARD_SIZE; i++){
        if (solutionRound[i] == round){
            solutionRound[i] = 0;
            solution[i] = 0;
        }
    }}
    {for (int i=0; i<POSSIBILITY_SIZE; i++){
        if (possibilities[i] == round){
            possibilities[i] = 0;
        }
    }}

    while(solveInstructions->size() > 0 && solveInstructions->back()->getRound() == round){
         solveInstructions->pop_back();
    }
}

bool SudokuBoard::isSolved(){
    {for (int i=0; i<BOARD_SIZE; i++){
        if (solution[i] == 0){
            return false;
        }
    }}
    return true;
}

bool SudokuBoard::isImpossible(){
    for (int position=0; position<BOARD_SIZE; position++){
        if (solution[position] == 0){
            int count = 0;
            for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
                int valPos = getPossibilityIndex(valIndex,position);
                if (possibilities[valPos] == 0) count++;
            }
            if (count == 0) {
                return true;
            }
        }
    }
    return false;
}

int SudokuBoard::findPositionWithFewestPossibilities(){
    int minPossibilities = 10;
    int bestPosition = 0;
    {for (int i=0; i<BOARD_SIZE; i++){
        int position = randomBoardArray[i];
        if (solution[position] == 0){
            int count = 0;
            for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
                int valPos = getPossibilityIndex(valIndex,position);
                if (possibilities[valPos] == 0) count++;
            }
            if (count < minPossibilities){
                minPossibilities = count;
                bestPosition = position;
            }
        }
    }}
    return bestPosition;
}

bool SudokuBoard::guess(int round, int guessNumber){
    int localGuessCount = 0;
    int position = findPositionWithFewestPossibilities();
    {for (int i=0; i<NUM_POSS; i++){
        int valIndex = randomPossibilityArray[i];
        int valPos = getPossibilityIndex(valIndex,position);
        if (possibilities[valPos] == 0){
            if (localGuessCount == guessNumber){
                int value = valIndex+1;
                if (logHistory || recordHistory) addHistoryItem(new LogItem(round, LogItem::GUESS, value, position));
                mark(position, round, value);
                return true;
            }
            localGuessCount++;
        }
    }}
    return false;
}

bool SudokuBoard::singleSolveMove(int round){
    if (onlyPossibilityForCell(round)) return true;
    if (onlyValueInSection(round)) return true;
    if (onlyValueInRow(round)) return true;
    if (onlyValueInColumn(round)) return true;
    if (handleNakedPairs(round)) return true;
    if (pointingRowReduction(round)) return true;
    if (pointingColumnReduction(round)) return true;
    if (rowBoxReduction(round)) return true;
    if (colBoxReduction(round)) return true;
    if (hiddenPairInRow(round)) return true;
    if (hiddenPairInColumn(round)) return true;
    if (hiddenPairInSection(round)) return true;
    return false;
}

bool SudokuBoard::colBoxReduction(int round){
    for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
        for (int col=0; col<9; col++){
            int colStart = columnToFirstCell(col);
            bool inOneBox = true;
            int colBox = -1;
            {for (int i=0; i<3; i++){
                for (int j=0; j<3; j++){
                    int row = i*3+j;
                    int position = rowColumnToCell(row, col);
                    int valPos = getPossibilityIndex(valIndex,position);
                    if(possibilities[valPos] == 0){
                        if (colBox == -1 || colBox == i){
                            colBox = i;
                        } else {
                            inOneBox = false;
                        }
                    }

                }
            }}
            if (inOneBox && colBox != -1){
                bool doneSomething = false;
                int row = 3*colBox;
                int secStart = cellToSectionStartCell(rowColumnToCell(row, col));
                int secStartRow = cellToRow(secStart);
                int secStartCol = cellToColumn(secStart);
                {for (int i=0; i<3; i++){
                    for (int j=0; j<3; j++){
                        int row2 = secStartRow+i;
                        int col2 = secStartCol+j;
                        int position = rowColumnToCell(row2, col2);
                        int valPos = getPossibilityIndex(valIndex,position);
                        if (col != col2 && possibilities[valPos] == 0){
                            possibilities[valPos] = round;
                            doneSomething = true;
                        }
                    }
                }}
                if (doneSomething){
                    if (logHistory || recordHistory) addHistoryItem(new LogItem(round, LogItem::COLUMN_BOX, valIndex+1, colStart));
                    return true;
                }
            }
        }
    }
    return false;
}

bool SudokuBoard::rowBoxReduction(int round){
    for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
        for (int row=0; row<9; row++){
            int rowStart = rowToFirstCell(row);
            bool inOneBox = true;
            int rowBox = -1;
            {for (int i=0; i<3; i++){
                for (int j=0; j<3; j++){
                    int column = i*3+j;
                    int position = rowColumnToCell(row, column);
                    int valPos = getPossibilityIndex(valIndex,position);
                    if(possibilities[valPos] == 0){
                        if (rowBox == -1 || rowBox == i){
                            rowBox = i;
                        } else {
                            inOneBox = false;
                        }
                    }

                }
            }}
            if (inOneBox && rowBox != -1){
                bool doneSomething = false;
                int column = 3*rowBox;
                int secStart = cellToSectionStartCell(rowColumnToCell(row, column));
                int secStartRow = cellToRow(secStart);
                int secStartCol = cellToColumn(secStart);
                {for (int i=0; i<3; i++){
                    for (int j=0; j<3; j++){
                        int row2 = secStartRow+i;
                        int col2 = secStartCol+j;
                        int position = rowColumnToCell(row2, col2);
                        int valPos = getPossibilityIndex(valIndex,position);
                        if (row != row2 && possibilities[valPos] == 0){
                            possibilities[valPos] = round;
                            doneSomething = true;
                        }
                    }
                }}
                if (doneSomething){
                    if (logHistory || recordHistory) addHistoryItem(new LogItem(round, LogItem::ROW_BOX, valIndex+1, rowStart));
                    return true;
                }
            }
        }
    }
    return false;
}

bool SudokuBoard::pointingRowReduction(int round){
    for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
        for (int section=0; section<9; section++){
            int secStart = sectionToFirstCell(section);
            bool inOneRow = true;
            int boxRow = -1;
            for (int j=0; j<3; j++){
                {for (int i=0; i<3; i++){
                    int secVal=secStart+i+(9*j);
                    int valPos = getPossibilityIndex(valIndex,secVal);
                    if(possibilities[valPos] == 0){
                        if (boxRow == -1 || boxRow == j){
                            boxRow = j;
                        } else {
                            inOneRow = false;
                        }
                    }
                }}
            }
            if (inOneRow && boxRow != -1){
                bool doneSomething = false;
                int row = cellToRow(secStart) + boxRow;
                int rowStart = rowToFirstCell(row);

                {for (int i=0; i<9; i++){
                    int position = rowStart+i;
                    int section2 = cellToSection(position);
                    int valPos = getPossibilityIndex(valIndex,position);
                    if (section != section2 && possibilities[valPos] == 0){
                        possibilities[valPos] = round;
                        doneSomething = true;
                    }
                }}
                if (doneSomething){
                    if (logHistory || recordHistory) addHistoryItem(new LogItem(round, LogItem::POINTING_PAIR_TRIPLE_ROW, valIndex+1, rowStart));
                    return true;
                }
            }
        }
    }
    return false;
}

bool SudokuBoard::pointingColumnReduction(int round){
    for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
        for (int section=0; section<9; section++){
            int secStart = sectionToFirstCell(section);
            bool inOneCol = true;
            int boxCol = -1;
            {for (int i=0; i<3; i++){
                for (int j=0; j<3; j++){
                    int secVal=secStart+i+(9*j);
                    int valPos = getPossibilityIndex(valIndex,secVal);
                    if(possibilities[valPos] == 0){
                        if (boxCol == -1 || boxCol == i){
                            boxCol = i;
                        } else {
                            inOneCol = false;
                        }
                    }
                }
            }}
            if (inOneCol && boxCol != -1){
                bool doneSomething = false;
                int col = cellToColumn(secStart) + boxCol;
                int colStart = columnToFirstCell(col);

                {for (int i=0; i<9; i++){
                    int position = colStart+(9*i);
                    int section2 = cellToSection(position);
                    int valPos = getPossibilityIndex(valIndex,position);
                    if (section != section2 && possibilities[valPos] == 0){
                        possibilities[valPos] = round;
                        doneSomething = true;
                    }
                }}
                if (doneSomething){
                    if (logHistory || recordHistory) addHistoryItem(new LogItem(round, LogItem::POINTING_PAIR_TRIPLE_COLUMN, valIndex+1, colStart));
                    return true;
                }
            }
        }
    }
    return false;
}

int SudokuBoard::countPossibilities(int position){
    int count = 0;
    for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
        int valPos = getPossibilityIndex(valIndex,position);
        if (possibilities[valPos] == 0) count++;
    }
    return count;
}

bool SudokuBoard::arePossibilitiesSame(int position1, int position2){
    for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
        int valPos1 = getPossibilityIndex(valIndex,position1);
        int valPos2 = getPossibilityIndex(valIndex,position2);
        if ((possibilities[valPos1] == 0 || possibilities[valPos2] == 0) && (possibilities[valPos1] != 0 || possibilities[valPos2] != 0)){
            return false;
        }
    }
    return true;
}

bool SudokuBoard::removePossibilitiesInOneFromTwo(int position1, int position2, int round){
    bool doneSomething = false;
    for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
        int valPos1 = getPossibilityIndex(valIndex,position1);
        int valPos2 = getPossibilityIndex(valIndex,position2);
        if (possibilities[valPos1] == 0 && possibilities[valPos2] == 0){
            possibilities[valPos2] = round;
            doneSomething = true;
        }
    }
    return doneSomething;
}

bool SudokuBoard::hiddenPairInColumn(int round){
    for (int column=0; column<9; column++){
        for (int valIndex=0; valIndex<9; valIndex++){
            int r1 = -1;
            int r2 = -1;
            int valCount = 0;
            for (int row=0; row<9; row++){
                int position = rowColumnToCell(row,column);
                int valPos = getPossibilityIndex(valIndex,position);
                if (possibilities[valPos] == 0){
                    if (r1 == -1 || r1 == row){
                        r1 = row;
                    } else if (r2 == -1 || r2 == row){
                        r2 = row;
                    }
                    valCount++;
                }
            }
            if (valCount==2){
                for (int valIndex2=valIndex+1; valIndex2<9; valIndex2++){
                    int r3 = -1;
                    int r4 = -1;
                    int valCount2 = 0;
                    for (int row=0; row<9; row++){
                        int position = rowColumnToCell(row,column);
                        int valPos = getPossibilityIndex(valIndex2,position);
                        if (possibilities[valPos] == 0){
                            if (r3 == -1 || r3 == row){
                                r3 = row;
                            } else if (r4 == -1 || r4 == row){
                                r4 = row;
                            }
                            valCount2++;
                        }
                    }
                    if (valCount2==2 && r1==r3 && r2==r4){
                        bool doneSomething = false;
                        for (int valIndex3=0; valIndex3<9; valIndex3++){
                            if (valIndex3 != valIndex && valIndex3 != valIndex2){
                                int position1 = rowColumnToCell(r1,column);
                                int position2 = rowColumnToCell(r2,column);
                                int valPos1 = getPossibilityIndex(valIndex3,position1);
                                int valPos2 = getPossibilityIndex(valIndex3,position2);
                                if (possibilities[valPos1] == 0){
                                    possibilities[valPos1] = round;
                                    doneSomething = true;
                                }
                                if (possibilities[valPos2] == 0){
                                    possibilities[valPos2] = round;
                                    doneSomething = true;
                                }
                            }
                        }
                        if (doneSomething){
                            if (logHistory || recordHistory) addHistoryItem(new LogItem(round, LogItem::HIDDEN_PAIR_COLUMN, valIndex+1, rowColumnToCell(r1,column)));
                            return true;
                        }
                    }
                }
            }
        }
    }
    return false;
}

bool SudokuBoard::hiddenPairInSection(int round){
    for (int section=0; section<9; section++){
        for (int valIndex=0; valIndex<9; valIndex++){
            int si1 = -1;
            int si2 = -1;
            int valCount = 0;
            for (int secInd=0; secInd<9; secInd++){
                int position = sectionToCell(section,secInd);
                int valPos = getPossibilityIndex(valIndex,position);
                if (possibilities[valPos] == 0){
                    if (si1 == -1 || si1 == secInd){
                        si1 = secInd;
                    } else if (si2 == -1 || si2 == secInd){
                        si2 = secInd;
                    }
                    valCount++;
                }
            }
            if (valCount==2){
                for (int valIndex2=valIndex+1; valIndex2<9; valIndex2++){
                    int si3 = -1;
                    int si4 = -1;
                    int valCount2 = 0;
                    for (int secInd=0; secInd<9; secInd++){
                        int position = sectionToCell(section,secInd);
                        int valPos = getPossibilityIndex(valIndex2,position);
                        if (possibilities[valPos] == 0){
                            if (si3 == -1 || si3 == secInd){
                                si3 = secInd;
                            } else if (si4 == -1 || si4 == secInd){
                                si4 = secInd;
                            }
                            valCount2++;
                        }
                    }
                    if (valCount2==2 && si1==si3 && si2==si4){
                        bool doneSomething = false;
                        for (int valIndex3=0; valIndex3<9; valIndex3++){
                            if (valIndex3 != valIndex && valIndex3 != valIndex2){
                                int position1 = sectionToCell(section,si1);
                                int position2 = sectionToCell(section,si2);
                                int valPos1 = getPossibilityIndex(valIndex3,position1);
                                int valPos2 = getPossibilityIndex(valIndex3,position2);
                                if (possibilities[valPos1] == 0){
                                    possibilities[valPos1] = round;
                                    doneSomething = true;
                                }
                                if (possibilities[valPos2] == 0){
                                    possibilities[valPos2] = round;
                                    doneSomething = true;
                                }
                            }
                        }
                        if (doneSomething){
                            if (logHistory || recordHistory) addHistoryItem(new LogItem(round, LogItem::HIDDEN_PAIR_SECTION, valIndex+1, sectionToCell(section,si1)));
                            return true;
                        }
                    }
                }
            }
        }
    }
    return false;
}

bool SudokuBoard::hiddenPairInRow(int round){
    for (int row=0; row<9; row++){
        for (int valIndex=0; valIndex<9; valIndex++){
            int c1 = -1;
            int c2 = -1;
            int valCount = 0;
            for (int column=0; column<9; column++){
                int position = rowColumnToCell(row,column);
                int valPos = getPossibilityIndex(valIndex,position);
                if (possibilities[valPos] == 0){
                    if (c1 == -1 || c1 == column){
                        c1 = column;
                    } else if (c2 == -1 || c2 == column){
                        c2 = column;
                    }
                    valCount++;
                }
            }
            if (valCount==2){
                for (int valIndex2=valIndex+1; valIndex2<9; valIndex2++){
                    int c3 = -1;
                    int c4 = -1;
                    int valCount2 = 0;
                    for (int column=0; column<9; column++){
                        int position = rowColumnToCell(row,column);
                        int valPos = getPossibilityIndex(valIndex2,position);
                        if (possibilities[valPos] == 0){
                            if (c3 == -1 || c3 == column){
                                c3 = column;
                            } else if (c4 == -1 || c4 == column){
                                c4 = column;
                            }
                            valCount2++;
                        }
                    }
                    if (valCount2==2 && c1==c3 && c2==c4){
                        bool doneSomething = false;
                        for (int valIndex3=0; valIndex3<9; valIndex3++){
                            if (valIndex3 != valIndex && valIndex3 != valIndex2){
                                int position1 = rowColumnToCell(row,c1);
                                int position2 = rowColumnToCell(row,c2);
                                int valPos1 = getPossibilityIndex(valIndex3,position1);
                                int valPos2 = getPossibilityIndex(valIndex3,position2);
                                if (possibilities[valPos1] == 0){
                                    possibilities[valPos1] = round;
                                    doneSomething = true;
                                }
                                if (possibilities[valPos2] == 0){
                                    possibilities[valPos2] = round;
                                    doneSomething = true;
                                }
                            }
                        }
                        if (doneSomething){
                            if (logHistory || recordHistory) addHistoryItem(new LogItem(round, LogItem::HIDDEN_PAIR_ROW, valIndex+1, rowColumnToCell(row,c1)));
                            return true;
                        }
                    }
                }
            }
        }
    }
    return false;
}

bool SudokuBoard::handleNakedPairs(int round){
    for (int position=0; position<BOARD_SIZE; position++){
        int possibilities = countPossibilities(position);
        if (possibilities == 2){
            int row = cellToRow(position);
            int column = cellToColumn(position);
            int section = cellToSectionStartCell(position);
            for (int position2=position; position2<BOARD_SIZE; position2++){
                if (position != position2){
                    int possibilities2 = countPossibilities(position2);
                    if (possibilities2 == 2 && arePossibilitiesSame(position, position2)){
                        if (row == cellToRow(position2)){
                            bool doneSomething = false;
                            for (int column2=0; column2<9; column2++){
                                int position3 = rowColumnToCell(row,column2);
                                if (position3 != position && position3 != position2 && removePossibilitiesInOneFromTwo(position, position3, round)){
                                    doneSomething = true;
                                }
                            }
                            if (doneSomething){
                                if (logHistory || recordHistory) addHistoryItem(new LogItem(round, LogItem::NAKED_PAIR_ROW, 0, position));
                                return true;
                            }
                        }
                        if (column == cellToColumn(position2)){
                            bool doneSomething = false;
                            for (int row2=0; row2<9; row2++){
                                int position3 = rowColumnToCell(row2,column);
                                if (position3 != position && position3 != position2 && removePossibilitiesInOneFromTwo(position, position3, round)){
                                    doneSomething = true;
                                }
                            }
                            if (doneSomething){
                                if (logHistory || recordHistory) addHistoryItem(new LogItem(round, LogItem::NAKED_PAIR_COLUMN, 0, position));
                                return true;
                            }
                        }
                        if (section == cellToSectionStartCell(position2)){
                            bool doneSomething = false;
                            int secStart = cellToSectionStartCell(position);
                            {for (int i=0; i<3; i++){
                                for (int j=0; j<3; j++){
                                    int position3=secStart+i+(9*j);
                                    if (position3 != position && position3 != position2 && removePossibilitiesInOneFromTwo(position, position3, round)){
                                        doneSomething = true;
                                    }
                                }
                            }}
                            if (doneSomething){
                                if (logHistory || recordHistory) addHistoryItem(new LogItem(round, LogItem::NAKED_PAIR_SECTION, 0, position));
                                return true;
                            }
                        }
                    }
                }
            }
        }
    }
    return false;
}

/**
 * Mark exactly one cell which is the only possible value for some row, if
 * such a cell exists.
 * This method will look in a row for a possibility that is only listed
 * for one cell.  This type of cell is often called a "hidden single"
 */
bool SudokuBoard::onlyValueInRow(int round){
    for (int row=0; row<ROW_LENGTH; row++){
        for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
            int count = 0;
            int lastPosition = 0;
            for (int col=0; col<COL_HEIGHT; col++){
                int position = (row*ROW_LENGTH)+col;
                int valPos = getPossibilityIndex(valIndex,position);
                if (possibilities[valPos] == 0){
                    count++;
                    lastPosition = position;
                }
            }
            if (count == 1){
                int value = valIndex+1;
                if (logHistory || recordHistory) addHistoryItem(new LogItem(round, LogItem::HIDDEN_SINGLE_ROW, value, lastPosition));
                mark(lastPosition, round, value);
                return true;
            }
        }
    }
    return false;
}

/**
 * Mark exactly one cell which is the only possible value for some column, if
 * such a cell exists.
 * This method will look in a column for a possibility that is only listed
 * for one cell.  This type of cell is often called a "hidden single"
 */
bool SudokuBoard::onlyValueInColumn(int round){
    for (int col=0; col<COL_HEIGHT; col++){
        for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
            int count = 0;
            int lastPosition = 0;
            for (int row=0; row<ROW_LENGTH; row++){
                int position = rowColumnToCell(row,col);
                int valPos = getPossibilityIndex(valIndex,position);
                if (possibilities[valPos] == 0){
                    count++;
                    lastPosition = position;
                }
            }
            if (count == 1){
                int value = valIndex+1;
                if (logHistory || recordHistory) addHistoryItem(new LogItem(round, LogItem::HIDDEN_SINGLE_COLUMN, value, lastPosition));
                mark(lastPosition, round, value);
                return true;
            }
        }
    }
    return false;
}

/**
 * Mark exactly one cell which is the only possible value for some section, if
 * such a cell exists.
 * This method will look in a section for a possibility that is only listed
 * for one cell.  This type of cell is often called a "hidden single"
 */
bool SudokuBoard::onlyValueInSection(int round){
    for (int sec=0; sec<SEC_COUNT; sec++){
        int secPos = sectionToFirstCell(sec);
        for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
            int count = 0;
            int lastPosition = 0;
            {for (int i=0; i<3; i++){
                for (int j=0; j<3; j++){
                    int position = secPos + i + 9*j;
                    int valPos = getPossibilityIndex(valIndex,position);
                    if (possibilities[valPos] == 0){
                        count++;
                        lastPosition = position;
                    }
                }
            }}
            if (count == 1){
                int value = valIndex+1;
                if (logHistory || recordHistory) addHistoryItem(new LogItem(round, LogItem::HIDDEN_SINGLE_SECTION, value, lastPosition));
                mark(lastPosition, round, value);
                return true;
            }
        }
    }
    return false;
}

/**
 * Mark exactly one cell that has a single possibility, if such a cell exists.
 * This method will look for a cell that has only one possibility.  This type
 * of cell is often called a "single"
 */
bool SudokuBoard::onlyPossibilityForCell(int round){
    for (int position=0; position<BOARD_SIZE; position++){
        if (solution[position] == 0){
            int count = 0;
            int lastValue = 0;
            for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
                int valPos = getPossibilityIndex(valIndex,position);
                if (possibilities[valPos] == 0){
                    count++;
                    lastValue=valIndex+1;
                }
            }
            if (count == 1){
                mark(position, round, lastValue);
                if (logHistory || recordHistory) addHistoryItem(new LogItem(round, LogItem::SINGLE, lastValue, position));
                return true;
            }
        }
    }
    return false;
}

/**
 * Mark the given value at the given position.  Go through
 * the row, column, and section for the position and remove
 * the value from the possibilities.
 *
 * @param position Position into the board (0-80)
 * @param round Round to mark for rollback purposes
 * @param value The value to go in the square at the given position
 */
void SudokuBoard::mark(int position, int round, int value){
    if (solution[position] != 0) throw ("Marking position that already has been marked.");
    if (solutionRound[position] !=0) throw ("Marking position that was marked another round.");
    int valIndex = value-1;
    solution[position] = value;

    int possInd = getPossibilityIndex(valIndex,position);
    if (possibilities[possInd] != 0) throw ("Marking impossible position.");

    // Take this value out of the possibilities for everything in the row
    solutionRound[position] = round;
    int rowStart = cellToRow(position)*9;
    for (int col=0; col<COL_HEIGHT; col++){
        int rowVal=rowStart+col;
        int valPos = getPossibilityIndex(valIndex,rowVal);
        //cout << "Row Start: " << rowStart << " Row Value: " << rowVal << " Value Position: " << valPos << endl;
        if (possibilities[valPos] == 0){
            possibilities[valPos] = round;
        }
    }

    // Take this value out of the possibilities for everything in the column
    int colStart = cellToColumn(position);
    {for (int i=0; i<9; i++){
        int colVal=colStart+(9*i);
        int valPos = getPossibilityIndex(valIndex,colVal);
        //cout << "Col Start: " << colStart << " Col Value: " << colVal << " Value Position: " << valPos << endl;
        if (possibilities[valPos] == 0){
            possibilities[valPos] = round;
        }
    }}

    // Take this value out of the possibilities for everything in section
    int secStart = cellToSectionStartCell(position);
    {for (int i=0; i<3; i++){
        for (int j=0; j<3; j++){
            int secVal=secStart+i+(9*j);
            int valPos = getPossibilityIndex(valIndex,secVal);
            //cout << "Sec Start: " << secStart << " Sec Value: " << secVal << " Value Position: " << valPos << endl;
            if (possibilities[valPos] == 0){
                possibilities[valPos] = round;
            }
        }
    }}

    //This position itself is determined, it should have possibilities.
    {for (int valIndex=0; valIndex<9; valIndex++){
        int valPos = getPossibilityIndex(valIndex,position);
        if (possibilities[valPos] == 0){
            possibilities[valPos] = round;
        }
    }}

    //cout << "Col Start: " << colStart << " Row Start: " << rowStart << " Section Start: " << secStart<< " Value: " << value << endl;
    //printPossibilities();
}

/**
 * Print a human readable list of all the possibilities for the
 * squares that have not yet been filled in.
 */
void SudokuBoard::printPossibilities(){
    for(int i=0; i<BOARD_SIZE; i++){
        cout << " ";
        for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
            int posVal = (9*i)+valIndex;
            int value = valIndex+1;
            if (possibilities[posVal]==0){
                cout << value;
            } else {
                cout << ".";
            }
        }
        if (i != BOARD_SIZE-1 && i%SEC_GROUP_SIZE==SEC_GROUP_SIZE-1){
            cout << endl << "-------------------------------|-------------------------------|-------------------------------" << endl;
        } else if (i%9==8){
            cout << endl;
        } else if (i%3==2){
            cout << " |";
        }
    }
    cout << endl;
}

/**
 * print the given BOARD_SIZEd array of ints
 * as a sudoku puzzle.  Use print options from
 * member variables.
 */
void SudokuBoard::print(int* sudoku){
    for(int i=0; i<BOARD_SIZE; i++){
        if (printStyle == READABLE){
            cout << " ";
        }
        if (sudoku[i]==0){
            cout << '.';
        } else {
            cout << sudoku[i];
        }
        if (i == BOARD_SIZE-1){
            if (printStyle == CSV){
        
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.