11. Python | 遞歸函數(shù)_引申_漢諾塔游戲策略總結(jié)

漢諾塔游戲,是個佷益智的游戲,其中也蘊含了一些數(shù)學(xué)的知識,故事的背景甚至蘊含了一些古人對宇宙的思考。今天我們來聊下這個游戲,僅僅從游戲的方法和策略的總結(jié)上對這個游戲進(jìn)行一下解剖:

游戲簡介

漢諾塔_益智游戲
`由來與傳說:`

法國數(shù)學(xué)家`愛德華·盧卡斯`曾編寫過一個印度的古老傳說:在世界中心貝拿勒斯
(在印度北部)的圣廟里,一塊黃銅板上插著三根寶石針。印度教的主神`梵天`
在創(chuàng)造世界的時候,在其中一根針上從下到上地穿好了由大到小的64片金片,這
就是所謂的漢諾塔。不論白天黑夜,總有一個僧侶在按照下面的法則移動這些金
片:一次只移動一片,不管在哪根針上,小片必須在大片上面。僧侶們預(yù)言,當(dāng)所
有的金片都從梵天穿好的那根針上移到另外一根針上時,世界就將在一聲霹靂中消
滅,而`梵塔`、`廟宇`和`眾生`也都將同歸于盡。 

不管這個傳說的可信度有多大,如果考慮一下把64片金片,由一根針上移到另一
根針上,并且始終保持上小下大的順序。這需要多少次移動呢?這里需要遞歸的方
法。假設(shè)有n片,移動次數(shù)是f(n).顯然f(1)=1,f(2)=3,f(3)=7,且f(k+1)=2*f(k)+1。
此后不難證明f(n)=2^n-1。n=64時,

假如每秒鐘一次,共需多長時間呢?一個平年365天有31536000 秒,閏年366天有
31622400秒,平均每年31556952秒,計算一下:
                                        18446744073709551615秒

這表明移完這些金片需要5845.54億年以上,而地球存在至今不過45億年,太陽系
的預(yù)期壽命據(jù)說也就是數(shù)百億年。真的過了5845.54億年,不說太陽系和銀河系,
至少地球上的一切生命,連同梵塔、廟宇等,都早已經(jīng)灰飛煙滅。

游戲的目的

  • 很多人最初接觸到這個益智游戲,都是直接用5個以上圓盤開始游戲的,但是又不太清楚具體的移動規(guī)律,導(dǎo)致玩兒了半天也沒有將所有圓盤成功移動到C柱子上,甚至玩過以后就得出了一個結(jié)論,這游戲太沒意思了。。。

  • 實際上這種益智類的游戲,往往都是具有一定的方法和規(guī)律可循的,因為這類游戲的目的就是讓人開發(fā)思維,啟迪智慧。通常這類游戲或者玩具是最適合給孩子玩的。

  • 既然這個游戲有益智的作用,我們就應(yīng)該掌握玩這種游戲的方法或者至少我們應(yīng)該學(xué)會教孩子如何玩這個游戲,才能讓這個益智游戲開發(fā)孩子的思維啟迪孩子的智慧?。?/p>

游戲的策略

在這一部分,我們要分為兩點去講:1. 推導(dǎo)和歸納;2. Python代碼的實現(xiàn)。

1. 推導(dǎo)和歸納

說到歸納和總結(jié),我們可以參照數(shù)學(xué)上的歸納方法。
舉個例子:

`                     1 = 1                               `
`                   1×2 = 2                               `
`                 1×2×3 = 6                               `
`               1×2×3×4 = 24                              `
`             1×2×3×4×5 = 120                             `
`                 ...                                     `
`     1×2×3×...×(n-1)×n = f(n)                            `

上面的歸納的是一個函數(shù),也就是階乘,表達(dá)式為:
f(n) = n! = n * (n-1) * ... * 1 = n * (n-1)!
歸納之后便形成了一個比較抽象、但是很容易記住的方法——公式。

