百億のマインクラフトと千億のタートル

つまり、マイクラワールド1つあたりタートルが10匹生息しているわけですね。

変数を使いこなしてプログラムを改善しよう

はじめに

CCプログラミングの環境の設定の話で記事を書き始めたらそちらへの脱線が長くなってしまいました。

今回から、本格的にCCプログラミングやっていきます。

まずは床にブロックを設置するプログラムを再掲しましょう。

床貼りプログラム(1往復)

----------------------------------
-- yuka1: 床にブロックを設置する(1往復)
----------------------------------

-- 地面に置いたタートルでは床にブロック置けないので、浮かせる
turtle.up()

-- 床にブロックを敷き詰めながら6歩分前に進む
for i=1,6 do
  turtle.placeDown()
  turtle.forward()
end

-- 右の列に移動
turtle.turnRight()
turtle.forward()

-- 右の列のスタート地点に移動。こちら側を向いている。
turtle.turnRight()
turtle.forward()

-- 右の列に床ブロックを敷き詰めながら戻ってくる
for i=1,6 do
  turtle.placeDown()
  turtle.forward()
end

外部エディタ(VSCode)使うとこのようなコード(ソースコードの略)が色分けされて見やすいですよね。 なお、せっかくなので1行目〜3行目のように、このプログラムの名前とその説明についても書いてみました。 「yuka1」だけでは何をするプログラムなのかわからなくなりますからこのようなコメントは重要です。

上記のコードをエディタ側にコピー&ペーストもできるので、書くのも楽になります。 でもできれば、上記コードを見ながらでかまわないので、タートルの行動を頭の中でシミュレーションしながら自分でコードを書いてみてくださいね。1

このプログラムの問題点

さて、このプログラムなかなか便利なのですが問題点もあります。 それは「6歩分のブロックを設置する」と決め打ちでコード中に書いていることです。

場合によっては、「10歩にしたい」「100歩くらい余裕」「13kmや」などと変更したいときもありますよね。 そういうときは、おもむろにこの「yuka1」プログラムを書き換える方法があります。

該当する部分は、9行目と23行目の二箇所です。繰り返しfor文のカウンタの終端値が「6」になっているのでこれを好きな値に書き換えれば良いわけです。

ただし気をつけなくてはならないのは、9行目と23行目の両方を同じ値にしないとタートルがおかしな挙動になってしまうことです。たとえば、100歩先に進んだにも関わらず、6歩しか戻ってこないのではおかしいですよね。

このプログラムを使っていると、「二箇所も書き換えるの面倒。しかも同じ数字にしないといけないし!」と思うかもしれません。

そこでコードの改善ですよ!

変数ってなんだっけ?

学校の数学の時間では、xやyのような変数を習ったことがあるかもしれません。 様々な値(数値など)を変数に代入できたり2、またあるいは特定の値の代わりに変数で置き換えることもできたり3と、変数は数学の世界ではとても強力な道具です。

プログラミングでも変数は利用できます。数学の時間と異なるのは、変数に自分で好きな名前をつけてよいことです。4 いえむしろ、x・y・zではなく、他人がみてわかりやすい変数名をつけることが積極的に推奨されています。

変数の使い方

以下はプログラム中に変数の使い方を説明するためのサンプルコードです。

local x = 3  -- ローカル変数xの値は3と定義します
print(x+5)  -- x+5の値を表示しなさい

1行目で 変数xの値は3であると「定義」しています。「local」ってなぁに?と思うかもしれませんが、これはローカル変数(今の段階では、ここだけで使う「一時的な変数」と説明しておきます。より詳しく知りたいならば、「変数のスコープ」「グローバル変数」あたりのキーワードで自分で調べてみましょう)を定義するための構文で、(ローカル)変数を使いたいときには、最初に必ずこう書いて定義しなくてはなりません。

ここで注意して欲しいのが、local x = 3の「=」は、数学の時間の「等号=」の意味で使っていないことです。これ、世界で最初にプログラム言語を発明した人の最大のミスだと個人的に思っています5

ここでの「=」は「is」くらいの意味だと思ってください。

つまり、「x = 3」は「x is 3(xは3とします)」くらいの意味。なぜこのような細かいことを説明するかと言うと、次のようなサンプルコードを見せると、数学が得意な人ほど混乱してしまうのですよ。

local x = 3  -- 変数xの値は3と定義します
print(x+5)  -- x+5の値を表示しなさい

x=1  -- 変数xの値を1にします(変更します)
print(x+5)  -- x+5の値を表示しなさい

数学得意マン「x=3なんでしょ? なんでx=1とか言い始めるのさ。おかしいでしょ!」

わかります。学校でプログラミング教育やっているそうだけど、算数・数学の授業との整合性(=は等号でしょ?)はどうやっているのか・・・。現場の苦労が偲ばれます。

算数・数学の時間では、「=」は等号であり「x=3」は「xは3と等しい」という意味だけど、プログラミングの世界では「=」は「is」くらいの意味であり「x=3」は「(ここでは)xは3とします」くらいの意味です。世界が変わると記号の意味も変わるのです。

