### Author Topic: Tower of Hanoi puzzle  (Read 7127 times)

0 Members and 1 Guest are viewing this topic.

#### Arnold

• Hero Member
• Posts: 977
##### 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

• Hero Member
• Posts: 977
##### 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

• Hero Member
• Posts: 1993
##### Re: Tower of Hanoi puzzle
« Reply #17 on: March 29, 2016, 03:13:10 pm »
Very cool Roland, thnx!
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, nVidia GTX 1060Ti w/ 6GB VRAM, Windows 7 Ultimate Sp1)

#### John

• Hero Member
• Posts: 3966
##### Re: Tower of Hanoi puzzle
« Reply #18 on: March 29, 2016, 08:24:33 pm »
Runs fine on Wine.

.

#### Arnold

• Hero Member
• Posts: 977
##### 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

• Hero Member
• Posts: 1993
##### 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.

https://www.youtube.com/watch?v=CsrfovOPcjk
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, nVidia GTX 1060Ti w/ 6GB VRAM, Windows 7 Ultimate Sp1)

#### Charles Pegge

• Admin Support Member
• Posts: 4486
##### Re: Tower of Hanoi puzzle
« Reply #21 on: April 25, 2019, 06:26:24 am »
Thanks, Roland.

I'll include it in examples\console