用Python實現小遊戲 河內塔 可線上玩 Tower of Hanoi

閱讀時間約 11 分鐘

河內塔的遊戲描述

有三個柱子A柱,B柱,C柱。

A柱上有 N 個穿孔圓盤,圓盤的尺寸由下到上依次變小。
要求按下列規則透過合法移動,將所有圓盤移至 C 柱:

  1. 每次只能移動頂端的一個圓盤;
  2. 大圓盤不能疊在小圓盤上面


N=3的遊戲範例

raw-image



場景:


使用者輸入一個層數n

電腦填充A柱,讓A柱填滿n~1的正整數,每個數字就對應到圓盤的大小。

接著讓使用者扮演玩家,每次可以移動一個柱子頂端的一個盤子到另一個柱子

如果玩家最後成功把n個圓盤依序從大到小疊好,搬到終點的C柱,則玩家獲勝。
螢幕會秀出成功的提示訊息,並且顯示玩家花了幾步抵達終點。


上層思考邏輯與框架


讓使用者輸入層數n,接著讓電腦建立遊戲場景,填充A柱


遊戲開始後,讓玩家自由選擇要從哪個柱子開始移動圓盤到另一個柱子。


移動的過程中,電腦會判斷玩家的操作是否合法(也就是大圓盤不可以疊在小圓盤之上)。

如果合法,就把對應的圓盤移動過去。

過程中會統計移動步數。


若玩家最後成功把n個圓盤依序從大到小疊好,搬到終點的C柱,則玩家獲勝

螢幕會秀出成功的提示訊息,並且顯示玩家花了幾步抵達終點。


中層功能元件分析

1.怎麼接收使用者輸入?

python提供內建的input("提示訊息")的標準輸入function,

接收到的預設型別是字串。

接收層數時,記得要轉型成整數integer在儲存在變數n裡。

n = int( input("Please input level number of hanoi tower: ") )


接收移動圓盤的柱子時,直接接收字串即可。

src 代表要從哪個柱子拿起最上面的圓盤。

dest代表這個圓盤要放到哪個柱子。

src = input("Pick a tower to pick disk: ")

dest = input("Pick a tower to place disk: ")


2.怎麼建立遊戲場景,填充A柱?

遊戲場景總共有三個柱子A 柱, B柱, C柱,分別對應到三個堆疊。

# A, B, C
place = [ [], [], [] ]

# A柱對應到place[0]
# B柱對應到place[1]
# C柱對應到place[2]
mapping = {'A': 0, 'B': 1, 'C':2}


電腦根據n值,把A柱從下往上填滿n~1的正整數,
總個n個圓盤,數字的大小就代表圓盤的大小。


同時,會初始化步數為0。

之後步數會隨著玩家的操作而跟著累加上去。

def initialize(n, src):

  # 起點柱填充正整數 n ~ 1 ,代表碟子的大小
  place[ mapping[src] ] = [i for i in range(n, 0, -1) ]

  # 初始化總步數 = 0
  move_disk.step = 0

  return


3.怎麼建立C柱的解答?

目標是把所有的圓盤搬到C柱,從下往上 由大到小疊好所有的圓盤。

終點C柱的解答其實也是從下往上疊滿n~1的正整數,

我們只要把A柱一開始的樣子複製一份,就可以當作最終C柱的解答。

final_state = place[ mapping['A'] ].copy()


4.如何建立循環(相當於程式語言中迴圈的邏輯)?


如果 還有C柱還沒和解答的樣子相等:

則繼續遊戲...


對應到python的程式碼,就是while 的迴圈與流程控制

    while place[ mapping['C'] ] != final_state:

src = input("Pick a tower to pick disk: ")
dest = input("Pick a tower to place disk: ")

move_disk(src, dest)
showStatus()


5.怎麼移動圓盤到另一個柱子?


從使用者指定的src柱子移動到另一個dest柱子。

移動成功之後,步數step累加1


移動的時候,電腦會檢查是否為合法操作:

5-1.搬移的起點柱src不可以是空的。

5-2.大的圓盤不可以疊在小的圓盤之上


def move_disk(src, dest):

# src柱不可以是空的
if not place[ mapping[src] ]:
print(f"Tower {src} is empty!")
return

# 大的圓盤不可以疊在小的圓盤之上。
if place[ mapping[dest] ] and ( place[ mapping[src] ][-1] > place[ mapping[dest] ][-1] ):
print(f"Cannot place larger disk over smaller disk!")
return

# update總步數
move_disk.step += 1

cur = place[ mapping[src] ].pop()
place[ mapping[dest] ].append( cur )

print(f"Step {move_disk.step}: Move disk {cur} from {src} to {dest}.")

