學習Python已經有一段時間了,也學習了遞歸的方法,而能夠實踐該方法的當然就是漢諾塔問題了,但是這次我們不只是要完成對漢諾塔過程的計算,還要通過turtle庫來體現漢諾塔中每一層移動的過程。
一、設計一個類(Class)
類(Class):用來描述具有相同的屬性和方法的對象的集合。它定義了該集合中每個對象所共有的屬性和方法。對象是類的實例。
下面是此程序需用到的類(Class)代碼:
1 class Stack: 2 def __init__(self): 3 self.items = [] 4 def isEmpty(self): 5 return len(self.items) == 0 6 def push(self, item): 7 self.items.append(item) 8 def pop(self): 9 return self.items.pop() 10 def peek(self): 11 if not self.isEmpty(): 12 return self.items[len(self.items) - 1] 13 def size(self): 14 return len(self.items)
二、設計漢諾塔的底座
為了還原漢諾塔的移動過程,增強可視化程度,我們給它加上三個底座,代碼如下:
1 def drawpole_3():#畫出漢諾塔的poles 2 t = turtle.Turtle() 3 t.hideturtle() 4 def drawpole_1(k): 5 t.up() 6 t.pensize(10) 7 t.speed(100) 8 t.goto(400*(k-1), 100) 9 t.down() 10 t.goto(400*(k-1), -100) 11 t.goto(400*(k-1)-20, -100) 12 t.goto(400*(k-1)+20, -100) 13 drawpole_1(0)#畫出漢諾塔的poles[0] 14 drawpole_1(1)#畫出漢諾塔的poles[1] 15 drawpole_1(2)#畫出漢諾塔的poles[2]
三、制造漢諾塔的盤子
漢諾塔當然少不了盤子了,我們要寫一段代碼來繪制若干個盤子,代碼如下:
1 def creat_plates(n):#制造n個盤子 2 plates=[turtle.Turtle() for i in range(n)] 3 for i in range(n): 4 plates[i].up() 5 plates[i].hideturtle() 6 plates[i].shape("square") 7 plates[i].shapesize(1,8-i) 8 plates[i].goto(-400,-90+20*i) 9 plates[i].showturtle() 10 return plates
四、制造一個底座的棧
棧:棧作為一種數據結構,是一種只能在一端進行插入和刪除操作。它按照先進后出的原則存儲數據,先進入的數據被壓入棧底,最后的數據在棧頂,需要讀數據的時候從棧頂開始彈出數據(最后一個數據被第一個讀出來)。
此處使用的棧並非Python中真正意義上的棧,而是與之意思相仿的說法,我們都知道,漢諾塔必須將最上的盤子取走方可移動第二層的盤子,以此類推,不移動上方的盤子,就無法移動下方的盤子,廢話不多說,來看看這個代碼吧:
1 def pole_stack():#制造poles的棧 2 poles=[Stack() for i in range(3)] 3 return poles
五、設計移動盤子的代碼
准備完前面的工作,現在就要開始移動盤子了,代碼如下:
1 def moveDisk(plates,poles,fp,tp):#把poles[fp]頂端的盤子plates[mov]從poles[fp]移到poles[tp] 2 mov=poles[fp].peek() 3 plates[mov].goto((fp-1)*400,150) 4 plates[mov].goto((tp-1)*400,150) 5 l=poles[tp].size()#確定移動到底部的高度(恰好放在原來最上面的盤子上面) 6 plates[mov].goto((tp-1)*400,-90+20*l)
六、設計操控盤子移動方向的代碼
可以移動盤子了當然還不夠,只是胡亂地移動無法解決漢諾塔問題,我們要讓盤子向着能夠解決問題的方向移動,代碼如下:
1 def moveTower(plates,poles,height,fromPole, toPole, withPole):#遞歸放盤子 2 if height >= 1: 3 moveTower(plates,poles,height-1,fromPole,withPole,toPole) 4 moveDisk(plates,poles,fromPole,toPole) 5 poles[toPole].push(poles[fromPole].pop()) 6 moveTower(plates,poles,height-1,withPole,toPole,fromPole)
七、調用
終於完成了全部准備工作,現在就來調用函數,讓他們一起發揮作用吧!
1 import turtle 2 3 class Stack: 4 def __init__(self): 5 self.items = [] 6 def isEmpty(self): 7 return len(self.items) == 0 8 def push(self, item): 9 self.items.append(item) 10 def pop(self): 11 return self.items.pop() 12 def peek(self): 13 if not self.isEmpty(): 14 return self.items[len(self.items) - 1] 15 def size(self): 16 return len(self.items) 17 18 def drawpole_3():#畫出漢諾塔的poles 19 t = turtle.Turtle() 20 t.hideturtle() 21 def drawpole_1(k): 22 t.up() 23 t.pensize(10) 24 t.speed(100) 25 t.goto(400*(k-1), 100) 26 t.down() 27 t.goto(400*(k-1), -100) 28 t.goto(400*(k-1)-20, -100) 29 t.goto(400*(k-1)+20, -100) 30 drawpole_1(0)#畫出漢諾塔的poles[0] 31 drawpole_1(1)#畫出漢諾塔的poles[1] 32 drawpole_1(2)#畫出漢諾塔的poles[2] 33 34 def creat_plates(n):#制造n個盤子 35 plates=[turtle.Turtle() for i in range(n)] 36 for i in range(n): 37 plates[i].up() 38 plates[i].hideturtle() 39 plates[i].shape("square") 40 plates[i].shapesize(1,8-i) 41 plates[i].goto(-400,-90+20*i) 42 plates[i].showturtle() 43 return plates 44 45 def pole_stack():#制造poles的棧 46 poles=[Stack() for i in range(3)] 47 return poles 48 49 def moveDisk(plates,poles,fp,tp):#把poles[fp]頂端的盤子plates[mov]從poles[fp]移到poles[tp] 50 mov=poles[fp].peek() 51 plates[mov].goto((fp-1)*400,150) 52 plates[mov].goto((tp-1)*400,150) 53 l=poles[tp].size()#確定移動到底部的高度(恰好放在原來最上面的盤子上面) 54 plates[mov].goto((tp-1)*400,-90+20*l) 55 56 def moveTower(plates,poles,height,fromPole, toPole, withPole):#遞歸放盤子 57 if height >= 1: 58 moveTower(plates,poles,height-1,fromPole,withPole,toPole) 59 moveDisk(plates,poles,fromPole,toPole) 60 poles[toPole].push(poles[fromPole].pop()) 61 moveTower(plates,poles,height-1,withPole,toPole,fromPole) 62 63 myscreen=turtle.Screen() 64 drawpole_3() 65 n=int(input("請輸入漢諾塔的層數並回車:\n")) 66 plates=creat_plates(n) 67 poles=pole_stack() 68 for i in range(n): 69 poles[0].push(i) 70 moveTower(plates,poles,n,0,2,1) 71 myscreen.exitonclick()
八、效果
首先輸入一下我們想測試的漢諾塔層數,為節省時間我就選擇了3層

下面是移動過程



看來效果還不錯,這樣漢諾塔的可視化就實現啦!
