60
m_puzzle2 = Problem(m_graph->rulset());
65
bool Puzzle::createPartial(Solver *solver) {
66
// TODO after finding a solution try to find simpler ones
67
const ItemBoard *board = m_graph->board();
69
ChoiceItem *choiceItem;
71
int x = rand() % board->size(0);
72
int y = rand() % board->size(1);
73
int z = rand() % board->size(2);
74
Item *item = board->itemAt(x, y, z);
76
choiceItem = static_cast<ChoiceItem*>(item);
77
if(choiceItem->value(&solver->state())) continue;
80
// TODO don't iterate from the minimum to the maximum
81
// this will create relative easy puzzles with concentration of low values and almost no to none 9
82
// TODO prepare the state to speedup deeper tries
83
int min = choiceItem->minValue();
84
int max = choiceItem->maxValue();
85
int range = choiceItem->maxValue() - min + 1;
86
int start = rand() % range;
87
// count from start downward and continuing with max after min
88
for(int i = range+start; i > start; --i) {
89
int val = min + i % range;
91
if(!choiceItem->marker(&solver->state(), val)) continue;
94
choiceItem->setValue(&solver->state(), val);
97
int count = solver->results().count();
99
m_solution2 = solver->results()[0];
103
m_puzzle2 = solver->state();
105
} else if(count > 1) {
106
if(createPartial(solver))
116
65
bool Puzzle::init(int difficulty, int symmetry) {
117
66
if(m_initialized) return false;
120
solver.loadEmpty(m_graph->rulset());
122
if(createPartial(&solver)) {
68
QObject * owner = new QObject(); // Stands in for "this".
69
SudokuBoard * board = getBoard (owner);
74
// Generate a puzzle and its solution.
76
BoardContents solution;
77
board->generatePuzzle (puzzle, solution,
78
(Difficulty) difficulty, (Symmetry) symmetry);
79
board->getMoveList (m_hintList);
80
int boardSize = board->boardSize();
81
delete owner; // Also deletes the SudokuBoard object.
83
// Convert the puzzle and solution to KSudoku format.
84
m_puzzle = convertBoardContents(puzzle, boardSize);
85
m_solution = convertBoardContents(solution, boardSize);
129
90
int Puzzle::init(const QByteArray& values) {
130
91
if(m_initialized) return -1;
132
m_puzzle2 = Problem(m_graph->rulset());
133
for(int x = 0; x < m_graph->sizeX(); ++x) {
134
for(int y = 0; y < m_graph->sizeY(); ++y) {
135
for(int z = 0; z < m_graph->sizeZ(); ++z) {
136
int value = values[m_graph->cellIndex(x, y, z)];
137
Item *item = m_graph->board()->itemAt(x, y, z);
139
static_cast<ChoiceItem*>(item)->setValue(&m_puzzle2, value);
146
solver.loadProblem(&m_puzzle2);
149
int success = solver.results().count();
150
if(success == 1 && m_withSolution) {
151
m_solution2 = solver.results()[0];
93
QObject * owner = new QObject(); // Stands in for "this".
94
SudokuBoard * board = getBoard (owner);
99
// Convert the puzzle values to SudokuBoard format.
100
BoardContents puzzleValues = board->fromKSudoku(values);
102
// Save the puzzle values and SudokuBoard's solution (if any).
104
int boardSize = board->boardSize();
105
m_solution = convertBoardContents
106
(board->solveBoard(puzzleValues), boardSize);
108
// Get SudokuBoard to check the solution.
109
int result = board->checkPuzzle (puzzleValues);
111
result = 1; // There is one solution.
113
else if (result == -1) {
114
result = 0; // There is no solution.
117
result = 2; // There is more than one solution.
121
board->getMoveList (m_hintList);
123
delete owner; // Also deletes the SudokuBoard object.
127
const QByteArray Puzzle::convertBoardContents(const BoardContents & values,
129
// New solver stores by column within row and sets unused cells = -1.
130
// KSudoku stores values by row within column and sets unused cells = 0,
131
// e.g. the empty areas in a Samurai or Tiny Samurai puzzle layout.
132
QByteArray newValues;
133
if (values.size() < (boardSize * boardSize)) {
134
return newValues; // No solution.
138
for (int j = 0; j < boardSize; j++) {
139
for (int i = 0; i < boardSize; i++) {
140
index = i * boardSize + j;
141
value = values.at(index) < 0 ? 0 : values.at(index);
142
newValues.append(value);
148
SudokuBoard * Puzzle::getBoard(QObject * owner) {
150
for (int n = 2; n <= 5; n++) {
151
if (m_graph->order() == n * n) {
155
SudokuType type = m_graph->specificType();
156
qDebug() << "Type" << type; // IDW test.
157
SudokuBoard * board = 0;
158
// Generate a puzzle and solution of the required type.
161
board = new PlainSudokuBoard (owner, type, blockSize);
164
board = new XSudokuBoard (owner, type, blockSize);
167
board = new JigsawBoard (owner, type, blockSize);
170
board = new SamuraiBoard (owner, type, blockSize);
173
board = new TinySamuraiBoard (owner, type, blockSize);
176
board = new RoxdokuBoard (owner, type, blockSize);