How to make animation in *.gif run only once in Qt? [duplicate] - qt

I'm using QMovie and gif to create explosion after collision. The problem is that my gif is looping over and over, I've checked loopcount status and it returns -1 (infinite). How to display my gif just one time?
#include "Bullet.h"
#include <QTimer>
#include <QGraphicsScene>
#include <QList>
#include "Enemy.h"
#include "Game.h"
#include <typeinfo>
#include "levels.h"
extern Game * game; // there is an external global object called game
int Bullet::killed = 0;
int Bullet::missed = 0;
double Bullet::accurancy = 0;
Bullet::Bullet(QGraphicsItem *parent): QGraphicsPixmapItem(parent){
// draw graphics
setPixmap(QPixmap(":/images/res/images/bullets/bullet.png"));
missed++; // increse missed when bullet is created
movie = new QMovie(":/images/res/images/effects/explosion/64x48.gif");
processLabel = new QLabel;
processLabel->setMovie(movie);
// make/connect a timer to move() the bullet every so often
QTimer * timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),this,SLOT(move()));
// start the timer
timer->start(2);
}
void Bullet::move(){
// get a list of all the items currently colliding with this bullet
QList<QGraphicsItem *> colliding_items = collidingItems();
// if one of the colliding items is an Enemy, destroy both the bullet and the enemy
for (int i = 0, n = colliding_items.size(); i < n; ++i){
if (typeid(*(colliding_items[i])) == typeid(Enemy)){
// increase the score
game->score->increase();
//play explosion animation
movie->start();
movie->setSpeed(180);
processLabel->setAttribute(Qt::WA_NoSystemBackground);
processLabel->setGeometry(QRect(x()-15,y()-15,64,48));
scene()->addWidget(processLabel);
qDebug() << movie->loopCount();
//connect(movie,SIGNAL(finished()),movie,SLOT(stop()));
// remove them from the scene (still on the heap)
scene()->removeItem(colliding_items[i]);
scene()->removeItem(this);
// delete them from the heap to save memory
delete colliding_items[i];
delete this;
killed++;
missed--; // decrese missed if bullet colide with enemy
if((killed+1) % 9 == 0)
{
game->level->Levels::incrementLevels();
game->score->Score::addToSum(); /// TODO
}
//qDebug() << "Already killed: " << killed;
//qDebug() << "Already missed: " << missed;
// return (all code below refers to a non existint bullet)
return;
}
}
// if there was no collision with an Enemy, move the bullet forward
setPos(x(),y()-1);
// if the bullet is off the screen, destroy it
if (pos().y() < 0){
scene()->removeItem(this);
delete this;
}
}

I had the same question and didn't find anything, so here's my solution:
connect the signal "frameChanged(int)" to:
void Bullet::frameChanged_Handler(int frameNumber) {
if(frameNumber == (movie->frameCount()-1)) {
movie->stop();
}
}
If you want to run X times the loop you just have to add a static counter to know how many times you've passed the last frame:
void Bullet::frameChanged_Handler(int frameNumber) {
static int loopCount = 0;
if(frameNumber == (movie->frameCount()-1)) {
loopCount++;
if(loopCount >= MAX_LOOP_TIMES)
movie->stop();
}
}
and of course, connect with this:
connect(movie, SIGNAL(frameChanged(int)), this, SLOT(frameChanged_Handler(int)));
That's it... Hope it can help you.

Related

What does Intel PIN instruction count depend on and why it varies between executions?

