Day 6 - Beginner - Python Functions & Karel

Day 6 - Beginner - Python Functions & Karel

  1. Day 6 Goals: what we will make by the end of the day
  2. Defining and Calling Python Functions
  3. The Hurdles Loop Challenge
  4. Indentation in Python
    測驗 6: Code Indentation Quiz
  5. While Loops
  6. Hurdles Challenge using While Loops
  7. Jumping over Hurdles with Variable Heights
  8. Final Project: Escaping the Maze
  9. Why is this so Hard?! Can I really do this?

這一課,我在
63. Final Project: Escaping the Maze.
卡了很久,完全想不出如何解決 迷宮無限轉圈 的問題,最後沒辦法只能看答案了。
這種迷宮程式設計,應該很燒程式師的腦。
迷宮稍稍變一下,程式可能就出問題了。

3個讚

沒錯,這個走迷宮最基本的解法就是假設你一路左/右手摸著牆壁前進最終總會到達終點。
但是遇到往出口的路徑是中空的話,那永遠都不會到達,這也是做基本解法前必須先直走到底的考量。
進階的寫法就是將行進過的路線做紀錄,遇到死路時就退回上一個還有沒走過路線的交叉口。

2個讚

這一個project,我有兩個問題想跟大家討論,歡迎大家幫忙解惑:

  1. 我寫出跟老師不同的,但有成功通過三個情境挑戰,不過我也解釋不出來為什麼我的邏輯可以通,或者我的寫法會不會還有別的會困住的情境,如下(發現直接貼code,indentation會跑掉,貼一張screenshot,歡迎看我的code):

  1. 實務上,是怎麼找出有問題的情境呢?因為我想找找我的寫法會不會還有bug,會不會又在哪些情境下被困住?

這樣就死了!
image

1個讚

R大,我很好奇你是怎麼找出來的?

應該是使用了edit world的功能吧

1個讚

是用 edit world,就只打掉一塊牆而已!

1個讚

試著做了一個中空版本的 拿去跑maze也可以 程式碼有點醜 :sweat_smile:
這個技巧比較需要對function有掌握

擷取

不過方便起見有先把地圖大小跟起始位置當作常數先定義出來

再附上一個超過1000行的版本

擷取

set_max_nb_steps(2000)
travel = [[0, 0, 0, 0, 0, 1],[0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 1],[0, 0, 1, 0, 0, 1],[0, 0, 0, 0, 0, 1],[1, 1, 1, 1, 1, 1]]
current_x, current_y = 3, 2

# 函數
def turn_right():
    turn_left()
    turn_left()
    turn_left()
    
def turn_back():
    turn_left()
    turn_left()

def face_north():
    while not is_facing_north():
        turn_left()

def index_bound_check(x, y):
    if x < 0 or x > 2 or y < 0 or y > 3:
        return False
        
def up_available(current_x, current_y):
    index_bound_check(current_x - 1, current_y)
    return True if travel[current_x - 1][current_y] == 0 else False

def left_available(current_x, current_y):
    index_bound_check(current_x, current_y - 1)
    return True if travel[current_x][current_y - 1] == 0 else False
    
def down_available(current_x, current_y):
    index_bound_check(current_x + 1, current_y)
    return True if travel[current_x + 1][current_y] == 0 else False

def right_available(current_x, current_y):
    index_bound_check(current_x, current_y + 1)
    return True if travel[current_x][current_y + 1] == 0 else False
        
def go(current_x, current_y):
    if at_goal():
        done()
    travel[current_x][current_y] = 1
    face_north()
    if up_available(current_x, current_y) and front_is_clear():
        move()
        current_x -= 1
        go(current_x, current_y)
        face_north()
        turn_back()
        move()
        current_x += 1
    face_north()
    turn_left()
    if left_available(current_x, current_y) and front_is_clear():
        move()
        current_y -= 1
        go(current_x, current_y)
        face_north()
        turn_right()
        move()
        current_y += 1
    face_north()
    turn_back()
    if down_available(current_x, current_y) and front_is_clear():
        move()
        current_x += 1
        go(current_x, current_y)
        face_north()
        move()
        current_x -= 1
    face_north()
    turn_right()
    if right_available(current_x, current_y) and front_is_clear():
        move()
        current_y += 1
        go(current_x, current_y)
        face_north()
        turn_left()
        move()
        current_y -= 1
        
# 開始操作機器人
go(current_x, current_y)
3個讚

如果你在這些情況下,會一直打轉喔。(上下左右表示面對的方向、牆壁為示意,不完全代表牆壁)

牆牆牆牆 牆牆牆牆 牆牆牆牆 牆牆牆牆
牆上空牆 牆空右牆 牆空空牆 牆空空牆
牆空空牆 牆空空牆 牆空下牆 牆左空牆
牆牆牆牆 牆牆牆牆 牆牆牆牆 牆牆牆牆

你也是使用用右手摸牆壁前進的方法,但問題是如果你一開始就沒有用右手摸著牆壁的話,就等於會一直在原地打轉;然後你的第一個if裡面又塞了一個if,其實這是可以抽出來的,因為你做這兩個向右轉加前進也是為了讓右手能夠持續貼著牆壁,while也是依樣可以抽出來,你如果有看到老師的解法也是一開始就先直走到底,因為直走到底,然後向左轉,不就是用右手摸著牆壁了嗎?

這個機器人的起始點會隨機面向,加上地圖大小會有100種變化,所以會比較難Debug,其實目標就是能找到一個簡化的萬用規則讓程式能夠重複執行這樣。

貼code要使用連續三個重音符開頭再用連續三個重音符結尾,建議要換行,不然指標會跑走不好處理。

2個讚

謝謝D大的解說,我懂了

覺得這個code好像沒搞懂,尤其def index_bound_check(x,y):這裡就卡住了,但我先筆記,等Beginner課程結束後,我再來看一遍。

然後上面提到的edit world是什麼?我去google,看到一個WorldEdit小木斧指令的東西,跟你們說的是同一件事嗎?

這個遊戲可以自己修改、創建。

1個讚

原來,哈哈哈,剛剛還覺得很困惑,謝謝R大。

方便分享迷宮檔案嗎~

也想來測試各種案例 謝謝

1個讚