“Tower of Hanoi” Program
1.ハノイの塔
N枚のディスクを他の塔に移動する、というパズルゲームがあります。
ハノイの塔と言われるものです。
以前、何かの雑誌のプレゼント企画で、ハノイの塔のパズルをもらったことがありました。
それを機に、ハノイの塔を解くプログラムを作成してみました。

2.プログラム
ハノイの塔を解くプログラムは、よく再帰プログラムの例として紹介されたりしています。
以前、別ブログには掲載していたのですが、こちらには未アップでしたので、今回、iPadのプログラムをMacBookへ移植して動作するようにしました。
3.ソースコード
下記に貼り付けましたが、タブとかは正しくコピーできていないかもしれません。
import ui
import time #for sleep()
step = 1 #num. of proc.
lnum = 7 #num. of disk for Left_tower
cnum = rnum = 0 #num. of disk for Center,Right_tower
#Move proc. for each disk
def moveDisk(num_disk, from_twr, to_twr):
global lnum, cnum, rnum
if num_disk == 1: #for disk1
if to_twr == "Left":
d1.x = 80 - (num_disk-1) * 10
d1.y = 280 - lnum * 30
lnum += 1 #increment Left disk num.
if to_twr == "Center":
d1.x = 320 - (num_disk-1) * 10
d1.y = 280 - cnum * 30
cnum += 1 #increment Center disk num.
if to_twr == "Right":
d1.x = 560 - (num_disk-1) * 10
d1.y = 280 - rnum * 30
rnum += 1 #increment Right disk num.
if num_disk == 2: #for disk2
if to_twr == "Left":
d2.x = 80 - (num_disk-1) * 10
d2.y = 280 - lnum * 30
lnum += 1 #increment Left disk num.
if to_twr == "Center":
d2.x = 320 - (num_disk-1) * 10
d2.y = 280 - cnum * 30
cnum += 1 #increment Center disk num.
if to_twr == "Right":
d2.x = 560 - (num_disk-1) * 10
d2.y = 280 - rnum * 30
rnum += 1 #increment Right disk num.
if num_disk == 3: #for disk3
if to_twr == "Left":
d3.x = 80 - (num_disk-1) * 10
d3.y = 280 - lnum * 30
lnum += 1 #increment Left disk num.
if to_twr == "Center":
d3.x = 320 - (num_disk-1) * 10
d3.y = 280 - cnum * 30
cnum += 1 #increment Center disk num.
if to_twr == "Right":
d3.x = 560 - (num_disk-1) * 10
d3.y = 280 - rnum * 30
rnum += 1 #increment Right disk num.
if num_disk == 4: #for disk4
if to_twr == "Left":
d4.x = 80 - (num_disk-1) * 10
d4.y = 280 - lnum * 30
lnum += 1 #increment Left disk num.
if to_twr == "Center":
d4.x = 320 - (num_disk-1) * 10
d4.y = 280 - cnum * 30
cnum += 1 #increment Center disk num.
if to_twr == "Right":
d4.x = 560 - (num_disk-1) * 10
d4.y = 280 - rnum * 30
rnum += 1. #increment Right disk num.
if num_disk == 5: #for disk5
if to_twr == "Left":
d5.x = 80 - (num_disk-1) * 10
d5.y = 280 - lnum * 30
lnum += 1 #increment Left disk num.
if to_twr == "Center":
d5.x = 320 - (num_disk-1) * 10
d5.y = 280 - cnum * 30
cnum += 1 #increment Center disk num.
if to_twr == "Right":
d5.x = 560 - (num_disk-1) * 10
d5.y = 280 - rnum * 30
rnum += 1 #increment Right disk num.
if num_disk == 6: #for disk6
if to_twr == "Left":
d6.x = 80 - (num_disk-1) * 10
d6.y = 280 - lnum * 30
lnum += 1 #increment Left disk num.
if to_twr == "Center":
d6.x = 320 - (num_disk-1) * 10
d6.y = 280 - cnum * 30
cnum += 1 #increment Center disk num.
if to_twr == "Right":
d6.x = 560 - (num_disk-1) * 10
d6.y = 280 - rnum * 30
rnum += 1 #increment Right disk num.
if num_disk == 7: #for disk7
if to_twr == "Left":
d7.x = 80 - (num_disk-1) * 10
d7.y = 280 - lnum * 30
lnum += 1 #increment Left disk num.
if to_twr == "Center":
d7.x = 320 - (num_disk-1) * 10
d7.y = 280 - cnum * 30
cnum += 1 #increment Center disk num.
if to_twr == "Right":
d7.x = 560 - (num_disk-1) * 10
d7.y = 280 - rnum * 30
rnum += 1 #increment Right disk num.
if from_twr == "Left":
lnum = lnum -1 #decrement Left disk num.
if from_twr == "Center":
cnum = cnum - 1 #decrement Center disk num.
if from_twr == "Right":
rnum = rnum - 1 #decrement Right disk num.
time.sleep(0.3)
#Scroll proc. for textview
def scroll():
tv.content_offset = (0, tv.content_size[1] - tv.height)
if tv.content_offset[1] < 0:
#while y_offset is minus, no scroll.
tv.content_offset = (0,0)
#Main proc. for HANOI, using 'recursion'
def hanois(num_disk, from_twr, to_twr, tmp_twr):
global step
#Move disk from 'from_twr' to 'to_twr'.
if num_disk == 1:
#if 1disk, move it finished.
#print(f"step{step}: No.{num_disk}-disk from {from_twr} to {to_twr}.")
tv.text += (f"step{step}: No.{num_disk}-disk from {from_twr} to {to_twr}."+"\n")
scroll()
moveDisk(num_disk, from_twr, to_twr)
step = step + 1
return
#Move (N-1)th. disk from Left to Center. Right as temporary towerext
hanois(num_disk-1, from_twr, tmp_twr, to_twr)
#Move remaining disk from Left to Right
#print(f"step{step}: No.{num_disk}-disk from {from_twr} to {to_twr}.")
tv.text += (f"step{step}: No.{num_disk}-disk from {from_twr} to {to_twr}."+"\n")
scroll()
moveDisk(num_disk, from_twr, to_twr)
step = step + 1
#Move (N-1)th. disk from Center to Right. Left as temporary tower
hanois(num_disk-1, tmp_twr, to_twr, from_twr)
#Start UI
v = ui.load_view()
v.present('sheet')
tv = v['textview1'] #set textview controll
d1 = v['button1'] #set button_n controll
d2 = v['button2']
d3 = v['button3']
d4 = v['button4']
d5 = v['button5']
d6 = v['button6']
d7 = v['button7']
#start The Hanoi
hanois(7, "Left", "Right", "Center")
4.画面構成
diskはButtonで構成しています。
最下部は、テキストビューを使用し、実行中の進捗を表示します。

5.実行画面
iPhoneで撮影の動画をアップしようとしましたが、サイズオーバーのためできませんでした。
次の機会にします。
6.ファイル
ソースと.pyuiファイルをアップしようとしましたが、権限がないと言われ、ファイルをアップできませんでした。
こちらも、後日、調べてからアップします。