⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gd10-01.cpp

📁 以图形界面的方式形象的描述了数据结构中翰诺塔的过程
💻 CPP
字号:
// ============================================================================
//  GD10-01.cpp
//  Towers of Hanoi Graphical Demonstration.
// ============================================================================
#include <stdlib.h>
#include <time.h>
#include "SDLGUI.h"
#include "Stack.h"
#include "Queue.h"



// ============================================================================
//  Global Constants
// ============================================================================
const char PROGRAM_NAME[]   = "Towers of Hanoi Graphical Demonstration";
const int WIDTH             = 800;
const int HEIGHT            = 600;
const int ITEMS             = 32;
const int ARIAL             = 0;


// ============================================================================
//  Classes
// ============================================================================
class Move
{
public:
    int from;
    int to;
};

class Disc
{
public:
    int size;
    SDL_Color color;
};



// ============================================================================
//  Global Variables
// ============================================================================
SDLGUI* g_gui;

LQueue<Move> g_moves;
LStack<Disc> g_discs[3];

SDL_Color g_colors[10];


char g_numDiscs[3] = "4";
char g_speed[8] = "1000";

int g_delay = 1000;
int g_timer;
int g_totaldiscs = 4;

bool g_solve = false;
bool g_solved = false;

// ============================================================================
//  The Tower of Hanoi
// ============================================================================

// n = number of discs being moved
// s = source pole
// d = destination pole
// o = open pole
void Hanoi( int n, int s, int d, int o )
{
    static Move m;
    if( n > 0 )
    {
        // move the top n-1 discs from 's' to 'o'
        Hanoi( n-1, s, o, d );

        // move the nth disc from s to d
        m.from = s;
        m.to = d;
        g_moves.Enqueue( m );

        // move the top n-1 discs from 'o' to 'd'
        Hanoi( n-1, o, d, s );
    }
}


// ============================================================================
//  Draw Algorithms
// ============================================================================
void DrawStack( LStack<Disc>& p_stack,
                int p_x, int p_y )
{
    DListIterator< Disc > itr;
    int w;


    // draw the pillar:
    g_gui->Box( p_x - 8, p_y - 256, 16, 256, BLACK );

    itr = p_stack.GetIterator();
    for( itr.Start(); itr.Valid(); itr.Forth() )
    {
        w = itr.Item().size / 2;

        // draw the current disc
        g_gui->Box( p_x - w, p_y - 16, itr.Item().size, 16, itr.Item().color );

        p_y -= 16;
    }
}


// ============================================================================
//  Button Callbacks
// ============================================================================
void Reset()
{
    int d = atoi( g_numDiscs );
    int w = 24 * d;
    int i;
    Disc disc;

    if( d > 0 && d < 11 )
    {

        // pop off all discs first
        while( g_discs[0].Count() != 0 ||
               g_discs[1].Count() != 0 ||
               g_discs[2].Count() != 0 )
        {
            g_discs[0].Pop();
            g_discs[1].Pop();
            g_discs[2].Pop();
        }

        // dequeue all moves
        while( g_moves.Count() != 0 )
        {
            g_moves.Dequeue();
        }



        // put the right number of discs on pole 0
        for( i = 0; i < d; i++ )
        {
            disc.size = w;
            disc.color = g_colors[i];
            g_discs[0].Push( disc );
            w -= 24;
        }
        g_totaldiscs = d;
        g_solved = false;
        g_solve = false;
    }
}


void Speed()
{
    // set the new delay
    g_delay = atoi( g_speed );
}



void Solve()
{
    // if the tower is not currently solving, and has not been already
    // solved, start the solution
    if( g_solve == false && g_solved == false )
    {
        // solve the tower
        Hanoi( g_totaldiscs, 0, 2, 1 );

        // reset the timer
        g_timer = SDL_GetTicks();
        g_solve = true;
    }
}