I would like to get instruction count for bubblesort algorithm using Intel PIN. I thought that maybe I could analyse how instruction count increases, when there is more data to sort. But the result varies between executions for the same set of data.
For example few outputs: 1662097, 1811453, 1832990, 1745621
It varies quite a lot. Why isn't it the same? Is there a way to achieve it? How am I supposed to get any useful information from that? There is no way of telling how increase of data set influenced number of instructions, when it isn't even stable for the same execution.
Pintool code (copy-pasted from Pin User Guide):
#include <iostream>
#include <fstream>
#include "pin.H"
ofstream OutFile;
// The running count of instructions is kept here
// make it static to help the compiler optimize docount
static UINT64 icount = 0;
// This function is called before every instruction is executed
VOID docount() { icount++; }
// Pin calls this function every time a new instruction is encountered
VOID Instruction(INS ins, VOID *v)
{
// Insert a call to docount before every instruction, no arguments are passed
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)docount, IARG_END);
}
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool",
"o", "inscount.out", "specify output file name");
// This function is called when the application exits
VOID Fini(INT32 code, VOID *v)
{
// Write to a file since cout and cerr maybe closed by the application
OutFile.setf(ios::showbase);
OutFile << "Count " << icount << endl;
OutFile.close();
}
/* ===================================================================== */
/* Print Help Message */
/* ===================================================================== */
INT32 Usage()
{
cerr << "This tool counts the number of dynamic instructions executed" << endl;
cerr << endl << KNOB_BASE::StringKnobSummary() << endl;
return -1;
}
/* ===================================================================== */
/* Main */
/* ===================================================================== */
/* argc, argv are the entire command line: pin -t <toolname> -- ... */
/* ===================================================================== */
int main(int argc, char * argv[])
{
// Initialize pin
if (PIN_Init(argc, argv)) return Usage();
OutFile.open(KnobOutputFile.Value().c_str());
// Register Instruction to be called to instrument instructions
INS_AddInstrumentFunction(Instruction, 0);
// Register Fini to be called when the application exits
PIN_AddFiniFunction(Fini, 0);
// Start the program, never returns
PIN_StartProgram();
return 0;
}
Bubblesort implementation (nothing extraordinary, intentionally O(n^2)):
void bubblesort(int table[], int size) {
int i, j, temp;
for (i = 0; i < size - 1; i++)
{
for (j = 0; j < size - 1 - i; j++)
{
if (table[j] > table[j + 1])
{
temp = table[j + 1];
table[j + 1] = table[j];
table[j] = temp;
}
}
}
}

Programmatic scrolling with QGraphicsView and QGraphicsItem?

