📄 gd10-01.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 + -