戌咬音かんぬき(inugaminé)'s avatar

戌咬音かんぬき(inugaminé)

関数

新しい挙動を作る

目標: コンポジションを使って、右に曲がりましょう。

回答コード例↓

func move(steps: Int){
    for i in 1 ... steps {
        moveForward()
    }
}

move(steps: 3)

// ここがコンポジションのポイント
turnLeft()
turnLeft()
turnLeft()

move(steps: 3)
collectGem()

◇何をやってるの?

  1. func キーワードを使って、好きに指定した数だけ前進する、move() という名前の関数を作っています。
  2. 左を向く turnLeft() を3回実行して、右を向かせています。

このコードも、turnLeft() を 3 回実行して右を向いている以外には特別なことはしていないので、コードの詳しい解説は割愛します。


新しい関数を作る

目標: 右に曲がるための関数を定義して、使ってみましょう。

回答コード例↓

func turnRight() {
    for i in 1...3 {
        turnLeft()
    }
}

moveForward()
turnLeft()
moveForward()
turnRight()
moveForward()
turnRight()
moveForward()
turnRight()
moveForward()
turnLeft()
moveForward()
toggleSwitch()

◇何をやってるの?

  1. func キーワードを使って、turnRight() という名前の関数を作っています。
  2. for 文を使用して、turnLeft() を 3 回実行し、その場で右を向くようにしています。
  3. moveForward()toggleSwitch() などの基本的なコマンドも使って、マップを攻略しています。

◇コードを詳しく見てみよう!

func turnRight() {
    for i in 1...3 {
        turnLeft()
    }
}

func キーワードを使って、turnRight() という名前の関数を定義し、for 文を 3 回繰り返すように指定しました。
その中に turnLeft() コマンドを書くことで、turnRight() を呼び出した際に、中で turnLeft() が 3 回実行されます。
これ以降は、今回作成した turnRight() や、そのほかの基本的なコマンドを使って、マップを攻略しています。


集めて、切り替えて、繰り返す

目標: 繰り返しのパターンをまとめた関数を定義しましょう。

回答コード例↓

func collectYtoggle {
    moveForward()
    collectGem()
    moveForward()
    toggleSwitch()
    moveForward()
}

collectYtoggle()
turnLeft()
collectYtoggle()
moveForward()
turnLeft()
collectYtoggle()
turnLeft()
collectYtoggle()

◇何をやってるの?

  1. func キーワードを使って、宝石を取ったりスイッチをトグったりする動作をまとめています。
  2. まとめた一連の動作が終わったら、moveForward()turnLeft() を実行し、残りの宝石やスイッチを処理します。

◇コードを詳しく見てみよう!

func collectYtoggle {
    moveForward()
    collectGem()
    moveForward()
    toggleSwitch()
    moveForward()
}

「前に進む、宝石を取る、前に進む、スイッチをトグる、前に進む」をひとつのパターンとして、collectYtoggle() という関数を定義しました。また、and と書くのがなんとなく面倒だったので、and の意味を持つスペイン語である y を使っています。コーディング上の意味はありません。

今回の解答例のコードの中で、moveForward()turnLeft() が単体で実行されていることに気がつきましたか?
一見すると、まとめた一連のコードを for 文を使って 4 回実行すれば良いように見えますが、実はマスの数が違っているため、解答例では moveForward()turnLeft() を個別に実行することにしました。


往復する

目標: 繰り返しのパターンを見つけて、関数を定義しましょう。

回答コード例↓

func getGems() {
    for i in 1...3 {
        collectGem()
        moveForward()
    }
}

getGems()
turnRight()
moveForward()
turnRight()
getGems()
turnLeft()
moveForward()
turnLeft()
getGems()

◇何をやってるの?

  1. func キーワードを使って getGems() という関数を作り、collectGem()moveForward() を for 文を使って繰り返し実行するようにしています。
  2. getGems() を実行し、宝石を集め終えると左右に方向転換しています。

このコードも、全体的には特別なことはしていないので、コードの詳しい解説は割愛します。


パターンをネストする

目標: 関数を他の関数から呼び出してみましょう

回答コード例↓

func turnAround() {
    turnLeft()
    turnLeft()
}

func solveStair() {
    turnAround()
    moveForward()
}

func getGems() {
    moveForward
    collectGem()
    solveStair()
}

for i in 1...4 {
    getGems()
    turnLeft()
}

◇何をやってるの?

  1. 後ろを向くための関数 turnAround() を定義しています。
  2. 後ろを向いた後に階段を降りるための関数 solveStair() を定義しています。
  3. 「階段を登る、collectGem() を実行する、solveStair() を実行する」という一連の動作を行う関数 getGems() を定義しています。
  4. for 文を使って、getGems()turnLeft() を 4 回実行しています。

◇コードを詳しく見てみよう!

func turnAround() {
    turnLeft()
    turnLeft()
}

