QMetaEnum contains method to convert enum index to actual value:
int value(int index) const
But how to convert back to index, for example, if I want to use enum in some control where I need sequence by index?
int index(int value) const
?
Use the following function:
int indexFromValue(const QMetaEnum & e, int value){
for(int ix=0; ix< e.keyCount(); ix++){
if(e.key(ix) == e.valueToKey(value))
return ix;
}
return -1;
}
Example:
#include <QCoreApplication>
#include <QMetaEnum>
#include <QObject>
class Foo : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
enum class FooEnumType { TypeA=10, TypeB=21 };
Q_ENUM(FooEnumType)
};
static int indexFromValue(const QMetaEnum & e, int value){
for(int ix=0; ix< e.keyCount(); ix++){
if(e.key(ix) == e.valueToKey(value))
return ix;
}
return -1;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
const QMetaObject &mo = Foo::staticMetaObject;
int index = mo.indexOfEnumerator("FooEnumType");
QMetaEnum metaEnum = mo.enumerator(index);
Q_ASSERT(indexFromValue(metaEnum, 10) == 0);
Q_ASSERT(indexFromValue(metaEnum, 21) == 1);
Q_ASSERT(indexFromValue(metaEnum, 100) == -1);
return 0;
}
#include "main.moc"
Related
I am writing a program where I want to use QMetaObject to write Data from a QList to an xml string/file. However, when I go to initialize the QMetaObject in the function to write the xml, it gives me an error.
Let me quickly post my code:
//container.h, basic data class
#include <QObject>
class Container : public QObject
{
Q_OBJECT
public:
explicit Container(QObject *parent = nullptr);
virtual int getLen() = 0;
virtual int getHei() = 0;
virtual int getBre() = 0;
virtual int getDia() = 0;
virtual int getWei() = 0;
virtual int getVol() = 0;
virtual QString getCode() = 0;
};
//box.h, first concrete class, am intending on adding a second later
#include <container.h>
#include <QObject>
#include <QString>
class Box : public Container
{
Q_OBJECT
Q_PROPERTY(QString code READ getCode)
Q_PROPERTY(int height READ getHei)
Q_PROPERTY(int weight READ getWei)
Q_PROPERTY(int length READ getLen)
public:
explicit Box(QString C, int l, int b, int h, int w);
int getLen();
int getHei();
int getBre();
int getDia();
int getWei();
int getVol();
QString getCode();
private:
QString Code;
int length, breadth, height;
int weight;
int volume;
};
//box.cpp
#include "box.h"
Box::Box(QString C, int l, int b, int h, int w)
: Code(C),
length(l),
breadth(b),
height(h),
weight(w)
{
}
int Box::getLen()
{
return length;
}
int Box::getHei()
{
return height;
}
int Box::getBre()
{
return breadth;
}
int Box::getDia()
{
return 0;
}
int Box::getWei()
{
return weight;
}
int Box::getVol()
{
return length * height * breadth;
}
QString Box::getCode()
{
return Code;
}
//pallet.h, a class that holds a QList of Objects of type 'Container'
#include "box.h"
#include "container.h"
#include <QList>
class Pallet
{
public:
Pallet();
void add_to_Container_List(QString C, int l, int b, int h, int w); //Box
void add_to_Container_List(Container *X); //Container Item
QList<Container *>* get_Container_List() const;
void setPallet_Number(int num);
int getPallet_Number();
int getPallet_Weight();
int getPallet_Volume();
private:
QList<Container*> *CList;
int Pallet_Number;
int PWeight;
int PVolume;
};
//pallet.cpp
#include "pallet.h"
#include <QDebug>
Pallet::Pallet(): Pallet_Number(0), PWeight(0), PVolume(0)
{
}
void Pallet::add_to_Container_List(QString C, int l, int b, int h, int w)
{
Container *Xn = new Box(C, l, b, h, w);
PWeight += Xn->getWei();
PVolume += Xn->getVol();
CList->append(Xn);
}
void Pallet::add_to_Container_List(QString C, int h, int d, int w)
{
Container *Xn = new Cylinder(C, h, d, w);
PWeight += Xn->getWei();
PVolume += Xn->getVol();
CList->append(Xn);
}
QList<Container *> *Pallet::get_Container_List() const
{
return CList;
}
void Pallet::add_to_Container_List(Container *X)
{
Container *Xn = X;
PWeight += Xn->getWei();
PVolume += Xn->getVol();
CList->append(Xn);
}
void Pallet::setPallet_Number(int num)
{
Pallet_Number = num;
}
int Pallet::getPallet_Number()
{
return Pallet_Number;
}
int Pallet::getPallet_Weight()
{
return PWeight;
}
int Pallet::getPallet_Volume()
{
return PVolume;
}
Lastely, I also have a MainWindow class that holds a QList of type 'Pallet', a GUI that allows you to create a QList of type 'Container', and then allocate those items to separate Pallets, but this is irrelevant to the problem.
The problem comes when I try to compile the next class I created:
//write_xml.h, the purpose is simply to take a QList of type 'Pallet' and turn it into a xml string
#include "pallet.h"
class Write_XML
{
public:
Write_XML();
QString Write_XML_String(QList<Pallet*> PList);
};
//write_xml.cpp
#include "write_xml.h"
#include <QMetaObject>
#include <QXmlStreamWriter>
Write_XML::Write_XML()
{
}
QString Write_XML::Write_XML_String(QList<Pallet *> PList)
{
QMetaObject *meta;
int numProperties;
QMetaProperty *meta_prop;
QString XString;
QXmlStreamWriter writing(&XString);
writing.setAutoFormatting(true);
writing.writeStartElement("Pallets"); //Pallet
writing.writeAttribute("Number_of_Pallets", QString::number(PList.length()));
foreach(auto P, PList)
{
writing.writeStartElement("Pallet");
writing.writeAttribute("Number",QString::number(P->getPallet_Number()));
writing.writeAttribute("Weight",QString::number(P->getPallet_Weight()));
writing.writeAttribute("Volume",QString::number(P->getPallet_Volume()));
foreach(auto *C, *P->get_Container_List())
{
meta = C->metaObject(); //problem encountered here.
// numProperties = meta->propertyCount();
}
writing.writeEndElement(); //end Pallet
}
writing.writeEndElement(); //end Pallets
return XString;
}
When Compiling, I get the following error message:
invalid conversion from 'const QMetaObject*' to 'QMetaObject*' [-fpermissive]
Where have I made my mistake and how can I fix it?
I'm porting a project which uses Curses to visualize a large (5000x5000, for example) 2D array of chars. The problem is, it must be a high-performance project where the array is constantly updated, but in its current state, the output to stdout is a bottleneck no matter how I optimize the back-end. The project would benefit from using a faster and object-oriented approach Qt can provide. What I've tried:
#include <QtWidgets>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene scene;
QGraphicsView view(&scene);
double totalY = 0;
for (size_t i = 0; i < 5000; ++i) {
double totalX = 0;
for (size_t j = 0; j < 5000; ++j) {
// Add an arbitrary char
QGraphicsSimpleTextItem *simpleText = scene.addSimpleText(QChar('.'));
simpleText->setPos(totalX, totalY);
// Add cell's width and height respectively
totalX += 10;
}
totalY += 10;
}
view.show();
return a.exec();
}
But it turned out that creating 5000x5000 graphic items is waaay slower. My next idea is to create some sort of viewport which will eliminate the need to use graphic items. It could be some canvas (QImage), which I will clear and draw on every time the array is updated. But what do you recommend?
2nd Attempt
After the 1st attempt wasn't really satisfying, I followed the hint of V.K.:
I mean that drawing a character is very expensive operation. So I suggest that you draw each possible character (I assume there are not many of them) to some small image in memory. And than do bitblt (if you do not understand some word, then google for it), i.e. copy blocks of bytes to the final QImage. It will be much faster than painting texts.
testQLargeCharTable2.cc:
#include <cassert>
#include <algorithm>
#include <random>
#include <vector>
#include <QtWidgets>
template <typename Value>
class MatrixT {
private:
size_t _nCols;
std::vector<Value> _values;
public:
MatrixT(size_t nRows, size_t nCols, Value value = Value()):
_nCols((assert(nCols > 0), nCols)), _values(nRows * nCols, value)
{ }
size_t rows() const { return _values.size() / _nCols; }
size_t cols() const { return _nCols; }
Value* operator[](size_t i)
{
assert(i < rows());
return &_values[i * _nCols];
}
const Value* operator[](size_t i) const
{
assert(i < rows());
return &_values[i * _nCols];
}
};
using CharTable = MatrixT<char>;
class CharTableView: public QAbstractScrollArea {
private:
const CharTable* pTbl = nullptr;
using CharCache = std::map<char, QPixmap>;
int wCell;
int hCell;
CharCache cacheChars;
public:
CharTableView(QWidget* pQParent = nullptr);
virtual ~CharTableView() = default;
CharTableView(const CharTableView&) = delete;
CharTableView& operator=(const CharTableView&) = delete;
void set(CharTable* pTbl)
{
this->pTbl = pTbl;
updateScrollBars();
update();
}
protected:
virtual void resizeEvent(QResizeEvent* pQEvent) override;
virtual void paintEvent(QPaintEvent* pQEvent) override;
private:
void updateScrollBars();
const QPixmap& getCharPixmap(char c);
};
void CharTableView::resizeEvent(QResizeEvent* pQEvent)
{
updateScrollBars();
}
void CharTableView::paintEvent(QPaintEvent* pQEvent)
{
if (!pTbl) return;
const int xView = horizontalScrollBar()
? horizontalScrollBar()->value() : 0;
const int yView = verticalScrollBar()
? verticalScrollBar()->value() : 0;
const int wView = viewport()->width();
const int hView = viewport()->height();
const int iRow0 = yView / hCell;
const int iCol0 = xView / wCell;
const int iRowN = std::min((int)pTbl->rows(), (yView + hView) / hCell + 1);
const int iColN = std::min((int)pTbl->cols(), (xView + wView) / wCell + 1);
QPainter qPainter(viewport());
for (int iRow = iRow0; iRow < iRowN; ++iRow) {
const char*const row = (*pTbl)[iRow];
const int yCell = iRow * hCell - yView;
for (int iCol = iCol0; iCol < iColN; ++iCol) {
const int xCell = iCol * wCell - xView;
const QPixmap& qPixmap = getCharPixmap(row[iCol]);
qPainter.drawPixmap(
QRect(xCell, yCell, wCell, hCell),
qPixmap);
}
}
}
CharTableView::CharTableView(QWidget* pQWidget):
QAbstractScrollArea(pQWidget)
{
QFontMetrics qFontMetrics(viewport()->font());
wCell = 2 * qFontMetrics.averageCharWidth();
hCell = qFontMetrics.height();
}
void CharTableView::updateScrollBars()
{
const int w = (int)(pTbl ? pTbl->cols() : 0) * wCell;
const int h = (int)(pTbl ? pTbl->rows() : 0) * hCell;
const QSize sizeView = viewport()->size();
QScrollBar*const pQScrBarH = horizontalScrollBar();
pQScrBarH->setRange(0, w > sizeView.width() ? w - sizeView.width() : 0);
pQScrBarH->setPageStep(sizeView.width());
QScrollBar*const pQScrBarV = verticalScrollBar();
pQScrBarV->setRange(0, h > sizeView.height() ? h - sizeView.height() : 0);
pQScrBarV->setPageStep(sizeView.height());
}
const QPixmap& CharTableView::getCharPixmap(char c)
{
const CharCache::iterator iter = cacheChars.find(c);
if (iter != cacheChars.end()) return iter->second;
QPixmap& qPixmap = cacheChars[c] = QPixmap(wCell, hCell);
qPixmap.fill(QColor(0, 0, 0, 0));
{ QPainter qPainter(&qPixmap);
qPainter.drawText(
QRect(0, 0, wCell, hCell),
Qt::AlignCenter,
QString(QChar(c)));
}
return qPixmap;
}
int main(int argc, char** argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
const size_t n = 10;
QApplication app(argc, argv);
// setup data
const char chars[]
= "0123456789()[]{}/&%$!'+#?="
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
CharTable tbl(5000, 5000);
std::random_device rd;
std::mt19937 rng(rd()); // seed the generator
std::uniform_int_distribution<size_t> distr(0, std::size(chars) - 1);
for (size_t i = 0; i < tbl.rows(); ++i) {
char*const row = tbl[i];
for (size_t j = 0; j < tbl.cols(); ++j) {
row[j] = chars[distr(rng)];
}
}
// setup GUI
CharTableView qCharTableView;
qCharTableView.setWindowTitle("Large Character Table View - 2nd Attempt");
qCharTableView.resize(1024, 768);
qCharTableView.set(&tbl);
qCharTableView.show();
// runtime loop
return app.exec();
}
Output:
I did the same test with a full screen window (2560×1280). The performance still was comparable. (The snapped GIF animations were too large to be uploaded here.)
In opposition to the hint of V.K., I used QPixmap. QImage can be modified with a QPainter as well. There is also a QPainter::drawImage() available.
1st Attempt
My first attempt was to print characters in the paintEvent() of a class derived from QAbstractScrollArea. Thereby, I carefully skipped all rows and columns which are outside of the view area. At the first glance, the performance seemed not that bad but with full screen window size, the approach showed weaknesses. While dragging the scrollbars, the output was significantly lacking behind.
testQLargeCharTable1.cc:
#include <cassert>
#include <algorithm>
#include <random>
#include <vector>
#include <QtWidgets>
template <typename Value>
class MatrixT {
private:
size_t _nCols;
std::vector<Value> _values;
public:
MatrixT(size_t nRows, size_t nCols, Value value = Value()):
_nCols((assert(nCols > 0), nCols)), _values(nRows * nCols, value)
{ }
size_t rows() const { return _values.size() / _nCols; }
size_t cols() const { return _nCols; }
Value* operator[](size_t i)
{
assert(i < rows());
return &_values[i * _nCols];
}
const Value* operator[](size_t i) const
{
assert(i < rows());
return &_values[i * _nCols];
}
};
using CharTable = MatrixT<char>;
class CharTableView: public QAbstractScrollArea {
private:
const CharTable* pTbl = nullptr;
int wCell;
int hCell;
public:
CharTableView(QWidget* pQParent = nullptr);
virtual ~CharTableView() = default;
CharTableView(const CharTableView&) = delete;
CharTableView& operator=(const CharTableView&) = delete;
void set(CharTable* pTbl)
{
this->pTbl = pTbl;
updateScrollBars();
update();
}
protected:
virtual void resizeEvent(QResizeEvent* pQEvent) override;
virtual void paintEvent(QPaintEvent* pQEvent) override;
private:
void updateScrollBars();
};
void CharTableView::resizeEvent(QResizeEvent* pQEvent)
{
updateScrollBars();
}
void CharTableView::paintEvent(QPaintEvent* pQEvent)
{
if (!pTbl) return;
const int xView = horizontalScrollBar()
? horizontalScrollBar()->value() : 0;
const int yView = verticalScrollBar()
? verticalScrollBar()->value() : 0;
const int wView = viewport()->width();
const int hView = viewport()->height();
const int iRow0 = yView / hCell;
const int iCol0 = xView / wCell;
const int iRowN = std::min((int)pTbl->rows(), (yView + hView) / hCell + 1);
const int iColN = std::min((int)pTbl->cols(), (xView + wView) / wCell + 1);
QPainter qPainter(viewport());
for (int iRow = iRow0; iRow < iRowN; ++iRow) {
const char*const row = (*pTbl)[iRow];
const int yCell = iRow * hCell - yView;
const int yC = yCell + hCell / 2;
for (int iCol = iCol0; iCol < iColN; ++iCol) {
const int xCell = iCol * wCell - xView;
const int xC = xCell + wCell / 2;
qPainter.drawText(
QRect(xCell, yCell, wCell, hCell),
Qt::AlignCenter,
QString(QChar(row[iCol])));
}
}
}
CharTableView::CharTableView(QWidget* pQWidget):
QAbstractScrollArea(pQWidget)
{
QFontMetrics qFontMetrics(viewport()->font());
wCell = 2 * qFontMetrics.averageCharWidth();
hCell = qFontMetrics.height();
}
void CharTableView::updateScrollBars()
{
const int w = (int)pTbl->cols() * wCell;
const int h = (int)pTbl->rows() * hCell;
const QSize sizeView = viewport()->size();
QScrollBar*const pQScrBarH = horizontalScrollBar();
pQScrBarH->setRange(0, w - sizeView.width());
pQScrBarH->setPageStep(sizeView.width());
QScrollBar*const pQScrBarV = verticalScrollBar();
pQScrBarV->setRange(0, h - sizeView.height());
pQScrBarV->setPageStep(sizeView.height());
}
int main(int argc, char** argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
const size_t n = 10;
QApplication app(argc, argv);
// setup data
const char chars[]
= "0123456789()[]{}/&%$!'+#?="
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
CharTable tbl(5000, 5000);
std::random_device rd;
std::mt19937 rng(rd()); // seed the generator
std::uniform_int_distribution<size_t> distr(0, std::size(chars) - 1);
for (size_t i = 0; i < tbl.rows(); ++i) {
char*const row = tbl[i];
for (size_t j = 0; j < tbl.cols(); ++j) {
row[j] = chars[distr(rng)];
}
}
// setup GUI
CharTableView qCharTableView;
qCharTableView.setWindowTitle("Large Character Table View - 1st Attempt");
qCharTableView.resize(640, 480);
qCharTableView.set(&tbl);
qCharTableView.show();
// runtime loop
return app.exec();
}
Output:
I tried to create a qspinbox64 as suggested in
64bit int Spin Box in QT
qspinbox64.h
#define QSPINBOX64_H
#include <QtGui>
#include <QtWidgets>
namespace Ui {
class QSpinBox64;
}
class QSpinBox64Private;
class Q_WIDGETS_EXPORT QSpinBox64 : public QAbstractSpinBox//QSpinBox
{
Q_OBJECT
Q_PROPERTY(int64_t minimum READ minimum WRITE setMinimum)
Q_PROPERTY(int64_t maximum READ maximum WRITE setMaximum)
Q_PROPERTY(int64_t value READ value WRITE setValue NOTIFY valueChanged USER true)
int64_t m_minimum;
int64_t m_maximum;
int64_t m_value;
public:
explicit QSpinBox64(QWidget *parent = nullptr)
{
connect(lineEdit(), SIGNAL(textEdited(QString)), this, SLOT(onEditFinished()));
}
~QSpinBox64()
{
}
int64_t value() const
{
return m_value;
}
int64_t minimum() const
{
return m_minimum;
}
int64_t maximum() const
{
return m_maximum;
}
void setMinimum(int64_t min)
{
m_minimum = min;
}
void setMaximum(int64_t max)
{
m_maximum = max;
}
void setRange(int64_t min, int64_t max)
{
setMinimum(min);
setMaximum(max);
}
virtual void stepBy(int steps)
{
auto new_value = m_value;
if (steps < 0 && new_value + steps > new_value) {
new_value = std::numeric_limits<qlonglong>::min();
}
else if (steps > 0 && new_value + steps < new_value) {
new_value = std::numeric_limits<qlonglong>::max();
}
else {
new_value += steps;
}
lineEdit()->setText(textFromValue(new_value));
setValue(new_value);
}
protected:
virtual QValidator::State validate(QString &text, int &pos) const
{
//return validator->validate(text, pos);
bool ok;
int64_t val = text.toLongLong(&ok);
if (!ok)
return QValidator::Invalid;
if (val < m_minimum || val > m_maximum)
return QValidator::Invalid;
return QValidator::Acceptable;
}
virtual int64_t valueFromText(const QString &text) const
{
bool ok;
return text.toLongLong(&ok, 10);
}
virtual QString textFromValue(int64_t value) const
{
return QString::number(value, 10).toUpper();
}
virtual QAbstractSpinBox::StepEnabled stepEnabled() const;
public
Q_SLOTS:
void setValue(int64_t val)
{
if (m_value != val) {
lineEdit()->setText(textFromValue(val));
m_value = val;
}
}
void onEditFinished()
{
QString input = lineEdit()->text();
int pos = 0;
if (QValidator::Acceptable == validate(input, pos))
setValue(valueFromText(input));
else
lineEdit()->setText(textFromValue(m_value));
}
Q_SIGNALS:
void valueChanged(int64_t v);
private:
Ui::QSpinBox64 *ui;
Q_DISABLE_COPY(QSpinBox64)
Q_DECLARE_PRIVATE(QSpinBox64)
};
#endif
main.cpp
#include <QHBoxLayout>
#include "qspinbox64.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QSpinBox64 spinBox;
spinBox.setWindowTitle(QObject::tr("QSpinBox64"));
spinBox.show();
return app.exec();
}
An error occurs after compilation:
G:\proj\build-qspinbox64-Desktop_Qt_5_15_2_MSVC2019_64bit-Debug\debug\moc_qspinbox64.cpp:141:
error: C2491: 'QSpinBox64::staticMetaObject': definition of dllimport static data member not allowed
What should I do to avoid this error?
The culprit is Q_WIDGETS_EXPORT, defined in qtwidgetsglobal.h
# if defined(QT_BUILD_WIDGETS_LIB)
# define Q_WIDGETS_EXPORT Q_DECL_EXPORT
# else
# define Q_WIDGETS_EXPORT Q_DECL_IMPORT
# endif
You should declare QT_BUILD_WIDGETS_LIB in your project by adding this line to the .pro file
DEFINES += QT_BUILD_WIDGETS_LIB
Some side notes:
You are missing the header guard #ifndef QSPINBOX64_H
The constructor should call the base class constructor and set the min/max as instructed in the original post.
stepEnabled() needs to be implemented
explicit QSpinBox64(QWidget *parent = nullptr) : QAbstractSpinBox{parent}
{
setMaximum(std::numeric_limits<int64_t>::max());
setMinimum(std::numeric_limits<int64_t>::min());
connect(lineEdit(), SIGNAL(textEdited(QString)), this, SLOT(onEditFinished()));
}
virtual QAbstractSpinBox::StepEnabled stepEnabled() const
{
return QAbstractSpinBox::StepUpEnabled | QAbstractSpinBox::StepDownEnabled;
}
i have this code at main.cpp :
#include <iostream>
#include <limits>
#include <conio.h>
#include "Ghost/SmartGhost/SmartGhost.h"
#include "Player/Player.h"
#include "PlayerInfo/PlayerInfo.h"
#include "GameBoard/GameBoard.h"
#include "ManualPlayer/ManualPlayer.h"
#include <vector>
using namespace std;
class Position {
public:
int x;
int y;
Position();
Position(int xo,int yo) {x=xo; y=yo;} };
class FancyPlayer : public Player
{
private: vector<Position> visited; //vector of visited nodes int size[2]; //width and height of maze Position start; vector <Position> path; //last visited node(backtrack) public:
void init(int width,int height,int x,int y) {
size[0]=width;
size[1]=height;
start.x=x; //starting position
start.y=y; visited.push_back(Position(start.x,start.y)); path.push_back(Position(start.x,start.y)); }
bool isValid(char ** ViewAround,int x,int y) {
return (ViewAround[x][y]!='#' && ViewAround[x][y]!='*'); }
bool isvisited(int x,int y){
bool f=false;
for(int i=0;i<visited.size();i++) {
if (visited[i].x==x && visited[i].y==y)
f=true;
} return f; }
int getMove(char** ViewAround) {
if (isValid(ViewAround,1,2) && !isvisited(start.x-1,start.y))
{
visited.push_back(Position(start.x-1,start.y));
path.push_back(Position(start.x-1,start.y));
start.x--;
return 0; }
else if (isValid(ViewAround,3,2) && !isvisited(start.x+1,start.y))
{
visited.push_back(Position(start.x+1,start.y));
path.push_back(Position(start.x+1,start.y));
start.x++;
return 1; } else if (isValid(ViewAround,2,3) && !isvisited(start.x,start.y+1))
{
visited.push_back(Position(start.x,start.y+1));
path.push_back(Position(start.x,start.y+1));
start.y++;
return 2; } else if (isValid(ViewAround,2,1) && !isvisited(start.x,start.y-1))
{
visited.push_back(Position(start.x,start.y-1));
path.push_back(Position(start.x,start.y-1));
start.y--;
return 3; } else
{
if (path[path.size()-1].x<start.x){
path.pop_back();
start.x++;
return 1;
}
if (path[path.size()-1].x>start.x){
path.pop_back();
start.x--;
return 0;
}
if (path[path.size()-1].y<start.y){
path.pop_back();
start.y++;
return 2; }
if (path[path.size()-1].y>start.y){
path.pop_back();
start.y--;
return 3;
}
}
}
std::string getName() { return std::string("mplampla"); }
std::string getId() { return std::string("cs141065"); }
};
int main() {
std::vector<ObjectInfo *> PlayersVector; //vector with players engaged
PlayersVector.push_back(new PlayerInfo(*new FancyPlayer(), 'A')); //Erase the comments to play with keyboard
PlayersVector.push_back(new PlayerInfo(*new StupidPlayer(), 'B')); //Fool Standby player
PlayersVector.push_back(new PlayerInfo(*new StupidPlayer(), 'C')); //Fool Standby player
PlayersVector.push_back(new PlayerInfo(*new StupidPlayer(), 'D')); //Fool Standby player
GameBoard *MainGameObject; //Main Game Object
InfoBoard *ptrToInfoBoard = new InfoBoard();
for (int j = 0; j < PlayersVector.size(); ++j) {
ptrToInfoBoard->addPlayer(*static_cast<PlayerInfo *>(PlayersVector[j]));
}
std::ostringstream he;
std::vector<std::string>*ptr = GameBoard::getMapFileNames(DEVCPP_PATH);
for (unsigned int i = 0; i < ptr->size(); ++i) {
he<<DEVCPP_PATH<<ptr->operator[](i);
for (int j = 0; j < EATCH_MAP_PLAY_TIMES; ++j) {
MainGameObject=new GameBoard(true,he.str().c_str(),PlayersVector,EXETASI_MODE,ptrToInfoBoard);
MainGameObject->StartGame();
delete(MainGameObject);
getchar();
}
he.str("");
}
while(1); }
Player.h code :
#ifndef GHOST_PLAYER_H
#define GHOST_PLAYER_H
#include <iostream>
#include <windows.h>
class Player{
private:
public:
Player(){}
virtual std::string getName()=0 ;
virtual std::string getId()=0 ;
virtual int getMove(const char **ViewAround)=0;
virtual void init(int width,int height,int CurrentX,int CurrentY )=0;
};
#endif //GHOST_PLAYER_H
When i am putting at main the
*new FancyPlayer(), 'A')) i am getting an error that telling "[Error] invalid new-expression of abstract class type 'FancyPlayer'" , if i put this line in comment the code works properly...
the stupidplayer code :
StupidPlayer.h :
#ifndef GHOST_STUPIDPLAYER_H
#define GHOST_STUPIDPLAYER_H
#include "../Player/Player.h"
#include "../Move.h"
class StupidPlayer: public Player {
int getMove(const char **ViewAround);
void init(int width,int height,int x,int y);
std::string getName();
std::string getId();
};
#endif //GHOST_STUPIDPLAYER_H
StupidPlayer.cpp :
#include <cstdlib>
#include "StupidPlayer.h"
#include <fstream>
int StupidPlayer::getMove(const char **ViewAround) {
std::ofstream he("inner.txt");
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 5; ++j) {
he<<ViewAround[i][j];
}
he<<'\n';
}
return STAND;
}
void StupidPlayer::init(int width, int height, int x, int y) {
}
std::string StupidPlayer::getName() {
return std::string("StupidPlayer");
}
std::string StupidPlayer::getId() {
return std::string("cs161119");
}
i cant see any difference between stupidplayer and fancy... what can i do... in order to make fancy works properly... it may be a problem that have 2 classes in use for fancy?
I am currently learning QtConncurrenct for multi threaded applications. So for testing purposes I decided to implement a simple program that sums integers in a list, here is the code:
#include <QCoreApplication>
#include <QtConcurrent>
#include <functional>
class intObj{
int m_value;
public:
intObj(int val = 0):m_value(val){}
int val() const {return m_value;}
};
static intObj mapFunction(const intObj &num){
return intObj(num.val());
}
static void reduceFunction(intObj &sum, const intObj &term){
int x = sum.val();
int y = term.val();
sum = intObj(x+y);
}
class myTest{
public:
int getSum(QList<intObj> numbers);
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QList<intObj> n;
for(int i = 0; i < 1000 ; i++){
n.append(intObj(i));
}
myTest m;
int sum = m.getSum(n);
return a.exec();
}
int myTest::getSum(QList<intObj> numbers){
auto sum = QtConcurrent::mappedReduced(numbers,mapFunction,reduceFunction);
return sum.result().val();
}
This program now runs correctly but the map and reduce functions are outside the class. How can I modify this program such that map and reduce functions are in class intObj?
I would really appreciate a working example. Thanks in advance.
You cannot pass pointer to method to mappedReduced like that.
If you don't need the object inside the MapFunction and ReduceFunction, you should make the two functions static:
static int mappedFunction(const int num){
return num;
}
static void reduce(int &sum, const int term){
sum += term;
}
If you need to use the object, you could use std::bind (see using bound function arguments):
auto sum = QtConcurrent::mappedReduced(numbers,
std::bind(&myTest::mappedFunction, this, std::placeholders::_1),
std::bind(&myTest::reduce, this, std::placeholders::_1, std::placeholders::_2));
// Or lambda if Qt support them:
auto sum = QtConcurrent::mappedReduced(numbers,
[this] (int num) { mappedFunction(num); },
[this] (int &sum, int num) { reduce(sum, num); });
You could also use Function Objects and store a reference to your current myTest instance.
After a little more digging and rereading the Qtconcurrency on using member functions
I realised that there are 2 major points
The class of the container and the member functions SHOULD be the same
In order to avoid head aches with passing this parameter, make the member functions static
Here is the final working version
#include <QCoreApplication>
#include <QtConcurrent>
#include <functional>
class intObj{
int m_value;
public:
intObj(int val = 0):m_value(val){}
int val() const {return m_value;}
static intObj mapFunction(const intObj &num){
return intObj(num.val());
}
static void reduceFunction(intObj &sum, const intObj &term){
int x = sum.val();
int y = term.val();
sum = intObj(x+y);
}
};
class myTest{
public:
int getSum(QList<intObj> numbers);
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QList<intObj> n;
for(int i = 0; i < 1000 ; i++){
n.append(intObj(i));
}
myTest m;
int sum = m.getSum(n);
return a.exec();
}
int myTest::getSum(QList<intObj> numbers){
auto sum = QtConcurrent::mappedReduced(numbers,&intObj::mapFunction,&intObj::reduceFunction);
return sum.result().val();
}
Any suggestions on how to improve this program are most welcome.