home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / cprog / ev_201.zip / HANOI.ZIP / MODULE.CPP < prev    next >
C/C++ Source or Header  |  1993-07-03  |  16KB  |  396 lines

  1. /*
  2.    Module        : MODULE.CPP
  3.    Version       : 2.0
  4.    Revision date : July 3rd, 1993
  5.    Author(s)     : Remy Gendron
  6.  
  7.    Description   : Hanoi's towers functions file.
  8. */
  9.  
  10.  
  11. // Headers ------------------------------------------------------------------
  12.  
  13. #include <math.h>                                       // System's libraries
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #pragma hdrstop
  17.  
  18. #include "hanoi.hcm"                                         // Other modules
  19. #include "main.hpp"
  20. #include "stdfcts.h"
  21. #include "tdisk.hpp"
  22. #include "tinput.hpp"
  23. #include "tstatusline.hpp"
  24. #include "ttower.hpp"
  25. #include "twindow.hpp"
  26.  
  27. #include "module.hpp"                            // This module's header file
  28.  
  29.  
  30. // --------------------------------------------------------------------------
  31.  
  32. void about ()                               // Displays infos on this program
  33.  
  34. {
  35.    twindow  huge *winptr ;                          // Ptr to a twindow class
  36.    input_info     ii ;                                        // User's input
  37.  
  38.  
  39.    winptr = new twindow ;                                 // Creates a window
  40.    assert (winptr != NULL,"about",msg_stderr[1],1) ;
  41.  
  42.    winptr->winsetpos (5,20,TRUE) ;                         // Displays window
  43.    winptr->winsetsize (15,40) ;
  44.    winptr->winsettitle ("A propos") ;
  45.    winptr->winsetcolors (BLUE) ;
  46.    winptr->winsethlpctx (HC_WINDOW_APROPOS) ;
  47.    winptr->winopen () ;
  48.  
  49.    winptr->winwrite ("Les tours de Hanoi 2.0",2,1,2) ;        // Writes infos
  50.    winptr->winwrite ("Un programme de démonstration",4,1,2) ;
  51.    winptr->winwrite ("de l'interface EasyVision 2.0!",5,1,2) ;
  52.    winptr->winwrite ("Copyright (c) 1993 par",7,1,2) ;
  53.    winptr->winwrite ("TNG SOFT",9,1,2) ;
  54.    winptr->winwrite ("The Next Generation Software",10,1,2) ;
  55.                                                           // Creates a button
  56.    winptr->buttoncreate (12,16,"   Ok",13,"~ENTER~ pour continuer") ;
  57.  
  58.    ii.key_code = II_NUL ;
  59.    winptr->wininput (ii) ;                              // Makes window alive
  60.  
  61.    winptr->winclose () ;                                     // Closes window
  62.    delete (winptr) ;
  63.  
  64.  
  65.    return ;                                // About screen has been displayed
  66. }                                                                // End about
  67.  
  68.  
  69. // --------------------------------------------------------------------------
  70.  
  71. config_info configuration                             // Configure the puzzle
  72. (
  73.    config_info config                                // Configuration's infos
  74. )
  75.  
  76. {
  77.    twindow  huge *winptr ;                          // Ptr to a twindow class
  78.    input_info    ii ;                                         // User's input
  79.    char          tmpstr[18] ;            // To convert from integer to string
  80.  
  81.  
  82.    winptr = new twindow ;                                 // Creates a window
  83.    assert (winptr != NULL,"configuration",msg_stderr[1],1) ;
  84.  
  85.    winptr->winsetpos (7,20,TRUE) ;                         // Displays window
  86.    winptr->winsetsize (11,40) ;
  87.    winptr->winsethlpctx (HC_WINDOW_CONFIGURATION) ;
  88.    winptr->winsettitle ("Configuration") ;
  89.    winptr->winopen () ;
  90.  
  91.    winptr->winwrite ("Disque(s)",2,2) ;                      // Field's names
  92.    winptr->winwrite ("Tige départ",2,20) ;
  93.    winptr->winwrite ("Vitesse",5,2) ;
  94.    winptr->winwrite ("Tige arrivée",5,20) ;
  95.  
  96.    itoa (config.nb_disks,tmpstr,10) ;           // Number of disks to be used
  97.    winptr->fieldcreate (3,2,2,2,2,"",FALSE,FALSE,tmpstr,
  98.                         "Nombre de disque à utiliser (1-10)",EV_NOHLPCTX) ;
  99.  
  100.    itoa (config.source,tmpstr,10) ;                           // Source shaft
  101.    winptr->fieldcreate (3,20,1,1,4,"123",FALSE,FALSE,tmpstr,
  102.                         "Numéro de la tige de départ (1-3)",EV_NOHLPCTX) ;
  103.  
  104.    itoa (config.speed,tmpstr,10) ;                       // Execution's speed
  105.    winptr->fieldcreate (6,2,1,1,2,"",FALSE,FALSE,tmpstr,
  106.                         "Vitesse d'exécution (0-9)",EV_NOHLPCTX) ;
  107.  
  108.    itoa (config.target,tmpstr,10) ;                           // Target shaft
  109.    winptr->fieldcreate (6,20,1,1,2,"",FALSE,FALSE,tmpstr,
  110.                         "Numéro de la tige d'arrivée (1-3)",EV_NOHLPCTX) ;
  111.  
  112.                                                       // Creates some buttons
  113.    winptr->buttoncreate (9,2,"   Ok",II_CR,
  114.                          "Accepte et sauve la configuration",EV_NOHLPCTX) ;
  115.    winptr->buttoncreate (9,29," Annule",II_ESC,
  116.                          "Annule les changements",EV_NOHLPCTX) ;
  117.  
  118.    ii.key_code = II_NUL ;                               // Makes window alive
  119.    ii = winptr->wininput (ii) ;
  120.  
  121.    if (ii.key_code == II_CR)                              // Accepted changes
  122.    {
  123.       winptr->fieldgetasw (tmpstr,1) ;                    // Gets nb of disks
  124.       config.nb_disks = atoi (tmpstr) ;
  125.       if ((config.nb_disks) > 10)                    // Validates nb of disks
  126.          config.nb_disks = 10 ;
  127.       if ((config.nb_disks) < 1)
  128.          config.nb_disks = 1 ;
  129.  
  130.       winptr->fieldgetasw (tmpstr,2) ;                         // Gets source
  131.       config.source = atoi (tmpstr) ;
  132.  
  133.       winptr->fieldgetasw (tmpstr,4) ;                         // Gets target
  134.       config.target = atoi (tmpstr) ;
  135.       if (config.target == config.source)      // Validates source and target
  136.          if (config.source == 1) config.target = 3 ;
  137.          else config.target = 1 ;
  138.  
  139.       winptr->fieldgetasw (tmpstr,3) ;                          // Gets speed
  140.       config.speed = atoi (tmpstr) ;
  141.    }
  142.  
  143.    winptr->winclose () ;                                     // Closes window
  144.    delete (winptr) ;
  145.  
  146.  
  147.    return config ;                                // Configuration is updated
  148. }                                                        // End configuration
  149.  
  150.  
  151. // --------------------------------------------------------------------------
  152.  
  153. void animation                                       // Animates the solution
  154. (
  155.    config_info config                           // Configuration informations
  156. )
  157.  
  158. {
  159.    twindow  huge *winptr1 ;                        // Ptr to animation window
  160.    twindow  huge *winptr2 ;                           // Ptr to status window
  161.    ttower   huge *towers[3] ;                        // 3 ptrs to tower class
  162.    ttower   huge *source ;                                    // Source tower
  163.    ttower   huge *target ;                                    // target tower
  164.    ttower   huge *temporary ;                              // Temporary tower
  165.    tdisk    huge *disks[10] ;                        // 10 Ptrs to disk class
  166.    int            loop ;                                           // Counter
  167.  
  168.  
  169.    winptr1 = new twindow ;                        // Creates animation window
  170.    assert (winptr1 != NULL,"animation",msg_stderr[1],1) ;
  171.  
  172.    winptr1->winsetpos (2,1) ;                                 // Opens window
  173.    winptr1->winsetsize (20,80) ;
  174.    winptr1->winsetcolors (BLACK) ;
  175.    winptr1->winsettitle ("Animation") ;
  176.    winptr1->winsethlpctx (EV_NOHLPCTX) ;
  177.    winptr1->winopen () ;
  178.  
  179.    winptr2 = new twindow ;                            // Create status window
  180.    assert (winptr2 != NULL,"animation",msg_stderr[1],1) ;
  181.  
  182.    winptr2->winsetpos (22,1) ;                                // Opens window
  183.    winptr2->winsetsize (3,80) ;
  184.    winptr2->winsetcolors (BLUE) ;
  185.    winptr2->winsettitle ("Informations") ;
  186.    winptr2->winsethlpctx (EV_NOHLPCTX) ;
  187.    winptr2->winopen () ;
  188.  
  189.    towers[0] = new ttower (1,17,4,BROWN,winptr1) ;        // Creates 3 towers
  190.    assert (towers[0] != NULL,"animation",msg_stderr[1],1) ;
  191.    towers[1] = new ttower (2,17,29,BROWN,winptr1) ;
  192.    assert (towers[1] != NULL,"animation",msg_stderr[1],1) ;
  193.    towers[2] = new ttower (3,17,54,BROWN,winptr1) ;
  194.    assert (towers[2] != NULL,"animation",msg_stderr[1],1) ;
  195.  
  196.    for (loop=1 ; loop<=3 ; loop++)                              // Shows them
  197.       towers[loop-1]->show () ;
  198.  
  199.  
  200.    source = towers[config.source-1] ;      // Selects source, target and temp
  201.    target = towers[config.target-1] ;
  202.    if ((config.source != 1) && (config.target != 1))
  203.       temporary = towers[0] ;
  204.    else if ((config.source != 2) && (config.target != 2))
  205.            temporary = towers[1] ;
  206.         else temporary = towers[2] ;
  207.  
  208.  
  209.    winptr2->winwrite ("Placement des disques sur la tour de départ",1,1,2) ;
  210.  
  211.    for (loop=1 ; loop<=config.nb_disks ; loop++)             // Creates disks
  212.    {
  213.       disks[loop-1] = new tdisk (loop,2,2,winptr1) ;      // Creates one disk
  214.       assert (disks[loop-1] != NULL,"animation",msg_stderr[1],1) ;
  215.  
  216.       disks[loop-1]->show () ;                                    // Shows it
  217.       disks[loop-1]->moveto (source->getrow () - 2 - source->getnbdisks (),
  218.                              source->getcol (),
  219.                              source->getcolor (),source->getcolor (),
  220.                              config.speed) ;
  221.       source->pushdisk (disks[loop-1]) ;             // Updates tower's infos
  222.    }
  223.  
  224.                     // Displays number of moves necessary to solve the puzzle
  225.  
  226.    itoa ((int)pow (2,config.nb_disks) - 1,nbmoves,10) ;
  227.    winptr2->winclear () ;
  228.    winptr2->winwrite ("Déplacements nécessaires:",1,2) ;
  229.    winptr2->winwrite (nbmoves,1,28) ;
  230.    winptr2->winwrite ("Déplacements effectués:",1,37) ;
  231.    winptr2->winwrite ("Vitesse:",1,67) ;
  232.  
  233.    statusline.display ("~+~ ou ~-~ pour changer la vitesse, "
  234.                        "~Une autre touche~ pour terminer") ;
  235.    while ( kbhit() ) (void) getch () ;             // Empties keyboard buffer
  236.  
  237.    move_count = 0 ;                               // Initialises move counter
  238.    globspeed = config.speed ;            // Initialises global speed variable
  239.    end_anim = FALSE ;                   // Initialises animation's abort flag
  240.  
  241.  
  242.                                // Finds solution with the recursive algorithm
  243.  
  244.    hanoi (config.nb_disks,source,target,temporary,winptr2) ;
  245.  
  246.  
  247.    pause () ;                                       // Pauses after animation
  248.  
  249.    for (loop=1 ; loop<=config.nb_disks ; loop++)             // Deletes disks
  250.       delete disks[loop-1] ;
  251.  
  252.    for (loop=1 ; loop<=3 ; loop++)                          // Deletes towers
  253.       delete towers[loop-1] ;
  254.  
  255.    winptr2->winclose () ;                                   // Closes windows
  256.    delete (winptr2) ;
  257.    winptr1->winclose () ;
  258.    delete (winptr1) ;
  259.  
  260.    statusline.display () ;                               // Clears statusline
  261.  
  262.  
  263.    return ;                                               // Animation's done
  264. }                                                            // End animation
  265.  
  266.  
  267. // --------------------------------------------------------------------------
  268.  
  269. void hanoi                    // Finds solution for the current configuration
  270. (
  271.    int            nb_disks,                        // Number of disks to move
  272.    ttower   huge *source,                                 // Moves from tower
  273.    ttower   huge *target,                                   // Moves to tower
  274.    ttower   huge *temporary,                               // Temporary tower
  275.    twindow  huge *winptr2                             // Ptr to status window
  276. )
  277.  
  278. {
  279.    anim_input () ;                          // Checks inputs during animation
  280.    if (end_anim == TRUE) return ;   // Animation has been aborted, stops here
  281.  
  282.    if (nb_disks == 1)                              // If last disk to move...
  283.    {
  284.       itoa (globspeed,alphaspeed,10) ;
  285.       winptr2->winwrite (alphaspeed,1,76) ;
  286.       source->popdiskto (target,globspeed) ;                 // Then moves it
  287.       move_count++ ;                                          // Counts moves
  288.       itoa (move_count,nbmoves,10) ;                     // Shows progression
  289.       winptr2->winwrite (nbmoves,1,61) ;
  290.       return ;
  291.    }
  292.  
  293.    anim_input () ;                          // Checks inputs during animation
  294.    if (end_anim == TRUE) return ; // Animation has been aborted, stop here...
  295.  
  296.    hanoi (nb_disks-1,source,temporary,target,winptr2) ;
  297.  
  298.    anim_input () ;                          // Checks inputs during animation
  299.    if (end_anim == TRUE) return ; // Animation has been aborted, stop here...
  300.  
  301.    itoa (globspeed,alphaspeed,10) ;        // Shows current animation's speed
  302.    winptr2->winwrite (alphaspeed,1,76) ;
  303.  
  304.    source->popdiskto (target,globspeed) ;
  305.    move_count++ ;                                             // Counts moves
  306.    itoa (move_count,nbmoves,10) ;                        // Shows progression
  307.    winptr2->winwrite (nbmoves,1,61) ;
  308.  
  309.    anim_input () ;                          // Checks inputs during animation
  310.    if (end_anim == TRUE) return ; // Animation has been aborted, stop here...
  311.  
  312.    hanoi (nb_disks-1,temporary,target,source,winptr2) ;
  313.  
  314.    anim_input () ;                          // Checks inputs during animation
  315.    if (end_anim == TRUE) return ; // Animation has been aborted, stop here...
  316.  
  317.  
  318.    return ;                                        // Solution has been found
  319. }                                                                // End hanoi
  320.  
  321.  
  322. // --------------------------------------------------------------------------
  323.  
  324. void pause ()                                       // Pauses after animation
  325.  
  326. {
  327.    twindow  huge *winptr ;                          // Ptr to a twindow class
  328.    input_info     ii ;                                        // User's input
  329.  
  330.  
  331.    winptr = new twindow ;                                 // Creates a window
  332.    assert (winptr != NULL,"pause",msg_stderr[1],1) ;
  333.  
  334.    winptr->winsetpos (8,28,TRUE) ;                         // Displays window
  335.    winptr->winsetsize (7,24) ;
  336.    winptr->winsetcolors (RED) ;
  337.    winptr->winsettitle ("Pause") ;
  338.    winptr->winsethlpctx (HC_WINDOW_PAUSE) ;
  339.    winptr->winopen () ;
  340.  
  341.    winptr->winwrite ("Animation terminée",2,1,2) ;        // Displays message
  342.  
  343.    winptr->buttoncreate (5,8,"   Ok",13,"~ENTER~ pour continuer") ;
  344.  
  345.    ii.key_code = II_NUL ;
  346.    winptr->wininput (ii) ;                              // Makes window alive
  347.  
  348.    winptr->winclose () ;                                     // Closes window
  349.    delete (winptr) ;
  350.  
  351.  
  352.    return ;                                          // A pause has been made
  353. }                                                                // End pause
  354.  
  355.  
  356. // --------------------------------------------------------------------------
  357.  
  358. void anim_input ()                          // Checks inputs during animation
  359.  
  360. {
  361.    int inchar ;                             // Character returned by getch ()
  362.  
  363.  
  364.    if (kbhit () || input.mouse_lb_down ()) // Checks user abort/speed changes
  365.    {
  366.       inchar = II_NUL ;
  367.  
  368.       if (kbhit ())
  369.       {
  370.          inchar = getch () ;            // A key has been pressed, gets it...
  371.          while ( kbhit() ) (void) getch () ;       // Empties keyboard buffer
  372.       }
  373.  
  374.       if (inchar == '+')                           // Makes animation faster?
  375.       {
  376.          globspeed++ ;
  377.          if (globspeed > 9) globspeed = 9 ;
  378.       }
  379.       else
  380.       {
  381.          if (inchar == '-')                        // Makes animation slower?
  382.          {
  383.             globspeed-- ;
  384.             if (globspeed < 0) globspeed = 0 ;
  385.          }
  386.          else end_anim = TRUE ;          // Not '+' or '-', so ends animation
  387.       }
  388.    }
  389.  
  390.  
  391.    return ;                                     // Inputs have been processed
  392. }                                                           // End anim_input
  393.  
  394.  
  395. // End source file ----------------------------------------------------------
  396.