New solver
This commit is contained in:
parent
c696f62534
commit
fe3b10e35a
@ -21,6 +21,127 @@
|
||||
#include <QImage>
|
||||
|
||||
namespace libqnono {
|
||||
static void boolsFromImage(bool ** & data, const QImage &image) {
|
||||
int cols = image.width(), rows = image.height();
|
||||
data = new bool*[cols];
|
||||
for (int col = 0; col < cols; ++col) data[col] = new bool[rows];
|
||||
for (int row = 0; row < rows; ++row) {
|
||||
for (int col = 0; col < cols; ++col) {
|
||||
data[col][row] = 0 == (image.pixel(col, row) & 0x00FFFFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void freeBools(const QSize & size, bool ** data) {
|
||||
int cols = size.width();
|
||||
for (int col = 0; col < cols; ++col) delete [] data[col];
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
static const quint64 CNonogramNumbers_MAGIC = Q_UINT64_C(0xd33efcacc0050164);
|
||||
|
||||
CNonogramNumbers::CNonogramNumbers(const vv_num & rows, const vv_num & columns)
|
||||
: m_rows(rows), m_columns(columns) {
|
||||
}
|
||||
|
||||
CNonogramNumbers::CNonogramNumbers(const CNonogram & source)
|
||||
: m_rows(source.height()), m_columns(source.width()) {
|
||||
// remove the "0" blocks (they are used for otherwise empty lines)
|
||||
for (int i = 0; i < source.height(); ++i) {
|
||||
m_rows[i] = source.rowNumbers(i);
|
||||
if (1 == m_rows[i].count() && 0 == m_rows[i][0]) m_rows[i].clear();
|
||||
}
|
||||
for (int i = 0; i < source.width(); ++i) {
|
||||
m_columns[i] = source.columnNumbers(i);
|
||||
if (1 == m_columns[i].count() && 0 == m_columns[i][0]) m_columns[i].clear();
|
||||
}
|
||||
}
|
||||
|
||||
CNonogramNumbers::CNonogramNumbers(QSize size, bool **data) {
|
||||
calcFromImage(size, data);
|
||||
}
|
||||
|
||||
CNonogramNumbers::CNonogramNumbers(const QImage & image) {
|
||||
bool ** data = 0;
|
||||
boolsFromImage(data, image);
|
||||
calcFromImage(image.size(), data);
|
||||
freeBools(image.size(), data);
|
||||
}
|
||||
|
||||
void CNonogramNumbers::calcFromImage(QSize size, bool **data) {
|
||||
int rows = size.height(), cols = size.width();
|
||||
m_rows.clear(); m_rows.resize(rows);
|
||||
m_columns.clear(); m_columns.resize(cols);
|
||||
for (int row = 0; row < rows; ++row) {
|
||||
quint16 *val = 0;
|
||||
for (int col = 0; col < cols; ++col) {
|
||||
bool b = data[col][row];
|
||||
if (!val && b) {
|
||||
m_rows[row].append(1);
|
||||
val = &m_rows[row].last();
|
||||
} else if (b) {
|
||||
++(*val);
|
||||
} else {
|
||||
val = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int col = 0; col < cols; ++col) {
|
||||
quint16 *val = 0;
|
||||
for (int row = 0; row < rows; ++row) {
|
||||
bool b = data[col][row];
|
||||
if (!val && b) {
|
||||
m_columns[col].append(1);
|
||||
val = &m_columns[col].last();
|
||||
} else if (b) {
|
||||
++(*val);
|
||||
} else {
|
||||
val = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CNonogramNumbers::readFromStream(QDataStream & stream) {
|
||||
quint64 magic;
|
||||
stream >> magic;
|
||||
if (CNonogramNumbers_MAGIC != magic || QDataStream::Ok != stream.status()) {
|
||||
if (QDataStream::ReadPastEnd != stream.status()) stream.setStatus(QDataStream::ReadCorruptData);
|
||||
return false;
|
||||
}
|
||||
stream >> m_rows >> m_columns;
|
||||
return QDataStream::Ok == stream.status();
|
||||
}
|
||||
|
||||
void CNonogramNumbers::writeToStream(QDataStream & stream) {
|
||||
stream << CNonogramNumbers_MAGIC << m_rows << m_columns;
|
||||
}
|
||||
|
||||
bool CNonogramNumbers::operator==(const CNonogramNumbers &other) const {
|
||||
return m_rows == other.m_rows && m_columns == other.m_columns;
|
||||
}
|
||||
|
||||
bool CNonogramNumbers::check(bool **data) const {
|
||||
CNonogramNumbers tmp(size(), data);
|
||||
return *this == tmp;
|
||||
}
|
||||
|
||||
bool CNonogramNumbers::check(const QImage & image) const {
|
||||
if (size() != image.size()) return FALSE;
|
||||
CNonogramNumbers tmp(image);
|
||||
return *this == tmp;
|
||||
}
|
||||
|
||||
QDataStream & operator<<(QDataStream & stream, CNonogramNumbers & numbers) {
|
||||
numbers.writeToStream(stream);
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream & operator>>(QDataStream & stream, CNonogramNumbers & numbers) {
|
||||
numbers.readFromStream(stream);
|
||||
return stream;
|
||||
}
|
||||
|
||||
CNonogram::CNonogram()
|
||||
: m_Size(0, 0),
|
||||
m_Data(NULL),
|
||||
|
@ -27,6 +27,41 @@
|
||||
class QImage;
|
||||
|
||||
namespace libqnono {
|
||||
class CNonogram;
|
||||
class CNonogramNumbers;
|
||||
|
||||
class CNonogramNumbers {
|
||||
public:
|
||||
typedef QVector<quint16> v_num;
|
||||
typedef QVector<v_num> vv_num;
|
||||
|
||||
CNonogramNumbers(const vv_num & rows, const vv_num & columns);
|
||||
CNonogramNumbers(const CNonogram & source);
|
||||
CNonogramNumbers(QSize size, bool **data);
|
||||
CNonogramNumbers(const QImage & image);
|
||||
|
||||
void calcFromImage(QSize size, bool **data);
|
||||
|
||||
bool readFromStream(QDataStream & stream);
|
||||
void writeToStream(QDataStream & stream);
|
||||
|
||||
bool operator==(const CNonogramNumbers &other) const;
|
||||
|
||||
inline const vv_num & rows() const { return m_rows; }
|
||||
inline const vv_num & columns() const { return m_columns; }
|
||||
|
||||
inline QSize size() const { return QSize(m_columns.count(), m_rows.count()); }
|
||||
inline int width() const { return m_columns.count(); }
|
||||
inline int height() const { return m_rows.count(); }
|
||||
|
||||
bool check(bool **data) const;
|
||||
bool check(const QImage & image) const;
|
||||
|
||||
private:
|
||||
vv_num m_rows, m_columns;
|
||||
};
|
||||
|
||||
|
||||
class CNonogram {
|
||||
public:
|
||||
typedef QVector<quint16> NumbersVector;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,8 +2,36 @@
|
||||
#define LIBQCROSS_CNONOGRAMSOLVER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QSize>
|
||||
#include <QList>
|
||||
|
||||
namespace libqnono {
|
||||
class CNonogramNumbers;
|
||||
|
||||
class CNonogramSolution {
|
||||
public:
|
||||
CNonogramSolution(QSize size, bool ** data)
|
||||
: m_size(size), m_data(data) {
|
||||
}
|
||||
|
||||
~CNonogramSolution() {
|
||||
int cols = m_size.width();
|
||||
for (int col = 0; col < cols; ++col) delete [] m_data[col];
|
||||
delete[] m_data;
|
||||
}
|
||||
|
||||
QSize size() const { return m_size; }
|
||||
bool** data() { return m_data; }
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(CNonogramSolution)
|
||||
|
||||
QSize m_size;
|
||||
bool ** m_data;
|
||||
};
|
||||
|
||||
QList<CNonogramSolution*> solve(const CNonogramNumbers & numbers);
|
||||
|
||||
class CNonogram;
|
||||
|
||||
class CNonogramSolver : public QObject {
|
||||
@ -20,59 +48,7 @@ namespace libqnono {
|
||||
protected:
|
||||
enum MarkerType {CMT_UNMARKED = 0, CMT_MARKED = 1, CMT_CROSSED = 2, CMT_NONE = 3};
|
||||
|
||||
struct NumberOverlay {
|
||||
int borderLeft;
|
||||
int borderRight;
|
||||
|
||||
quint16 entry;
|
||||
bool finished;
|
||||
};
|
||||
|
||||
struct LineOverlay {
|
||||
NumberOverlay * numbers;
|
||||
int numbersSize;
|
||||
|
||||
bool dirty;
|
||||
|
||||
inline int borderLeftDef(int index, int def) {
|
||||
return (index > -1 && index < numbersSize) ? numbers[index].borderLeft : def;
|
||||
}
|
||||
|
||||
inline int borderRightDef(int index, int def) {
|
||||
return (index > -1 && index < numbersSize) ? numbers[index].borderRight : def;
|
||||
}
|
||||
|
||||
LineOverlay() : numbers(NULL), dirty(false) {}
|
||||
~LineOverlay() { if (numbers) delete[] numbers; }
|
||||
};
|
||||
|
||||
CNonogram * m_Nonogram;
|
||||
|
||||
LineOverlay * m_RowsOverlay;
|
||||
LineOverlay * m_ColumnsOverlay;
|
||||
|
||||
int ** m_OverlayData;
|
||||
|
||||
void cleanup();
|
||||
void prepare();
|
||||
|
||||
inline void mark(int x, int y, int marker);
|
||||
inline void fillRow(int index, int marker);
|
||||
inline void fillColumn(int index, int marker);
|
||||
|
||||
void printOverlays();
|
||||
bool solveLine_ng(int index, bool isRow);
|
||||
|
||||
inline bool solveLine(int index, bool isRow);
|
||||
inline bool fillGaps(int index, bool isRow);
|
||||
inline void prepareBorders(LineOverlay * overlay);
|
||||
inline void updateBorders(int index, bool isRow);
|
||||
|
||||
void updateBorders();
|
||||
|
||||
inline int safeLength(NumberOverlay * overlay) {
|
||||
return (overlay->entry * 2) + overlay->borderLeft - overlay->borderRight;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user