big ugly commit
- renamed library - added support for saving loading current game - added (still crappy) nonogram solver - some code cleanups
This commit is contained in:
parent
6aa6b59c88
commit
8ebd6975d7
@ -22,7 +22,7 @@
|
||||
#include <QDataStream>
|
||||
#include <QFile>
|
||||
|
||||
namespace libqcross {
|
||||
namespace libqnono {
|
||||
//public:
|
||||
CCrossPackage::CCrossPackage() {}
|
||||
CCrossPackage::CCrossPackage(QString fileName) : m_FileName(fileName) {}
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
|
||||
namespace libqcross {
|
||||
namespace libqnono {
|
||||
class CNonogram;
|
||||
|
||||
typedef QList<CNonogram *> QMonoPictureList;
|
||||
|
@ -22,10 +22,10 @@
|
||||
#include "cnonogram.h"
|
||||
#include "ccrosspackagelistmodel.h"
|
||||
|
||||
namespace libqcross {
|
||||
namespace libqnono {
|
||||
//public:
|
||||
CCrossPackageListModel::CCrossPackageListModel(QString dataPath, QObject * parent) : QAbstractItemModel(parent),
|
||||
m_DataPath(dataPath) {
|
||||
CCrossPackageListModel::CCrossPackageListModel(QString dataPath, QString dataFilter, QObject * parent) : QAbstractItemModel(parent),
|
||||
m_DataPath(dataPath), m_DataFilter(dataFilter) {
|
||||
update();
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ namespace libqcross {
|
||||
CCrossPackage * newPackage;
|
||||
|
||||
QDir workDir(m_DataPath);
|
||||
QStringList fileNames = workDir.entryList(QStringList("*.cpk"), QDir::Files | QDir::NoDotAndDotDot, QDir::Name);
|
||||
QStringList fileNames = workDir.entryList(QStringList(m_DataFilter), QDir::Files | QDir::NoDotAndDotDot, QDir::Name);
|
||||
foreach (QString fileName, fileNames) {
|
||||
newPackage = new CCrossPackage(workDir.filePath(fileName));
|
||||
if (newPackage->open())
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <QAbstractItemModel>
|
||||
#include <QList>
|
||||
|
||||
namespace libqcross {
|
||||
namespace libqnono {
|
||||
class CCrossPackage;
|
||||
|
||||
/**
|
||||
@ -32,7 +32,7 @@ namespace libqcross {
|
||||
class CCrossPackageListModel : public QAbstractItemModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
CCrossPackageListModel(QString dataPath, QObject * parent = 0);
|
||||
CCrossPackageListModel(QString dataPath, QString dataFilter, QObject * parent = 0);
|
||||
~CCrossPackageListModel();
|
||||
|
||||
void update();
|
||||
@ -47,8 +47,9 @@ namespace libqcross {
|
||||
virtual bool hasChildren(const QModelIndex & parent = QModelIndex()) const;
|
||||
private:
|
||||
QString m_DataPath;
|
||||
QString m_DataFilter;
|
||||
|
||||
QList<libqcross::CCrossPackage *> m_PackageList;
|
||||
QList<libqnono::CCrossPackage *> m_PackageList;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
#define COL_NAME 0
|
||||
#define COL_TIME 1
|
||||
|
||||
namespace libqcross {
|
||||
namespace libqnono {
|
||||
QString formatedTime(quint32 seconds, bool showSeconds = false) {
|
||||
quint32 strippedSeconds = seconds % 60;
|
||||
quint8 minutes = seconds / 60;
|
||||
@ -67,7 +67,7 @@ namespace libqcross {
|
||||
setPackage(NULL);
|
||||
}
|
||||
|
||||
void CCrossPackageModel::setPackage(libqcross::CCrossPackage * package) {
|
||||
void CCrossPackageModel::setPackage(libqnono::CCrossPackage * package) {
|
||||
if (m_Package)
|
||||
m_Package->pictures().clear();
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
namespace libqcross {
|
||||
namespace libqnono {
|
||||
class CCrossPackage;
|
||||
|
||||
/**
|
||||
@ -34,7 +34,7 @@ namespace libqcross {
|
||||
CCrossPackageModel(QObject * parent = 0);
|
||||
~CCrossPackageModel();
|
||||
|
||||
void setPackage(libqcross::CCrossPackage * package);
|
||||
void setPackage(libqnono::CCrossPackage * package);
|
||||
|
||||
virtual QModelIndex index(int row, int column = 0, const QModelIndex & parent = QModelIndex()) const;
|
||||
virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
|
||||
@ -53,7 +53,7 @@ namespace libqcross {
|
||||
virtual bool insertRows(int row, int count, const QModelIndex & parent = QModelIndex());
|
||||
virtual bool removeRows(int row, int count, const QModelIndex & parent = QModelIndex());
|
||||
protected:
|
||||
libqcross::CCrossPackage * m_Package;
|
||||
libqnono::CCrossPackage * m_Package;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "cnonogram.h"
|
||||
#include <QImage>
|
||||
|
||||
namespace libqcross {
|
||||
namespace libqnono {
|
||||
CNonogram::CNonogram()
|
||||
: m_Size(0, 0),
|
||||
m_Data(NULL),
|
||||
@ -32,6 +32,14 @@ namespace libqcross {
|
||||
init();
|
||||
}
|
||||
|
||||
CNonogram::CNonogram(QImage & image) : m_Data(NULL), m_MaximumNumberCount(0) {
|
||||
loadFromImage(image);
|
||||
}
|
||||
|
||||
CNonogram::CNonogram(QDataStream & stream) : m_Data(NULL), m_MaximumNumberCount(0) {
|
||||
loadFromStream(stream);
|
||||
}
|
||||
|
||||
CNonogram::~CNonogram() {
|
||||
cleanup();
|
||||
}
|
||||
@ -42,9 +50,24 @@ namespace libqcross {
|
||||
|
||||
resize(image.size());
|
||||
|
||||
for (int i = 0; i < m_Size.width(); i++)
|
||||
for (int j = 0; j < m_Size.height(); j++)
|
||||
m_Data[i][j] = !(image.pixel(i, j) & 0x00FFFFFF);
|
||||
for (int iy = 0; iy < m_Size.height(); iy++)
|
||||
for (int ix = 0; ix < m_Size.width(); ix++)
|
||||
m_Data[ix][iy] = !(image.pixel(ix, iy) & 0x00FFFFFF);
|
||||
}
|
||||
|
||||
void CNonogram::loadFromStream(QDataStream & stream) {
|
||||
qDebug("loading picture from stream...");
|
||||
stream >> m_Name; qDebug("m_Name = %s", qPrintable(m_Name));
|
||||
int imageWidth, imageHeight;
|
||||
stream >> imageWidth; qDebug("imageWidth = %i", imageWidth);
|
||||
stream >> imageHeight; qDebug("imageHeight = %i", imageHeight);
|
||||
resize(QSize(imageWidth, imageHeight));
|
||||
|
||||
stream >> m_Timeout;
|
||||
|
||||
for (int iy = 0; iy < m_Size.height(); iy++)
|
||||
for (int ix = 0; ix < m_Size.width(); ix++)
|
||||
stream >> m_Data[ix][iy];
|
||||
}
|
||||
|
||||
void CNonogram::resize(QSize size) {
|
||||
@ -130,4 +153,23 @@ namespace libqcross {
|
||||
m_RowNumbers = new NumbersVector[m_Size.height()];
|
||||
m_ColumnNumbers = new NumbersVector[m_Size.width()];
|
||||
}
|
||||
|
||||
QDataStream & operator<<(QDataStream & stream, CNonogram & nonogram) {
|
||||
stream << nonogram.name();
|
||||
stream << nonogram.width();
|
||||
stream << nonogram.height();
|
||||
stream << nonogram.timeout();
|
||||
|
||||
for (int iy = 0; iy < nonogram.height(); iy++)
|
||||
for (int ix = 0; ix < nonogram.width(); ix++)
|
||||
stream << nonogram.pixel(ix, iy);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream & operator>>(QDataStream & stream, CNonogram & nonogram) {
|
||||
nonogram.loadFromStream(stream);
|
||||
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Oliver Groß *
|
||||
* z.o.gross@gmx.de *
|
||||
* Copyright (C) 2008 by Oliver Groß *
|
||||
* z.o.gross@gmx.de *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
@ -26,36 +26,40 @@
|
||||
|
||||
class QImage;
|
||||
|
||||
namespace libqcross {
|
||||
namespace libqnono {
|
||||
class CNonogram {
|
||||
public:
|
||||
typedef QVector<quint16> NumbersVector;
|
||||
|
||||
CNonogram();
|
||||
CNonogram(QSize size);
|
||||
CNonogram(QImage & image);
|
||||
CNonogram(QDataStream & stream);
|
||||
~CNonogram();
|
||||
|
||||
void loadFromImage(QImage & image);
|
||||
void loadFromStream(QDataStream & stream);
|
||||
void resize(QSize size);
|
||||
|
||||
QString name() const { return m_Name; }
|
||||
void setName(QString value) { m_Name = value; }
|
||||
inline QString name() const { return m_Name; }
|
||||
inline void setName(QString value) { m_Name = value; }
|
||||
|
||||
quint16 timeout() const { return m_Timeout; }
|
||||
inline quint16 timeout() const { return m_Timeout; }
|
||||
void setTimeout(quint16 value) { m_Timeout = value; }
|
||||
|
||||
int width() const { return m_Size.width(); }
|
||||
int height() const { return m_Size.height(); }
|
||||
inline QSize size() const { return m_Size; }
|
||||
inline int width() const { return m_Size.width(); }
|
||||
inline int height() const { return m_Size.height(); }
|
||||
|
||||
bool pixel(int x, int y) const { return m_Data[x][y]; }
|
||||
inline bool pixel(int x, int y) const { return m_Data[x][y]; }
|
||||
void setPixel(int x, int y, bool value);
|
||||
|
||||
NumbersVector & rowNumbers(int index) const { return m_RowNumbers[index]; }
|
||||
NumbersVector & columnNumbers(int index) const { return m_ColumnNumbers[index]; }
|
||||
|
||||
int maximumNumberCount() const { return m_MaximumNumberCount; }
|
||||
inline int maximumNumberCount() const { return m_MaximumNumberCount; }
|
||||
|
||||
quint32 blackPixels() const { return m_BlackPixels; }
|
||||
inline quint32 blackPixels() const { return m_BlackPixels; }
|
||||
|
||||
void updateNumbers();
|
||||
|
||||
@ -79,6 +83,9 @@ namespace libqcross {
|
||||
void cleanup();
|
||||
void init();
|
||||
};
|
||||
|
||||
QDataStream & operator<<(QDataStream & stream, CNonogram & nonogram);
|
||||
QDataStream & operator>>(QDataStream & stream, CNonogram & nonogram);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,12 +1,65 @@
|
||||
#include "cnonogramsolver.h"
|
||||
#include "cnonogram.h"
|
||||
|
||||
namespace libqcross {
|
||||
CNonogramSolver::CNonogramSolver(QObject * parent) : QObject(parent), m_Nonogram(NULL), m_OverlayData(NULL) {
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
|
||||
namespace libqnono {
|
||||
CNonogramSolver::CNonogramSolver(QObject * parent) : QObject(parent),
|
||||
m_Nonogram(NULL),
|
||||
|
||||
m_RowsOverlay(NULL),
|
||||
m_ColumnsOverlay(NULL),
|
||||
|
||||
m_OverlayData(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
CNonogramSolver::~CNonogramSolver() {
|
||||
cleanup();
|
||||
if (m_Nonogram)
|
||||
cleanup();
|
||||
}
|
||||
|
||||
void CNonogramSolver::setNonogram(CNonogram * nonogram) {
|
||||
if (m_Nonogram)
|
||||
cleanup();
|
||||
|
||||
m_Nonogram = nonogram;
|
||||
}
|
||||
|
||||
void CNonogramSolver::printOverlays() {
|
||||
qDebug("row overlays:");
|
||||
QString debugoutput;
|
||||
for (int i = 0; i < m_Nonogram->height(); i++) {
|
||||
if (i) debugoutput += '\n';
|
||||
for (int e = 0; e < m_RowsOverlay[i].numbersSize; e++) {
|
||||
debugoutput += ' ' + QString::number(m_RowsOverlay[i].numbers[e].borderLeft)
|
||||
+ '-' + QString::number(m_RowsOverlay[i].numbers[e].borderRight - 1);
|
||||
|
||||
if (m_RowsOverlay[i].numbers[e].finished)
|
||||
debugoutput += '*';
|
||||
|
||||
debugoutput += ' ';
|
||||
}
|
||||
}
|
||||
qDebug(qPrintable(debugoutput));
|
||||
|
||||
debugoutput.clear();
|
||||
|
||||
qDebug("column overlays:");
|
||||
for (int i = 0; i < m_Nonogram->width(); i++) {
|
||||
if (i) debugoutput += '\n';
|
||||
for (int e = 0; e < m_ColumnsOverlay[i].numbersSize; e++) {
|
||||
debugoutput += ' ' + QString::number(m_ColumnsOverlay[i].numbers[e].borderLeft)
|
||||
+ '-' + QString::number(m_ColumnsOverlay[i].numbers[e].borderRight - 1);
|
||||
|
||||
if (m_ColumnsOverlay[i].numbers[e].finished)
|
||||
debugoutput += '*';
|
||||
|
||||
debugoutput += ' ';
|
||||
}
|
||||
}
|
||||
qDebug(qPrintable(debugoutput));
|
||||
}
|
||||
|
||||
bool CNonogramSolver::solve() {
|
||||
@ -14,52 +67,461 @@ namespace libqcross {
|
||||
return false;
|
||||
|
||||
cleanup();
|
||||
prepare();
|
||||
|
||||
m_OverlayData = new int *[m_Nonogram->width()];
|
||||
for (int i = 0; i < m_Nonogram->width(); i++) {
|
||||
m_OverlayData[i] = new int[m_Nonogram->height()];
|
||||
for (int j = 0; j < m_Nonogram->height(); j++)
|
||||
m_OverlayData[i][j] = 0;
|
||||
qDebug("clearing trivial lines ...");
|
||||
|
||||
// nach trivial lösbaren Reihen suchen und diese füllen bzw. abkreuzen
|
||||
for (int i = 0; i < m_Nonogram->height(); i++) {
|
||||
if (m_RowsOverlay[i].numbersSize == 1) {
|
||||
if (m_RowsOverlay[i].numbers[0].entry == 0) {
|
||||
fillRow(i, CMT_CROSSED);
|
||||
m_RowsOverlay[i].numbers[0].finished = true;
|
||||
}
|
||||
else if (m_RowsOverlay[i].numbers[0].entry == m_Nonogram->height()) {
|
||||
fillRow(i, CMT_MARKED);
|
||||
m_RowsOverlay[i].numbers[0].finished = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_Nonogram->height(); i++)
|
||||
solveRow(i);
|
||||
for (int i = 0; i < m_Nonogram->width(); i++) {
|
||||
if (m_ColumnsOverlay[i].numbersSize == 1) {
|
||||
if (m_ColumnsOverlay[i].numbers[0].entry == 0) {
|
||||
fillColumn(i, CMT_CROSSED);
|
||||
m_ColumnsOverlay[i].numbers[0].finished = true;
|
||||
}
|
||||
else if (m_ColumnsOverlay[i].numbers[0].entry == m_Nonogram->width()) {
|
||||
fillColumn(i, CMT_MARKED);
|
||||
m_ColumnsOverlay[i].numbers[0].finished = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printOverlays();
|
||||
|
||||
qDebug("processing non-trivial lines...");
|
||||
|
||||
bool changed;
|
||||
int iter = 0;
|
||||
const int iter_max = 10;
|
||||
do {
|
||||
changed = false;
|
||||
|
||||
for (int l = 0; l < m_Nonogram->height(); l++)
|
||||
if (solveLine_ng(l, true))
|
||||
changed = true;
|
||||
|
||||
for (int i = 0; i < m_Nonogram->width(); i++)
|
||||
if (solveLine_ng(i, false))
|
||||
changed = true;
|
||||
|
||||
iter++;
|
||||
} while (changed && iter < iter_max);
|
||||
|
||||
// qDebug("needed %i iterations", iter);
|
||||
|
||||
printOverlays();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CNonogramSolver::solveLine_ng(int index, bool isRow) {
|
||||
LineOverlay * overlay = isRow ? &(m_RowsOverlay[index]) : &(m_ColumnsOverlay[index]);
|
||||
int rightMax = isRow ? m_Nonogram->width() : m_Nonogram->height();
|
||||
|
||||
NumberOverlay * number;
|
||||
|
||||
bool result = false;
|
||||
|
||||
for (int i = 0; i < overlay->numbersSize; i++) {
|
||||
number = &(overlay->numbers[i]);
|
||||
|
||||
if (number->finished)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* |-start- null
|
||||
*
|
||||
* null -marked-> markierung
|
||||
* null -crossed-> kreuze
|
||||
* null -unmarked-> keine
|
||||
*
|
||||
* kreuze -marked-> markierung
|
||||
* kreuze -crossed-> kreuze
|
||||
* kreuze -unmarked-> keine
|
||||
*
|
||||
* keine -marked-> markierung
|
||||
* keine -crossed-> kreuzstop
|
||||
* keine -unmarked-> keine
|
||||
*
|
||||
* markierung -marked-> markierung
|
||||
* markierung -crossed-> kreuzstop
|
||||
* markierung -unmarked-> keine
|
||||
*
|
||||
* kreuzstop -stop-|
|
||||
* fertig -stop-|
|
||||
*
|
||||
* null : keine aktion
|
||||
* fertig : rechten rand stzen, als fertig markieren und stop
|
||||
* kreuze : linken rand anpassen
|
||||
* keine : keine aktion
|
||||
*
|
||||
* markierung : rechten rand anpassen
|
||||
* kreuzstop : rechten rand setzen und stop
|
||||
*
|
||||
*/
|
||||
|
||||
{
|
||||
enum{ST_NULL = 0, ST_NONE = 1, ST_CROSSES = 2, ST_MARK = 3, ST_FINISHED = 4, ST_CROSS_STOP = 5} state = ST_NULL;
|
||||
int f = number->borderLeft;
|
||||
MarkerType marker;
|
||||
while (f < number->borderRight && state < ST_FINISHED) {
|
||||
marker = static_cast<MarkerType>(m_OverlayData[isRow ? f : index][isRow ? index : f]);
|
||||
|
||||
switch (state) {
|
||||
case ST_NULL:
|
||||
case ST_CROSSES:
|
||||
switch (marker) {
|
||||
case CMT_MARKED: state = ST_MARK; break;
|
||||
case CMT_CROSSED: state = ST_CROSSES; break;
|
||||
case CMT_UNMARKED: state = ST_NONE; break;
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
case ST_NONE:
|
||||
case ST_MARK:
|
||||
switch (marker) {
|
||||
case CMT_MARKED: state = ST_MARK; break;
|
||||
case CMT_CROSSED: state = ST_CROSS_STOP; break;
|
||||
case CMT_UNMARKED: state = ST_NONE; break;
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
case ST_FINISHED:
|
||||
case ST_CROSS_STOP:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case ST_NONE:
|
||||
case ST_NULL:
|
||||
default:
|
||||
break;
|
||||
case ST_CROSSES:
|
||||
number->borderLeft = f + 1;
|
||||
break;
|
||||
case ST_MARK:
|
||||
if ((f < overlay->borderLeftDef(i + i, rightMax)) &&
|
||||
(overlay->borderRightDef(i - 1, 0) < f) &&
|
||||
(f + number->entry < number->borderRight))
|
||||
number->borderRight = f + number->entry;
|
||||
break;
|
||||
case ST_FINISHED:
|
||||
number->finished = true;
|
||||
number->borderRight = f + number->entry;
|
||||
if (i + 1 < overlay->numbersSize && overlay->numbers[i+1].borderLeft < number->borderRight + 1)
|
||||
overlay->numbers[i+1].borderLeft = number->borderRight + 1;
|
||||
break;
|
||||
case ST_CROSS_STOP:
|
||||
number->borderRight = f;
|
||||
if (i + 1 < overlay->numbersSize && overlay->numbers[i+1].borderLeft < number->borderRight + 1)
|
||||
overlay->numbers[i+1].borderLeft = number->borderRight + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
f++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
sicher markierbare Steine
|
||||
r - l < 2m - 1
|
||||
0 < l + m - r + m - 1
|
||||
0 < (l + m - 1) - (r - m)
|
||||
*/
|
||||
for (int k = number->borderRight - number->entry; k < number->borderLeft + number->entry; k++)
|
||||
mark(isRow ? k : index, isRow ? index : k, CMT_MARKED);
|
||||
|
||||
if (!number->finished && number->borderRight - number->borderLeft == number->entry)
|
||||
number->finished = true;
|
||||
|
||||
for (int g = overlay->borderRightDef(i - 1, 0); g < number->borderLeft; g++)
|
||||
mark(isRow ? g : index, isRow ? index : g, CMT_CROSSED);
|
||||
|
||||
for (int g = number->borderRight; g < overlay->borderLeftDef(i + 1, rightMax); g++)
|
||||
mark(isRow ? g : index, isRow ? index : g, CMT_CROSSED);
|
||||
|
||||
|
||||
result = result || overlay->dirty;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void CNonogramSolver::cleanup() {
|
||||
if (m_OverlayData && m_Nonogram) {
|
||||
if (m_OverlayData) {
|
||||
for (int i = 0; i < m_Nonogram->width(); i++)
|
||||
delete[] m_OverlayData[i];
|
||||
delete[] m_OverlayData;
|
||||
}
|
||||
|
||||
if (m_RowsOverlay)
|
||||
delete[] m_RowsOverlay;
|
||||
|
||||
if (m_ColumnsOverlay)
|
||||
delete[] m_ColumnsOverlay;
|
||||
}
|
||||
|
||||
bool CNonogramSolver::solveRow(int /*y*/) {
|
||||
return false;
|
||||
// int left = 0;
|
||||
// int right = m_Nonogram->width()-1;
|
||||
//
|
||||
// foreach (int k, m_Nonogram->rowNumbers(y)) {
|
||||
// if (k == m_Nonogram->width())
|
||||
// for (int i = 0; )
|
||||
// m_OverlayData[i][y] = 1;
|
||||
// }
|
||||
inline void CNonogramSolver::mark(int x, int y, int marker) {
|
||||
if ((x < 0) || (y < 0) || (x > m_Nonogram->width() - 1) || (y > m_Nonogram->height() - 1) || m_OverlayData[x][y] == marker)
|
||||
return;
|
||||
|
||||
//
|
||||
// while (m_OverlayData[right][y] && left < right)
|
||||
// right++;
|
||||
//
|
||||
// if (left == right)
|
||||
// return true;
|
||||
//
|
||||
// if (m_Nonogram->rowNumbers(y)[0] == 0)
|
||||
// for (int i = left; i <= right; i++)
|
||||
// m_OverlayData[i][y] = MT_CROSSED;
|
||||
//
|
||||
// foreach (int k, m_Nonogram->rowNumbers(y)) {
|
||||
//
|
||||
// }
|
||||
emit markRequested(x, y, marker);
|
||||
m_OverlayData[x][y] = marker;
|
||||
|
||||
m_RowsOverlay[y].dirty = true;
|
||||
m_ColumnsOverlay[x].dirty = true;
|
||||
}
|
||||
|
||||
inline void CNonogramSolver::fillRow(int index, int marker) {
|
||||
for (int i = 0; i < m_Nonogram->width(); i++)
|
||||
mark(i, index, marker);
|
||||
}
|
||||
|
||||
inline void CNonogramSolver::fillColumn(int index, int marker) {
|
||||
for (int i = 0; i < m_Nonogram->height(); i++)
|
||||
mark(index, i, marker);
|
||||
}
|
||||
|
||||
void CNonogramSolver::prepare() {
|
||||
m_OverlayData = new int *[m_Nonogram->width()];
|
||||
|
||||
for (int i = 0; i < m_Nonogram->width(); i++) {
|
||||
m_OverlayData[i] = new int[m_Nonogram->height()];
|
||||
for (int j = 0; j < m_Nonogram->height(); j++)
|
||||
m_OverlayData[i][j] = static_cast<int>(CMT_UNMARKED);
|
||||
}
|
||||
|
||||
int leftSum, rightSum, numSize;
|
||||
|
||||
m_RowsOverlay = new LineOverlay [m_Nonogram->height()];
|
||||
|
||||
for (int i = 0; i < m_Nonogram->height(); i++) {
|
||||
m_RowsOverlay[i].numbersSize = m_Nonogram->rowNumbers(i).size();
|
||||
m_RowsOverlay[i].numbers = new NumberOverlay [m_RowsOverlay[i].numbersSize];
|
||||
|
||||
numSize = m_Nonogram->rowNumbers(i).size();
|
||||
|
||||
leftSum = 0;
|
||||
for (int j = 0; j < numSize; j++) {
|
||||
m_RowsOverlay[i].numbers[j].entry = m_Nonogram->rowNumbers(i).at(j);
|
||||
m_RowsOverlay[i].numbers[j].finished = false;
|
||||
m_RowsOverlay[i].numbers[j].borderRight = m_Nonogram->width();
|
||||
|
||||
m_RowsOverlay[i].numbers[j].borderLeft = leftSum + j;
|
||||
leftSum += m_RowsOverlay[i].numbers[j].entry;
|
||||
}
|
||||
|
||||
rightSum = 0;
|
||||
for (int j = numSize - 1; j > -1; j--) {
|
||||
m_RowsOverlay[i].numbers[j].borderRight -= rightSum;
|
||||
rightSum += m_RowsOverlay[i].numbers[j].entry + 1;
|
||||
}
|
||||
}
|
||||
|
||||
m_ColumnsOverlay = new LineOverlay [m_Nonogram->width()];
|
||||
|
||||
for (int i = 0; i < m_Nonogram->width(); i++) {
|
||||
m_ColumnsOverlay[i].numbersSize = m_Nonogram->columnNumbers(i).size();
|
||||
m_ColumnsOverlay[i].numbers = new NumberOverlay [m_ColumnsOverlay[i].numbersSize];
|
||||
|
||||
numSize = m_Nonogram->columnNumbers(i).size();
|
||||
|
||||
leftSum = 0;
|
||||
for (int j = 0; j < numSize; j++) {
|
||||
m_ColumnsOverlay[i].numbers[j].borderRight = m_Nonogram->height();
|
||||
m_ColumnsOverlay[i].numbers[j].finished = false;
|
||||
m_ColumnsOverlay[i].numbers[j].entry = m_Nonogram->columnNumbers(i).at(j);
|
||||
|
||||
m_ColumnsOverlay[i].numbers[j].borderLeft = leftSum + j;
|
||||
leftSum += m_ColumnsOverlay[i].numbers[j].entry;
|
||||
}
|
||||
|
||||
rightSum = 0;
|
||||
for (int j = numSize - 1; j > -1; j--) {
|
||||
m_ColumnsOverlay[i].numbers[j].borderRight -= rightSum;
|
||||
rightSum += m_ColumnsOverlay[i].numbers[j].entry + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline bool CNonogramSolver::solveLine(int index, bool isRow) {
|
||||
LineOverlay * overlay = isRow ? &(m_RowsOverlay[index]) : &(m_ColumnsOverlay[index]);
|
||||
|
||||
bool result = false;
|
||||
|
||||
QString dbgOut;
|
||||
QTextStream dbg(&dbgOut);
|
||||
|
||||
dbg << "overlay ";
|
||||
if (isRow)
|
||||
dbg << "row ";
|
||||
else
|
||||
dbg << "col ";
|
||||
|
||||
dbg << index << ": ";
|
||||
|
||||
int length = 0;
|
||||
int offset = 0;
|
||||
for (int i = 0; i < overlay->numbersSize; i++) {
|
||||
if (overlay->numbers[i].finished) {
|
||||
dbg << "(fin)";
|
||||
continue;
|
||||
}
|
||||
|
||||
dbg << '(' << overlay->numbers[i].borderLeft << ", " << overlay->numbers[i].borderRight << "; ";
|
||||
|
||||
length = safeLength(&(overlay->numbers[i]));
|
||||
offset = overlay->numbers[i].entry - length + overlay->numbers[i].borderLeft;
|
||||
|
||||
dbg << length << ", " << offset << ") ";
|
||||
|
||||
if (length > 0) {
|
||||
if (isRow) {
|
||||
for (int j = 0; j < length; j++)
|
||||
mark(offset + j, index, CMT_MARKED);
|
||||
}
|
||||
else {
|
||||
for (int j = 0; j < length; j++)
|
||||
mark(index, offset + j, CMT_MARKED);
|
||||
}
|
||||
|
||||
if (length == overlay->numbers[i].entry) {
|
||||
if (isRow) {
|
||||
mark(overlay->numbers[i].borderLeft - 1, index, CMT_CROSSED);
|
||||
mark(overlay->numbers[i].borderRight, index, CMT_CROSSED);
|
||||
}
|
||||
else {
|
||||
mark(index, overlay->numbers[i].borderLeft - 1, CMT_CROSSED);
|
||||
mark(index, overlay->numbers[i].borderRight, CMT_CROSSED);
|
||||
}
|
||||
overlay->numbers[i].finished = true;
|
||||
}
|
||||
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << dbgOut;
|
||||
|
||||
if (fillGaps(index, isRow))
|
||||
return true;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline bool CNonogramSolver::fillGaps(int index, bool isRow) {
|
||||
LineOverlay * overlay = isRow ? &(m_RowsOverlay[index]) : &(m_ColumnsOverlay[index]);
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (isRow) {
|
||||
for (int i = 0; i < overlay->numbersSize + 1; i++) {
|
||||
for (int j = overlay->borderRightDef(i - 1, 0); j < overlay->borderLeftDef(i, m_Nonogram->width()); j++) {
|
||||
if (m_OverlayData[j][index] == 0) {
|
||||
mark(j, index, CMT_CROSSED);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < overlay->numbersSize + 1; i++) {
|
||||
for (int j = overlay->borderRightDef(i - 1, 0); j < overlay->borderLeftDef(i, m_Nonogram->height()); j++) {
|
||||
if (m_OverlayData[index][j] == 0) {
|
||||
mark(index, j, CMT_CROSSED);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void gtSet(int & target, int value) {
|
||||
if (target > value)
|
||||
target = value;
|
||||
}
|
||||
|
||||
inline void ltSet(int & target, int value) {
|
||||
if (target < value)
|
||||
target = value;
|
||||
}
|
||||
|
||||
inline void CNonogramSolver::prepareBorders(LineOverlay * overlay) {
|
||||
for (int i = 1; i < overlay->numbersSize; i++)
|
||||
ltSet(overlay->numbers[i].borderLeft, overlay->numbers[i - 1].borderLeft + overlay->numbers[i - 1].entry + 1);
|
||||
|
||||
for (int i = overlay->numbersSize - 1; i > 0; i--)
|
||||
gtSet(overlay->numbers[i - 1].borderRight, overlay->numbers[i].borderRight - overlay->numbers[i].entry - 1);
|
||||
}
|
||||
|
||||
inline void CNonogramSolver::updateBorders(int index, bool isRow) {
|
||||
LineOverlay * overlay = isRow ? &(m_RowsOverlay[index]) : &(m_ColumnsOverlay[index]);
|
||||
|
||||
if (!overlay->dirty)
|
||||
return;
|
||||
|
||||
int marker = 0;
|
||||
|
||||
for (int i = 0; i < overlay->numbersSize; i++) {
|
||||
if (overlay->numbers[i].finished)
|
||||
continue;
|
||||
|
||||
int j = overlay->numbers[i].borderLeft;
|
||||
// int markedCount = 0;
|
||||
while (j < overlay->numbers[i].borderRight) {
|
||||
marker = (isRow ? m_OverlayData[j][index] : m_OverlayData[index][j]);
|
||||
switch (marker) {
|
||||
case CMT_CROSSED:
|
||||
if (overlay->numbers[i].borderLeft == j)
|
||||
overlay->numbers[i].borderLeft = j+1;
|
||||
else {
|
||||
if (j - overlay->numbers[i].borderLeft + 1 < j + overlay->numbers[i].entry)
|
||||
overlay->numbers[i].borderLeft = j+1;
|
||||
else
|
||||
overlay->numbers[i].borderRight = j;
|
||||
if (i < overlay->numbersSize-1)
|
||||
ltSet(overlay->numbers[i + 1].borderLeft, j);
|
||||
}
|
||||
break;
|
||||
case CMT_MARKED:
|
||||
gtSet(overlay->numbers[i].borderRight, j + overlay->numbers[i].entry);
|
||||
/* if (markedCount != -1)
|
||||
markedCount++;*/
|
||||
break;
|
||||
default:
|
||||
/* if (markedCount > 0) {
|
||||
markedCount = -1;
|
||||
ltSet(overlay->numbers[i].borderLeft, j - overlay->numbers[i].entry + 1);
|
||||
}*/
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
overlay->dirty = false;
|
||||
}
|
||||
|
||||
void CNonogramSolver::updateBorders() {
|
||||
for (int i = 0; i < m_Nonogram->height(); i++)
|
||||
updateBorders(i, true);
|
||||
|
||||
for (int i = 0; i < m_Nonogram->width(); i++)
|
||||
updateBorders(i, false);
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace libqcross {
|
||||
namespace libqnono {
|
||||
class CNonogram;
|
||||
|
||||
class CNonogramSolver : public QObject {
|
||||
@ -12,27 +12,67 @@ namespace libqcross {
|
||||
CNonogramSolver(QObject * parent = 0);
|
||||
~CNonogramSolver();
|
||||
|
||||
void setNonogram(CNonogram * nonogram) { m_Nonogram = nonogram; }
|
||||
void setNonogram(CNonogram * nonogram);
|
||||
public slots:
|
||||
bool solve();
|
||||
signals:
|
||||
void markRequested(int x, int y, int type);
|
||||
protected:
|
||||
// struct Range {
|
||||
// int left;
|
||||
// int right;
|
||||
//
|
||||
// Range() : left(-1), right(-1) {}
|
||||
// bool isNULL() { return left == -1; }
|
||||
// };
|
||||
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();
|
||||
|
||||
bool solveRow(int y);
|
||||
bool solveColumn(int x);
|
||||
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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,10 @@
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
#include "ccrossfieldwidget.h"
|
||||
#include <libqcross/cnonogram.h>
|
||||
|
||||
#include <libqnono/cnonogram.h>
|
||||
#include <libqnono/cnonogramsolver.h>
|
||||
|
||||
#include <QPainter>
|
||||
#include <QMouseEvent>
|
||||
#include <QLCDNumber>
|
||||
@ -30,7 +33,7 @@
|
||||
#include <QApplication>
|
||||
|
||||
namespace qcross {
|
||||
using namespace libqcross;
|
||||
using namespace libqnono;
|
||||
|
||||
int min(int a, int b) {
|
||||
return (a < b) ? a : b;
|
||||
@ -54,28 +57,28 @@ namespace qcross {
|
||||
m_MessageTimeoutId(-1),
|
||||
m_Clock(NULL),
|
||||
m_ErrorCount(0),
|
||||
m_LastErrorMark(-1,-1)
|
||||
m_LastErrorMark(-1, -1)
|
||||
{
|
||||
m_Notifier = new QFrame(this);
|
||||
m_Notifier->setLineWidth(10);
|
||||
m_Notifier->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
|
||||
// m_Notifier = new QFrame(this);
|
||||
// m_Notifier->setLineWidth(10);
|
||||
// m_Notifier->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
|
||||
QPalette notifierPalette(QApplication::palette().color(QPalette::ToolTipBase));
|
||||
notifierPalette.setColor(QPalette::Text, QApplication::palette().color(QPalette::ToolTipText));
|
||||
|
||||
m_Notifier->setPalette(notifierPalette);
|
||||
m_Notifier->setAutoFillBackground(true);
|
||||
// m_Notifier->setPalette(notifierPalette);
|
||||
// m_Notifier->setAutoFillBackground(true);
|
||||
|
||||
QHBoxLayout * notifierLayout = new QHBoxLayout(m_Notifier);
|
||||
m_NotifierIcon = new QLabel(m_Notifier);
|
||||
m_NotifierText = new QLabel(m_Notifier);
|
||||
// QHBoxLayout * notifierLayout = new QHBoxLayout(m_Notifier);
|
||||
// m_NotifierIcon = new QLabel(m_Notifier);
|
||||
// m_NotifierText = new QLabel(m_Notifier);
|
||||
|
||||
m_NotifierText->setWordWrap(true);
|
||||
notifierLayout->addWidget(m_NotifierIcon);
|
||||
notifierLayout->addWidget(m_NotifierText);
|
||||
notifierLayout->addStretch();
|
||||
m_Notifier->setLayout(notifierLayout);
|
||||
// m_NotifierText->setWordWrap(true);
|
||||
// notifierLayout->addWidget(m_NotifierIcon);
|
||||
// notifierLayout->addWidget(m_NotifierText);
|
||||
// notifierLayout->addStretch();
|
||||
// m_Notifier->setLayout(notifierLayout);
|
||||
|
||||
m_Notifier->hide();
|
||||
// m_Notifier->hide();
|
||||
|
||||
m_Clock = new QLCDNumber(8, this);
|
||||
m_Clock->setVisible(m_Picture);
|
||||
@ -92,12 +95,15 @@ namespace qcross {
|
||||
CCrossFieldWidget::~CCrossFieldWidget() {
|
||||
cleanup();
|
||||
|
||||
delete m_Clock;
|
||||
// delete m_Clock;
|
||||
}
|
||||
|
||||
void CCrossFieldWidget::setPicture(CNonogram * picture) {
|
||||
cleanup();
|
||||
if (m_Picture)
|
||||
cleanup();
|
||||
|
||||
m_Picture = picture;
|
||||
|
||||
if (m_Picture) {
|
||||
m_LastErrorMark.setX(-1);
|
||||
m_LastErrorMark.setY(-1);
|
||||
@ -120,7 +126,7 @@ namespace qcross {
|
||||
}
|
||||
m_Clock->setVisible(m_Picture);
|
||||
}
|
||||
//beim Laden eines neuen Spiels nach einem beendeten wird das neue nicht automatisch gestartet (Restart nötig)
|
||||
|
||||
void CCrossFieldWidget::showMessage(const QString message, int timeout, MessageType type) {
|
||||
if (!message.isEmpty()) {
|
||||
Message newMessage;
|
||||
@ -134,15 +140,85 @@ namespace qcross {
|
||||
nextMessage();
|
||||
}
|
||||
|
||||
void CCrossFieldWidget::applyState(QDataStream & stream) {
|
||||
qDebug("trying to apply state...");
|
||||
qDebug("reading basic stuff:");
|
||||
|
||||
// error state
|
||||
stream >> m_ErrorAware; qDebug("m_ErrorAware = %i", int(m_ErrorAware));
|
||||
stream >> m_ErrorCount; qDebug("m_ErrorCount = %i", m_ErrorCount);
|
||||
|
||||
// time(out)
|
||||
stream >> m_Time; qDebug("m_Time = %i", m_Time);
|
||||
updateTimeDisplay();
|
||||
emit timeChanged(m_Time);
|
||||
|
||||
// messages
|
||||
int messageCount;
|
||||
stream >> messageCount; qDebug("messageCount = %i", messageCount);
|
||||
|
||||
m_Messages.clear();
|
||||
|
||||
unsigned char byteBuffer;
|
||||
for (int i = 0; i < messageCount; i++) {
|
||||
qDebug("message #%i:", i);
|
||||
stream >> byteBuffer; qDebug("type = %i", byteBuffer);
|
||||
m_Message.type = MessageType(byteBuffer);
|
||||
if (m_Message.type != Invalid) {
|
||||
stream >> m_Message.timeout; qDebug("timeout = %i", m_Message.timeout);
|
||||
stream >> m_Message.text; qDebug("text = %s", qPrintable(m_Message.text));
|
||||
|
||||
m_Messages.enqueue(m_Message);
|
||||
}
|
||||
}
|
||||
nextMessage();
|
||||
|
||||
// overlaydata
|
||||
for (int iy = 0; iy < m_Picture->height(); iy++) {
|
||||
for (int ix = 0; ix < m_Picture->width(); ix++) {
|
||||
stream >> byteBuffer;
|
||||
m_OverlayData[ix][iy] = MarkerType(byteBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCrossFieldWidget::dumpState(QDataStream & stream) {
|
||||
if (!m_OverlayData || !m_Picture)
|
||||
return;
|
||||
|
||||
// error state
|
||||
stream << m_ErrorAware;
|
||||
stream << m_ErrorCount;
|
||||
|
||||
// time(out)
|
||||
stream << m_Time;
|
||||
|
||||
// messages
|
||||
// actually we should dump the message queue
|
||||
// for now only dump last displayed
|
||||
// TODO dump message queue
|
||||
stream << 1; // dummy message count
|
||||
stream << (unsigned char)(m_Message.type);
|
||||
if (m_Message.type != Invalid) {
|
||||
stream << m_Message.timeout;
|
||||
stream << m_Message.text;
|
||||
}
|
||||
|
||||
// overlaydata
|
||||
for (int iy = 0; iy < m_Picture->height(); iy++) {
|
||||
for (int ix = 0; ix < m_Picture->width(); ix++)
|
||||
stream << (unsigned char)(m_OverlayData[ix][iy]);
|
||||
}
|
||||
}
|
||||
|
||||
//public slots
|
||||
void CCrossFieldWidget::mark(int x, int y, qcross::MarkerType type) {
|
||||
void CCrossFieldWidget::mark(int x, int y, int type) {
|
||||
if (type == CMT_NONE || x < 0 || x >= m_Picture->width() || y < 0 || y >= m_Picture->height())
|
||||
return;
|
||||
|
||||
if (type == CMT_MARKED && checkNoError(x, y))
|
||||
m_OverlayData[x][y] = CMT_MARKED;
|
||||
else
|
||||
m_OverlayData[x][y] = type;
|
||||
MarkerType marker = static_cast<qcross::MarkerType>(type);
|
||||
|
||||
execMark(x, y, marker);
|
||||
}
|
||||
|
||||
void CCrossFieldWidget::setTime(int value) {
|
||||
@ -154,6 +230,7 @@ namespace qcross {
|
||||
|
||||
if (m_ErrorAware && !m_Time) {
|
||||
killTimer(m_TimerId);
|
||||
m_TimerId = -1;
|
||||
m_Paused = true;
|
||||
emit timeUp();
|
||||
}
|
||||
@ -182,6 +259,17 @@ namespace qcross {
|
||||
return;
|
||||
|
||||
killTimer(m_TimerId);
|
||||
m_TimerId = -1;
|
||||
|
||||
if (m_Message.type != Invalid) {
|
||||
m_Messages.enqueue(m_Message);
|
||||
|
||||
if (m_MessageTimeoutId != -1) {
|
||||
killTimer(m_MessageTimeoutId);
|
||||
m_MessageTimeoutId = -1;
|
||||
}
|
||||
}
|
||||
|
||||
m_Paused = true;
|
||||
setEnabled(false);
|
||||
}
|
||||
@ -205,31 +293,33 @@ namespace qcross {
|
||||
|
||||
if (m_Messages.isEmpty()) {
|
||||
m_Message.type = Invalid;
|
||||
// m_Notifier->hide();
|
||||
// updateMetrics();
|
||||
update();
|
||||
return;
|
||||
}
|
||||
|
||||
Message m_Next = m_Messages.dequeue();
|
||||
m_Message = m_Messages.dequeue();
|
||||
update();
|
||||
|
||||
// switch (next.type) {
|
||||
// case Information:
|
||||
// m_NotifierIcon->setPixmap(style()->standardIcon(QStyle::SP_MessageBoxInformation).pixmap(22, 22));
|
||||
// break;
|
||||
// case Warning:
|
||||
// m_NotifierIcon->setPixmap(style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(22, 22));
|
||||
// break;
|
||||
// case Critical:
|
||||
// m_NotifierIcon->setPixmap(style()->standardIcon(QStyle::SP_MessageBoxCritical).pixmap(22, 22));
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
/* switch (m_Message.type) {
|
||||
case Information:
|
||||
m_NotifierIcon->setPixmap(style()->standardIcon(QStyle::SP_MessageBoxInformation).pixmap(22, 22));
|
||||
break;
|
||||
case Warning:
|
||||
m_NotifierIcon->setPixmap(style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(22, 22));
|
||||
break;
|
||||
case Critical:
|
||||
m_NotifierIcon->setPixmap(style()->standardIcon(QStyle::SP_MessageBoxCritical).pixmap(22, 22));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// m_NotifierText->setText(next.text);
|
||||
m_NotifierText->setText(m_Message.text);
|
||||
|
||||
// m_Notifier->show();
|
||||
// updateMetrics();
|
||||
m_Notifier->show();
|
||||
updateMetrics();*/
|
||||
|
||||
if (m_Message.timeout)
|
||||
m_MessageTimeoutId = startTimer(m_Message.timeout);
|
||||
@ -259,8 +349,16 @@ namespace qcross {
|
||||
}
|
||||
|
||||
void CCrossFieldWidget::cleanup() {
|
||||
killTimer(m_TimerId);
|
||||
killTimer(m_MessageTimeoutId);
|
||||
qDebug("m_TimerId = %i m_MessageTimeoutId = %i", m_TimerId, m_MessageTimeoutId);
|
||||
if (m_TimerId != -1) {
|
||||
killTimer(m_TimerId);
|
||||
m_TimerId = -1;
|
||||
}
|
||||
|
||||
if (m_MessageTimeoutId != -1) {
|
||||
killTimer(m_MessageTimeoutId);
|
||||
m_MessageTimeoutId = -1;
|
||||
}
|
||||
|
||||
if (m_OverlayData) {
|
||||
for (int i = 0; i < m_Picture->width(); i++)
|
||||
@ -321,27 +419,24 @@ namespace qcross {
|
||||
m_Clock->display(time);
|
||||
}
|
||||
|
||||
void CCrossFieldWidget::execMark(int x, int y) {
|
||||
/* if (m_OverlayData[x][y] == m_MouseMark)
|
||||
return;*/
|
||||
|
||||
switch (m_MouseMark) {
|
||||
void CCrossFieldWidget::execMark(int x, int y, MarkerType & marker) {
|
||||
switch (marker) {
|
||||
case CMT_MARKED:
|
||||
if (m_Picture->pixel(x, y)) {
|
||||
m_RemainingPixels--;
|
||||
m_OverlayData[x][y] = m_MouseMark;
|
||||
}
|
||||
else if (m_ErrorAware) {
|
||||
m_ErrorCount++;
|
||||
m_MouseMark = CMT_NONE;
|
||||
m_OverlayData[x][y] = CMT_CROSSED;
|
||||
m_LastErrorMark.setX(x);
|
||||
m_LastErrorMark.setY(y);
|
||||
emit markError();
|
||||
m_OverlayData[x][y] = marker;
|
||||
}
|
||||
else {
|
||||
m_ErrorCount++;
|
||||
m_OverlayData[x][y] = m_MouseMark;
|
||||
if (m_ErrorAware) {
|
||||
m_OverlayData[x][y] = CMT_CROSSED;
|
||||
marker = CMT_NONE;
|
||||
m_LastErrorMark.setX(x);
|
||||
m_LastErrorMark.setY(y);
|
||||
emit markError();
|
||||
}
|
||||
else
|
||||
m_OverlayData[x][y] = marker;
|
||||
}
|
||||
break;
|
||||
case CMT_CROSSED:
|
||||
@ -354,11 +449,11 @@ namespace qcross {
|
||||
if (m_OverlayData[x][y] == CMT_MARKED) {
|
||||
if (m_Picture->pixel(x, y))
|
||||
m_RemainingPixels++;
|
||||
else
|
||||
else if (!m_ErrorAware)
|
||||
m_ErrorCount--;
|
||||
}
|
||||
|
||||
m_OverlayData[x][y] = m_MouseMark;
|
||||
m_OverlayData[x][y] = marker;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -366,6 +461,7 @@ namespace qcross {
|
||||
|
||||
if (!m_RemainingPixels && (m_ErrorAware || !m_ErrorCount)) {
|
||||
killTimer(m_TimerId);
|
||||
m_TimerId = -1;
|
||||
m_Paused = true;
|
||||
m_Solved = true;
|
||||
emit solved();
|
||||
@ -387,6 +483,7 @@ namespace qcross {
|
||||
int gridWidth = m_RasterWidth - m_HeaderWidth;
|
||||
int gridHeight = m_RasterHeight - m_HeaderHeight;
|
||||
|
||||
// draw background
|
||||
{
|
||||
const int delta = 5 * m_BoxSize;
|
||||
|
||||
@ -395,76 +492,81 @@ namespace qcross {
|
||||
int deltaX = delta;
|
||||
int deltaY;
|
||||
|
||||
bool useBase = false;
|
||||
bool useBaseX;
|
||||
bool useBaseY = true;
|
||||
|
||||
while (offsetX < gridWidth) {
|
||||
offsetY = 0;
|
||||
deltaY = delta;
|
||||
while (offsetY < gridHeight) {
|
||||
painter.fillRect(originX + offsetX, originY + offsetY, deltaX, deltaY,
|
||||
palette().color(useBase ? QPalette::Base : QPalette::AlternateBase));
|
||||
|
||||
useBase = !useBase;
|
||||
|
||||
offsetY += delta;
|
||||
|
||||
if (gridWidth - offsetY < delta)
|
||||
deltaY = gridWidth - offsetY;
|
||||
}
|
||||
|
||||
useBase = !useBase;
|
||||
|
||||
offsetX += delta;
|
||||
|
||||
if (gridWidth - offsetX < delta)
|
||||
deltaX = gridWidth - offsetX;
|
||||
|
||||
offsetY = 0;
|
||||
deltaY = delta;
|
||||
|
||||
useBaseX = useBaseY;
|
||||
while (offsetY < gridHeight) {
|
||||
if (gridHeight - offsetY < delta)
|
||||
deltaY = gridHeight - offsetY;
|
||||
|
||||
painter.fillRect(originX + offsetX, originY + offsetY, deltaX, deltaY,
|
||||
palette().color(useBaseX ? QPalette::Base : QPalette::AlternateBase));
|
||||
|
||||
useBaseX = !useBaseX;
|
||||
|
||||
offsetY += deltaY;
|
||||
}
|
||||
|
||||
useBaseY = !useBaseY;
|
||||
|
||||
offsetX += deltaX;
|
||||
}
|
||||
}
|
||||
|
||||
painter.setBrush(palette().color(QPalette::Highlight));
|
||||
|
||||
QFont font = painter.font();
|
||||
font.setPixelSize(m_MarkerSize * 0.9);
|
||||
|
||||
// draw markers and crosses
|
||||
{
|
||||
QPen pen;
|
||||
|
||||
pen.setWidth(m_MarkerSize / 10);
|
||||
|
||||
pen.setWidth(m_MarkerSize / 8);
|
||||
painter.setPen(pen);
|
||||
}
|
||||
|
||||
QRectF markerRect(m_MarkerOffset, m_MarkerOffset, m_MarkerSize, m_MarkerSize);
|
||||
|
||||
for (int i = 0; i < m_Picture->width(); i++) {
|
||||
originX = m_OffsetX + m_HeaderWidth + i * m_BoxSize;
|
||||
markerRect.moveLeft(originX + m_MarkerOffset);
|
||||
|
||||
for (int j = 0; j < m_Picture->height(); j++) {
|
||||
originY = m_OffsetY + m_HeaderHeight + j * m_BoxSize;
|
||||
markerRect.moveTop(originY + m_MarkerOffset);
|
||||
QRectF markerRect(m_MarkerOffset, m_MarkerOffset, m_MarkerSize, m_MarkerSize);
|
||||
|
||||
QColor markerColor = palette().color(QPalette::Highlight);
|
||||
QColor errorColor = markerColor;
|
||||
errorColor.setAlpha(128);
|
||||
|
||||
painter.setBrush(markerColor);
|
||||
for (int i = 0; i < m_Picture->width(); i++) {
|
||||
originX = m_OffsetX + m_HeaderWidth + i * m_BoxSize;
|
||||
markerRect.moveLeft(originX + m_MarkerOffset);
|
||||
|
||||
switch (m_OverlayData[i][j]) {
|
||||
case CMT_MARKED:
|
||||
painter.fillRect(markerRect, painter.brush());
|
||||
break;
|
||||
case CMT_CROSSED:
|
||||
if (m_Solved)
|
||||
break;
|
||||
for (int j = 0; j < m_Picture->height(); j++) {
|
||||
originY = m_OffsetY + m_HeaderHeight + j * m_BoxSize;
|
||||
markerRect.moveTop(originY + m_MarkerOffset);
|
||||
|
||||
if (m_ErrorAware && m_ErrorCount && i == m_LastErrorMark.x() && j == m_LastErrorMark.y()) {
|
||||
switch (m_OverlayData[i][j]) {
|
||||
case CMT_MARKED:
|
||||
painter.fillRect(markerRect, painter.brush());
|
||||
break;
|
||||
case CMT_CROSSED:
|
||||
if (m_Solved)
|
||||
break;
|
||||
|
||||
if (m_ErrorAware && m_ErrorCount && i == m_LastErrorMark.x() && j == m_LastErrorMark.y()) {
|
||||
painter.setBrush(errorColor);
|
||||
painter.fillRect(markerRect, painter.brush());
|
||||
painter.setBrush(markerColor);
|
||||
}
|
||||
|
||||
painter.drawLine(markerRect.topLeft(), markerRect.bottomRight());
|
||||
painter.drawLine(markerRect.bottomLeft(), markerRect.topRight());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
painter.drawLine(markerRect.topLeft(), markerRect.bottomRight());
|
||||
painter.drawLine(markerRect.bottomLeft(), markerRect.topRight());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// draw grid lines
|
||||
painter.setPen(palette().color(QPalette::Dark));
|
||||
|
||||
for (int i = m_OffsetX + m_HeaderWidth; i < m_OffsetX + m_RasterWidth; i += m_BoxSize) {
|
||||
@ -475,9 +577,13 @@ namespace qcross {
|
||||
painter.drawLine(m_OffsetX + m_HeaderWidth, i, m_OffsetX + m_RasterWidth-1, i);
|
||||
}
|
||||
|
||||
// draw numbers area
|
||||
if (m_Paused)
|
||||
painter.setPen(palette().color(QPalette::Shadow));
|
||||
|
||||
QFont font = painter.font();
|
||||
font.setPixelSize(m_MarkerSize * 0.9);
|
||||
|
||||
painter.setFont(font);
|
||||
|
||||
for (int i = 0; i < m_Picture->width(); i++) {
|
||||
@ -514,10 +620,19 @@ namespace qcross {
|
||||
painter.drawLine(m_OffsetX, originY, m_OffsetX + m_RasterWidth-1, originY);
|
||||
}
|
||||
|
||||
// draw message if needed
|
||||
if (m_Message.type != Invalid) {
|
||||
painter.drawText(m_HeaderWidth + m_OffsetX, m_HeaderHeight + m_OffsetY, m_Message.text);
|
||||
QRect boxrect(m_HeaderWidth + m_OffsetX, m_HeaderHeight + m_OffsetY, m_RasterWidth - m_HeaderWidth, m_RasterHeight - m_HeaderHeight);
|
||||
|
||||
QColor fillColor = palette().color(QPalette::Base);
|
||||
fillColor.setAlpha(220);
|
||||
painter.fillRect(boxrect, fillColor);
|
||||
|
||||
font.setPixelSize(font.pixelSize() * 2);
|
||||
|
||||
painter.setFont(font);
|
||||
painter.drawText(boxrect, Qt::AlignVCenter | Qt::AlignCenter | Qt::TextWordWrap, m_Message.text);
|
||||
}
|
||||
// painter.drawLine(m_OffsetX, m_OffsetY + m_RasterHeight, m_OffsetX + m_RasterWidth, m_OffsetY + m_RasterHeight);
|
||||
}
|
||||
|
||||
/* void CCrossFieldWidget::updateCell(int x, int y) {
|
||||
@ -570,12 +685,12 @@ namespace qcross {
|
||||
m_OffsetX = (width() - m_RasterWidth) / 2;
|
||||
m_OffsetY = (height() - m_RasterHeight) / 2;
|
||||
|
||||
int clockHeight = m_Notifier->isVisible() ? m_HeaderHeight - m_Notifier->sizeHint().height() /* * 3.0 / 4.0 */ : m_HeaderHeight;
|
||||
int clockHeight = /*m_Notifier->isVisible() ? m_HeaderHeight - m_Notifier->sizeHint().height()*/ /* * 3.0 / 4.0 */ /*:*/ m_HeaderHeight;
|
||||
|
||||
if (m_Clock)
|
||||
m_Clock->setGeometry(m_OffsetX, m_OffsetY, m_HeaderWidth, clockHeight);
|
||||
if (m_Notifier && m_Notifier->isVisible())
|
||||
m_Notifier->setGeometry(m_OffsetX, m_OffsetY + clockHeight, m_HeaderWidth, m_Notifier->sizeHint().height());
|
||||
// if (m_Notifier && m_Notifier->isVisible())
|
||||
// m_Notifier->setGeometry(m_OffsetX, m_OffsetY + clockHeight, m_HeaderWidth, m_Notifier->sizeHint().height());
|
||||
}
|
||||
|
||||
void CCrossFieldWidget::mousePressEvent(QMouseEvent * event) {
|
||||
@ -600,7 +715,7 @@ namespace qcross {
|
||||
if (m_OverlayData[pressedX][pressedY] == m_MouseMark)
|
||||
m_MouseMark = CMT_UNMARKED;
|
||||
|
||||
execMark(pressedX, pressedY);
|
||||
execMark(pressedX, pressedY, m_MouseMark);
|
||||
update();
|
||||
}
|
||||
|
||||
@ -621,7 +736,7 @@ namespace qcross {
|
||||
pressedY = (pressedY - m_HeaderHeight) / m_BoxSize;
|
||||
|
||||
if (m_OverlayData[pressedX][pressedY] != m_MouseMark) {
|
||||
execMark(pressedX, pressedY);
|
||||
execMark(pressedX, pressedY, m_MouseMark);
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
@ -27,8 +27,9 @@ class QLCDNumber;
|
||||
class QFrame;
|
||||
class QLabel;
|
||||
|
||||
namespace libqcross {
|
||||
namespace libqnono {
|
||||
class CNonogram;
|
||||
class CNonogramSolver;
|
||||
}
|
||||
|
||||
namespace qcross {
|
||||
@ -37,7 +38,7 @@ namespace qcross {
|
||||
class CCrossFieldWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum MessageType {Information, Warning, Critical, Invalid};
|
||||
enum MessageType {Information = 1, Warning = 2, Critical = 3, Invalid = 0};
|
||||
|
||||
bool isPaused() const { return m_Paused; }
|
||||
bool isSolved() const { return m_Solved; }
|
||||
@ -46,17 +47,20 @@ namespace qcross {
|
||||
int time() const { return m_Time; }
|
||||
qint32 errorCount() const { return m_ErrorCount; }
|
||||
|
||||
CCrossFieldWidget(libqcross::CNonogram * picture, QWidget * parent = 0);
|
||||
CCrossFieldWidget(libqnono::CNonogram * picture, QWidget * parent = 0);
|
||||
~CCrossFieldWidget();
|
||||
|
||||
QPoint lastErrorMark() const { return m_LastErrorMark; }
|
||||
|
||||
void setPicture(libqcross::CNonogram * picture);
|
||||
void setPicture(libqnono::CNonogram * picture);
|
||||
|
||||
void showMessage(const QString message = QString(), int timeout = 0, MessageType type = Information);
|
||||
|
||||
void applyState(QDataStream & stream);
|
||||
void dumpState(QDataStream & stream);
|
||||
|
||||
public slots:
|
||||
void mark(int x, int y, qcross::MarkerType type);
|
||||
void mark(int x, int y, int type);
|
||||
void setTime(int value);
|
||||
void setErrorAware(bool value);
|
||||
void setNumbersMarkable(bool value);
|
||||
@ -81,7 +85,7 @@ namespace qcross {
|
||||
|
||||
QQueue<Message> m_Messages;
|
||||
|
||||
libqcross::CNonogram * m_Picture;
|
||||
libqnono::CNonogram * m_Picture;
|
||||
MarkerType ** m_OverlayData;
|
||||
quint32 m_RemainingPixels;
|
||||
|
||||
@ -107,9 +111,9 @@ namespace qcross {
|
||||
|
||||
QLCDNumber * m_Clock;
|
||||
|
||||
QFrame * m_Notifier;
|
||||
QLabel * m_NotifierIcon;
|
||||
QLabel * m_NotifierText;
|
||||
// QFrame * m_Notifier;
|
||||
// QLabel * m_NotifierIcon;
|
||||
// QLabel * m_NotifierText;
|
||||
|
||||
qint32 m_ErrorCount;
|
||||
QPoint m_LastErrorMark;
|
||||
@ -126,7 +130,7 @@ namespace qcross {
|
||||
void timerEvent(QTimerEvent * event);
|
||||
inline void updateTimeDisplay();
|
||||
|
||||
inline void execMark(int x, int y);
|
||||
inline void execMark(int x, int y, MarkerType & marker);
|
||||
|
||||
void paintEvent(QPaintEvent * event);
|
||||
|
||||
|
@ -28,16 +28,18 @@
|
||||
#include <QDir>
|
||||
#include <QInputDialog>
|
||||
|
||||
#include <libqcross/cnonogram.h>
|
||||
#include <libqcross/ccrosspackage.h>
|
||||
#include <libqnono/cnonogram.h>
|
||||
#include <libqnono/cnonogramsolver.h>
|
||||
#include <libqnono/ccrosspackage.h>
|
||||
|
||||
#include "constants.h"
|
||||
#include "cgamewindow.h"
|
||||
#include "ccrossfieldwidget.h"
|
||||
#include "cnewgamedialog.h"
|
||||
#include "chighscore.h"
|
||||
|
||||
namespace qcross {
|
||||
using namespace libqcross;
|
||||
using namespace libqnono;
|
||||
//public
|
||||
CGameWindow::CGameWindow(QWidget * parent) : QMainWindow(parent) {
|
||||
m_Highscore = NULL;
|
||||
@ -49,11 +51,13 @@ namespace qcross {
|
||||
m_Field->setTime(42 * 60 + 23);
|
||||
|
||||
setCentralWidget(m_Field);
|
||||
// m_Field->showMessage(tr("Welcome to QCross!"));
|
||||
m_Field->showMessage(tr("Welcome to QCross!"));
|
||||
|
||||
createActions();
|
||||
// statusBar()->show();
|
||||
m_Solver = new CNonogramSolver(this);
|
||||
|
||||
connect(m_Solver, SIGNAL(markRequested(int, int, int)), m_Field, SLOT(mark(int, int, int)));
|
||||
connect(m_Field, SIGNAL(solved()), this, SLOT(wonGame()));
|
||||
connect(m_Field, SIGNAL(timeUp()), this, SLOT(lostGame()));
|
||||
connect(m_Field, SIGNAL(markError()), this, SLOT(handleErrorMark()));
|
||||
@ -73,6 +77,9 @@ namespace qcross {
|
||||
currentMenu = menuBar()->addMenu(tr("&Game"));
|
||||
currentMenu->addAction(tr("&New..."), this, SLOT(newGame()), Qt::CTRL + Qt::Key_N);
|
||||
currentMenu->addSeparator();
|
||||
currentMenu->addAction(tr("&Save..."), this, SLOT(saveGame()), Qt::CTRL + Qt::Key_N);
|
||||
currentMenu->addAction(tr("&Load..."), this, SLOT(loadGame()), Qt::CTRL + Qt::Key_N);
|
||||
currentMenu->addSeparator();
|
||||
m_RestartGameAction = currentMenu->addAction(tr("&Restart"), this, SLOT(restartGame()), Qt::CTRL + Qt::Key_R);
|
||||
m_RestartGameAction->setEnabled(false);
|
||||
m_PauseGameAction = currentMenu->addAction(tr("&Pause"));
|
||||
@ -82,8 +89,8 @@ namespace qcross {
|
||||
m_PauseGameAction->setEnabled(false);
|
||||
currentMenu->addSeparator();
|
||||
currentMenu->addAction(tr("&Quit"), this, SLOT(close()), Qt::CTRL + Qt::Key_Q);
|
||||
// currentMenu->addSeparator();
|
||||
// currentMenu->addAction(tr("debug: win"), this, SLOT(wonGame()));
|
||||
currentMenu->addSeparator();
|
||||
currentMenu->addAction(tr("debug: solve"), this, SLOT(startSolver()));
|
||||
|
||||
currentToolBar = addToolBar(currentMenu->title());
|
||||
currentToolBar->addActions(currentMenu->actions());
|
||||
@ -97,33 +104,119 @@ namespace qcross {
|
||||
void CGameWindow::newGame() {
|
||||
bool notPaused = !m_Field->isPaused();
|
||||
if (notPaused)
|
||||
m_Field->pause();
|
||||
pauseGame(true);
|
||||
|
||||
CNewGameDialog dialog;
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
if (m_Highscore)
|
||||
delete m_Highscore;
|
||||
|
||||
m_Field->setPicture(NULL);
|
||||
if (m_Picture)
|
||||
delete m_Picture;
|
||||
|
||||
m_Highscore = dialog.takeHighscore();
|
||||
m_PictureIndex = m_Highscore ? dialog.nonogramIndex() : -1;
|
||||
|
||||
m_Picture = dialog.takeNonogram();
|
||||
m_Picture->updateNumbers();
|
||||
CNonogram * newPicture = dialog.takeNonogram();
|
||||
newPicture->updateNumbers();
|
||||
|
||||
m_PauseGameAction->setEnabled(true);
|
||||
m_RestartGameAction->setEnabled(true);
|
||||
|
||||
m_Field->setPicture(m_Picture);
|
||||
m_Field->setPicture(newPicture);
|
||||
|
||||
if (m_Picture)
|
||||
delete m_Picture;
|
||||
|
||||
m_Picture = newPicture;
|
||||
|
||||
m_Field->resume();
|
||||
m_Field->showMessage(tr("Game started!"), 1000);
|
||||
}
|
||||
else if (notPaused)
|
||||
m_Field->resume();
|
||||
else
|
||||
pauseGame(false);
|
||||
}
|
||||
|
||||
const char magicSaveGameHeader[] = {'C', 'R', 'S', 'V'};
|
||||
|
||||
void CGameWindow::saveGame() {
|
||||
if (!m_Field->isPaused())
|
||||
m_PauseGameAction->setChecked(true);
|
||||
|
||||
QString fileName = QFileDialog::getSaveFileName(this, tr("Save current game"),
|
||||
QDir::homePath(), tr("QCross Saved games (*.csg)"));
|
||||
|
||||
qDebug("saving game state file: %s", fileName.toAscii().data());
|
||||
QFile file(fileName);
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
return;
|
||||
|
||||
QDataStream out(&file);
|
||||
out.setVersion(QDataStream::Qt_4_0);
|
||||
|
||||
out.writeRawData(magicSaveGameHeader, 4);
|
||||
|
||||
out << int(-1); // debug: m_PicutreIndex
|
||||
|
||||
out << *m_Picture;
|
||||
|
||||
m_Field->dumpState(out);
|
||||
|
||||
m_PauseGameAction->setChecked(false);
|
||||
}
|
||||
|
||||
void CGameWindow::loadGame() {
|
||||
if (!m_Field->isPaused())
|
||||
m_PauseGameAction->setChecked(true);
|
||||
|
||||
QString fileName = QFileDialog::getOpenFileName(this, tr("Open saved game"),
|
||||
QDir::homePath(), tr("QCross Saved games (*.csg)"));
|
||||
|
||||
qDebug("opening game state file: %s", fileName.toAscii().data());
|
||||
QFile file(fileName);
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
return;
|
||||
|
||||
QDataStream in(&file);
|
||||
in.setVersion(QDataStream::Qt_4_0);
|
||||
|
||||
char magicHeader[4];
|
||||
in.readRawData(magicHeader, 4);
|
||||
|
||||
qDebug("checking magic header");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (magicHeader[i] != magicSaveGameHeader[i])
|
||||
return;
|
||||
}
|
||||
|
||||
// picture index
|
||||
in >> m_PictureIndex; qDebug("m_PictureIndex = %i", m_PictureIndex);
|
||||
|
||||
// delete current highscore
|
||||
if (m_Highscore)
|
||||
delete m_Highscore;
|
||||
|
||||
// package name
|
||||
if (m_PictureIndex > -1) {
|
||||
QString highscoreFileName, packageName;
|
||||
in >> packageName; qDebug("packageName = %s", qPrintable(packageName));
|
||||
in >> highscoreFileName; qDebug("highscoreFileName = %s", qPrintable(highscoreFileName));
|
||||
|
||||
// TODO handle save game porting correctly
|
||||
m_Highscore = new CHighscore(0);
|
||||
m_Highscore->setFileName(QCROSS_STRING_DATAPATH + QDir::separator() + highscoreFileName);
|
||||
m_Highscore->open();
|
||||
}
|
||||
|
||||
// picture
|
||||
CNonogram * newPicture = new CNonogram(in);
|
||||
|
||||
m_Field->setPicture(newPicture);
|
||||
if (m_Picture)
|
||||
delete m_Picture;
|
||||
|
||||
m_Picture = newPicture;
|
||||
m_Field->applyState(in);
|
||||
|
||||
m_PauseGameAction->setEnabled(true);
|
||||
m_PauseGameAction->setChecked(false);
|
||||
}
|
||||
|
||||
void CGameWindow::restartGame() {
|
||||
@ -137,8 +230,8 @@ namespace qcross {
|
||||
|
||||
void CGameWindow::pauseGame(bool value) {
|
||||
if (value) {
|
||||
m_Field->showMessage(tr("Game paused."));
|
||||
m_Field->pause();
|
||||
m_Field->showMessage(tr("Game paused."));
|
||||
}
|
||||
else {
|
||||
m_Field->showMessage(tr("Game resumed."), 1000);
|
||||
@ -172,4 +265,12 @@ namespace qcross {
|
||||
void CGameWindow::about() {
|
||||
QMessageBox::about(this, tr("About"), tr("This is a still unfancy gui for solving nonograms."));
|
||||
}
|
||||
|
||||
void CGameWindow::startSolver() {
|
||||
m_Solver->setNonogram(m_Picture);
|
||||
|
||||
restartGame();
|
||||
|
||||
m_Solver->solve();
|
||||
}
|
||||
}
|
||||
|
@ -22,8 +22,9 @@
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
namespace libqcross {
|
||||
namespace libqnono {
|
||||
class CNonogram;
|
||||
class CNonogramSolver;
|
||||
}
|
||||
|
||||
namespace qcross {
|
||||
@ -40,8 +41,10 @@ namespace qcross {
|
||||
~CGameWindow();
|
||||
|
||||
protected:
|
||||
libqnono::CNonogramSolver * m_Solver;
|
||||
|
||||
CCrossFieldWidget * m_Field;
|
||||
libqcross::CNonogram * m_Picture;
|
||||
libqnono::CNonogram * m_Picture;
|
||||
|
||||
CHighscore * m_Highscore;
|
||||
int m_PictureIndex;
|
||||
@ -53,8 +56,10 @@ namespace qcross {
|
||||
|
||||
protected slots:
|
||||
void newGame();
|
||||
// void createPackage();
|
||||
// void openPackageImage();
|
||||
|
||||
void saveGame();
|
||||
void loadGame();
|
||||
|
||||
void restartGame();
|
||||
void pauseGame(bool value);
|
||||
|
||||
@ -64,6 +69,8 @@ namespace qcross {
|
||||
void handleErrorMark();
|
||||
|
||||
void about();
|
||||
|
||||
void startSolver();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -17,8 +17,8 @@
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
#include <libqcross/ccrosspackage.h>
|
||||
#include <libqcross/cnonogram.h>
|
||||
#include <libqnono/ccrosspackage.h>
|
||||
#include <libqnono/cnonogram.h>
|
||||
|
||||
#include "cmaskedcrosspackagemodel.h"
|
||||
#include "chighscore.h"
|
||||
@ -28,7 +28,7 @@
|
||||
#define COL_TIME 1
|
||||
|
||||
namespace qcross {
|
||||
using namespace libqcross;
|
||||
using namespace libqnono;
|
||||
//public:
|
||||
CMaskedCrossPackageModel::CMaskedCrossPackageModel(QObject * parent) :
|
||||
CCrossPackageModel(parent), m_Highscore(NULL) {}
|
||||
|
@ -20,7 +20,7 @@
|
||||
#ifndef QCROSS_CMASKEDCROSSPACKAGEMODEL_H
|
||||
#define QCROSS_CMASKEDCROSSPACKAGEMODEL_H
|
||||
|
||||
#include <libqcross/ccrosspackagemodel.h>
|
||||
#include <libqnono/ccrosspackagemodel.h>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
namespace qcross {
|
||||
@ -29,7 +29,7 @@ namespace qcross {
|
||||
/**
|
||||
@author Oliver Groß <z.o.gross@gmx.de>
|
||||
*/
|
||||
class CMaskedCrossPackageModel : public libqcross::CCrossPackageModel {
|
||||
class CMaskedCrossPackageModel : public libqnono::CCrossPackageModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
CMaskedCrossPackageModel(QObject * parent = 0);
|
||||
|
@ -25,10 +25,9 @@
|
||||
#include <QFileDialog>
|
||||
#include <QInputDialog>
|
||||
|
||||
#include <libqcross/ccrosspackagelistmodel.h>
|
||||
// #include <libqcross/ccrosspackagemodel.h>
|
||||
#include <libqcross/ccrosspackage.h>
|
||||
#include <libqcross/cnonogram.h>
|
||||
#include <libqnono/ccrosspackagelistmodel.h>
|
||||
#include <libqnono/ccrosspackage.h>
|
||||
#include <libqnono/cnonogram.h>
|
||||
#include "cmaskedcrosspackagemodel.h"
|
||||
#include "chighscore.h"
|
||||
#include "cnewgamedialog.h"
|
||||
@ -36,12 +35,12 @@
|
||||
#include "common.h"
|
||||
|
||||
namespace qcross {
|
||||
using namespace libqcross;
|
||||
using namespace libqnono;
|
||||
|
||||
//public:
|
||||
CNewGameDialog::CNewGameDialog(QWidget * parent, Qt::WindowFlags f) :
|
||||
QDialog(parent, f),
|
||||
m_Highscore(new CHighscore(0)),
|
||||
m_Highscore(NULL),
|
||||
m_Nonogram(NULL)
|
||||
{
|
||||
ui.setupUi(this);
|
||||
@ -56,7 +55,7 @@ namespace qcross {
|
||||
ui.buttonBox->addButton(importButton, QDialogButtonBox::ActionRole);
|
||||
ui.buttonBox->addButton(openPicFileButton, QDialogButtonBox::ActionRole);
|
||||
|
||||
ui.packageList->setModel(new CCrossPackageListModel(QCROSS_STRING_DATAPATH));
|
||||
ui.packageList->setModel(new CCrossPackageListModel(QCROSS_STRING_DATAPATH, "*" QCROSS_STRING_PACKAGE_EXT));
|
||||
m_PicModel = new CMaskedCrossPackageModel();
|
||||
m_PicProxyModel = new CMaskedCrossPackageProxyModel();
|
||||
m_PicProxyModel->setSourceModel(m_PicModel);
|
||||
@ -84,7 +83,7 @@ namespace qcross {
|
||||
delete m_Nonogram;
|
||||
}
|
||||
|
||||
/* libqcross::CNonogram * CNewGameDialog::selectedNonogramData() const {
|
||||
/* libqnono::CNonogram * CNewGameDialog::selectedNonogramData() const {
|
||||
QModelIndex selected = ui.picList->selectionModel()->selectedIndexes()[0];
|
||||
return static_cast<CNonogram *>(selected.internalPointer());
|
||||
}*/
|
||||
@ -94,13 +93,13 @@ namespace qcross {
|
||||
return selected.row();
|
||||
}
|
||||
|
||||
libqcross::CCrossPackage * CNewGameDialog::selectedPackage() const {
|
||||
libqnono::CCrossPackage * CNewGameDialog::selectedPackage() const {
|
||||
QModelIndex selected = ui.packageList->selectionModel()->selectedIndexes()[0];
|
||||
return static_cast<CCrossPackage *>(selected.internalPointer());
|
||||
}
|
||||
|
||||
libqcross::CNonogram * CNewGameDialog::takeNonogram() {
|
||||
libqcross::CNonogram * result;
|
||||
libqnono::CNonogram * CNewGameDialog::takeNonogram() {
|
||||
libqnono::CNonogram * result;
|
||||
|
||||
if (m_Nonogram) {
|
||||
result = m_Nonogram;
|
||||
@ -134,6 +133,9 @@ namespace qcross {
|
||||
QString fileName = QFileDialog::getOpenFileName(this, tr("Select a package to import"),
|
||||
QDir::homePath(), tr("QCross Package (*.cpk)"));
|
||||
if (!fileName.isEmpty()) {
|
||||
/* if (!File::exists(QCROSS_STRING_DATAPATH))
|
||||
QDir::mkpath(QCROSS_STRING_DATAPATH);*/
|
||||
|
||||
QString newFileName = QCROSS_STRING_DATAPATH + QDir::separator() + fileName.section(QDir::separator(), -1);
|
||||
if (QFile::copy(fileName, newFileName))
|
||||
dynamic_cast<CCrossPackageListModel *>(ui.packageList->model())->update();
|
||||
@ -169,6 +171,9 @@ namespace qcross {
|
||||
m_PicModel->setHighscore(NULL);
|
||||
m_PicModel->setPackage(package);
|
||||
|
||||
if (!m_Highscore)
|
||||
m_Highscore = new CHighscore(0);
|
||||
|
||||
m_Highscore->setFileName(getHighscoreFileName(package->fileName()));
|
||||
if (!m_Highscore->open()) {
|
||||
qDebug("opening highscore file failed. will create a new one when nonogram is solved");
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <QDialog>
|
||||
#include "ui_picselect.h"
|
||||
|
||||
namespace libqcross {
|
||||
namespace libqnono {
|
||||
class CNonogram;
|
||||
class CCrossPackage;
|
||||
}
|
||||
@ -43,9 +43,9 @@ namespace qcross {
|
||||
~CNewGameDialog();
|
||||
|
||||
int nonogramIndex() const;
|
||||
libqcross::CCrossPackage * selectedPackage() const;
|
||||
libqnono::CCrossPackage * selectedPackage() const;
|
||||
|
||||
libqcross::CNonogram * takeNonogram();
|
||||
libqnono::CNonogram * takeNonogram();
|
||||
CHighscore * takeHighscore();
|
||||
protected slots:
|
||||
void importPackage();
|
||||
@ -53,7 +53,7 @@ namespace qcross {
|
||||
private:
|
||||
Ui::picselect ui;
|
||||
CHighscore * m_Highscore;
|
||||
libqcross::CNonogram * m_Nonogram;
|
||||
libqnono::CNonogram * m_Nonogram;
|
||||
CMaskedCrossPackageModel * m_PicModel;
|
||||
CMaskedCrossPackageProxyModel * m_PicProxyModel;
|
||||
private slots:
|
||||
|
@ -21,8 +21,9 @@
|
||||
#ifndef QCROSS_CONSTANTS_H
|
||||
#define QCROSS_CONSTANTS_H
|
||||
|
||||
#include <libqcross/constants.h>
|
||||
#include <libqnono/constants.h>
|
||||
|
||||
#define QCROSS_STRING_DATAPATH ((QDir::homePath() + QDir::separator()) + ".qcross")
|
||||
#define QCROSS_STRING_PACKAGE_EXT ".cpk"
|
||||
|
||||
#endif
|
||||
|
@ -16,13 +16,13 @@
|
||||
#include <QFileDialog>
|
||||
#include <QInputDialog>
|
||||
|
||||
#include <libqcross/ccrosspackagemodel.h>
|
||||
#include <libqcross/ccrosspackage.h>
|
||||
#include <libqnono/ccrosspackagemodel.h>
|
||||
#include <libqnono/ccrosspackage.h>
|
||||
|
||||
#include "cmainwindow.h"
|
||||
|
||||
namespace qcrossedit {
|
||||
using namespace libqcross;
|
||||
using namespace libqnono;
|
||||
//public:
|
||||
CMainWindow::CMainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
@ -60,9 +60,11 @@ namespace qcrossedit {
|
||||
//edit menu
|
||||
menu = menuBar()->addMenu("&Edit");
|
||||
menu->addAction("&Create empty nonogram...", this, SLOT(editCreateEmpty()));
|
||||
menu->addAction("&Create nonogram from picture...", this, SLOT(editCreateFromPicture()));
|
||||
menu->addAction("Create nonogram from &picture...", this, SLOT(editCreateFromPicture()));
|
||||
menu->addSeparator();
|
||||
menu->addAction("&Delete nongram", this, SLOT(editDelete()));
|
||||
menu->addAction("&Rename nonogram", this, SLOT(editRename()));
|
||||
menu->addAction("Set nonogram &time-out", this, SLOT(editSetTimeout()));
|
||||
menu->addAction("&Delete nonogram", this, SLOT(editDelete()));
|
||||
menu->addSeparator();
|
||||
menu->addAction("Set Package&name...", this, SLOT(editSetPackageName()));
|
||||
|
||||
@ -180,6 +182,13 @@ namespace qcrossedit {
|
||||
}
|
||||
}
|
||||
|
||||
void CMainWindow::editRename() {
|
||||
}
|
||||
|
||||
void CMainWindow::editSetTimeout() {
|
||||
QInputDialog::getInt(this, tr("Set time-out for selected nonogram (in minutes)"));
|
||||
}
|
||||
|
||||
void CMainWindow::editDelete() {
|
||||
QModelIndexList selectedIndexes = m_PicListView->selectionModel()->selectedIndexes();
|
||||
foreach (QModelIndex i, selectedIndexes)
|
||||
|
@ -14,7 +14,7 @@ class QTreeView;
|
||||
// class QBitmap;
|
||||
//class QMenu;
|
||||
|
||||
namespace libqcross {
|
||||
namespace libqnono {
|
||||
class CCrossPackage;
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ namespace qcrossedit {
|
||||
// QString m_File;
|
||||
bool m_Unsaved;
|
||||
|
||||
libqcross::CCrossPackage * m_Package;
|
||||
libqnono::CCrossPackage * m_Package;
|
||||
|
||||
/* QBitmap * m_Pics;
|
||||
QString * m_PackName;*/
|
||||
@ -51,6 +51,8 @@ namespace qcrossedit {
|
||||
|
||||
void editCreateEmpty();
|
||||
void editCreateFromPicture();
|
||||
void editRename();
|
||||
void editSetTimeout();
|
||||
void editDelete();
|
||||
void editSetPackageName();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user