'=========================================================================== ' Subject: SOLVE TOWERS OF HANOI PROBLEM Date: 07-31-99 (16:12) ' Author: Bernt Figaro Code: QB, QBasic, PDS ' Origin: bernt.figaro@swipnet.se Packet: ALGOR.ABC '=========================================================================== DECLARE SUB Init () DECLARE SUB Incr (Value%) DECLARE SUB Decr (Value%) DECLARE SUB DisplayMove () DECLARE SUB GetRowCol (Row%, Col%, X%, Y%) DECLARE SUB DisplayScreen () DECLARE SUB DoMoves (NumMoves%) REM REM +++++++++++++++++++++++++++++++ REM + bernt.figaro@swipnet.se + REM + Tower of Hanoi + REM + An example from Turbo Basic + REM + translated to QBAsic + REM +++++++++++++++++++++++++++++++ REM REM $STACK 32767 ' allocate plenty of stack space since it's a recursive program DIM SHARED X% DIM SHARED Y% X% = 1 ' named constants used for indexing and screen positioning Y% = 0 CONST PromptLine% = 24 ' named constant indicating line for all user prompts CONST MaxDisks% = 13 ' named constant indicating maximum number of disks CONST CsrOff% = 0 ' global variable declarations DIM DisksTotal%(MaxDisks% + 10), SourceTower%(MaxDisks% + 10) DIM TargetTower%(MaxDisks% + 10), Disk$(MaxDisks% + 10) DIM DisksPos%(MaxDisks% + 10, MaxDisks% + 10), TowerHgth%(13) MoveNumbers% = 0 ' used to keep track of number of moves made BottomRow% = 24 ' used to indicate bottom line of display TowerBase% = 2 ' start of main program CALL Init ' initialize the array of disks FOR X% = 1 TO DisksTotal%(1) ' for the number of disks Disk$(X%) = STRING$(26, 32) ' fill the array with spaces ' put the correct size disk in the array element ' 219 ( Ű ) is character used to make disks MID$(Disk$(X%), MaxDisks% + 1 - X%, X% * 2 - 1) = STRING$(30, 219) NEXT X% ' display the initial disks Top% = TowerBase% - DisksTotal%(1) FOR X% = 1 TO DisksTotal%(1) DisksPos%(X%, Y%) = Top% + X% ' assign row display DisksPos%(X%, X%) = 1 ' assign column display LOCATE Top% + X%, 1, CsrOff% ' position cursor COLOR X% MOD 14 + 1, 0 ' change color PRINT Disk$(X%); ' display the current disk NEXT X% CALL DisplayScreen ' display game screen TowerHgth%(1) = Top% ' initialize global variables TowerHgth%(2) = TowerBase% TowerHgth%(3) = TowerBase% SourceTower%(1) = 1 TargetTower%(1) = 3 RecursionDepth% = 0 LOCATE 1, 1, CsrOff%: PRINT "Start time: "; TIME$ CALL DoMoves(MoveNumbers%) ' start game LOCATE 2, 1, CsrOff%: PRINT "Stop time : "; TIME$ LOCATE 3, 1, CsrOff%: PRINT "Done in"; MoveNumbers%; "moves" LOCATE 5, 1, CsrOff%: PRINT "Hit any key !" l$ = INPUT$(1) END ' end of program SUB Decr (Value%) STATIC Value% = Value% - 1 END SUB SUB DisplayMove STATIC ' specify the global variables we need SHARED Column%, RecursionDepth%, DisksTotal%(), SourceTower%() SHARED TowerHgth%(), DisksPos%() SHARED TargetTower%(), Disk$() ' based on current tower, set display column IF TargetTower%(RecursionDepth%) = 1 THEN Column% = 1 ELSEIF TargetTower%(RecursionDepth%) = 2 THEN Column% = 27 ELSEIF TargetTower%(RecursionDepth%) = 3 THEN Column% = 54 END IF CALL GetRowCol(Row%, Col%, X%, Y%) 'LOCATE DisksPos%(DisksTotal%(RecursionDepth%),Y%), DisksPos%(DisksTotal%(RecursionDepth%),X%), CsrOff% LOCATE 1, 76: PRINT Col% ' go to the position of the next disk to move IF Col% = 0 THEN Col% = 1 LOCATE Row%, Col%, CsrOff% COLOR 7, 0 PRINT SPACE$(26) ' erase current disk ' increment the height of the tower the disk is moving to CALL Incr(TowerHgth%(SourceTower%(RecursionDepth%))) ' position cursor at top of destination tower LOCATE TowerHgth%(TargetTower%(RecursionDepth%)), Column%, CsrOff% ' get the color COLOR DisksTotal%(RecursionDepth%) MOD 14 + 1, 0 PRINT Disk$(DisksTotal%(RecursionDepth%)); ' display the disk COLOR 7, 0 ' update the current position of this disk DisksPos%(DisksTotal%(RecursionDepth%), Y%) = TowerHgth%(TargetTower%(RecursionDepth%)) DisksPos%(DisksTotal%(RecursionDepth%), X%) = Column% ' decrement the height of the tower the disk came from TowerHgth%(TargetTower%(RecursionDepth%)) = TowerHgth%(TargetTower%(RecursionDepth%)) - 1 END SUB ' end procedure DisplayMove SUB DisplayScreen STATIC REM REM +++++++++++++++++++++++++++++++++++++++++++++++++++ REM + This procedure displays a message on the screen + REM +++++++++++++++++++++++++++++++++++++++++++++++++++ REM SHARED DisksTotal%(), TowerBase% ' indicate which global vars we need LOCATE 1, 26, CsrOff% ' position the cursor and turn it on COLOR 4, 0 ' set the display color PRINT USING "Tornen of ™rebro for ## DISKS"; DisksTotal%(1) LOCATE TowerBase% + 1, X%, CsrOff% ' position the cursor COLOR 1, 0 ' set the display color PRINT STRING$(80, 176); ' display a bar on the screen COLOR 7, 0 ' set the display color END SUB ' end procedure DisplayScreen SUB DoMoves (NumMoves%) STATIC ' specify the global variables we need SHARED RecursionDepth%, DisksTotal%(), SourceTower%() SHARED TargetTower%(), TowerHgth%() ' increment level of recursion CALL Incr(RecursionDepth%) ' check if we should exit routine IF DisksTotal%(RecursionDepth%) = 0 THEN CALL Decr(RecursionDepth%) EXIT SUB END IF DisksTotal%(RecursionDepth% + 1) = DisksTotal%(RecursionDepth%) - 1 SourceTower%(RecursionDepth% + 1) = SourceTower%(RecursionDepth%) TargetTower%(RecursionDepth% + 1) = 6 - SourceTower%(RecursionDepth%) - TargetTower%(RecursionDepth%) CALL DoMoves(NumMoves%) CALL Incr(NumMoves%) CALL DisplayMove DisksTotal%(RecursionDepth% + 1) = DisksTotal%(RecursionDepth%) - 1 SourceTower%(RecursionDepth% + 1) = 6 - SourceTower%(RecursionDepth%) - TargetTower%(RecursionDepth%) TargetTower%(RecursionDepth% + 1) = TargetTower%(RecursionDepth%) CALL DoMoves(NumMoves%) CALL Decr(RecursionDepth%) END SUB ' end procedure DoMoves SUB GetRowCol (Row%, Col%, X%, Y%) STATIC SHARED DisksPos%() SHARED DisksTotal%() SHARED RecursionDepth% Row% = DisksPos%(DisksTotal%(RecursionDepth%), Y%) Col% = DisksPos%(DisksTotal%(RecursionDepth%), X%) END SUB SUB Incr (Value%) STATIC Value% = Value% + 1 END SUB SUB Init STATIC ' This procedure is used to initialize the screen and get the number ' of disks to use. SHARED DisksTotal%(), TowerBase% ' indicate which global vars we need STATIC C% ' declare a local variable KEY OFF ' turn key display off COLOR 7, 0 ' initialize screen color CLS COLOR 4, 0 LOCATE 1, 26, CsrOff% PRINT "Tower of ™rebro" ' display the program banner COLOR 6, 0 LOCATE PromptLine%, X%, CsrOff% PRINT "Number of Disks (1 TO " + STR$(MaxDisks%) + ") "; DO ' get the number of disks from the user LOCATE PromptLine%, LEN("Number of Disks (1 TO " + STR$(MaxDisks%) + ") ") + 1, CsrOff% INPUT DisksTotal%(1) IF DisksTotal%(1) > MaxDisks% THEN BEEP LOOP UNTIL DisksTotal%(1) <= MaxDisks% TowerBase% = TowerBase% + DisksTotal%(1) COLOR 7, 0 CLS 'LOCATE PromptLine%, X%, CsrOff% 'PRINT SPACE$(79) ' clear prompt line END SUB ' end procedure Init