Towers of Hanoi question

一曲冷凌霜 提交于 2019-12-06 22:18:26

Pass a reference to the stacks:

stack<int>&

Also consider using a vector rather than a stack so you can iterate it to see the current content of the towers.

PigBen's answer also correctly identifies a bug in your code where you're not moving the disks from the intermediate tower to the destination tower.

Pass the stacks by reference, and change the order you pass them in the last step so that you are moving from intermed to dest, using source as the intermediate.

void Hanoi(int nDisks, stack<int> &source, stack<int> &intermed, stack<int> &dest){
    if(nDisks == 1){
        dest.push(source.top()); 
        source.pop(); 
    }
    else{
        Hanoi(nDisks - 1, source, dest, intermed); 
        dest.push(source.top()); 
        source.pop(); 
        Hanoi(nDisks - 1, intermed, source, dest); 
    }
}

To display the stack, just copy it and pop from the copy.

Consider your original code:

void Hanoi3(int nDisks, char source, char intermed, char dest)
{
    if(nDisks == 1){
        cout << "Move the plate from " << source << " to " << dest << endl; 
    }
    else{
        Hanoi3(nDisks - 1, source, dest, intermed); 
        cout << "Move the plate from " << source << " to " << dest << endl; 
        Hanoi3(nDisks - 1, dest, intermed, source); 
    }
}

It's not correct, so that's possibly why your teacher suggests presenting the towers.

As you note, a std::stack is a good container to use to represent a tower's current disks, but as you also note, it's not entirely straightforward to get at the elements of a std::stack without popping them. You can pop them and push them down on another stack, and move them back, but that's intricate and silly, not to mention inefficient for the general case. That's why std::stack has a protected member c, the underlying container, that you can access by deriving from the class.

There are no virtual members in std::stack, so the only purpose of having a protected member is to make it slightly hard to get at. I think it's a bad design decision. But it's what you have, so,

#include <iostream>
#include <string>
#include <stack>
#include <stddef.h>
using namespace std;

typedef ptrdiff_t   Size;
typedef Size        Index;

class IntStack
    : public stack<int>
{
public:
    Size count() const { return size(); }
    int at( Index i ) const { return c[i]; }
};

class Hanoi
{
private:
    IntStack    towers_[3];
    int         nDisks_;

public:
    Hanoi( int nDisks )
        : nDisks_( nDisks )
    {
        for( int disk = nDisks;  disk >= 1;  --disk )
        {
            towers_[0].push( disk );
        }
    }

    IntStack const& towers( Index i ) const { return towers_[i]; }
};

int main()
{
    int const   nDisksTotal = 2;

    Hanoi   puzzle( nDisksTotal );

    for( Index i = 0;  i < 3;  ++i )
    {
        IntStack const& tower   = puzzle.towers( i );
        Size const      nDisks  = tower.count();

        cout << "Tower " << i << ": ";        
        for( Index diskPos = 0;  diskPos < nDisks;  ++diskPos )
        {
            if( diskPos > 0 ) { cout << ", "; }
            cout << tower.at( diskPos );
        }
        cout << endl;
    }
}

Note that this code only illustrates how you can access the elements of those stacks.

The display can be made much more fancy, e.g. graphical.

I suggest you make your solver function a member of class Hanoi. And add a member function to display the puzzle state. Later you might want to turn that into a callback, in order to support a graphical user interface.

EDIT: hm, I see another answer has shown "the solution" for the bug. That removes the OP's learning experience and the whole reason for displaying the towers. This answer intentionally only affirmed that the bug is real, and showed instead what the OP asked for, namely how to display stacks, efficiently.

Cheers & hth.,

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!