return


6.怎麼顯示當前的遊戲狀態?


依序把A柱、B柱、C柱的狀態顯示在螢幕上即可。


def showStatus():

print(f"Status is shown as folloing.")
print(f"A: { place[0]} ")
print(f"B: { place[1]} ")
print(f"C: { place[2]} ")
print()
return


7.遊戲成功後,怎麼顯示玩家勝利的訊息?


當C柱的狀態等於解答,也就是玩家成功把n個圓盤從大到小疊好後,
輸出玩家獲勝的訊息,並寫顯示玩家總共用了幾步完成遊戲。


    total_step = move_disk.step         

print(f"Good job, you finish the game with {total_step} steps.")
return total_step

底層的完整實作: 小遊戲 河內塔 Tower of Hanoi

# A柱, B柱, C柱
place = [ [], [], [] ]

# A柱對應到place[0]
# B柱對應到place[1]
# C柱對應到place[2]
mapping = {'A': 0, 'B': 1, 'C':2}

def showStatus():

print(f"Status is shown as folloing.")
print(f"A: { place[0]} ")
print(f"B: { place[1]} ")
print(f"C: { place[2]} ")
print()
return

def move_disk(src, dest):

if not place[ mapping[src] ]:
print(f"Tower {src} is empty!")
return

if place[ mapping[dest] ] and ( place[ mapping[src] ][-1] > place[ mapping[dest] ][-1] ):
print(f"Cannot place larger disk over smaller disk!")
return

# update總步數
move_disk.step += 1

cur = place[ mapping[src] ].pop()
place[ mapping[dest] ].append( cur )

print(f"Step {move_disk.step}: Move disk {cur} from {src} to {dest}.")

return


def initialize(n, src):
# 起點柱填充正整數 n ~ 1 ,代表碟子的大小
place[ mapping[src] ] = [i for i in range(n, 0, -1) ]

# 初始化總步數 = 0
move_disk.step = 0
return


def play(n):

# 填滿起點A柱
initialize(n, src='A')
showStatus()

# 設定解答狀態
final_state = place[ mapping['A'] ].copy()

while place[ mapping['C'] ] != final_state:

src = input("Pick a tower to pick disk: ")
dest = input("Pick a tower to place disk: ")
move_disk(src, dest)
showStatus()

total_step = move_disk.step

print(f"Good job, you finish the game with {total_step} steps.")
return total_step


if __name__ == "__main__":
n = int( input("Please input level number of honoi tower: ") )
play(n)



試玩畫面

raw-image

線上執行 與 試玩(在新的頁面按Run開始玩)

https://bit.ly/4clCg1q


延伸思考:


如果對程式或者演算法有興趣的同學,
可以試著觀察圓盤的移動規律,想出演算法,寫個解題程式,
能夠用最少的步數,解開河內塔這個遊戲!

很有趣喔~