I would like to programmatically scroll a scene to the left / right, but I am not sure how to do that properly. Note that I do not want to have (visible) scroll bars.
I use a standard QGraphicsView + QGraphicsScene + QGraphicsItem setup. I have downsized it to the minimum, with one single QGraphicsItem (a QGraphicsRectItem) in the scene.
I have managed to achieve programmatic scrolling by setting my view like this:
// view setup
view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
and then, in another part of the code:
// programmatic scrolling
QScrollBar* const sb = view->horizontalScrollBar();
sb->setRange(0, 1000); // some values for experimenting
sb->setValue(sb->value() + 100 or -100); // some increment for experimenting
This works, but... scrolling through invisible scrollbars doesn't feel right.
I tried this more straightforward approach:
// programmatic scrolling - doesn't quite work
view->viewport()->scroll(100 or -100, 0); // some increment for experimenting
This code does scroll, but when the rectangle goes off the left edge of the view, and I reverse the scrolling direction (increment changed from 100 to -100 in the call to scroll()), the uncovered part of the rectangle is not repainted. The reason is that QGraphicsRectItem::paint() is not called in that case (it is called when using the scrollbar method).
So, is there a way to get viewport()->scroll() work? Or some other simple way to achieve programmatic scrolling? Or is the artificial scrollbar method just the way to go?
Moving the view assumes that it's smaller than its scene. If they're the same size, it won't move.
QGraphicsView can be set to centerOn any position in scene coordinates. Use a timer to call centerOn to move the view one frame at a time.
Here's a working example: -
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QTimer>
class MyView : public QGraphicsView
{
private:
public:
MyView(QGraphicsScene* pScene)
: QGraphicsView(pScene, NULL)
{}
void AnimateBy(int x)
{
float updateFrequency = (1000/30.0); // ~30 frames per second
QPointF currScenePos = sceneRect().center();
int curX = currScenePos.x();
int endPos = curX + x;
int distanceToAnimate = (endPos - curX);
// speed = dist / time
float updatePosInterval = (float)distanceToAnimate / updateFrequency;
printf("updatePosInterval: %f \n", updatePosInterval);
static float newXPos = sceneRect().center().x();
QTimer* pTimer = new QTimer;
QObject::connect(pTimer, &QTimer::timeout, [=](){
newXPos += updatePosInterval;
centerOn(newXPos, sceneRect().center().y());
// check for end position or time, then....
if(newXPos >= endPos)
{
pTimer->stop();
pTimer->deleteLater();
}
});
pTimer->start(updateFrequency);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene scene(0, 0, 10000, 20000);
MyView* view = new MyView(&scene);
QGraphicsRectItem* pRect = new QGraphicsRectItem(0, 0, 100, 100);
pRect->setPos(scene.width()/2, scene.height()/2);
scene.addItem(pRect);
// timer to wait for the window to appear, before starting to move
QTimer* pTimer = new QTimer;
pTimer->setSingleShot(true);
QObject::connect(pTimer, &QTimer::timeout,[=](){
view->centerOn(pRect); // centre on the rectangle
view->AnimateBy(100);
pTimer->deleteLater();
});
pTimer->start(1000);
view->show();
return a.exec();
}
So, we create the animation by moving the view frame-by-frame using the call to centerOn.
For simplicity, the code just deals with moving in one axis. To move in 2 axis, use 2D vector maths to calculate the interval position.
Try to change the view transformation with the QGraphicsView::translate() or QGraphicsView::setTransform().
But keep in mind that you can't move the viewport "outside" the scene, so make sure that your scene rectangle is large enough.
If I got your question correctly, there is a dojo classes library with such class as PanWebView that allow QWebView to scroll smoothly with mouse without any scrollbars. Take a look at sources. It supports panning and can be suitable for mobile apps, but maybe it'll help you too.
PanWebView class looks like this
#include <QWebView>
#include <QWebFrame>
#include <QMouseEvent>
#include <QApplication>
class PanWebView : public QWebView
{
Q_OBJECT
private:
bool pressed;
bool scrolling;
QPoint position;
QPoint offset;
QList<QEvent*> ignored;
public:
PanWebView(QWidget *parent = 0): QWebView(parent), pressed(false), scrolling(false) {
QWebFrame *frame = page()->mainFrame();
frame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
frame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
}
protected:
void mousePressEvent(QMouseEvent *mouseEvent) {
if (ignored.removeAll(mouseEvent))
return QWebView::mousePressEvent(mouseEvent);
if (!pressed && !scrolling && mouseEvent->modifiers() == Qt::NoModifier)
if (mouseEvent->buttons() == Qt::LeftButton) {
pressed = true;
scrolling = false;
position = mouseEvent->pos();
QWebFrame *frame = page()->mainFrame();
int x = frame->evaluateJavaScript("window.scrollX").toInt();
int y = frame->evaluateJavaScript("window.scrollY").toInt();
offset = QPoint(x, y);
QApplication::setOverrideCursor(Qt::OpenHandCursor);
return;
}
return QWebView::mousePressEvent(mouseEvent);
}
void mouseReleaseEvent(QMouseEvent *mouseEvent) {
if (ignored.removeAll(mouseEvent))
return QWebView::mouseReleaseEvent(mouseEvent);
if (scrolling) {
pressed = false;
scrolling = false;
QApplication::restoreOverrideCursor();
return;
}
if (pressed) {
pressed = false;
scrolling = false;
QMouseEvent *event1 = new QMouseEvent(QEvent::MouseButtonPress,
position, Qt::LeftButton,
Qt::LeftButton, Qt::NoModifier);
QMouseEvent *event2 = new QMouseEvent(*mouseEvent);
ignored << event1;
ignored << event2;
QApplication::postEvent(this, event1);
QApplication::postEvent(this, event2);
QApplication::restoreOverrideCursor();
return;
}
return QWebView::mouseReleaseEvent(mouseEvent);
}
void mouseMoveEvent(QMouseEvent *mouseEvent) {
if (scrolling) {
QPoint delta = mouseEvent->pos() - position;
QPoint p = offset - delta;
QWebFrame *frame = page()->mainFrame();
frame- >evaluateJavaScript(QString("window.scrollTo(%1,%2);").arg(p.x()).arg(p.y()));
return;
}
if (pressed) {
pressed = false;
scrolling = true;
return;
}
return QWebView::mouseMoveEvent(mouseEvent);
}
};
And usage:
PanWebView web;
web.setUrl(QUrl("http://news.google.com"));
web.setWindowTitle("Web View - use mouse to drag and pan around");
web.show();
Also did you check this and this topics? I think it can be usefull.

Updating ac value for Qtimer

I am using qt tool for mini2440.
I make a gui for i2c adc having starti2c and stopi2c.
All things are working well: it reads value of signal when starti2c button press, but I want this value to be updated. I know that Qtimer can be used, but how can I do it?
Here is the code:
# include <termio.h>
# include <time.h>
# include <string.h>
# include <sys/time.h>
HelloForm::HelloForm(QWidget* parent, const char* name, WFlags fl):
HelloBaseForm(parent, name, fl)
{
connect(PushButton1,SIGNAL(clicked()),this,SLOT(starti2c()));
connect(PushButton2,SIGNAL(clicked()),this,SLOT(stopi2c()));
}
HelloForm::~HelloForm()
{
}
//*********************Code for getting i2c**************************//
char HelloForm::geti2c()
{
char buf[100];
char buff[100];
char valuee;
int m1;
char con_buff[10];
int fd=open("/dev/i2c/0",O_RDWR);
if (fd<0)
{
Message->setText(" NOT ABLE TO OPEN THE DRIVER ");
}
else
{
Message->setText(" I2C IS WORKING ");
}
int io,wbyte,rbyte,i;
//********i2cdetect and read************
buf[0]=0x48;
buf[1]=0x00;
buf[2]=0x91;
io=ioctl(fd,I2C_SLAVE,0x48);
if(io<0)
{
Message->setText(" ");
Message->setText("error ioctl");
}
else
{
wbyte=write(fd,buf,3);
// write all three control word to arm
usleep(1*1000);
}
if(wbyte!=3)
{
Message->setText("error write");
Message->setText(QString::number(wbyte));
rbyte=read(fd,buff,10);
//ADC->setText(buff);
sscanf(buff,"%c",&valuee);
m1=int(valuee);
return(m1);
}
void HelloForm::starti2c()
{
while(1)
{
float adc_val=0;
adc_val=geti2c();
adc_val=(adc_val*5)/255.00;
usleep(1*1000);
ADC->setText(QString::number(adc_val));
}
}
//***********stop********//
void HelloForm::stopi2c()
{
ADC->setText(" ");
Message->setText("Stopped");
}
Hopefully this will get you started - it creates a timer which times out every 1000 milli seconds. The timer's timeout signal is connected to the same slot that your PushButton1 is connected to - starti2c.
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(starti2c()));
timer->start(1000);
That code should be placed below where you have your 2 connection statements.

navigate between widgets using arrows in QT

I'm working on UI using QT. The ui is simple, it's app based like IPhone or Android. Say there are 9 items (3 rows x 3 cols).
What I want to do is to navigate between widgets using arrow keys.
If the focus is in [row 1,col 1] and I press down arrow, I want it to go to [row 2, col 1]
another example.
If the focus is in [row 2,col 3] and I press up arrow, I want it to go to [row 1, col 3]
But the current behavior is up and right always go to next widget and down and left always go to previous widget.
Is there any way to do this in qt? or I need to create some algorithm to do this?
Thanks
UPDATE: See amazing example at the end.
Basic Widget focus navigation starts out with this:
http://qt-project.org/doc/qt-4.8/focus.html
Arrow navigation is available easily with a QTableView:
http://qt-project.org/doc/qt-4.8/qtableview.html#navigation
If you can get your widgets to work inside the structure of a QTableView, then you don't need to implement it, it comes as a part of the wrapper/view widget.
http://qt-project.org/doc/qt-4.8/qtablewidget.html#details
http://qt-project.org/doc/qt-4.8/model-view-programming.html
Model View programming does have a learning curve, but it is worth while to learn and use.
But this is by no means the only way to accomplish this.
There are event filters, key events, focus events that can be leveraged to accomplish this feat without using a QTableView or QTableWidget. But figuring out the best way to do it without making it look messy may take some time.
http://qt-project.org/doc/qt-4.8/qcoreapplication.html#notify
http://doc.qt.digia.com/qq/qq11-events.html
http://qt-project.org/doc/qt-4.8/eventsandfilters.html
http://qt-project.org/doc/qt-4.8/qkeyevent.html#details
http://qt-project.org/doc/qt-4.8/qfocusevent.html
Key events are set to the item with the focus, and if they ignore the event it propagates up to its parent. So as long as your items in your table/grid ignore the key events having to do with the arrow keys, then you could have your parent widget listen for the key events and handle them appropriately.
http://qt-project.org/doc/qt-4.8/qt.html#Key-enum
http://qt-project.org/doc/qt-4.8/qt.html#FocusReason-enum
http://qt-project.org/doc/qt-4.8/qwidget.html#setFocus
http://qt-project.org/doc/qt-4.8/qapplication.html#focusWidget
Hope that helps.
EDIT: Fully working example in QGraphicsView of what you want to do:
Qt Creator > Welcome tab > Examples > Pad Navigator Example
http://qt-project.org/doc/qt-4.8/graphicsview-padnavigator.html
Here is the relevant code from the example:
// Enable key navigation using state transitions
for (int y = 0; y < rows; ++y) {
for (int x = 0; x < columns; ++x) {
QState *state = stateGrid[y][x];
QKeyEventTransition *rightTransition = new QKeyEventTransition(this, QEvent::KeyPress,
Qt::Key_Right, state);
QKeyEventTransition *leftTransition = new QKeyEventTransition(this, QEvent::KeyPress,
Qt::Key_Left, state);
QKeyEventTransition *downTransition = new QKeyEventTransition(this, QEvent::KeyPress,
Qt::Key_Down, state);
QKeyEventTransition *upTransition = new QKeyEventTransition(this, QEvent::KeyPress,
Qt::Key_Up, state);
rightTransition->setTargetState(stateGrid[y][(x + 1) % columns]);
leftTransition->setTargetState(stateGrid[y][((x - 1) + columns) % columns]);
downTransition->setTargetState(stateGrid[(y + 1) % rows][x]);
upTransition->setTargetState(stateGrid[((y - 1) + rows) % rows][x]);
EDIT:
Amazing example using QShortcuts and a QGridLayout and a bunch of QPushButtons:
widget.cpp
#include "widget.h"
#include <QPushButton>
#include <QApplication>
#include <QShortcut>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
m_grid = new QGridLayout;
for(int r = 0; r < 10; r++)
{
for(int c = 0; c < 10; c++)
{
m_grid->addWidget(new QPushButton("Row " + QString::number(r)
+ ", Col " + QString::number(c)),
r, c);
}
}
this->setLayout(m_grid);
m_grid->itemAtPosition(1, 1)->widget()->setFocus();
this->setStyleSheet("QPushButton::focus{ background: black; color: white;}");
// only works for in Qt for Embedded Linux, Symbian and Windows CE only.
// QApplication::setNavigationMode(Qt::NavigationModeKeypadDirectional);
QShortcut * shortcut;
shortcut = new QShortcut(QKeySequence(Qt::Key_Up),this,
SLOT(on_up()));
shortcut = new QShortcut(QKeySequence(Qt::Key_Down),this,
SLOT(on_down()));
shortcut = new QShortcut(QKeySequence(Qt::Key_Left),this,
SLOT(on_left()));
shortcut = new QShortcut(QKeySequence(Qt::Key_Right),this,
SLOT(on_right()));
}
void Widget::on_up()
{
moveFocus(0, -1);
}
void Widget::on_down()
{
moveFocus(0, 1);
}
void Widget::on_left()
{
moveFocus(-1, 0);
}
void Widget::on_right()
{
moveFocus(1, 0);
}
void Widget::moveFocus(int dx, int dy)
{
if(qApp->focusWidget() == 0)
return;
int idx = m_grid->indexOf(qApp->focusWidget());
if(idx == -1)
return;
int r, c, rowSpan, colSpan;
m_grid->getItemPosition(idx, &r, &c, &rowSpan, &colSpan);
QLayoutItem* layoutItem = m_grid->itemAtPosition(r + dy, c + dx);
if(layoutItem == 0)
return;
layoutItem->widget()->setFocus();
}
Widget::~Widget()
{
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QGridLayout>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
QGridLayout * m_grid;
public slots:
void on_up();
void on_down();
void on_left();
void on_right();
void moveFocus(int dx, int dy);
};
#endif // WIDGET_H
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
To enable keypad navigation, build Qt with QT_KEYPAD_NAVIGATION defined.
https://het.as.utexas.edu/HET/Software/html/qapplication.html#keypadNavigationEnabled

Stack-recursion program problems

I am a novice C++ coder and obviously not very good at it. I am having an immense amount of trouble with this program.
I am getting syntax errors on my opening and closing parenthesis on my functions, syntax errors on my "<" in my header cpp file, and errors that I'm missing parenthesis.
My first stack is not recognized (main driver file) and in my StackType.cpp file - original is an "undeclared identifier".
Lastly, the left of Push must have class/struct/union - in my for loop when filling the first stack with the rings.
I apologize for all of these issues in advance. Any help you could give me would be greatly appreciated!
Thank you.
======================Stack Header================================
// File: StackType.h
// Stack template class definition.
// Dynamic array implementation
#ifndef StackType
#define StackType
template <class ItemType>
class StackType
{
private:
int ItemType;
ItemType *myStack; // pointer to dynamic array
int _top, _maxSize; // using underscores to remind that it's private
public:
StackType(int numRings = 50); // Constructor
StackType (const StackType<ItemType>&); // Copy Constructor
// Member Functions
void Push(ItemType); // Push
void Pop(ItemType &); // Pop
void stackTop(ItemType &) const; // retrieve top
bool stackIsEmpty() const; // Test for Empty stack
bool stackIsFull() const; // Test for Full stack
~StackType(); // Destructor
};
#endif
=====================Stack cpp file==================================
#include "StackType.h"
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
// Constructor with argument, size is numRings, limit is 50 (set in .h header)
template <class ItemType>
StackType<ItemType>::StackType()
{
_maxSize = numRings;
_top = -1;
}
// Copy Constructor
template <class ItemType>
StackType<ItemType>::StackType(const StackType<ItemType>& original :
_maxSize(original._maxSize), top(original._top)
{
myStack = new ItemType[_maxSize];
for (int i = 0; i <= top; i++) myStack[i] = original.myStack[i];
}
// Destructor
template <class ItemType>
StackType<ItemType>::~StackType()
{
delete [] myStack;
}
// Push
template <class ItemType>
void StackType<ItemType>::Push(StackType<ItemType> ringVal)
{
if(stackIsFull()) cout << "\t There is not enough available memory = the stack is
full!" << endl;
else myStack[++_top] = ringVal;
}
// Pop
template <class ItemType>
void StackType<ItemType>::Pop(StackType<ItemType> &ringVal)
{
if(stackIsEmpty()) cout << "\t The stack is empty!" << endl;
else ringVal = myStack[_top--];
}
// Retrieve stack top without removing it
template <class ItemType>
void StackType<ItemType>::stackTop(StackType<ItemType> &ringVal) const
{
if(stackIsEmpty()) cout << "The stack is empty!";
else ringVal = myStack[_top];
}
// Test for Empty stack
template <class ItemType>
bool StackType<ItemType>::stackIsEmpty() const
{
return (_top < 0);
}
// Test for Full stack
template <class ItemType>
bool StackType<class ItemType>::stackIsFull() const
{
return (_top >= (_maxSize - 1));
}
// end StackType.cpp
=========================Main Driver file=======================================
#include "StackType.h"
#ifdef _DEBUG
#include "StackType.cpp"
#endif // _DEBUG
#include <stack>
#include "StdAfx.h"
#include <iostream>
using namespace std;
// Global Variable - Counter to display the number of moves.
int count = 0;
class StackType;
// Functions Prototypes
void MoveRings(StackType<ItemType>&, StackType<ItemType>&);
// Function to move the rings
void Pegs(int D,StackType<ItemType>& b,StackType<ItemType>& e, StackType<ItemType>& h);
// This is a recursive function.
void Display (int, StackType <ItemType>& , StackType<ItemType>&, StackType<ItemType>&);
// Function to display the pegs
// Main - Driver File
int main()
{
// create 3 empty stacks
StackType<ItemType> FirstPeg; // Receiving an error that this is not identified
StackType<ItemType> EndPeg;
StackType<ItemType> HelperPeg;
// Number of rings.
int numRings;
cout << "\n\t *********** Rings to Pegs (Towers of Hanoi) ***********\n" << endl;
cout << "\t Please Enter the number of rings you want to play with: ";
// Input number of rings
cin >> numRings;
cout << endl;
while(numRings < 0 || isalpha(numRings)) // To make sure that the user did not
// enter an invalid number
{
cout << " Your entry is invalid. Please use only integers. Please re-
enter: ";
cin >> numRings;
cout << endl;
}
for(int i = 1; i <= numRings; i++)
// Fill the first peg with the number of rings.
{
FirstPeg.Push(i);
}
Pegs(int, StackType<ItemType>&, StackType<ItemType>&, StackType<ItemType>&);
// To call the recursive function that will move the rings
Display (int, StackType<ItemType>&, StackType<ItemType>&, StackType<ItemType>&);
// To call the display function
cin.clear();
cin.ignore('\n');
cin.get();
return 0;
}
// This function will move an ring from first peg to the second peg
void MoveRings(StackType<ItemType>& beg, StackType<ItemType>& theEnd) //End
{
int r; // disk will be removed from one stack and added to the other
beg.Pop(r);//pop from source
theEnd.Push(r);//and move to target
}
// This function displays the moves
void Display(int R, StackType<ItemType>& toBegin , StackType<ItemType>& toEnd,
StackType<ItemType>& toHelp)
{
StackType<int> B;// create temporarily first stack
StackType<int> E;// create temporarily End(End) stack
StackType<int> H;// create temporarily helper stack
for(int i = 1; i <= R; i++)
{
toBegin.Pop(i);//moves the ring from source
B.Push(i);//to the temporarily stack to display it
cout << "Beginning Peg:" << &B << endl;
toEnd.Pop(i);//moves the ring from source
E.Push(i);//to the temporarily stack to display it
cout << " End(Final) Peg: " << &E << endl;
toHelp.Pop(i);//moves the ring from source
H.Push(i);//to the temporarily stack to display it
cout << " Helper Peg:" << &H << endl;
}
}
//-------------------------------------------------------------------
void Pegs(int D,StackType<ItemType>& b,StackType<ItemType>& e,StackType<ItemType>& h)
// This is a recursive function.
{
if (D == 0) // The base
{
return 1;
}
else if(D == 1) // If there is only one ring, move this ring from the
// first peg to the end(final) peg
{
MoveRings(b, e); // moves the ring from the first to the end(final) peg
cout<<" Really? You have entered one ring..." << endl;
cout<<" It moves directly from the first peg to the End peg." << endl;
count++; // increment the number of moves
cout << "There has been " << count << " move. "<< endl;// display the
// number of moves
Display (D, b, e, h);
}
else if (D > 1) // a recursive function in order to move the rings
{
Pegs(D - 1, b, e, h); // to move N-1 rings from the first peg to the
// end(final) peg by using the helper peg
MoveRings(b, e);// to move the last ring to the end(final) peg
count++; // increment the number of steps before displaying
cout << "There has been " << count << " moves. "<< endl;
Pegs(D - 1, b, e, h);
// to move N-1 rings from the helper peg to the end(final) peg with the help of
// first peg
//Display ( D(rings), First Peg, End(Final) Peg, Helper Peg );
}
}
One problem that I can see immediately is that your header file defines StackType to prevent double inclusion, which is also used as a class name. After #define StackType, it ends up being a macro that expands to nothing, so your code looks like class { ... }.
You should use a symbol to prevent double inclusion that isn't used for anything else. The typical thing to use is STACKTYPE_H for a file called StackType.h.
Once you've fixed this, some other problems you're experiencing might go away. Please come back with an update if you're having more problems, and post the exact compiler errors if you do.

Resources