作者:楊于葳
Playgrounds 是 Apple 設計給想學 Swift 語言的初學者而設計的互動式教學程式,《開始編寫程式碼》就是其中一個主題,可以在 Mac 或 iPad 上操作,而且是繁體中文介面,雖然某些部分解釋的並不完全,但只要跟進度循序漸進,或者是直接動手操作看看,就能以遊戲化、視覺化的方式,更容易理解 Swift 語言的基本概念。以下是我在《開始編寫程式碼》的解題記錄。
「開始編寫程式碼」裡只有九大學習目標,每個目標裡面都有各自的實作子題,每一題都是以玩家的角度,配不同單元學到的概念,操作遊戲角色達到指定目的才能過關,例如:「獲得寶石」或「打開開關」。
在正式開始操作之前,每個「簡介」都會有視覺化、生活化與非常淺顯易懂例子,讓我們理解該目標的概念與使用方式,雖然說是破關遊戲,但實際上並沒有所謂的正確解答,達成目的的方式有很多種,系統也期待玩家可以使用不同的方式達到目的。
一、指令
(一)簡介
(二)發出指令
moveForward() moveForward() moveForward() collectGem()
(三)切換開關
moveForward() moveForward() turnLeft() moveForward() collectGem() moveForward() turnLeft() moveForward() moveForward() toggleSwitch()
(四)尋找並修正程式錯誤
moveForward() moveForward() turnLeft() moveForward() collectGem() moveForward() toggleSwitch()
二、For 迴圈
(一)簡介
(二)使用迴圈
for i in 1 ...5 { moveForward() moveForward() collectGem() moveForward() }
(三)迴圈每一側
for i in 1 ... 4 { moveForward() collectGem() moveForward() moveForward() moveForward() turnRight() }
三、條件碼
(一)簡介
(二)檢查開關
moveForward() moveForward() if isOnClosedSwitch{ toggleSwitch() } moveForward() if isOnClosedSwitch{ toggleSwitch() } moveForward() if isOnClosedSwitch{ toggleSwitch() }
(三)使用 else if
moveForward() if isOnGem{ collectGem() } else if isOnClosedSwitch{ toggleSwitch() } moveForward() if isOnGem{ collectGem() } else if isOnClosedSwitch{ toggleSwitch() }
(四)符合條件時往上爬
for i in 1 ... 3 { if isOnGem { collectGem() } else { moveForward() } } turnLeft() for i in 1 ... 5 { if isOnGem { collectGem() } else { moveForward() } } turnLeft() for i in 1 ... 3 { if isOnGem { collectGem() } else { moveForward() } } turnLeft() for i in 1 ... 5 { if isOnGem { collectGem() } else { moveForward() } }
四、邏輯運算子
(一)簡介
(二)使用 NOT 運算子
第一次解出這題的時候,完全沒有使用到題目希望使用的 NOT,而是使用其他功能達到相同目的,系統也能夠偵測到是否有用教學的方式解題,如果使用其他方法,系統就會告訴你:「 恭喜你找到了一個有創意的解決方法!」
for i in 1 ... 4 { moveForward() if isOnGem { collectGem() }else { turnLeft() moveForward() moveForward() collectGem() turnLeft() turnLeft() moveForward() moveForward() turnLeft() }
上圖是第二種解法「如果不在寶石處,就這麼做」。
for i in 1 ... 4 { moveForward() if !isOnGem { turnLeft() moveForward() moveForward() collectGem() turnLeft() turnLeft() moveForward() moveForward() turnLeft() } else { collectGem() } }
五、變數
(一)簡介
變數是用來儲存資訊的。
var name = "Mia" var age = 19
如果要建立新變數,要使用 var,並在它後面加一個新的變數名稱和一個值。建立之後,該變數的資料類型,永遠不會改變。
指定值運算子(等號)會設定變數的值。
name 會儲存 String(引號中的文字)。
age 會儲存 Int (一個整數或整個數字)。
(二)持續追蹤
var gemCounter = 0 moveForward() moveForward() collectGem() gemCounter = +1
(三)遞增數值
var gemCounter = 0 moveForward() for i in 1 ... 7 { if isOnGem { collectGem() gemCounter = +1 moveForward() }else { moveForward() } } turnRight() for i in 1 ... 2 { if isOnGem { collectGem() gemCounter = +1 moveForward() }else { moveForward() } } turnRight() for i in 1 ... 7 { if isOnGem { collectGem() gemCounter = +1 moveForward() }else { moveForward() } }
六、類型
(一)簡介
類型就是房子的藍圖,呈現了房子的特徵和動作。在類型中,功能稱為「屬性」(實際上只是在類型內部被定義的變數),動作增為「方法」(實際上只是在類型內部被定義的函數)。
(二)關閉傳送門
greenPortal.isActive = true moveForward() moveForward() while greenPortal.isActive { greenPortal.isActive = false moveForward() } for i in 1 ... 3 { turnRight() moveForward() moveForward() moveForward() toggleSwitch() turnRight() turnRight() moveForward() moveForward() moveForward() }
(三)設定正確的傳送門
moveForward() for i in 1 ... 6 { moveForward() if isOnGem { collectGem() }else { while isBlocked { turnRight() turnRight() while bluePortal.isActive { bluePortal.isActive = false } } } } bluePortal.isActive = true moveForward() moveForward() for i in 1 ... 2 { moveForward() if isOnGem { collectGem() }else { while isBlocked { turnRight() turnRight() moveForward() } } } bluePortal.isActive = false moveForward() turnRight() turnRight() pinkPortal.isActive = false moveForward() moveForward() collectGem()
七、初始化
(一)簡介
傳送門稱為 Portal 類型,我們的角色稱為 Character 類型,現在可以控制一個新的類型「Expert」,他有一個新方法(動作)叫做「turnLockUp()」。
(二)初始化你的專家
let expert = Expert() for i in 1 ... 3 { expert.moveForward() } expert.turnLockUp() while expert.isBlocked { expert.turnRight() expert.turnRight() expert.moveForward() expert.moveForward() expert.moveForward() } expert.turnLeft() for i in 1 ... 3 { expert.moveForward() expert.moveForward() expert.moveForward() expert.moveForward() expert.collectGem() while expert.isBlocked { expert.turnRight() expert.turnRight() expert.moveForward() expert.moveForward() expert.moveForward() } expert.turnLeft() }
八、函數
(一)簡介
(二)收集、切換、重複
func doIt(){
collectGem()
moveForward()
toggleSwitch()
}
moveForward()
doIt()
moveForward()
turnLeft()
moveForward()
doIt()
moveForward()
moveForward()
turnLeft()
moveForward()
doIt()
moveForward()
turnLeft()
moveForward()
doIt()
九、參數
(一)簡介
參數=建立選項。函數可以包括多個參數。
(二)繼續前行
let expert = Expert() func move(distance: Int){ for i in 1 ... distance{ expert.moveForward() } } expert.move(distance:6) expert.turnRight() expert.move(distance:2) expert.turnRight() for i in 1 ... 2 { expert.move(distance:5) expert.turnLeft() } expert.turnLockUp() expert.turnLeft() for i in 1 ... 2 { expert.move(distance:3) expert.turnRight() } expert.move(distance:4) expert.collectGem()
(三)置於特定位置
let expert = Expert() world.place(expert, atColumn: 1, row: 1) expert.collectGem() world.place(expert, atColumn: 6, row: 1) expert.collectGem() world.place(expert, atColumn: 1, row: 6) expert.collectGem()