Author Topic: Tower of Hanoi puzzle  (Read 7598 times)

0 Members and 1 Guest are viewing this topic.

Arnold

  • Guest
Re: Tower of Hanoi puzzle
« Reply #15 on: March 28, 2016, 07:39:31 AM »
Hi Mike,

thank you for your help and your modifications of the code. I commented out my seeMoves print options and got these results:

Number of discs? 28
See the moves? (y/n)
Minimum moves required: 268435455

Calculating binary, wait ...
Calculated 268435455 moves in 19.438 seconds

Calculating binary with Roland's ASM, wait ...
Calculated 268435455 moves in 18.065 seconds

Calculating binary with Mike's ASM, wait ...
Calculated 268435455 moves in 3.791 seconds

Another Try? (y/n)

This difference is really significant and it is even more impressive with older computers. Although I consider Oxygen to be fast, this result will encourage me to learn and to use assembly in some special situations.

Thank you again for your help and advice.

Roland

Arnold

  • Guest
Re: Tower of Hanoi puzzle
« Reply #16 on: March 29, 2016, 10:46:00 AM »
Hello,

as a last exercise this is the Tower of Hanoi puzzle with simple animation in a console window. It uses the recursive approach and is inspired by examples\Console\TextSquash.o2bas. There is an option to press Enter for each move otherwise the discs will move automatically.

Roland

Code: OxygenBasic
  1. $ filename "Hanoi.exe"
  2. '#include "$/inc/RTL32.inc"
  3.  
  4. #include "$/inc/console.inc"
  5.  
  6. ! Sleep lib "KERNEL32.DLL" (dword dwMilliseconds)
  7.  
  8. macro display(x, y, txt) (SetPos(x-1, y-1): print txt)
  9.  
  10. SetConsoleTitle "Towers of Hanoi Puzzle"
  11.  
  12.  
  13. string disc[10] <= {
  14. "         MMM         ",
  15. "        MMMMM        ",
  16. "       MMMMMMM       ",
  17. "      MMMMMMMMM      ",
  18. "     MMMMMMMMMMM     ",
  19. "    MMMMMMMMMMMMM    ",
  20. "   MMMMMMMMMMMMMMM   ",
  21. "  MMMMMMMMMMMMMMMMM  ",
  22. " MMMMMMMMMMMMMMMMMMM ",
  23. "MMMMMMMMMMMMMMMMMMMMM"
  24. }
  25.  
  26. string answer
  27.  
  28. int num, count, seeMoves, countMoves, intervall
  29. int px[3]   'x of A,B,C
  30. int top[3]  'top position of disks
  31.  
  32.  
  33. sub createBoard()
  34.   string board=space 75
  35.   color 0x60 'FG black, BG yellow
  36.  display 4,20, board
  37.   for y=9 to 19
  38.     for x=1 to 3
  39.       display px[x],y, " "
  40.     next
  41.   next
  42.   color 0x07 'BG black, FG white
  43.  display 17,22,"A" : display 41,22,"B" : display 65,22,"C"
  44. end sub
  45.  
  46. sub pushDisk(string disk, rod)
  47.   color 0x0c 'FG black, BG lightred
  48.  top(rod)-=1
  49.   display px(rod)-10, top(rod), disk
  50. end sub
  51.  
  52. sub popDisk(string disk, rod)
  53.   color 0x0 : display px(rod)-10, top(rod), space 21
  54.   color 0x60 'FG black, BG yellow
  55.  display px[rod], top(rod), " "
  56.   top(rod)+=1
  57. end sub
  58.  
  59. sub addDisks(int num)
  60.   color 0x0c 'FG black, BG lightred
  61.  for iy=num to 1 step -1
  62.      pushDisk(disc(iy),1)
  63.   next
  64.   top[1]=20-num  
  65. end sub
  66.  
  67. sub initGame()
  68.   color 0x07 'BG black, FG white
  69.  display 1,1, "How many discs? (3-10): "
  70.   num=val(input)
  71.   if num<3 then
  72.     num=3
  73.   elseif num>10 then
  74.     num=10
  75.   end if
  76.   countMoves=pow(2,num)-1
  77.   intervall=(5000\countMoves)  
  78.   display 25,1, str(num) & "    "
  79.   addDisks(num)
  80.   color 0x07 'BG black, FG white                
  81.  display  1,2, "Enter key for next move? (y/n) "
  82.   answer=getkey()
  83.   if lcase(chr(answer))="y" then
  84.     seeMoves=1
  85.     display 1,2, "Press Enter to see next Move"
  86.   else
  87.     display 1,2, "                              "  
  88.   end if
  89. end sub
  90.  
  91. sub move (int n, fromPeg, toPeg, viaPeg)
  92.   if n>0 then
  93.     move n-1, fromPeg, viaPeg, toPeg
  94.     count+=1
  95.     if seeMoves then waitkey()
  96.     popDisk(disc(n),fromPeg)
  97.     pushDisk(disc(n),toPeg)
  98.     if seeMoves=0 then Sleep(Intervall)
  99.     move n-1, viaPeg, toPeg, fromPeg
  100.   end if
  101. end sub
  102.  
  103.  
  104. start:
  105.  
  106. px[] ={17,41,65}   'x pos of A,B,C
  107. top[]={20,20,20}   'top pos of disks
  108.  
  109. color 0x07 'BG black, FG white
  110.  
  111. cls
  112. count=0 : seeMoves=0 : intervall=0
  113.  
  114. createBoard()
  115. initGame()
  116.  
  117. move (num, 1,2,3)
  118.  
  119. display 1,24, "Solved in " count " moves"
  120. display 1,25, "Enter to continue ..." : waitkey()
  121.  
  122. color 0x07 'BG black, FG white
  123. display 1,25, "Another Try? (y/n)   "
  124.  
  125. answer=getkey() : if lcase(chr(answer))="y" then goto start
  126.  