通過歸納和演繹,用一些簡單的、易操作的數(shù)字和步驟進(jìn)行推演,形成適用于更廣范圍的通行公式。

  • 我們來看一下漢諾塔如何推演
    要求:將圓盤從 <起點A柱子>借助<緩沖B柱子>移動到<終點C柱子>
    分析:為了更好的解釋說明操作步驟,我們講圓盤從小到大依次取名為1、2、3、4、5...
    步驟:

    1. 當(dāng)A柱子上有1個圓盤時
      A-->C表示將1移到C:1-->C:圓盤為奇數(shù)時,第一步指向終點C柱

    2. 當(dāng)A柱子上有2個圓盤時
      ①A-->B表示將1移到B:1-->B:圓盤為偶數(shù)時,第一步指向緩沖B柱
      ②A-->C表示將2移到C:2-->C:最下面的圓盤,移動到終點C柱
      ③B-->C表示將1移到C:1-->C:緩沖柱上的圓盤,移動到終點C柱

    3. 當(dāng)A柱子上有3個圓盤時
      ①A-->C表示將1移到C:1-->C:圓盤為奇數(shù)時,第一步指向終點C柱
      ①A-->B表示將2移到B:2-->B:將2號圓盤移到緩沖B柱
      ①C-->B表示將1移到B:1-->B:將1號圓盤移到緩沖B柱
      ②A-->C表示將3移到C:3-->C:最下面的圓盤,移到到終點C柱
      ③B-->A表示將1移到A:1-->A:將1號圓盤移到起點A柱
      ③B-->C表示將2移到C:2-->C:將2號圓盤移到終點C柱
      ③A-->C表示將1移到C:1-->C:將1號圓盤移到終點C柱

  • 根據(jù)上面寫的3個推演步驟,我們進(jìn)行歸納如下:

    1. 整個移動過程(排除只有一個圓盤的特殊情況),可以分為三個階段,用①②③表示。
    2. ①階段,把 n-1個圓盤移到緩沖B柱;
      ②階段,把第n個圓盤移到終點C柱;
      ③階段,把 n-1個圓盤移到終點C柱
    3. 其中,第②階段,是在最中間的一步,第①階段和第③階段的移動步數(shù)是一樣多的。
    4. 第一步的移動方向,根據(jù)圓盤的個數(shù)不同而定
      奇數(shù)個圓盤,第一步一定是移到終點C柱
      偶數(shù)個圓盤,第一步一定是移到緩沖B柱
      別小瞧這個方向的定位,以后每次移動1、2圓盤時,都是按照這個方向定位的。
    5. 我們把移動圓盤的過程分為n輪,每一輪都要移動1、2、1和另一個圓盤;
      并且每一輪移動1、2、1圓盤的時候,都是按照固定的規(guī)律去移動的。
      我們會以1、2圓盤同時所在的柱子為視角做定位,判斷移動的方向。下面有一個圖,上面詳細(xì)寫了具體的移動順序和方法:
    6. 要想明白具體是如何做的,只用眼睛看是很難理解的,當(dāng)你跟著我寫的步驟操作幾次之后,你一定會豁然開朗,原來移動起來是這么簡單~

2. Python代碼的實現(xiàn)
當(dāng)然了用文字,或者截圖去描述這個過程,無論如何都算不上簡單明了。Python語言中,用函數(shù)將這個游戲的移動方法,定義成了一個遞歸函數(shù),寫法竟然非常的簡單:

# 請編寫 `move(n, a, b, c)`函數(shù),它接收參數(shù) n,表示3個柱子A、B、C中
# 第1個柱子A的盤子數(shù)量,然后打印出把所有盤子從A借助B移動到C的方法
# -*- coding: utf-8 -*-
def move(n, a, b, c):

    if n == 1:
        print(a, '-->', c)
    # 下面else的部分是需補全的代碼,也就是移動方法
    else:
        move(n-1,a,c,b)   # 思考一下為什么要這樣寫?
        move(1,a,b,c)   # 想一下,這是哪個階段?
        move(n-1,b,a,c)   # 你知道,這最后的一步,是什么意思嗎?
# 有3個圓盤時
move(3, 'A', 'B', 'C')
# 換行
print('\n')
# 有4個圓盤時
move(4, 'A', 'B', 'C')

# 這是有3個圓盤時的【期待輸出結(jié)果】:
#     A --> C
#     A --> B
#     C --> B
#     A --> C
#     B --> A
#     B --> C
#     A --> C

你可以復(fù)制一下這段代碼,去驗證一下結(jié)果是不是和你自己移動的結(jié)果一樣!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 專業(yè)考題類型管理運行工作負(fù)責(zé)人一般作業(yè)考題內(nèi)容選項A選項B選項C選項D選項E選項F正確答案 變電單選GYSZ本規(guī)程...
    小白兔去釣魚閱讀 10,508評論 0 13
  • 選擇題部分 1.(),只有在發(fā)生短路事故時或者在負(fù)荷電流較大時,變流器中才會有足夠的二次電流作為繼電保護(hù)跳閘之用。...
    skystarwuwei閱讀 14,364評論 0 7
  • 選擇題部分 1.()部門負(fù)責(zé)日常監(jiān)督檢查工作,安全巡視的同時進(jìn)行消防檢查,推動消防安全制度的貫徹落實。 A: 消防...
    skystarwuwei閱讀 15,940評論 0 3
  • 前置文章:遞歸算法:www.itdecent.cn/p/703069f3ba3f . 漢諾塔問題是來源于印度傳...
    郎小凱閱讀 856評論 0 1
  • 題目: 漢諾塔的移動可以用遞歸函數(shù)非常簡單地實現(xiàn)。 請編寫move(n, a, b, c)函數(shù),它接收參數(shù)n,表示...
    快樂的殺馬特閱讀 492評論 0 0

友情鏈接更多精彩內(nèi)容