86會員
425內容數
由有業界實戰經驗的演算法工程師, 手把手教你建立解題的框架, 一步步寫出高效、清晰易懂的解題答案。 著重在讓讀者啟發思考、理解演算法,熟悉常見的演算法模板。 深入淺出地介紹題目背後所使用的演算法意義,融會貫通演算法與資料結構的應用。 在幾個經典的題目融入一道題目的多種解法,或者同一招解不同的題目,擴展廣度,並加深印象。
留言0
查看全部
發表第一個留言支持創作者!
今天要實作和體驗的是拼單字的小遊戲,類似小時候在報紙、英文童書、或著電子辭典的小遊戲,一開始都是空白,隨著使用者拼對而逐漸顯示原本的單字樣貌,直到整個單字拼出來為止。 場景: 電腦隨機從單字庫裡面撈一個單字出來。 讓使用者扮演玩家去玩拼單字的遊戲。
相信大家小時候都有和朋友或玩伴玩過一個猜數字的小遊戲,一個人先在1~100裡面設定一個隱藏數字,其他的人去猜,看誰是最後一個猜中的就算輸,或者看誰最快猜中就算贏。 今天要示範如何用Python寫一個猜數字遊戲, 並且會從上層的思考邏輯開始,一步步構建出這個猜數字的小遊戲。
在流程控制中,最常用的就是for loop 或是 while loop 語法了。 最常見的場景就是根據條件判斷式,重複執行特定的指令。 如果要在python寫出類似C/C++ for loop,可以怎麼寫呢? 透過索引去進行迭代 for var in range( start=0, sto
Array可以說是各種語言除了基本型別之外,最常用的資料型別與容器之一了。 Array 這種連續格子狀的資料結構,在Python要怎麼表達呢? 建立一個空的陣列 最簡單也最直接的寫法就是 array = [] # Python list [] 就對應到大家熟知的array 陣列型態的資料結
今天要實作和體驗的是拼單字的小遊戲,類似小時候在報紙、英文童書、或著電子辭典的小遊戲,一開始都是空白,隨著使用者拼對而逐漸顯示原本的單字樣貌,直到整個單字拼出來為止。 場景: 電腦隨機從單字庫裡面撈一個單字出來。 讓使用者扮演玩家去玩拼單字的遊戲。
相信大家小時候都有和朋友或玩伴玩過一個猜數字的小遊戲,一個人先在1~100裡面設定一個隱藏數字,其他的人去猜,看誰是最後一個猜中的就算輸,或者看誰最快猜中就算贏。 今天要示範如何用Python寫一個猜數字遊戲, 並且會從上層的思考邏輯開始,一步步構建出這個猜數字的小遊戲。
在流程控制中,最常用的就是for loop 或是 while loop 語法了。 最常見的場景就是根據條件判斷式,重複執行特定的指令。 如果要在python寫出類似C/C++ for loop,可以怎麼寫呢? 透過索引去進行迭代 for var in range( start=0, sto
Array可以說是各種語言除了基本型別之外,最常用的資料型別與容器之一了。 Array 這種連續格子狀的資料結構,在Python要怎麼表達呢? 建立一個空的陣列 最簡單也最直接的寫法就是 array = [] # Python list [] 就對應到大家熟知的array 陣列型態的資料結
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
美國總統大選只剩下三天, 我們觀察一整週民調與金融市場的變化(包含賭局), 到本週五下午3:00前為止, 誰是美國總統幾乎大概可以猜到60-70%的機率, 本篇文章就是以大選結局為主軸來討論近期甚至到未來四年美股可能的改變
Thumbnail
Faker昨天真的太扯了,中國主播王多多點評的話更是精妙,分享給各位 王多多的點評 「Faker是我們的處境,他是LPL永遠繞不開的一個人和話題,所以我們特別渴望在決賽跟他相遇,去直面我們的處境。 我們曾經稱他為最高的山,最長的河,以為山海就是盡頭,可是Faker用他28歲的年齡...
Thumbnail
先上成果圖,如果是螺母的話就標註 is circle來區分。 簡單的用圖表加文字說明AOI辨識 在此文章的範例中: 影像前處理:色彩空間轉換(灰階) -> 二值化閥值處理 演算法:尋找輪廓 數值判斷:長,寬,面積,周長 圖片來源 程式碼 import cv2 import nu
情感分析是一種自然語言處理技術,用於自動識別和分析文本中的情感傾向,通常是正向、負向或中性。 我們可以使用 NLTK 來實現一個基於單純貝斯分類器的情感分析模型。
Thumbnail
初入IT產業的人士在學習Python語言後,IT證照如ITS Python認證是否值得考取?本文以ITS證照特點、實施建議和IT認證考試資訊為主,詳述證照的好處和準備時間。
Thumbnail
本文主要應用deepface的正面(frontal)人臉檢測的預設模型,使用analyze 函數,用於分析一張人臉圖像的情感(emotion)。 在Colab上實現,若用其他平台需稍微修改程式碼。 Deepface Deepface是一個輕量級的Python人臉辨識和臉部屬性分析
Thumbnail
根據泰勒定理,f(x)可以寫成右邊一長串的導數的組合 為了更好理解這個東西我們可以用python實作 首先定義f(x)和定義factorial怎麼算 然後寫泰勒定理 f(x) = f(a) + f'(a)(x-a) ....後面還有一串 注意公式往後面看其實是有規律的 例如從
Thumbnail
繼「【🔒 Python實戰營 - Data Science 必修班】Pandas 資料清洗技 - 填補式」之後,我們已經學會怎麼填補空缺資料了,那這個章節我們來教您如何對某些欄位有條件的整形,有時候我們的資料來源某些欄位資料格式不一,甚至型態都不是正規統一的值,此時我們就需要針對這些值進行一些處理
Thumbnail
在21世紀的技術浪潮中,「Python」不僅是程式設計的代表性語言,更是從初學者到資深工程師的共同選擇。除了在網頁開發、大數據和AI等專業領域中的應用,Python在全球的開發者社群中也建立了一個繁榮的生態系統,推動技術進步。然而,背後還隱藏著許多鮮為人知的故事和趣味,等待著我們去探索與發掘。
Thumbnail
繼「【Google Colab Python系列】 資料處理神器 Pandas 起手式」之後,相信對於各位來說已經是小兒科了吧,沒關係! 我們今天來增加一點點小挑戰,你知道嗎? Pandas對於大部分人的第一印象就是「不就表格化而已,有什麼了不起?」、「幫我們整理格式轉換的介接器」...,但其實它不
Thumbnail
前言 上篇把定位講完,不過實務上很少真的用手刻,大多用錄製或者軟體輔助,先講XPATH主要是讓大家有個底,就像最近的AI風一樣,好玩是一回事,做出來的東西還是要人看得懂知道哪裡可能有問題。 這篇就會著重介紹如何錄製腳本並轉換成可以執行的程式。
Thumbnail
如果,你是個專業的工程師,在外面臨時遇到需要修改或測試專案的情況,但手邊又沒有電腦跟網路,又或是,今天你臨時需要外出一陣子,但又放不下自己的專案,你會怎麼辦呢?
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
美國總統大選只剩下三天, 我們觀察一整週民調與金融市場的變化(包含賭局), 到本週五下午3:00前為止, 誰是美國總統幾乎大概可以猜到60-70%的機率, 本篇文章就是以大選結局為主軸來討論近期甚至到未來四年美股可能的改變
Thumbnail
Faker昨天真的太扯了,中國主播王多多點評的話更是精妙,分享給各位 王多多的點評 「Faker是我們的處境,他是LPL永遠繞不開的一個人和話題,所以我們特別渴望在決賽跟他相遇,去直面我們的處境。 我們曾經稱他為最高的山,最長的河,以為山海就是盡頭,可是Faker用他28歲的年齡...
Thumbnail
先上成果圖,如果是螺母的話就標註 is circle來區分。 簡單的用圖表加文字說明AOI辨識 在此文章的範例中: 影像前處理:色彩空間轉換(灰階) -> 二值化閥值處理 演算法:尋找輪廓 數值判斷:長,寬,面積,周長 圖片來源 程式碼 import cv2 import nu
情感分析是一種自然語言處理技術,用於自動識別和分析文本中的情感傾向,通常是正向、負向或中性。 我們可以使用 NLTK 來實現一個基於單純貝斯分類器的情感分析模型。
Thumbnail
初入IT產業的人士在學習Python語言後,IT證照如ITS Python認證是否值得考取?本文以ITS證照特點、實施建議和IT認證考試資訊為主,詳述證照的好處和準備時間。
Thumbnail
本文主要應用deepface的正面(frontal)人臉檢測的預設模型,使用analyze 函數,用於分析一張人臉圖像的情感(emotion)。 在Colab上實現,若用其他平台需稍微修改程式碼。 Deepface Deepface是一個輕量級的Python人臉辨識和臉部屬性分析
Thumbnail
根據泰勒定理,f(x)可以寫成右邊一長串的導數的組合 為了更好理解這個東西我們可以用python實作 首先定義f(x)和定義factorial怎麼算 然後寫泰勒定理 f(x) = f(a) + f'(a)(x-a) ....後面還有一串 注意公式往後面看其實是有規律的 例如從
Thumbnail
繼「【🔒 Python實戰營 - Data Science 必修班】Pandas 資料清洗技 - 填補式」之後,我們已經學會怎麼填補空缺資料了,那這個章節我們來教您如何對某些欄位有條件的整形,有時候我們的資料來源某些欄位資料格式不一,甚至型態都不是正規統一的值,此時我們就需要針對這些值進行一些處理
Thumbnail
在21世紀的技術浪潮中,「Python」不僅是程式設計的代表性語言,更是從初學者到資深工程師的共同選擇。除了在網頁開發、大數據和AI等專業領域中的應用,Python在全球的開發者社群中也建立了一個繁榮的生態系統,推動技術進步。然而,背後還隱藏著許多鮮為人知的故事和趣味,等待著我們去探索與發掘。
Thumbnail
繼「【Google Colab Python系列】 資料處理神器 Pandas 起手式」之後,相信對於各位來說已經是小兒科了吧,沒關係! 我們今天來增加一點點小挑戰,你知道嗎? Pandas對於大部分人的第一印象就是「不就表格化而已,有什麼了不起?」、「幫我們整理格式轉換的介接器」...,但其實它不
Thumbnail
前言 上篇把定位講完,不過實務上很少真的用手刻,大多用錄製或者軟體輔助,先講XPATH主要是讓大家有個底,就像最近的AI風一樣,好玩是一回事,做出來的東西還是要人看得懂知道哪裡可能有問題。 這篇就會著重介紹如何錄製腳本並轉換成可以執行的程式。
Thumbnail
如果,你是個專業的工程師,在外面臨時遇到需要修改或測試專案的情況,但手邊又沒有電腦跟網路,又或是,今天你臨時需要外出一陣子,但又放不下自己的專案,你會怎麼辦呢?