File indexing completed on 2024-04-28 04:04:43

0001 /****************************************************************************
0002  *    Copyright 2015  Ian Wadham <iandw.au@gmail.com>                       *
0003  *                                                                          *
0004  *    This program is free software; you can redistribute it and/or         *
0005  *    modify it under the terms of the GNU General Public License as        *
0006  *    published by the Free Software Foundation; either version 2 of        *
0007  *    the License, or (at your option) any later version.                   *
0008  *                                                                          *
0009  *    This program is distributed in the hope that it will be useful,       *
0010  *    but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0011  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0012  *    GNU General Public License for more details.                          *
0013  *                                                                          *
0014  *    You should have received a copy of the GNU General Public License     *
0015  *    along with this program.  If not, see <http://www.gnu.org/licenses/>. *
0016  ****************************************************************************/
0017 
0018 #ifndef CAGEGENERATOR_H
0019 #define CAGEGENERATOR_H
0020 
0021 #include <QList>
0022 #include <QObject>
0023 
0024 #include "globals.h"
0025 #include "sudokuboard.h"
0026 
0027 enum Direction {ALONE = 0, N = 1, E = 2, S = 4, W = 8, TAKEN = 15};
0028 
0029 class SKGraph;
0030 class DLXSolver;
0031 
0032 /**
0033  * This class and its methods do all the work of generating a Mathdoku or
0034  * Killer Sudoku puzzle, starting from a solved set of cell-values in a Sudoku
0035  * grid. It lays down a pattern of irregular shaped cages, of different sizes,
0036  * which together cover the grid. Cages of size 1 have only one possible
0037  * solution, so they act as givens or clues. Cages of larger size are given an
0038  * operator (+*-/) and a target value. In the solution, the values in each cage
0039  * must combine together, using the operator, to equal the target value. Finally
0040  * the puzzle, represented by the targets, the operators and the single cells,
0041  * must have a unique solution. The DLX solver tests this. If there is no unique
0042  * solution, the puzzle must be rejected and the user of this class will need to
0043  * try again.
0044  *
0045  * In Killer Sudoku, the only operator is +, there are there are square boxes
0046  * (as well as rows and columns) that must satisfy Sudoku rules and a cage
0047  * cannot contain the same digit more than once.
0048  *
0049  * In Mathdoku (aka KenKen TM), all four operators can occur, a digit can occur
0050  * more than once in a cage and Sudoku rules apply only to rows and columns. The
0051  * latter means that a Mathdoku puzzle can have any size from 3x3 up to 9x9.
0052  * Division and subtraction operators are a special case. They can only appear
0053  * in cages of size 2. This is because the order in which you do divisions or
0054  * subtractions, in a cage of size 3 or more, can affect the result. 6 - (4 - 1)
0055  * = 3, but (6 - 4) - 1 = 1.
0056  *
0057  * @short A generator for Mathdoku and Killer Sudoku puzzles
0058  */
0059 class CageGenerator : public QObject
0060 {
0061     Q_OBJECT
0062 public:
0063     explicit CageGenerator (const BoardContents & solution);
0064     ~CageGenerator() override;
0065 
0066     /**
0067      * Fill the puzzle area with Mathdoku or Killer Sudoku cages. The graph
0068      * parameter indicates the size and type of puzzle. The other parameters
0069      * affect its difficulty. The cages are stored in the graph object, where
0070      * they can be used by other objects (e.g. to display the cages).
0071      *
0072      * @param graph           An SKGraph object representing the size, geometric
0073      *                        layout and rules of the particular kind of puzzle.
0074      * @param solutionMoves   A pointer that returns an ordered list of cells
0075      *                        found by the solver when it reached a solution.
0076      * @param maxSize         The maximum number of cells a cage can have.
0077      * @param maxValue        The maximum total value a cage's cells can have.
0078      * @param hideOperators   Whether operators are to be hidden in a Mathdoku
0079      *                        puzzle. In a Killer Sudoku the operators are all +
0080      *                        and are always hidden.
0081      * @param maxCombos       The maximum number of possible solutions any cage
0082      *                        can have.
0083      *
0084      * @return                The number of cages generated, or 0 = too many
0085      *                        failures to make an acceptable cage, or -1 = no
0086      *                        unique solution to the puzzle using the cages
0087      *                        generated (the caller may need to try again).
0088      */
0089     int  makeCages (SKGraph * graph, QList<int> * solutionMoves,
0090                     int maxSize, int maxValue,
0091                     bool hideOperators, int maxCombos);
0092 
0093     /**
0094      * Using just the puzzle-graph and its cages, solve a Mathdoku or Killer
0095      * Sudoku puzzle and check that it has only one solution. This method can
0096      * be used with a manually entered puzzle or one loaded from a saved file,
0097      * to obtain solution values and a move-sequence for hints, as well as
0098      * checking that the puzzle and its data are valid.
0099      *
0100      * @param graph           An SKGraph object representing the size, geometric
0101      *                        layout and rules of the particular kind of puzzle.
0102      * @param solution        The solution returned if a unique solution exists.
0103      * @param solutionMoves   A pointer that returns an ordered list of cells
0104      *                        found by the solver when it reached a solution.
0105      * @param hideOperators   Whether operators are to be hidden in a Mathdoku
0106      *                        puzzle. In a Killer Sudoku the operators are all +
0107      *                        and are always hidden.
0108      *
0109      * @return                0  = there is no solution,
0110      *                        1  = there is a unique solution,
0111      *                        >1 = there is more than one solution.
0112      */
0113     int checkPuzzle (SKGraph * graph, BoardContents & solution,
0114                      QList<int> * solutionMoves, bool hideOperators);
0115 
0116 private:
0117     SKGraph *     mGraph;       // The geometry of the puzzle.
0118     DLXSolver *   mDLXSolver;       // A solver for generated puzzles.
0119     BoardContents mSolution;
0120 
0121     int           mOrder;       // The height and width of the grid.
0122     int           mBoardArea;       // The number of cells in the grid.
0123 
0124     bool          mKillerSudoku;    // Killer Sudoku or Mathdoku rules?
0125     bool          mHiddenOperators; // Operators in cages are displayed?
0126 
0127     // Working-data used in the cage-generation algorithm.
0128     QList<int>    mUnusedCells;     // Cells not yet assigned to cages.
0129     QList<int>    mNeighbourFlags;  // The assigned neighbours cells have.
0130 
0131     int           mSingles;     // The number of 1-cell cages (clues).
0132     int           mMinSingles;      // The minimum number required.
0133     int           mMaxSingles;      // The maximum number required.
0134     int           mMaxCombos;       // The maximum combos a cage can have.
0135 
0136     // mPossibilities is a list of possible combinations and values all the
0137     // cages might have. It is used when setting up the DLX matrix for the
0138     // solver and again when decoding the solver's result into a solution grid.
0139     //
0140     // The Index list indicates where the combos for each cage begin and end.
0141     // It is used to find the first combo for each cage and the beginning of
0142     // the next cage's combos. The difference between these two gives the number
0143     // of possible values that might solve the cage. Divide that by the size of
0144     // the cage to get the number of combos for that cage. One or more of these
0145     // combos are correct ones, which the solver must find. The last entry in
0146     // the index is equal to the total size of mPossibilities.
0147 
0148     QList<int> *  mPossibilities;
0149     QList<int> *  mPossibilitiesIndex;
0150 
0151     // PRIVATE METHODS.
0152 
0153     // Form a group of cells that makes up a cage of a chosen size (or less).
0154     QList<int> makeOneCage (int seedCell, int requiredSize);
0155 
0156     // Choose an operator for the cage and calculate the cage's value.
0157     void setCageTarget (const QList<int> &cage, CageOperator & cageOperator,
0158                         int & cageValue);
0159 
0160     // Check whether a generated cage is within parameter requirements.
0161     bool cageIsOK (const QList<int> &cage, CageOperator cageOperator,
0162                    int cageValue);
0163 
0164     // Set all possible values for the cells of a cage (used by the solver).
0165     void setAllPossibilities (const QList<int> &cage, int nDigits,
0166                               CageOperator cageOperator, int cageValue);
0167 
0168     // Set all possible values for one operator in a cage (used by the solver).
0169     void setPossibilities (const QList<int> &cage, CageOperator cageOperator,
0170                            int cageValue);
0171 
0172     // Set all possible values for a cage that has a multiply or add operator.
0173     void setPossibleAddsOrMultiplies (const QList<int> &cage,
0174                                       CageOperator cageOperator, int cageValue);
0175 
0176     // Check if a cage contains duplicate digits (not allowed in Killer Sudoku).
0177     bool hasDuplicates (int nDigits, int digits[]);
0178 
0179     // Check if a combo of digits in a cage satisfies Sudoku rules (a Mathdoku
0180     // cage can contain a digit more than once, but not in the same row/column).
0181     bool isSelfConsistent (const QList<int> &cage, int nDigits, int digits[]);
0182 
0183     // Initialise the cage generator for a particular size and type of puzzle.
0184     void init (SKGraph * graph, bool hiddenOperators);
0185 };
0186 
0187 #endif // CAGEGENERATOR_H