use Marker in solver, put undo into a class
This commit is contained in:
parent
1c4b3a5f0d
commit
281109d1e4
@ -18,6 +18,7 @@
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#include "nonogramsolver.h"
|
#include "nonogramsolver.h"
|
||||||
#include "nonogramimage.h"
|
#include "nonogramimage.h"
|
||||||
|
#include "nonogrammarker.h"
|
||||||
#include "nonogramnumbers.h"
|
#include "nonogramnumbers.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
@ -27,86 +28,95 @@ namespace libqnono {
|
|||||||
struct Block {
|
struct Block {
|
||||||
int minFirst, maxFirst, length;
|
int minFirst, maxFirst, length;
|
||||||
};
|
};
|
||||||
enum Mark { MARK_UNKNOWN = 0, MARK_BLACK, MARK_WHITE };
|
typedef NonogramMarker::Mark Mark;
|
||||||
struct UndoOp {
|
|
||||||
union {
|
static const Mark MARK_UNKNOWN = NonogramMarker::NONE;
|
||||||
struct {
|
static const Mark MARK_BLACK = NonogramMarker::MARKED;
|
||||||
int *ptr, old;
|
static const Mark MARK_WHITE = NonogramMarker::CROSSED;
|
||||||
} data_int;
|
|
||||||
struct {
|
class UndoState {
|
||||||
Mark *ptr, old;
|
private:
|
||||||
} data_mark;
|
struct UndoOp {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
int *ptr, old;
|
||||||
|
} data_int;
|
||||||
|
struct {
|
||||||
|
Mark *ptr, old;
|
||||||
|
} data_mark;
|
||||||
|
};
|
||||||
|
enum { UNDO_INT, UNDO_MARK } type;
|
||||||
};
|
};
|
||||||
enum { UNDO_INT, UNDO_MARK } type;
|
|
||||||
};
|
QList<UndoOp> m_ops;
|
||||||
typedef QList<UndoOp> UndoState;
|
|
||||||
|
public:
|
||||||
static void trackInt(UndoState *undo_state, bool &changed, int &ptr, int val) {
|
void trackInt(bool &changed, int &ptr, int val) {
|
||||||
if (val == ptr) return;
|
if (val == ptr) return;
|
||||||
changed = TRUE;
|
changed = TRUE;
|
||||||
if (undo_state) {
|
if (this) {
|
||||||
UndoOp op;
|
UndoOp op;
|
||||||
op.type = UndoOp::UNDO_INT;
|
op.type = UndoOp::UNDO_INT;
|
||||||
op.data_int.ptr = &ptr;
|
op.data_int.ptr = &ptr;
|
||||||
op.data_int.old = ptr;
|
op.data_int.old = ptr;
|
||||||
undo_state->push_front(op);
|
m_ops.push_front(op);
|
||||||
}
|
|
||||||
ptr = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void trackMark(UndoState *undo_state, bool &changed, Mark &ptr, Mark val) {
|
|
||||||
if (val == ptr) return;
|
|
||||||
changed = TRUE;
|
|
||||||
if (undo_state) {
|
|
||||||
UndoOp op;
|
|
||||||
op.type = UndoOp::UNDO_MARK;
|
|
||||||
op.data_mark.ptr = &ptr;
|
|
||||||
op.data_mark.old = ptr;
|
|
||||||
undo_state->push_front(op);
|
|
||||||
}
|
|
||||||
ptr = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void undo(UndoState & undo_state) {
|
|
||||||
foreach (const UndoOp &op, undo_state) {
|
|
||||||
switch (op.type) {
|
|
||||||
case UndoOp::UNDO_INT:
|
|
||||||
*op.data_int.ptr = op.data_int.old;
|
|
||||||
break;
|
|
||||||
case UndoOp::UNDO_MARK:
|
|
||||||
*op.data_mark.ptr = op.data_mark.old;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
ptr = val;
|
||||||
}
|
}
|
||||||
undo_state.clear();
|
|
||||||
}
|
void trackMark(bool &changed, Mark &ptr, Mark val) {
|
||||||
|
if (val == ptr) return;
|
||||||
|
changed = TRUE;
|
||||||
|
if (this) {
|
||||||
|
UndoOp op;
|
||||||
|
op.type = UndoOp::UNDO_MARK;
|
||||||
|
op.data_mark.ptr = &ptr;
|
||||||
|
op.data_mark.old = ptr;
|
||||||
|
m_ops.push_front(op);
|
||||||
|
}
|
||||||
|
ptr = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void undo() {
|
||||||
|
foreach (const UndoOp &op, m_ops) {
|
||||||
|
switch (op.type) {
|
||||||
|
case UndoOp::UNDO_INT:
|
||||||
|
*op.data_int.ptr = op.data_int.old;
|
||||||
|
break;
|
||||||
|
case UndoOp::UNDO_MARK:
|
||||||
|
*op.data_mark.ptr = op.data_mark.old;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_ops.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
int nrows, ncols;
|
NonogramMarker m_marks;
|
||||||
QVector< QVector<Block> > rows, cols;
|
QVector< QVector<Block> > rows, cols;
|
||||||
Mark **m_data;
|
|
||||||
|
|
||||||
Mark& data(int row, int col) {
|
inline Mark& pixel(int x, int y) {
|
||||||
return m_data[col][row];
|
return m_marks.pixel(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct View : public T {
|
struct View : public T {
|
||||||
View(SolverState *state) : T(state) { }
|
View(SolverState & state) : T(state) { }
|
||||||
|
|
||||||
/* horizontal uses ViewRowColumn, vertical ViewColumnRow */
|
/* horizontal uses ViewRowColumn, vertical ViewColumnRow */
|
||||||
|
|
||||||
bool mark(UndoState *undo_state, bool & changed, int m, int from, int to) {
|
bool mark(UndoState *undo_state, bool & changed, int m, int from, int to) {
|
||||||
for (int i = from; i <= to; ++i) {
|
for (int i = from; i <= to; ++i) {
|
||||||
if (this->data(m, i) == MARK_WHITE) return FALSE;
|
if (this->data(m, i) == MARK_WHITE) return FALSE;
|
||||||
trackMark(undo_state, changed, this->data(m, i), MARK_BLACK);
|
undo_state->trackMark(changed, this->data(m, i), MARK_BLACK);
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
bool clear(UndoState *undo_state, bool & changed, int m, int from, int to) {
|
bool clear(UndoState *undo_state, bool & changed, int m, int from, int to) {
|
||||||
for (int i = from; i <= to; ++i) {
|
for (int i = from; i <= to; ++i) {
|
||||||
if (this->data(m, i) == MARK_BLACK) return FALSE;
|
if (this->data(m, i) == MARK_BLACK) return FALSE;
|
||||||
trackMark(undo_state, changed, this->data(m, i), MARK_WHITE);
|
undo_state->trackMark(changed, this->data(m, i), MARK_WHITE);
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -114,48 +124,40 @@ namespace libqnono {
|
|||||||
if (b.minFirst == b.maxFirst) {
|
if (b.minFirst == b.maxFirst) {
|
||||||
if (b.minFirst > 0) {
|
if (b.minFirst > 0) {
|
||||||
if (this->data(m, b.minFirst-1) == MARK_BLACK) return FALSE;
|
if (this->data(m, b.minFirst-1) == MARK_BLACK) return FALSE;
|
||||||
trackMark(undo_state, changed, this->data(m, b.minFirst-1), MARK_WHITE);
|
undo_state->trackMark(changed, this->data(m, b.minFirst-1), MARK_WHITE);
|
||||||
}
|
}
|
||||||
if (b.minFirst + b.length < this->dimSecond()) {
|
if (b.minFirst + b.length < this->dimSecond()) {
|
||||||
if (this->data(m, b.minFirst + b.length) == MARK_BLACK) return FALSE;
|
if (this->data(m, b.minFirst + b.length) == MARK_BLACK) return FALSE;
|
||||||
trackMark(undo_state, changed, this->data(m, b.minFirst + b.length), MARK_WHITE);
|
undo_state->trackMark(changed, this->data(m, b.minFirst + b.length), MARK_WHITE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mark(undo_state, changed, m, b.maxFirst, b.minFirst+b.length-1);
|
return mark(undo_state, changed, m, b.maxFirst, b.minFirst+b.length-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
SolverState *state;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ViewRowColumn {
|
struct ViewRowColumn {
|
||||||
ViewRowColumn(SolverState *state) : state(state) { }
|
ViewRowColumn(SolverState & state) : state(state) { }
|
||||||
|
|
||||||
Mark& data(int row, int col) { return state->data(row, col); }
|
inline Mark& data(int row, int col) { return state.pixel(col, row); }
|
||||||
int dimFirst() const { return state->nrows; }
|
inline int dimFirst() const { return state.m_marks.height(); }
|
||||||
int dimSecond() const { return state->ncols; }
|
inline int dimSecond() const { return state.m_marks.width(); }
|
||||||
|
|
||||||
SolverState *state;
|
SolverState & state;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ViewColumnRow {
|
struct ViewColumnRow {
|
||||||
ViewColumnRow(SolverState *state) : state(state) { }
|
ViewColumnRow(SolverState & state) : state(state) { }
|
||||||
|
|
||||||
Mark& data(int col, int row) { return state->data(row, col); }
|
inline Mark& data(int col, int row) { return state.pixel(col, row); }
|
||||||
int dimFirst() const { return state->ncols; }
|
inline int dimFirst() const { return state.m_marks.width(); }
|
||||||
int dimSecond() const { return state->nrows; }
|
inline int dimSecond() const { return state.m_marks.height(); }
|
||||||
|
|
||||||
SolverState *state;
|
SolverState & state;
|
||||||
};
|
};
|
||||||
|
|
||||||
SolverState(const NonogramNumbers & numbers)
|
SolverState(const NonogramNumbers & numbers)
|
||||||
: nrows(numbers.height()), ncols(numbers.width()) {
|
: m_marks(numbers.size()) {
|
||||||
m_data = new Mark*[ncols];
|
int nrows = m_marks.height(), ncols = m_marks.width();
|
||||||
for (int col = 0; col < ncols; ++col) {
|
|
||||||
m_data[col] = new Mark[nrows];
|
|
||||||
for (int row = 0; row < nrows; ++row) {
|
|
||||||
m_data[col][row] = MARK_UNKNOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rows.resize(nrows);
|
rows.resize(nrows);
|
||||||
cols.resize(ncols);
|
cols.resize(ncols);
|
||||||
for (int row = 0; row < nrows; ++row) {
|
for (int row = 0; row < nrows; ++row) {
|
||||||
@ -171,19 +173,15 @@ namespace libqnono {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
~SolverState() {
|
|
||||||
for (int col = 0; col < ncols; ++col) delete [] m_data[col];
|
|
||||||
delete[] m_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool update(UndoState *undo_state, QVector< QVector<Block> > & lines, View<T> *view, bool & changed) {
|
bool update(UndoState *undo_state, QVector< QVector<Block> > & lines, View<T> & view, bool & changed) {
|
||||||
for (int i = 0; i < lines.count(); ++i) {
|
for (int i = 0; i < lines.count(); ++i) {
|
||||||
QVector<Block> &line(lines[i]);
|
QVector<Block> &line(lines[i]);
|
||||||
int lineLen = line.count();
|
int lineLen = line.count();
|
||||||
|
|
||||||
if (0 == lineLen || (1 == lineLen && 0 == line[0].length)) {
|
if (0 == lineLen || (1 == lineLen && 0 == line[0].length)) {
|
||||||
if (!view->clear(undo_state, changed, i, 0, view->dimSecond()-1)) return FALSE;
|
if (!view.clear(undo_state, changed, i, 0, view.dimSecond()-1)) return FALSE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +190,7 @@ namespace libqnono {
|
|||||||
int cell = line[0].minFirst;
|
int cell = line[0].minFirst;
|
||||||
// there must be "length" adjacent non white cells
|
// there must be "length" adjacent non white cells
|
||||||
for (int cell1 = cell, end = cell + line[0].length; cell <= line[0].maxFirst && cell1 < end; ++cell1) {
|
for (int cell1 = cell, end = cell + line[0].length; cell <= line[0].maxFirst && cell1 < end; ++cell1) {
|
||||||
if (MARK_WHITE == view->data(i, cell1)) {
|
if (MARK_WHITE == view.data(i, cell1)) {
|
||||||
cell = cell1 + 1;
|
cell = cell1 + 1;
|
||||||
end = cell + line[0].length;
|
end = cell + line[0].length;
|
||||||
}
|
}
|
||||||
@ -200,12 +198,12 @@ namespace libqnono {
|
|||||||
|
|
||||||
if (cell > line[0].minFirst) {
|
if (cell > line[0].minFirst) {
|
||||||
if (cell > line[0].maxFirst) return FALSE; // no solution impossible
|
if (cell > line[0].maxFirst) return FALSE; // no solution impossible
|
||||||
trackInt(undo_state, changed, line[0].minFirst, cell);
|
undo_state->trackInt(changed, line[0].minFirst, cell);
|
||||||
}
|
}
|
||||||
// the first black can't be before the first block
|
// the first black can't be before the first block
|
||||||
while (cell < line[0].maxFirst && view->data(i, cell) != MARK_BLACK) ++cell;
|
while (cell < line[0].maxFirst && view.data(i, cell) != MARK_BLACK) ++cell;
|
||||||
if (cell < line[0].maxFirst) {
|
if (cell < line[0].maxFirst) {
|
||||||
trackInt(undo_state, changed, line[0].maxFirst, cell);
|
undo_state->trackInt(changed, line[0].maxFirst, cell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,19 +213,19 @@ namespace libqnono {
|
|||||||
int cell = line.last().maxFirst;
|
int cell = line.last().maxFirst;
|
||||||
// there must be "length" adjacent non white cells
|
// there must be "length" adjacent non white cells
|
||||||
for (int cell1 = cell + len - 1; cell >= line.last().minFirst && cell1 >= cell; --cell1) {
|
for (int cell1 = cell + len - 1; cell >= line.last().minFirst && cell1 >= cell; --cell1) {
|
||||||
if (MARK_WHITE == view->data(i, cell1)) {
|
if (MARK_WHITE == view.data(i, cell1)) {
|
||||||
cell = cell1 - len;
|
cell = cell1 - len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell < line.last().maxFirst) {
|
if (cell < line.last().maxFirst) {
|
||||||
if (cell < line.last().minFirst) return FALSE; // no solution impossible
|
if (cell < line.last().minFirst) return FALSE; // no solution impossible
|
||||||
trackInt(undo_state, changed, line.last().maxFirst, cell);
|
undo_state->trackInt(changed, line.last().maxFirst, cell);
|
||||||
}
|
}
|
||||||
// the last black can't be after the last block
|
// the last black can't be after the last block
|
||||||
while (cell > line.last().minFirst && view->data(i, cell+len-1) != MARK_BLACK) --cell;
|
while (cell > line.last().minFirst && view.data(i, cell+len-1) != MARK_BLACK) --cell;
|
||||||
if (cell > line.last().minFirst) {
|
if (cell > line.last().minFirst) {
|
||||||
trackInt(undo_state, changed, line.last().minFirst, cell);
|
undo_state->trackInt(changed, line.last().minFirst, cell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,10 +234,10 @@ namespace libqnono {
|
|||||||
{
|
{
|
||||||
int minFirst = qMax(line[j].minFirst, 1 + line[j-1].minFirst + line[j-1].length);
|
int minFirst = qMax(line[j].minFirst, 1 + line[j-1].minFirst + line[j-1].length);
|
||||||
// the cell before first can't be black
|
// the cell before first can't be black
|
||||||
while (minFirst <= line[j].maxFirst && MARK_BLACK == view->data(i, minFirst-1)) ++minFirst;
|
while (minFirst <= line[j].maxFirst && MARK_BLACK == view.data(i, minFirst-1)) ++minFirst;
|
||||||
// there must be "length" adjacent non white cells
|
// there must be "length" adjacent non white cells
|
||||||
for (int cell = minFirst, end = minFirst + line[j].length; minFirst <= line[j].maxFirst && cell < end; ++cell) {
|
for (int cell = minFirst, end = minFirst + line[j].length; minFirst <= line[j].maxFirst && cell < end; ++cell) {
|
||||||
if (MARK_WHITE == view->data(i, cell)) {
|
if (MARK_WHITE == view.data(i, cell)) {
|
||||||
minFirst = cell + 1;
|
minFirst = cell + 1;
|
||||||
end = minFirst + line[j].length;
|
end = minFirst + line[j].length;
|
||||||
}
|
}
|
||||||
@ -248,15 +246,15 @@ namespace libqnono {
|
|||||||
if (minFirst >= line[j-1].maxFirst + line[j-1].length) {
|
if (minFirst >= line[j-1].maxFirst + line[j-1].length) {
|
||||||
int cell = minFirst;
|
int cell = minFirst;
|
||||||
// next black cell can't be before this block
|
// next black cell can't be before this block
|
||||||
while (cell < line[j].maxFirst && view->data(i, cell) != MARK_BLACK) ++cell;
|
while (cell < line[j].maxFirst && view.data(i, cell) != MARK_BLACK) ++cell;
|
||||||
if (cell < line[j].maxFirst) {
|
if (cell < line[j].maxFirst) {
|
||||||
trackInt(undo_state, changed, line[j].maxFirst, cell);
|
undo_state->trackInt(changed, line[j].maxFirst, cell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (minFirst > line[j].minFirst) {
|
if (minFirst > line[j].minFirst) {
|
||||||
if (minFirst > line[j].maxFirst) return FALSE; // no solution impossible
|
if (minFirst > line[j].maxFirst) return FALSE; // no solution impossible
|
||||||
trackInt(undo_state, changed, line[j].minFirst, minFirst);
|
undo_state->trackInt(changed, line[j].minFirst, minFirst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,10 +262,10 @@ namespace libqnono {
|
|||||||
int len = line[k-1].length;
|
int len = line[k-1].length;
|
||||||
int maxFirst = qMin(line[k-1].maxFirst, line[k].maxFirst - len - 1);
|
int maxFirst = qMin(line[k-1].maxFirst, line[k].maxFirst - len - 1);
|
||||||
// the cell after last can't be black
|
// the cell after last can't be black
|
||||||
while (maxFirst >= line[k-1].minFirst && MARK_BLACK == view->data(i, maxFirst + len)) --maxFirst;
|
while (maxFirst >= line[k-1].minFirst && MARK_BLACK == view.data(i, maxFirst + len)) --maxFirst;
|
||||||
// there must be "length" adjacent non white cells
|
// there must be "length" adjacent non white cells
|
||||||
for (int cell = maxFirst + len - 1; maxFirst >= line[k-1].minFirst && cell >= maxFirst; --cell) {
|
for (int cell = maxFirst + len - 1; maxFirst >= line[k-1].minFirst && cell >= maxFirst; --cell) {
|
||||||
if (MARK_WHITE == view->data(i, cell)) {
|
if (MARK_WHITE == view.data(i, cell)) {
|
||||||
maxFirst = cell - len;
|
maxFirst = cell - len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -275,44 +273,36 @@ namespace libqnono {
|
|||||||
if (maxFirst + len <= line[k].minFirst) {
|
if (maxFirst + len <= line[k].minFirst) {
|
||||||
int cell = maxFirst;
|
int cell = maxFirst;
|
||||||
// next black cell before maxFirst+len can't be after this block
|
// next black cell before maxFirst+len can't be after this block
|
||||||
while (cell > line[k-1].minFirst && view->data(i, cell+len-1) != MARK_BLACK) --cell;
|
while (cell > line[k-1].minFirst && view.data(i, cell+len-1) != MARK_BLACK) --cell;
|
||||||
if (cell > line[k-1].minFirst) {
|
if (cell > line[k-1].minFirst) {
|
||||||
trackInt(undo_state, changed, line[k-1].minFirst, cell);
|
undo_state->trackInt(changed, line[k-1].minFirst, cell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxFirst < line[k-1].maxFirst) {
|
if (maxFirst < line[k-1].maxFirst) {
|
||||||
if (maxFirst < line[k-1].minFirst) return FALSE; // no solution impossible
|
if (maxFirst < line[k-1].minFirst) return FALSE; // no solution impossible
|
||||||
trackInt(undo_state, changed, line[k-1].maxFirst, maxFirst);
|
undo_state->trackInt(changed, line[k-1].maxFirst, maxFirst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!view->clear(undo_state, changed, i, 0, line[0].minFirst-1)) return FALSE;
|
if (!view.clear(undo_state, changed, i, 0, line[0].minFirst-1)) return FALSE;
|
||||||
for (int j = 0; j < lineLen; ++j) {
|
for (int j = 0; j < lineLen; ++j) {
|
||||||
if (j > 0 && !view->clear(undo_state, changed, i, line[j-1].maxFirst + line[j-1].length, line[j].minFirst-1)) return FALSE;
|
if (j > 0 && !view.clear(undo_state, changed, i, line[j-1].maxFirst + line[j-1].length, line[j].minFirst-1)) return FALSE;
|
||||||
if (!view->markBlock(undo_state, changed, i, line[j])) return FALSE;
|
if (!view.markBlock(undo_state, changed, i, line[j])) return FALSE;
|
||||||
}
|
}
|
||||||
if (!view->clear(undo_state, changed, i, line.last().maxFirst + line.last().length, view->dimSecond()-1)) return FALSE;
|
if (!view.clear(undo_state, changed, i, line.last().maxFirst + line.last().length, view.dimSecond()-1)) return FALSE;
|
||||||
|
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void storeSolution(NonogramImage & image) {
|
|
||||||
image.resize(QSize(ncols, nrows));
|
|
||||||
for (int i = 0; i < ncols; ++i) {
|
|
||||||
for (int j = 0; j < nrows; ++j) {
|
|
||||||
image.setPixel(i, j, data(j, i) == MARK_BLACK);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void debugState() {
|
void debugState() {
|
||||||
for (int j = 0; j < nrows; ++j) {
|
#ifndef QT_NO_DEBUG_OUTPUT
|
||||||
|
for (int j = 0; j < m_marks.height(); ++j) {
|
||||||
QDebug dbg = qDebug();
|
QDebug dbg = qDebug();
|
||||||
for (int i = 0; i < ncols; ++i) {
|
for (int i = 0; i < m_marks.width(); ++i) {
|
||||||
switch (data(j, i)) {
|
switch (pixel(i, j)) {
|
||||||
case MARK_UNKNOWN:
|
case MARK_UNKNOWN:
|
||||||
dbg << "?"; break;
|
dbg << "?"; break;
|
||||||
case MARK_BLACK:
|
case MARK_BLACK:
|
||||||
@ -323,46 +313,47 @@ namespace libqnono {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
qDebug() << "Row blocks:";
|
qDebug() << "Row blocks:";
|
||||||
for (int j = 0; j < nrows; ++j) {
|
for (int j = 0; j < rows.count(); ++j) {
|
||||||
QDebug dbg = qDebug() << j << ":";
|
QDebug dbg = qDebug() << j << ":";
|
||||||
foreach (Block block, rows[j]) {
|
foreach (Block block, rows[j]) {
|
||||||
dbg << "[" << block.minFirst << block.maxFirst << block.length << "]";
|
dbg << "[" << block.minFirst << block.maxFirst << block.length << "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qDebug() << "Col blocks:";
|
qDebug() << "Col blocks:";
|
||||||
for (int j = 0; j < ncols; ++j) {
|
for (int j = 0; j < cols.count(); ++j) {
|
||||||
QDebug dbg = qDebug() << j << ":";
|
QDebug dbg = qDebug() << j << ":";
|
||||||
foreach (Block block, cols[j]) {
|
foreach (Block block, cols[j]) {
|
||||||
dbg << "[" << block.minFirst << block.maxFirst << block.length << "]";
|
dbg << "[" << block.minFirst << block.maxFirst << block.length << "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void solve(QList<NonogramImage> &solutions, UndoState *undo_state = 0) {
|
void solve(QList<NonogramImage> &solutions, UndoState *undo_state = 0) {
|
||||||
bool changed = TRUE;
|
bool changed = TRUE;
|
||||||
View<ViewRowColumn> rowColumn(this);
|
View<ViewRowColumn> rowColumn(*this);
|
||||||
View<ViewColumnRow> columnRow(this);
|
View<ViewColumnRow> columnRow(*this);
|
||||||
while (changed) {
|
while (changed) {
|
||||||
changed = FALSE;
|
changed = FALSE;
|
||||||
if (!update(undo_state, rows, &rowColumn, changed)) return;
|
if (!update(undo_state, rows, rowColumn, changed)) return;
|
||||||
if (!update(undo_state, cols, &columnRow, changed)) return;
|
if (!update(undo_state, cols, columnRow, changed)) return;
|
||||||
}
|
}
|
||||||
if (!undo_state) {
|
if (!undo_state) {
|
||||||
qDebug() << "State after first run:";
|
qDebug() << "State after first run:";
|
||||||
debugState();
|
debugState();
|
||||||
}
|
}
|
||||||
for (int i = 0; i < ncols; ++i) {
|
for (int i = 0; i < m_marks.width(); ++i) {
|
||||||
for (int j = 0; j < nrows; ++j) {
|
for (int j = 0; j < m_marks.height(); ++j) {
|
||||||
if (data(j, i) == MARK_UNKNOWN) {
|
if (pixel(i, j) == MARK_UNKNOWN) {
|
||||||
UndoState subundo;
|
UndoState subundo;
|
||||||
|
|
||||||
trackMark(&subundo, changed, data(j, i), MARK_BLACK);
|
subundo.trackMark(changed, pixel(i, j), MARK_BLACK);
|
||||||
solve(solutions, &subundo);
|
solve(solutions, &subundo);
|
||||||
undo(subundo);
|
subundo.undo();
|
||||||
|
|
||||||
trackMark(&subundo, changed, data(j, i), MARK_WHITE);
|
subundo.trackMark(changed, pixel(i, j), MARK_WHITE);
|
||||||
solve(solutions, &subundo);
|
solve(solutions, &subundo);
|
||||||
undo(subundo);
|
subundo.undo();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -372,7 +363,7 @@ namespace libqnono {
|
|||||||
debugState();
|
debugState();
|
||||||
|
|
||||||
solutions.append(NonogramImage());;
|
solutions.append(NonogramImage());;
|
||||||
storeSolution(solutions.last());
|
solutions.last().load(m_marks);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user