作者:楊于葳

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()