後ろを向くための関数 turnAround() を定義しました。中身は turnLeft() を 2 回実行しています。既にある機能を組み合わせて新たな機能を実現することをコンポジションと言うのでしたね。ちなみに turnRight() を 2 回実行するでももちろん OK です。

func solveStair() {
    turnAround()
    moveForward()
}

solveStair() には、先ほど作成した turnAround()moveForward() を入れ、宝石を回収した後に「階段を降りる」という機能を持たせました。

func getGems() {
    moveForward
    collectGem()
    solveStair()
}

getGems() には、先ほど作成した solveStair()collectGem() などの基本的なコマンドを入れ、宝石を取る時の一連の動作を持たせました。

for i in 1...4 {
    getGems()
    turnLeft()
}

一連の動作を行う関数を for 文で回し、「階段の上にある宝石を撮っては階段を降り、左を向く」を行なっています。もちろん右を向くでも問題ありません。


並んだ階段

目標: ステージのクリア方法を複数の関数に分解しましょう。

回答コード例↓

func collectGemTurnAround() {
    moveForward()
    moveForward()
    collectGem()
    turnLeft()
    turnLeft()
    moveForward()
    moveForward()
}

func solveRow() {
    collectGemTurnAround()
    collectGemTurnAround()
    turnRight()
    moveForward()
    turnLeft()
}

for i in 1...3 {
    solveRow()
}

◇何をやってるの?

  1. 「2 歩進んで宝石を取り、後ろを向いて 2 歩進んで元の位置に戻る」という関数を作成しています。
  2. 上記の関数をネストし、一列終わったら隣の列に移るという solveRow() 関数を作成しています。
  3. solveRow() を for 文で 3 回実行しています。

このコードも、全体的には特別なことはしていないので、コードの詳しい解説は割愛します。


パターンを探す

目標: パターンを分解して、関数を作りましょう。

回答コード例↓

func moveThenToggle(){
    for i in 1...2{
        moveForward()
    }
    toggleSwitch()
}

func turnAround() {
    for i in 1...2 {
        turnLeft()
    }
}

func move(steps: Int) {
    for i in 1 ... steps {
        moveForward()
    }
}

func moreSteps() {
    for i in 1 ... 2 {
        move(steps: 2)
    }
}

for i in 1...2 {
    moveThenToggle()
    turnAround()
    move(steps: 2)
    turnLeft()
    for i in 1...2{
        moveThenToggle()
    }
    turnAround()
    moreSteps()
    turnLeft()
}

◇何をやってるの?

  1. 線対称の地形になっていることに気がついたでしょうか。
    今回は、「右斜め上」と「右斜め下」で分けて考えてみます。

  2. スイッチは 1 マス間隔で設置されています。つまり、「“2 歩進んで” スイッチをトグる」を繰り返せば良さそうです。
    moveThenToggle() を定義し、この中で

  • for 文で moveForward() を 2 回実行する
  • スイッチをトグる
    を実行しています。
  1. 行き止まりに到達したら turnAround() で方向転換をします。

  2. 既にトグったスイッチに用はないので、move()moreSteps() という関数を作成し、真ん中まで戻るようにしています。

  3. 短い道を往復、次に長い道を往復するというのを 1 セットとして for 文で回しています。

◇コードを詳しく見てみよう!

func moveThenToggle(){
    for i in 1...2{
        moveForward()
    }
    toggleSwitch()
}

↑今回の解答例の中心的な関数です。
「スイッチまで移動してトグる」という動作をまとめました。

func turnAround() {
    for i in 1...2 {
        turnLeft()
    }
}

↑もうおなじみ、振り返るという関数です。

func move(steps: Int) {
    for i in 1 ... steps {
        moveForward()
    }
}

↑指定した歩数分前進する関数です。“steps” というパラメータ名は自分で好きに決められるのでしたね。

func moreSteps() {
    for i in 1 ... 2 {
        move(steps: 2)
    }
}

↑引数に 2 を渡した move() 関数を for 文で 2 回実行する関数です。

for i in 1...2 {
    moveThenToggle()
    turnAround()
    move(steps: 2)
    turnLeft()
    for i in 1...2{
        moveThenToggle()
    }
    turnAround()
    moreSteps()
    turnLeft()
}

↑ for 文を使い 2 回実行されるループを作成します。
その中で、まず短い道を歩いてスイッチをトグりに行きます。
スイッチをトグったら、前方が行き止まりなので turnAround() で方向転換します。
move() の引数として 2 を渡し、来た道を戻ります。最初の位置に戻ってきたら、turnLeft() で長い道の方を向きます。
長い道には、同じ間隔でスイッチが設置してあります。つまり、moveThenToggle() を 2 回実行すれば良いわけです。for 文を使って 2 回実行しています。

💡豆知識:
for 文の i の部分はループ関数と言うのでしたね。今回、for 文の i が同じコード内に 2 つ登場します。通常の関数は同じ名前を使用することができませんが、for 文で使われるこのループ関数はローカル関数とも呼ばれ、その for 文でのみ参照されるという特徴があります。このため、同じ i という名前でも、衝突せずに使用することができるのです。