このサンプルコードは、1行目から順に素直に解釈していきましょう。

  • 1行目は、localとついているので(ローカル)変数xを定義していますね。
  • 2行目でそのローカル変数xを使った計算結果を画面に表示します。
  • 4行目で変数xの値を1に変えます
  • 5行目でそのローカル変数xを使った計算結果を画面に表示します。

このプログラムの実行結果は次のように画面に表示されます。

8
6

変数を使ってプログラムを改善する

はい、長々とお話しました。

当初の目的は、歩数の値を二箇所も書き換えるのがめんどうなので、変数を使うことで少し楽ができるようにしようというお話でした。

以下に結論となるコードを紹介します。

----------------------------------
-- yuka2: 床にブロックを設置する(1往復)
----------------------------------
local hosuu = 6

-- 地面に置いたタートルでは床にブロック置けないので、浮かせる
turtle.up()

-- 床にブロックを敷き詰めながら6歩分前に進む
for i=1,hosuu do
  turtle.placeDown()
  turtle.forward()
end

-- 右の列に移動
turtle.turnRight()
turtle.forward()

-- 右の列のスタート地点に移動。こちら側を向いている。
turtle.turnRight()
turtle.forward()

-- 右の列に床ブロックを敷き詰めながら戻ってくる
for i=1,hosuu do
  turtle.placeDown()
  turtle.forward()
end

注目して欲しいのは、4行目のlocal hosuu = 6ですね。変数hosuuをコードの先頭で定義しておき、その変数hosuuを以降の繰り返しfor文の終端値として使っています。

そのため、6歩から10歩に変えたいのなら、local hosuu = 6local hosuu = 10のように書き換えるだけで完了となります。

コードの先頭の数字を変えるだけOKなので、ちょっと楽になりましたね。

このように、プログラムの挙動を変える値(たとえば今回の、移動する歩数など)のことをパラメーターと呼ぶ場合があります。このようなパラメーターは、使用する際に書き換えることが多いので、たいていはコードの先頭に書いておくことが多いです。

それを明示的にするため、私は次のような書き方をします。どうですか?コード自体は長くなったけど、みやすくなっていません?

----------------------------------
-- yuka2: 床にブロックを設置する(1往復)
----------------------------------

------- Config -------
local hosuu = 6

------- Main -------
-- 地面に置いたタートルでは床にブロック置けないので、浮かせる
turtle.up()

-- 床にブロックを敷き詰めながら6歩分前に進む
for i=1,hosuu do
  turtle.placeDown()
  turtle.forward()
end

-- 右の列に移動
turtle.turnRight()
turtle.forward()

-- 右の列のスタート地点に移動。こちら側を向いている。
turtle.turnRight()
turtle.forward()

-- 右の列に床ブロックを敷き詰めながら戻ってくる
for i=1,hosuu do
  turtle.placeDown()
  turtle.forward()
end

つまり、------- Config -------以降はパラメータを設定する部分です。挙動を変えるときは書き換えてくださいね。 ------- Main -------以降はプログラムのメイン部分ね。これ以降を書き換えるときは気をつけて。

今後もこの方針でサンプルコードを紹介していきますのでご承知ください。

f:id:hevohevo:20191002131603p:plain
床にブロック設置するプログラム

次回のお話

使うたびにコードを二箇所も書き換えることに辟易としていたhevohevoは、変数を使う方式に書き換えることで少し楽になるのだった。だが人間の欲望とは尽きないもの。

「毎回書き換えるの面倒になりますた(^p^)」

このようなめんどくさがりやがプログラミングチュートリアルを完結できるのか。次の更新日はいつにしよう。チュートリアルなのに文章多すぎかも。

次回「コマンドライン引数の使い方」 乞うご期待。


  1. すでにお気づきかもしれませんが、ComputerCraft内のeditコマンド(CC内エディタ)ではコピー&ペーストの機能が制限されています。これはCCの作者であるDan200氏による意図的なものです。おそらく、既存のコードを思考停止状態でコピー&ペーストするのでなくできるだけ考えながら自分でプログラミングして欲しいというDan200氏の思想(願い)でしょう。まぁ私たちは外部エディタを使うのでこの制限は意味がないのですけどね。しかし、Dan200氏の願いであろう「考えながら自分でプログラミング」については完全に同意します。このページを読んでる皆さんもがんばろう!

  2. 「xは3です。x+5はいくつになるでしょうか?」など

  3. 「(x+3)2+2(x+3)+1=0 の方程式で(x+3)をAとおくと、A2+2A+1=0となります。そうすると・・・(以下略)」

  4. 数学の途中計算で、変数名としてx/y/z/X/Y/Zだけでは物足りなくなって、□や△のような記号使ったことあります?僕はあります。出来心で「(x+3)を♂とする」と小テストでやらかしたけどしっかりとマルをもらえました。それをみた友人には笑われたけど。

  5. ちなみに、2つの値が等しいかどうかを調べるときは、Luaを含むたいていのプログラミング言語はx == 3という表記を使います(==を等号演算子と呼びます)。うん。小学校でこれ教えると絶対混乱すると思う。プログラミング言語によってはこのあたりの問題点に対応するためか、変数の定義にlocal x := 3のような表記が使える場合もあります。