.

Mike Lobanovsky

  • Guest
Re: Tower of Hanoi puzzle
« Reply #17 on: March 29, 2016, 03:13:10 PM »
Very cool Roland, thnx! :)

JRS

  • Guest
Re: Tower of Hanoi puzzle
« Reply #18 on: March 29, 2016, 08:24:33 PM »
Runs fine on Wine.



.

Arnold

  • Guest
Re: Tower of Hanoi puzzle
« Reply #19 on: April 25, 2019, 02:17:19 AM »
Oxygenbasic has changed a bit in the last three years, and the code above will not run without some modifications. So I adapted it for the latest version of February 2019. At the same time I added some adjustments: fix the size of the console window, hide the cursor during the movements of the disks, force to answer with y or n. I applied some tricks of \examples\console\TextSquash.o2bas. (who is the watcher?) The app is not intended to run with older versions of Oxygen, but it will run in 32-bit and 64-bit mode now. And hopefully the code is better readable than my first try.

Code: OxygenBasic
  1. 'https://en.wikipedia.org/wiki/Tower_of_Hanoi
  2.  
  3. $ filename "Hanoi.exe"
  4. 'uses rtl32
  5. 'uses rtl64
  6.  
  7. uses console
  8.  
  9. type CONSOLE_CURSOR_INFO ' cci  
  10.    dword dwSize
  11.     bool  bVisible
  12. end type
  13.  
  14. extern lib "KERNEL32.DLL"
  15. ! SetConsoleCursorInfo (sys hConsoleOutput, CONSOLE_CURSOR_INFO *lpConsoleCursorInfo) as bool
  16. ! SetConsoleWindowInfo (sys hConsoleOutput, bool bAdsolute, SMALL_RECT *lpConsoleWindow)
  17. ! Sleep                (dword dwMilliseconds)
  18. end extern
  19.  
  20. extern lib "user32.dll"
  21. ! GetSystemMenu (sys hWnd, dword bRevert) as sys
  22. ! DeleteMenu    (sys hMenu, uint uPosition, uint uFlags)
  23. end extern
  24.  
  25. sub setcolor(int fg, bg)
  26.   SetConsoleTextAttribute (ConsOut, fg+bg*16)
  27. end sub
  28.  
  29. sub locate (int row,int col, optional int visible=1,int shape=12)
  30.   CONSOLE_CURSOR_INFO cci
  31.   SetPos(col-1,row-1)
  32.   cci.bVisible = visible
  33.   cci.dwSize   = shape
  34.   SetConsoleCursorInfo(ConsOut, cci)
  35. end sub
  36.  
  37. sub display(int col, row, string txt, optional int visible=1,int shape=12)
  38.   locate(row, col, visible)
  39.   print txt
  40. end sub  
  41.  
  42. sub AdaptConsole()
  43.    'Set size to 80,24
  44.   dim ConsoleWindow as SMALL_RECT
  45.    ConsoleWindow.Right = 80: ConsoleWindow.Bottom = 24
  46.    SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE), 1, ConsoleWindow)
  47.    'Fix size
  48.   sys hConsMenu=GetSystemMenu(GetConsoleWindow(), 0)
  49.    DeleteMenu(hConsMenu, &HF000, 0)
  50.    DeleteMenu(hConsMenu, &HF020, 0)
  51.    DeleteMenu(hConsMenu, &HF030, 0)  
  52. end sub
  53.  
  54. SetConsoleTitle "Towers of Hanoi Puzzle"
  55.  
  56.  
  57. string disk[10] = {
  58. "         MMM         ",
  59. "        MMMMM        ",
  60. "       MMMMMMM       ",
  61. "      MMMMMMMMM      ",
  62. "     MMMMMMMMMMM     ",
  63. "    MMMMMMMMMMMMM    ",
  64. "   MMMMMMMMMMMMMMM   ",
  65. "  MMMMMMMMMMMMMMMMM  ",
  66. " MMMMMMMMMMMMMMMMMMM ",
  67. "MMMMMMMMMMMMMMMMMMMMM"
  68. }
  69.  
  70. string answer
  71.  
  72. int num, count, seeMoves, countMoves, intervall
  73. int rodCol[3] ={17,41,65}   'x pos of A,B,C
  74. int diskRow[3]               'row position of disks
  75.  
  76.  
  77. sub createBoard()
  78.   int idx, row
  79.   string board=space 75
  80.   setcolor 0,6 ' black, yellow
  81.  display 4,20, board, 0
  82.   for row=9 to 19
  83.     for idx=1 to 3
  84.       display rodCol[idx],row, " ", 0
  85.     next
  86.   next
  87.   setcolor 7,0 ' white, black
  88.  display 17,22,"A",0 : display 41,22,"B",0 : display 65,22,"C",0
  89. end sub
  90.  
  91. sub pushDisk(string disk, int rod)
  92.   setcolor 13,0 ' magenta, black
  93.  diskRow(rod)-=1
  94.   display rodCol(rod)-10, diskRow(rod), disk,0
  95. end sub
  96.  
  97. sub popDisk(string disk, int rod)
  98.   setcolor 0,0 ' black, black
  99.  display rodCol(rod)-10, diskRow(rod), space(21),0
  100.   setcolor 0,6 ' black, yellow
  101.  display rodCol[rod], diskRow(rod), " ",0
  102.   diskRow(rod)+=1
  103. end sub
  104.  
  105. sub addDisks(int num)
  106.   int row
  107.   setcolor 13,0 ' magenta, black
  108.  for row=num to 1 step -1
  109.      pushDisk(disk(row),1)
  110.   next
  111.   diskRow[1]=20-num  
  112. end sub
  113.  
  114. sub initGame()
  115.   setcolor 7,0 ' white, black
  116.  display 1,1, "How many disks? (3-10): "
  117.   num=val(input)
  118.   if num<3 then
  119.     num=3
  120.   elseif num>10 then
  121.     num=10
  122.   end if
  123.   countMoves=pow(2,num)-1
  124.   intervall=(5000\countMoves)  
  125.   display 25,1, str(num) & "    ",0
  126.   addDisks(num)
  127. loop1:  
  128.   setcolor 7,0 ' white, black                
  129.  display  1,2, "Use Enter for next move? (y/n) "
  130.   answer=getkey()
  131.   if lcase(chr(answer))="y" then
  132.     seeMoves=1
  133.     display 1,2, "Press Enter to see next Move  "
  134.   elseif lcase(chr(answer))="n" then
  135.     display 1,2, "                              ",0
  136.   else
  137.     goto loop1    
  138.   end if
  139. end sub
  140.  
  141. sub movedisk (int n, fromPeg, toPeg, viaPeg)
  142.   'recursive method
  143.  if n>0 then
  144.     movedisk n-1, fromPeg, viaPeg, toPeg
  145.     count+=1
  146.     if seeMoves then waitkey()
  147.     popDisk(disk(n),fromPeg)
  148.     pushDisk(disk(n),toPeg)
  149.     if seeMoves=0 then Sleep(Intervall)
  150.     movedisk n-1, viaPeg, toPeg, fromPeg
  151.   end if
  152. end sub
  153.  
  154. ================================================================================
  155. 'Prepare console, fix size
  156. AdaptConsole()
  157.  
  158. 'Start the app
  159. start:
  160. diskRow[]={20,20,20}   'row position of disks
  161.  
  162. setcolor 7,0 ' white, black
  163.  
  164. cls
  165. count=0 : seeMoves=0 : intervall=0
  166.  
  167. createBoard()
  168. initGame()
  169.  
  170. movedisk (num, 1,2,3)
  171.  
  172. display 1,24, "Solved in " count " moves",0
  173. display 1,25, "Enter to continue ...",0 : waitkey()
  174.  
  175. loop2:  
  176. setcolor 7,0 ' white, black
  177. display 1,25, "Another Try? (y/n)   "
  178.  
  179. answer=getkey() : if lcase(chr(answer))="y" then goto start
  180. if lcase(chr(answer))<>"n" then goto loop2
  181.  

Mike Lobanovsky

  • Guest
Re: Tower of Hanoi puzzle
« Reply #20 on: April 25, 2019, 05:32:13 AM »
... (who is the watcher?) ...

It's me when in a don't-care stand-by mode. ;D

https://www.youtube.com/watch?v=CsrfovOPcjk

Charles Pegge

  • Guest
Re: Tower of Hanoi puzzle
« Reply #21 on: April 25, 2019, 06:26:24 AM »
Thanks, Roland.

I'll include it in examples\console :)