// ============================================================================
//  Main
// ============================================================================
int main( int argc, char* argv[] )
{
    int x;
    int y;

    Disc disc;

    srand( time(0) );

    //initialize systems
    SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER );
    SDL_WM_SetCaption( PROGRAM_NAME, 0); 
    TTF_Init();
    g_gui = new SDLGUI( WIDTH, HEIGHT, ITEMS, WHITE );
    g_gui->SetFont( "arial.ttf", ARIAL, 20, TTF_STYLE_NORMAL );

    SDL_EnableUNICODE( true );

    // add the items to the g_gui
    g_gui->AddButton( 0, 0, "gbup.bmp", "gbdown.bmp", "Reset", 
                      ARIAL, BLACK, WHITE, Reset );
    g_gui->AddLabel( 128, 0, "Discs:", ARIAL, BLACK, WHITE );
    g_gui->AddTextBox( 128, 32, 128, TTF_FontHeight( g_gui->GetFont(ARIAL)),
                       g_numDiscs, 2, ARIAL, BLACK, WHITE, true, Reset );

    g_gui->AddButton( 0, 64, "gbup.bmp", "gbdown.bmp", "Set Delay", 
                      ARIAL, BLACK, WHITE, Speed );
    g_gui->AddLabel( 128, 64, "Delay (ms):", ARIAL, BLACK, WHITE );
    g_gui->AddTextBox( 128, 96, 128, TTF_FontHeight( g_gui->GetFont(ARIAL)),
                       g_speed, 4, ARIAL, BLACK, WHITE, true, Speed );
    
    g_gui->AddButton( 0, 128, "gbup.bmp", "gbdown.bmp", "Solve", 
                      ARIAL, BLACK, WHITE, Solve );

    g_colors[0] = BLUE;
    g_colors[1] = GREEN;
    g_colors[2] = ORANGE;
    g_colors[3] = CYAN;
    g_colors[4] = RED;
    g_colors[5] = DCYAN;
    g_colors[6] = YELLOW;
    g_colors[7] = PINK;
    g_colors[8] = GREY;
    g_colors[9] = DKRED;

    Reset();
    
    // set our at exit function
    atexit( SDL_Quit ) ;

    // declare event variable
    SDL_Event event;

    g_gui->Draw();
    g_gui->Update();

    // loop until we get a quit message.
    while( 1 )
    {
        //look for an event
        if( SDL_PollEvent( &event ) )
        {
            //an event was found
            if( event.type == SDL_QUIT ) 
                break;

            // mouse button was pressed
            if( event.type == SDL_MOUSEBUTTONDOWN ) 
            {
                // get the mouse g_state.
                SDL_GetMouseState( &x, &y );

                // tell the GUI that a button has been pressed
                g_gui->MouseDown( x, y );

            }

            // mouse button was released
            if( event.type == SDL_MOUSEBUTTONUP ) 
            {
                // get the mouse state.
                SDL_GetMouseState( &x, &y );

                // tell the GUI that a button has been released
                g_gui->MouseUp( x, y );
            }

            if( event.type == SDL_KEYDOWN )
            {
                // a key was pressed.
                if( event.key.keysym.sym == SDLK_ESCAPE )
                {
                    // if ESC was pressed, quit the program.
                    SDL_Event quit;
                    quit.type = SDL_QUIT;
                    SDL_PushEvent( &quit );
                }

                // tell the GUI that a key was pressed.
                g_gui->KeyDown( event.key.keysym.sym, 
                                event.key.keysym.mod,
                                event.key.keysym.unicode );
            }
        }


        if( g_solve == true && (SDL_GetTicks() - g_timer) >= g_delay )
        {
            // pick off a move, and do it.
            x = g_moves.Front().from;
            y = g_moves.Front().to;

            // get the disc and pop it
            disc = g_discs[x].Top();
            g_discs[x].Pop();

            // push it onto the destination.
            g_discs[y].Push( disc );

            g_timer = SDL_GetTicks();
            g_moves.Dequeue();

            if( g_moves.Count() == 0 )
            {
                g_solve = false;
                g_solved = true;
            }
        }


        // draw the g_gui at the end of each loop.
        g_gui->Draw();

        DrawStack( g_discs[0], 160, 600 );
        DrawStack( g_discs[1], 400, 600 );
        DrawStack( g_discs[2], 640, 600 );

        g_gui->Update();
    }

    return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -