Swift Playground - コードを学ぼう2【型】解答例と解説 Part 2

Swift Playground「コードを学ぼう2」で2組のワープを操作する方法を学習しましょう。本記事ではプログラミング初心者にも分かりやすいように解説し、コードの正解例を掲載しています。

Swift Playground - コードを学ぼう2【型】解答例と解説 Part 2

2組のワープを操作しよう

プログラミング言語 Swift を楽しく体験できる Swift Playground で、コーディングの基礎を学びましょう。

「コードを学ぼう2」の第2章「型」のレッスンを2回に分けて解説しています。今回はその Part 2 です。

  • レッスン1〜2:前回の Part 1 で取り上げ、ワープのオンとオフを操作する方法を学びました。
  • レッスン3〜5:この記事で解説します。2組のワープのオンとオフをタイミングよく切り替えて、効率的にクリアするコードを書けるようになりましょう。

型のレッスン1〜2は実習済みですか?まだの方は Part 1 の記事からご覧ください。

Swift Playground - コードを学ぼう2【型】解答例と解説 Part 1
Swift Playground「コードを学ぼう2」で型について学習しましょう。本記事ではプログラミング初心者にも分かりやすいように解説し、コードの正解例を掲載しています。

レッスンのポイント

前回の Part 1 で学んだことの復習も兼ねて、レッスンを始める際に知っておきたいポイントを下にまとめました。

  • 型とは、そのデータが「どんな情報を持ち(プロパティ)、どんな振る舞いができるか(メソッド)」のルールを決めた「設計図」のようなものです。
  • 型をもとに作られたものを「インスタンス」といい、これが実行の主体となります。
    • 例:Portal 型から作られた greenPortal(緑のワープ)
  • ワープのインスタンスは、「ワープが有効か無効か」という状態を保存する isActive プロパティを持っています。
  • ワープのオンとオフを変えるためには、「ドット表記」で特定のインスタンスの isActive プロパティにアクセスし、 true または false を設定します。
    • 例:greenPortal.isActive = true(緑のワープを有効にする)
緑のワープを有効にする文
緑のワープを有効にする文

では、次のセクションからレッスン開始です!

※ この記事で紹介しているコードは、あくまで一つの例です(動作確認 Swift Playground 4.7)。プログラミングでは、同じ動きを作る方法がいくつもあります。いろいろなやり方を試しながら、自分なりの答えを見つけてみてください。

レッスン3「ワープを正しく操作する」

【目標】

  • 2組のワープを操作する
  • 適切なタイミングでプロパティの値を切り替える
Swift Playground/コードを学ぼう2/型/ワープを正しく操作する
Swift Playground/コードを学ぼう2/型/ワープを正しく操作する

課題解決の流れ

1. 繰り返すパターンを関数にまとめよう
ワープのオンとオフを切り替えて、すべての宝石を集められるようコーディングしていきます。

このステージでは、前進して宝石を取る動きや、来た道を引き返す動きが何度も出てきます。まずは、よく使う一連の動きをまとめた関数を2つ定義しておきましょう。

  • moveAndCollect():2マス進んで宝石を取る
  • turnAround():180度向きを変えて後ろを向く
// 2マス進んで宝石を取る関数を定義する
func moveAndCollect() {
	moveForward()
	moveForward()
	collectGem()
}

// 後ろを向く関数を定義する
func turnAround() {
	turnLeft()
	turnLeft()
}

2. 青のワープを通って宝石を集めよう
このステージには、青のワープ bluePortal とピンクのワープ pinkPortal があります。はじめは、どちらのワープも有効(true)です。

効率よくすべての宝石を集めるため、そのまま進んで青のワープに入ります。先ほど定義した関数を使って、出口付近の2つの宝石を集めましょう。1つ目の宝石を取った後、2つ目に向かう前に青のワープを無効にするのを忘れないでくださいね。

// 青ワープを通り、前方にある宝石を取って後ろを向く
moveAndCollect()
turnAround()

// 青ワープをオフにする
bluePortal.isActive = false

// 反対側の宝石を取って後ろを向く
moveAndCollect()
turnAround()
青のワープを通って出口の周りにある宝石を集める
青のワープを通って出口の周りにある宝石を集める

3. 青のワープで元の列に戻ろう
宝石を2つ集め終えたら、青のワープを再び有効にして、スタート地点があった最初の列に戻りましょう。戻ったあとは、ピンクのワープを無効にしてから、宝石を集めに行きます。

// 青ワープをオンにする
bluePortal.isActive = true
// ワープで元の列に戻る
moveForward()

// ピンクワープをオフにする
pinkPortal.isActive = false
// 宝石を取って後ろを向く
moveAndCollect()
turnAround()

4. ピンクのワープを通って最後の宝石を取りに行こう
残る宝石はあと1つです。無効にしたピンクのワープを有効に戻してワープし、最後の宝石を取りましょう。

// ピンクワープをオンにして、ワープする
pinkPortal.isActive = true
moveForward()

// 宝石のある方へ向きを変える
turnAround()
// 最後の宝石を取りに行く
moveForward()
collectGem()

5. 完成コードを実行しよう
「コードを実行」を押して動きを確かめます。ワープのオンとオフを上手に切り替えて宝石を全部集めたら、ステージクリアです!

// コード正解例

func moveAndCollect() {
	moveForward()
	moveForward()
	collectGem()
}

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

// 青ワープを通って1つ目の宝石を取り、オフにして2つ目を取る
moveAndCollect()
turnAround()
bluePortal.isActive = false
moveAndCollect()
turnAround()
// 青ワープをオンにして戻り、ピンクワープをオフにして3つ目を取る
bluePortal.isActive = true
moveForward()
pinkPortal.isActive = false
moveAndCollect()
turnAround()
// ピンクワープをオンにしてワープし、最後の宝石を取る
pinkPortal.isActive = true
moveForward()
turnAround()
moveForward()
collectGem()

レッスン4「隅々まで歩き回る」

【目標】

  • 2組のワープを操作する
  • 適切なタイミングでプロパティの値を切り替える
Swift Playground/コードを学ぼう2/型/隅々まで歩き回る
Swift Playground/コードを学ぼう2/型/隅々まで歩き回る

課題解決の流れ

1. 繰り返すパターンを関数にまとめよう
このステージでは、ワープの周りに宝石や切れているスイッチがあります。2組のワープの isActive プロパティを切り替えながら、宝石を集めてスイッチをオンにするコードを書いていきましょう。

最初に、よく出てくる動きのパターンを見つけて関数を作ります。

  • checkOneTile():ワープの周りにあるマスの1つをチェックしてから、向きを変える
// マス1つをチェックする関数を定義する 
func checkOneTile() {
	// ワープマスから1マス進む
	moveForward()
	// 宝石があれば取り、切れているスイッチがあればオンにする
	if isOnGem {
		collectGem()
	} else if isOnClosedSwitch {
		toggleSwitch()
	}
	// ワープマスに戻れるように後ろを向く
	turnLeft()
	turnLeft()
}

2. 緑のワープを通ってスイッチを切り替えよう
スタート位置から左を向いて進み、緑のワープに入りましょう。ワープから出たあとは、そのワープを無効にしておきます。理由は、周りのスイッチをすべてオンにする途中で、誤ってワープに入ってしまうのを防ぐためです。

// 緑ワープへ進んでワープする
turnLeft()
moveForward()
moveForward()

// ワープから出たら、ワープをオフにする
greenPortal.isActive = false

for 文で同じ動きを繰り返して、ワープの周りにあるスイッチをオンにしていきましょう。1つのスイッチを処理する一連の流れは以下のとおりです。

  1. checkOneTile():外側へ進んでスイッチを入れ、後ろを向く
  2. moveForward():中央(ワープのあるマス)へ戻る
  3. turnRight():次のスイッチの方へ向きを変える

ここで注意したいのが、「スイッチは4つあるけれど、ループは3回で止める」という点です。

ワープは、「有効の状態でそのマスに入った瞬間」に発動します。中央に戻ってからワープを有効にしても、すでにワープマスの上に乗っているためワープできません。

そのため、4つ目のスイッチを入れた後は中央へ戻らず、そのマスで一旦ストップします。4つ目のスイッチを入れる checkOneTile() はループの外に書いておきましょう。

// 最初の3つのスイッチをループで処理する
for i in 1 ... 3 {
	// マス1つをチェックしてスイッチを入れて後ろを向く
	checkOneTile()
	// ワープマスに戻って、別のスイッチの方を向く
	moveForward()
	turnRight()
}

// 4つ目のスイッチを入れて後ろを向き、中央に戻らずそのマスで止まる
checkOneTile()
4つ目のスイッチを切り替えた後はそのマスで止まる
4つ目のスイッチを切り替えた後はそのマスで止まる

3. 緑のワープを通って宝石を集めよう
スイッチを4つオンにできたら、緑のワープを有効にしてから進み、ワープします。ワープから出たあとは、再び緑のワープを無効にしておきましょう。

// 緑ワープをオンにしてから、ワープマスに進んでワープする
greenPortal.isActive = true
moveForward()

// ワープから出たら、ワープをオフにする
greenPortal.isActive = false

同じ動きを繰り返して、周りにある2つの宝石を集めます。集め終わったら、オレンジのワープの方へ2マス進みましょう。

// 周りにある宝石を2つ取る
for i in 1 ... 2 {
	checkOneTile()
	moveForward()
	turnLeft()
}

// オレンジワープの方へ進む
moveForward()
moveForward()

4. オレンジのワープの周りにある宝石を集めよう
オレンジのワープを無効にしてから進み、その周りにある宝石を集めます。今回も for ループで繰り返すのは3回です。4つ目の宝石を取るcheckOneTile() はループの外に書いてください。

// オレンジワープをオフにしてから、ワープマスに進む
orangePortal.isActive = false
moveForward()

// 周りにある宝石を3つ取る
for i in 1 ... 3 {
	checkOneTile()
	moveForward()
	turnRight()
}

// 残り1つの宝石を取り、そのマスで止まる
checkOneTile()

5. オレンジのワープを通ってスイッチを切り替えよう
宝石を4つ集めたら、オレンジのワープを有効にしてから進み、ワープします。ワープから出たあとは、再びオレンジのワープを無効にしておきましょう。

// オレンジワープをオンにしてから、ワープマスに進んでワープする
orangePortal.isActive = true
moveForward()

// ワープから出たら、ワープをオフにする
orangePortal.isActive = false

ワープから出たときに向いている方向にはスイッチがありません。スイッチのある方へ向きを変えてから、2つのスイッチをオンにしましょう。

// 周りにあるスイッチを2つ入れる
turnLeft()
checkOneTile()
moveForward()
turnRight()
checkOneTile()

6. 完成コードを実行しよう
「コードを実行」を押して動きを確かめます。2組のワープを上手に操作し、スイッチをオンにして宝石を集められたら、ステージクリアです!

// コード正解例

func checkOneTile() {
	moveForward()
	if isOnGem {
		collectGem()
	} else if isOnClosedSwitch {
		toggleSwitch()
	}
	turnLeft()
	turnLeft()
}

// 緑ワープに入る
turnLeft()
moveForward()
moveForward()
// 緑ワープをオフにして、スイッチを切り替える
greenPortal.isActive = false
for i in 1 ... 3 {
	checkOneTile()
	moveForward()
	turnRight()
}
checkOneTile()
// 緑ワープをオンにして戻る
greenPortal.isActive = true
moveForward()
// 緑ワープをオフにして、宝石を集める
greenPortal.isActive = false
for i in 1 ... 2 {
	checkOneTile()
	moveForward()
	turnLeft()
}
// オレンジワープの方へ進む
moveForward()
moveForward()
// オレンジワープをオフにして、宝石を集める
orangePortal.isActive = false
moveForward()
for i in 1 ... 3 {
	checkOneTile()
	moveForward()
	turnRight()
}
checkOneTile()
// オレンジワープをオンにしてワープ
orangePortal.isActive = true
moveForward()
// オレンジワープをオフにして、スイッチを切り替える
orangePortal.isActive = false
turnLeft()
checkOneTile()
moveForward()
turnRight()
checkOneTile()

レッスン5「宝石があちこちにランダムに」

【目標】

  • 2組のワープを操作する
  • ワープのオンとオフを調べる
Swift Playground/コードを学ぼう2/型/宝石があちこちにランダムに
Swift Playground/コードを学ぼう2/型/宝石があちこちにランダムに

課題解決の流れ

1. 入力済みのコードを確認しよう
型のレッスンはこれが最後です。このレッスンでは以下のコードがすでに入力されています。

// 入力済みのコード

let totalGems = randomNumberOfGems

これは、出現した宝石の数 randomNumberOfGems を、定数 totalGems に格納する文です。

定数については以下の記事で解説していますので参考にしてください。

Swift Playground - コードを学ぼう2【変数】解答例と解説 Part 3
Swift Playground「コードを学ぼう2」で変数と定数について学習しましょう。本記事ではプログラミング初心者にも分かりやすいように解説し、コードの正解例を掲載しています。

今回のステージでは、中央と両端の3本の道に宝石が現れます。ただし、コードを実行してみるまで、どのマスに宝石が現れるかは分かりません。出現した宝石を残らず集められるよう、3本の道を往復して宝石を集めるアルゴリズムを考えましょう。

2. 変数と関数を作ろう
まずは、宝石をいくつ集めたか記録するための変数を宣言してください。そして、よく出てくる動きのパターンを見つけて関数を2つ作っておきましょう。

  • gemCounter:集めた宝石の数を記録する変数
  • moveAndCollect():行き止まりになるまで宝石を集めながら進む関数
  • turnAround():道を行ったり来たりできるように向きを変える関数
// 宝石の数を記録する変数を宣言する
var gemCounter = 0

// 宝石を集めながら進む関数を定義する
func moveAndCollect() {
	// 行き止まりになるまで繰り返す
	while !isBlocked {
		// 1マス進み、宝石があれば取って変数の値を1増やす
		moveForward()
		if isOnGem {
			collectGem()
			gemCounter += 1
		}
	}
}

// 後ろを向く関数を定義する
func turnAround() {
	turnLeft()
	turnLeft()
}

3. 同じ数になるまで繰り返そう
出現した宝石を全部取るまで、 while ループで宝石を集め続けましょう。ループで繰り返す条件は、変数と定数を比較して「集めた宝石の数が、出現した宝石の数より小さい間」となります。

// 宝石カウンターが宝石の合計数より小さい間は繰り返す
while gemCounter < totalGems {

}

4. 宝石を集めながら進もう
行き止まりになるまで宝石を集めながら進みましょう。はじめはワープが有効なので、ピンクのワープに入り、ワープ先の宝石を集めます。行き止まりになったら、往復できるように向きを変えます。

while gemCounter < totalGems {

	// 行き止まりになるまで宝石を集めながら進む
	moveAndCollect()
	// 行き止まりになったら後ろを向く
	turnAround()
}

5. ピンクのワープのオンとオフを切り替えよう
道の端で行き止まりになって向きを変えたら、ピンクのワープの状態を確認します。もしワープが有効なら無効に切り替えて、道の反対側まで行けるようにしましょう。

ワープが有効かどうかを調べるには、if 文の条件式で比較演算子 == を使って次のように書きます。

while gemCounter < totalGems {
	moveAndCollect()
	turnAround()

	// ピンクワープがオンかどうかを判定する
	if pinkPortal.isActive == true {
		// 条件が成立する(オンである)場合はオフにする
		pinkPortal.isActive = false
	} 
}

等しいかどうかを調べる比較演算子 == と、値を設定する代入演算子 = は見た目が似ているので、書き間違えないように気をつけてくださいね。

  • pinkPortal.isActive == true:有効であるかを確認する
  • pinkPortal.isActive = false:無効の状態を設定する

