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