summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Wadham <[email protected]>2015-06-23 15:33:06 +1000
committerIan Wadham <[email protected]>2015-06-23 15:33:06 +1000
commitae2ddddab5c707a43741c39fa5ac0b69fbfeccae (patch)
tree8d8595d16dc35318b44e577e6393d3767b72de26
parent037556cbe4590f47b345909a010f410fa0f66024 (diff)
Integrate Mathdoku and Killer Sudoku code into KSudoku GUI and logic.
-rw-r--r--src/generator/sudokuboard.cpp48
-rw-r--r--src/generator/sudokuboard.h32
2 files changed, 65 insertions, 15 deletions
diff --git a/src/generator/sudokuboard.cpp b/src/generator/sudokuboard.cpp
index 9d996c1..48c57df 100644
--- a/src/generator/sudokuboard.cpp
+++ b/src/generator/sudokuboard.cpp
@@ -20,6 +20,8 @@
#include "sudokuboard.h"
#include "state.h"
+#include "mathdokugenerator.h"
+#include <QDebug> // IDW test.
#include <KLocale>
#include <KMessageBox>
@@ -71,16 +73,48 @@ void SudokuBoard::setSeed()
}
}
-void SudokuBoard::generatePuzzle (BoardContents & puzzle,
- BoardContents & solution,
- Difficulty difficultyRequired,
- Symmetry symmetry)
+void SudokuBoard::generatePuzzle (BoardContents & puzzle,
+ BoardContents & solution,
+ Difficulty difficultyRequired,
+ Symmetry symmetry)
{
dbe "Entered generatePuzzle(): difficulty %d, symmetry %d\n",
difficultyRequired, symmetry);
- QTime t;
- t.start();
setSeed();
+
+ SudokuType puzzleType = m_graph->specificType();
+ if ((puzzleType == Mathdoku) || (puzzleType == KillerSudoku)) {
+ // Generate variants of Mathdoku (aka KenKen TM) or Killer Sudoku types.
+ int maxTries = 10;
+ int numTries = 0;
+ bool r = false;
+ while (numTries < maxTries) {
+ MathdokuGenerator mg (m_graph);
+ solution = fillBoard();
+ numTries++;
+ r = mg.generateMathdokuTypes (puzzle, solution, difficultyRequired);
+ if (r) {
+ qDebug() << "SudokuBoard::generatePuzzle SUCCEEDED: numTries"
+ << numTries;
+ return;
+ }
+ }
+ // TODO - Issue a popup message for the user to decide how to proceed.
+ qDebug() << "SudokuBoard::generatePuzzle FAILED MISERABLY !!! numTries"
+ << numTries;
+ }
+ else {
+ // Generate variants of Sudoku (2D) and Roxdoku (3D) types.
+ generateSudokuRoxdokuTypes (puzzle, solution,
+ difficultyRequired, symmetry);
+ }
+}
+
+void SudokuBoard::generateSudokuRoxdokuTypes (BoardContents & puzzle,
+ BoardContents & solution,
+ Difficulty difficultyRequired,
+ Symmetry symmetry)
+{
const int maxTries = 20;
int count = 0;
float bestRating = 0.0;
@@ -91,6 +125,8 @@ void SudokuBoard::generatePuzzle (BoardContents & puzzle,
BoardContents currPuzzle;
BoardContents currSolution;
+ QTime t;
+ t.start();
if (m_graph->sizeZ() > 1) {
symmetry = NONE; // Symmetry not implemented in 3-D.
}
diff --git a/src/generator/sudokuboard.h b/src/generator/sudokuboard.h
index 159a6ab..7586d6a 100644
--- a/src/generator/sudokuboard.h
+++ b/src/generator/sudokuboard.h
@@ -39,6 +39,13 @@ enum GuessingMode {Random, NotRandom};
class SKGraph;
class State;
+// TODO - SudokuBoard, MathdokuGenerator, CageGenerator and DLXSolver could be
+// factored better. At the moment, MathdokuGenerator needs SudokuBoard's
+// fillBoard() method to create a square that satisfies Sudoku rules for
+// Killer Sudoku or Mathdoku puzzles. But fillBoard() depends on large
+// parts of SudokuBoard's solver logic... so we have two solver objects
+// co-existing for now, but this happens only for a second or so.
+
/**
* @class SudokuBoard sudokuboard.h
* @short Generalized data-structures and methods for handling Sudoku puzzles.
@@ -90,7 +97,7 @@ class State;
* Classic Sudoku in several sizes and variants, Samurai Sudoku with five
* overlapping grids and the three-dimensional Roxdoku in several sizes.
*
- * Each group (row, column, blocki or plane) contains N cells in which the
+ * Each group (row, column, block or plane) contains N cells in which the
* numbers 1 to N must appear exactly once. N can be 4, 9, 16 or 25, but not
* all types of puzzle support all four sizes.
*
@@ -196,6 +203,16 @@ public:
GuessingMode gMode = Random);
/**
+ * Fill the board with randomly chosen valid values, thus generating a
+ * solution from which a puzzle can be created (virtual). It is made
+ * public so that it can be used to fill a Mathdoku or Killer Sudoku
+ * board with numbers that satisfy Sudoku constraints.
+ *
+ * @return The filled board-vector.
+ */
+ virtual BoardContents & fillBoard();
+
+ /**
* Initialize or re-initialize the random number generator.
*/
void setSeed();
@@ -241,14 +258,6 @@ protected:
*/
virtual void clear (BoardContents & boardValues);
- /**
- * Fill the board with randomly chosen valid values, thus generating a
- * solution from which a puzzle can be created (virtual).
- *
- * @return The filled board-vector.
- */
- virtual BoardContents & fillBoard();
-
/*
* Fill a vector of integers with values from 1 up to the size of the
* vector, then shuffle the integers into a random order.
@@ -258,6 +267,11 @@ protected:
void randomSequence (QVector<int> & sequence);
private:
+ void generateSudokuRoxdokuTypes (BoardContents & puzzle,
+ BoardContents & solution,
+ Difficulty difficulty,
+ Symmetry symmetry);
+
SKGraph * m_graph;
int m_vacant;
int m_unusable;