ワープを無効にして反対側の端まで進んだら、再び180度向きを変えて、今度は中央の道へ移動できるようピンクのワープを有効に戻します。

if のあとに else(そうでなければ = 無効の場合)を追加して、ワープが無効であれば有効にしましょう。

while gemCounter < totalGems {
	moveAndCollect()
	turnAround()

	if pinkPortal.isActive == true {
		pinkPortal.isActive = false

	} else { // そうでなければ(ピンクワープがオフなら)、オンにする
		pinkPortal.isActive = true
	}
}
道の端まで進んで向きを変えたらワープのオンとオフを切り替える
道の端まで進んで向きを変えたらワープのオンとオフを切り替える

ここまでで、道の端に着くたびにピンクのワープのオンとオフが切り替わるようになりました。

6. 青のワープのオンとオフを切り替えよう
続いては、青のワープについて考えます。ステージ全体を見渡すと、ピンクのワープをオフにしたいタイミングでは青もオフ、オンにしたいタイミングでは青もオンにすれば、すべての宝石を集められることが分かります。

ピンクのワープと連動して切り替わるよう、青のワープを有効または無効にするコードを if / else の中に追加しましょう。

while gemCounter < totalGems {
	moveAndCollect()
	turnAround()

	if pinkPortal.isActive == true {
		pinkPortal.isActive = false

		// 青ワープをオフにする
		bluePortal.isActive = false

	} else {
		pinkPortal.isActive = true

		// 青ワープをオンにする
		bluePortal.isActive = true
	}
}

7. 完成コードを実行しよう
「コードを実行」を押して動きを確かめます。2組のワープの状態を切り替えて宝石を残らず集められたら、ステージクリアです!

// コード正解例

let totalGems = randomNumberOfGems
var gemCounter = 0

func moveAndCollect() {
	while !isBlocked {
		moveForward()
		if isOnGem {
			collectGem()
			gemCounter += 1
		}
	}
}

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

// 出現した宝石を全て集めるまで繰り返す
while gemCounter < totalGems {
	moveAndCollect()
	turnAround()
	// ピンクワープがオンなら
	if pinkPortal.isActive == true {
        //2組のワープをオフにする
		pinkPortal.isActive = false
		bluePortal.isActive = false
	} else { // ピンクワープがオフなら
        // 2組のワープをオンにする
		pinkPortal.isActive = true
		bluePortal.isActive = true
	}
}

まとめ

今回は、Swift Playground の「コードを学ぼう2」で、2組のワープを操作する課題に取り組みました。

この章では、型やインスタンス、プロパティ、ドット表記といった新しい用語が登場し、最初は難しく感じられたかもしれません。けれども、ワープのオンとオフを切り替えるコードそのものは単純でしたよね。改めて、以下の内容を振り返っておきましょう。

  • 型には、プロパティ(特徴・情報)やメソッド(振る舞い・動作)が含まれる
  • 型(設計図)をもとにインスタンス(実行の主体となるもの)が作られる
  • ドット表記でインスタンスを操作することができる

次回予告

次回は初期化について学びます。これまではステージにキャラクター(バイトやホッパー)が最初から存在していましたが、今後は型から新しいキャラクターのインスタンスを生成する課題が出てきます。自分でキャラクターを作れるのは、とてもワクワクしますね。

次の記事(準備中) →

最後まで読んでいただき、ありがとうございます。この記事をシェアしてくれると嬉しいです!

SNS で Pyxofy とつながりましょう! LinkedIn・ Threads・Bluesky・ Mastodon・ X (Twitter) @pyxofy・ Facebook

関連記事

Swift Programming
Swift Playgrounds アプリで学ぶ初心者向けのコーディングチュートリアルを解説しています。
Scratch - Pyxofy
Scratch 3.0の使い方を、プログラミング初心者や子どもにも分かりやすく紹介しています。
JavaScript - Pyxofy
プログラミング言語のJavaScriptについて、初心者向けに解説しています。
CSS Art
Articles for creating CSS Art.
CSS Animation
Articles for creating CSS Animation.