Scratch2MCPI プログラミング③チェック模様の床を作る

③チェック模様の床を作る


Image


チェック模様の床はかっこいいです。でも自分で建築してみるとわかると思いますが、白と黒を交互に設置していくのは面倒です。大きな床を敷き詰めるとなると、かなり時間もかかります。こういった作業はコンピューターに任せてしまいましょう。

コンピューターが得意なのは同じ作業の繰り返しです。白、黒、白、黒… と繰り返し、ブロックを設置していくスクリプトを考えていきます。


サイズ10 x 10 の真っ白な床を作る


Image


前回作った壁と同じように、床を作っていきます。壁は上(Y)方向に伸ばしていきましたが、床はZ方向に伸ばしていきます。blockTypeId = 35、blockData = 0(白い羊毛)に変えました。


[mcpiX v] を [0] にする
[mcpiY v] を [0] にする
[mcpiZ v] を [10] にする
[blockTypeId v] を [35] にする
[blockData v] を [0] にする
(10) 回繰り返す 
  (10) 回繰り返す 
    [setBlock v] を送る
    (0.1) 秒待つ
    [mcpiX v] を (1) ずつ変える
  end
  [mcpiX v] を [0] にする
  [mcpiZ v] を (1) ずつ変える
end

ここまでは前回のおさらいです。


サイズ10 x 10 の縞模様(白黒)の床を作る


今までは同じブロックを積み上げていったので簡単でしたが、途中でブロックの種類を変えるにはどうすればよいでしょうか?

コンピューターに「こういうときは白のブロックを置け。そうじゃないときは黒のブロックを置け。」と命令をしなくてはならないのです。これが「条件分岐」と言われるものです。


Image


つまり条件分岐とは、プログラムの途中で処理が2つに分かれて、「条件式に合致した(YES)ときは処理1を実行せよ。合致しない(NO)ときは処理2を実行せよ」と命令するということです。


Image


カウンター変数を設定する


条件分岐の使い方について、具体的に考えていきましょう。縞模様の床を作るのですから、X方向に動くたびに、白を置く、黒を置く、白を置く、黒を置く… と処理を変えなくてはなりません。その目印として、カウンター変数を設定します。カウンター変数とは、処理の回数を数えておいて、それを目印として処理の仕方を変えるときに使う変数のことです。


Image


カテゴリ「変数」→「新しい変数を作る」→変数名「i(英文字のアイ)」を作成します。同じように「j(ジェイ)」「k(ケイ)」を作ります。(カウンター変数には慣習的に、i, j, k が使われます。別のプログラミング言語に移るときに迷わないように、カウンター変数として、「i」「j」「k」の英文字を使いました。)


Image


カウンター変数を使えるようにスクリプトを変更します。


[mcpiX v] を [0] にする
[mcpiY v] を [0] にする
[mcpiZ v] を [10] にする
[blockTypeId v] を [35] にする
[blockData v] を [0] にする
[i v] を [0] にする
(10) 回繰り返す 
  (10) 回繰り返す
    [setBlock v] を送る
    (0.1) 秒待つ
    [mcpiX v] を (1) ずつ変える
    [i v] を (1) ずつ変える
  end
  [mcpiX v] を [0] にする
  [mcpiZ v] を (1) ずつ変える
end

変数として、[i v]を[0]にするを追加します。数を数えるときは、1, 2, 3, 4, 5 …と数えるのが普通ですが、プログラミングの世界では、0 から数えていくのです。違和感があるかもしれませんが、今は素直に「0 から数えるんだ」と覚えておいていただければ十分です。

X方向に10回繰り返す部分には、[i v]を(1)ずつ変えるを追加しました。これで処理のたびに、i の値が、0, 1, 2, 3, 4 … と増えていくスクリプトができました。


縞模様のための条件分岐


i の値によって「白を置く処理」と「黒を置く処理」を分岐させる部分を作っていきます。

i の値が、0, 1, 2, 3, 4 … と増えていくのですが、これを偶数と奇数に分けるにはどうすればよいでしょう? 


  もし <((i)を(2)で割った余り) = [0]> なら
    [blockData v]を[0]にする
  でなければ
    [blockData v]を[15]にする
  end

偶数とは2で割り切れる数、奇数は2で割り切れない数です。つまり2で割った余りを見ればよいのです。


Image


条件分岐は次のようになります。

(i)を(2)で割った余りが 0(偶数)のときは、 [blockData v]を[0]にする(白の羊毛)

(i)を(2)で割った余りが 1(奇数)のときは、 [blockData v]を[15]にする(黒の羊毛)


[mcpiX v] を [0] にする
[mcpiY v] を [0] にする
[mcpiZ v] を [10] にする
[blockTypeId v] を [35] にする
[blockData v] を [0] にする
[i v] を [0] にする
(10) 回繰り返す 
  (10) 回繰り返す 
    もし <((i) を (2) で割った余り) = [0]> なら 
      [blockData v] を [0] にする
    でなければ
      [blockData v] を [15] にする
    end
    [setBlock v] を送る
    (0.1) 秒待つ
    [mcpiX v] を (1) ずつ変える
    [i v] を (1) ずつ変える
  end
  [mcpiX v] を [0] にする
  [mcpiZ v] を (1) ずつ変える
end

これを上のスクリーンショットのように条件分岐にして、[setBlock v]を送るの処理の前に置けば完成です。スクリプトを実行して、縞模様ができることを確認してください。


サイズ10 x 10 のチェック模様(白黒)の床を作る


Image


チェック模様を作るには、Z方向にもカウンター変数を設置しましょう。そして条件式を少し変更するだけでチェック模様が現れます。


2つ目のカウンター変数の設置


Image


先ほどと同じように、変数として、[j v]を[0]にするを追加します。繰り返し処理の最後に、[j v]を(1)ずつ変えるを追加しました。


[mcpiX v] を [0] にする
[mcpiY v] を [0] にする
[mcpiZ v] を [10] にする
[blockTypeId v] を [35] にする
[blockData v] を [0] にする
[i v] を [0] にする
[j v] を [0] にする
(10) 回繰り返す 
  (10) 回繰り返す 
    もし <(((i)+(j)) を (2) で割った余り) = [0]> なら 
      [blockData v] を [0] にする
    でなければ  
      [blockData v] を [15] にする
    end
    [setBlock v] を送る
    (0.1) 秒待つ
    [mcpiX v] を (1) ずつ変える
    [i v] を (1) ずつ変える
  end
  [mcpiX v] を [0] にする
  [mcpiZ v] を (1) ずつ変える
  [j v] を (1) ずつ変える
end

これで処理のたびに、j の値が、0, 1, 2, 3, 4 … と増えていくスクリプトができました。


条件式の修正


Image


条件式の部分も修正が必要です。結論から言うと、「i」を「i + j」にするだけです。上の図を見てください。「i + j」の値が書かれていますが、偶数に「白を置く」、奇数に「黒を置く」と、目的通りにチェック模様ができるのです。

したがって条件式は以下のようになります。


 
もし <(((i)+(j)) を (2) で割った余り) = [0]> なら 
  [blockData v] を [0] にする
でなければ  
  [blockData v] を [15] にする
end

スクリプトを実行してみると、チェック模様の床が作成されました。成功です。


バグフィックス(bug fix)


「これでOK !」と言いたいところですが、あと一つだけ作業が残っています。「X方向の繰り返しが10回の時はうまくいったが、別の回数の時はどうなるか?」の検証です。これがバグフィックスと言われている修正作業で、ある条件でうまくいっても、別の条件ならうまくいかないことが多いので、色々条件を変えてやってみる。バグ(プログラム上の誤り)があれば修正(fix)する、を繰り返すわけです。

このスクリプトの場合は、繰り返し回数が偶数ならうまくいくが、奇数ならうまくいかない(縞模様になってしまう)ことがわかりました。


Image


バグフィックスは簡単でした。繰り返し処理の最後に、[i v]を[0]にするを追加することです。


[mcpiX v] を [0] にする
[mcpiY v] を [0] にする
[mcpiZ v] を [10] にする
[blockTypeId v] を [35] にする
[blockData v] を [0] にする
[i v] を [0] にする
[j v] を [0] にする
(10) 回繰り返す 
  (10) 回繰り返す 
    もし <(((i)+(j)) を (2) で割った余り) = [0]> なら 
      [blockData v] を [0] にする
    でなければ  
      [blockData v] を [15] にする
    end
    [setBlock v] を送る
    (0.1) 秒待つ
    [mcpiX v] を (1) ずつ変える
    [i v] を (1) ずつ変える
  end
  [mcpiX v] を [0] にする
  [mcpiZ v] を (1) ずつ変える
  [i v] を [0] にする
  [j v] を (1) ずつ変える
end

X方向の繰り返しの前に、必ずカウンター変数「i」の値を 0(偶数)にリセットしてやることで、目的の動作を得ることができました。X方向の繰り返しを「11」回(奇数)にして検証し、成功しました。

これで完璧です(のはずです)。


Image


最後に、「ファイル」→「名前を付けて保存」から、「mcpi_check_floor」として保存しておきましょう。


縞模様からチェック模様に改造するのは、思ったより簡単でした。難しそうな課題(チェック模様)が与えられたときは、より簡単な課題(縞模様)から考えていくと、うまくいくことが多いのです。プログラミングで迷ったときは、そのことを思い出してください。


今まで習った「繰り返し処理」「条件分岐」を使えば、家作りの多くのプロセスを自動化することができます。

次回は、「窓付きの壁」をプログラミングしてみましょう。今までの知識でそれほど難しくなくできるはずです。


このプロジェクト(mcpi_check_floor.sb)はダウンロードして、自分で確かめることがきます。

サンプルプログラムのページへ

(サンプルプログラムのページに移動します。ダウンロードしたいファイルのリンクをマウスで右クリックして、「対象をファイルに保存」などのメニューを実行してください。)


【追加ミッション】2 x 2 のチェック模様を作ってみる


Image


さらにスクリプトを改造していきます。改造するのは楽しいだけでなく、プログラミングの力をアップしてくれます。


幅が 2 の縞模様を作る


Image


先ほどと同じで、まずは簡単な縞模様から考えます。条件によって「白を置く処理」「黒を置く処理」を分けるところは変わりませんから、「条件式」を変更するだけで済みそうです。

カウンター変数 「i」の値は、0, 1, 2, 3, 4, 5, 6, 7, 8 と増えていきます。「0, 1」は白、「2, 3」は黒、「4, 5」は白、「6, 7」は黒を置けばよい。つまり4回ごとに「白黒」が繰り返していることになります。

カウンター変数「i」を 4で割った余りは、0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 … のように繰り返します。だから「0, 1」のときは「白を置く処理」、「2, 3」のときは「黒を置く処理」をさせれば、縞模様が書けるはずです。条件式を変更してみましょう。


Image


条件式を書き換えてみましょう。


もし <((i) を (4) で割った余り) < [2]> なら 
  [blockData v] を [0] にする
でなければ  
  [blockData v] を [15] にする
end

作成したスクリプトをクリックしてみると、幅が 2の模様の床が作成されました。成功です。


2 x 2 のチェック模様を作る


条件式の部分のみ見直します。今度は Z方向のカウンター変数「j」についても修正しなければなりません。カウンター変数「i」と同じように、カウンター変数「j」も 4で割った余りを考えれば良さそうです。4で割った余りが「0, 1」のときは「白を置く処理」、「2, 3」のときは「黒を置く処理」をさせれば、Z方向にも縞模様が書けるはずです。


Image


条件式を書き換えました。新しいブロック< >かつ< >は、カウンター変数「i」も「j」も共に、4で割った余りが「0, 1」だったときは「白を置く」という意味です。


[mcpiX v] を [0] にする
[mcpiY v] を [0] にする
[mcpiZ v] を [10] にする
[blockTypeId v] を [35] にする
[blockData v] を [0] にする
[i v] を [0] にする
[j v] を [0] にする
(10) 回繰り返す 
  (10) 回繰り返す 
    もし <<((i) を (4) で割った余り) < [2]> かつ <((j) を (4) で割った余り) < [2]>> なら 
      [blockData v] を [0] にする
    でなければ  
      [blockData v] を [15] にする
    end
    [setBlock v] を送る
    (0.1) 秒待つ
    [mcpiX v] を (1) ずつ変える
    [i v] を (1) ずつ変える
  end
  [mcpiX v] を [0] にする
  [mcpiZ v] を (1) ずつ変える
  [i v] を [0] にする
  [j v] を (1) ずつ変える
end

スクリプトを実行すると、チェック模様ができました。しかし黒の部分が多すぎて、目的の模様になっていないのです。黒の部分にさらに改造が必要です。もう一歩です。(これはこれで綺麗な模様です。)


コラム 集合について


Image


集合で「A かつ B」は図の黄色の部分を表します。「共通部分(または積集合)」と呼ばれ、記号は「A∩B」となります。この例では、「ネコも犬も両方好きな人」が属するグループのことです。


Image


集合で「A または B」は図の黄色の部分を表します。「和集合」と呼ばれ、記号は「A∪B」となります。この例では、「ネコも犬も両方好きな人」と「ネコだけ好きな人」と「犬だけ好きな人」が属するグループのことです。


2 x 2 チェック模様の床の完成


Image


黒を置く処理の部分に、条件式を追加しました。意味は、カウンター変数「i」も「j」も共に、4で割った余りが「2, 3」だったときは「白を置く」という意味です。

スクリプトを実行すると、「2 x 2 のチェック模様」が現れました。成功です。


[mcpiX v] を [0] にする
[mcpiY v] を [0] にする
[mcpiZ v] を [10] にする
[blockTypeId v] を [35] にする
[blockData v] を [0] にする
[i v] を [0] にする
[j v] を [0] にする
(10) 回繰り返す 
  (10) 回繰り返す 
    もし <<((i) を (4) で割った余り) < [2]> かつ <((j) を (4) で割った余り) < [2]>> なら 
      [blockData v] を [0] にする
    でなければ 
      もし <<((i) を (4) で割った余り) > [1]> かつ <((j) を (4) で割った余り) > [1]>> なら 
        [blockData v] を [0] にする
      でなければ 
        [blockData v] を [15] にする
      end
    end
    [setBlock v] を送る
    (0.1) 秒待つ
    [mcpiX v] を (1) ずつ変える
    [i v] を (1) ずつ変える
  end
  [mcpiX v] を [0] にする
  [mcpiZ v] を (1) ずつ変える
  [i v] を [0] にする
  [j v] を (1) ずつ変える
end

【宿題】3 x 3 のチェック模様を作成せよ

条件式を見直すことにより、3 x 3 チェック模様を作成せよ。


Image


自分で考えて、手を動かして、とにかくやってみる。

うまくいかなかったら、なぜうまくいかないか考える。

うまくいったら、なぜうまくいったか考える。それがプログラミング上達の秘訣です。

【付録】blockTypeId, blockData について

マインクラフトのプログラミングでは、ブロックの種類を2つの変数(blockTypeId, blockData)で表します。家作りでよく使うブロックについて、リストを上げておきます。建築の参考にしてください。「blockTypeId」「blockData」の値を調べることができます。(別のブロックを使いたいときは、「ブロックid」をネットで検索してみてください。)


blockTypeIdblockDataimagename名前
00imageair空気
10imagestone
20imagegrass
30imagedirt
40imagecobblestone丸石
50imageplank木材
200imageglassガラス
350imagewhite_wool白の羊毛
351imageorange_woolオレンジの羊毛
352imagemagenta_woolマゼンタの羊毛
353imagelight_blue_woolライトブルーの羊毛
354imageyellow_wool黄色の羊毛
355imagelime_woolライムの羊毛
356imagepink_woolピンクの羊毛
357imagegray_woolグレイの羊毛
358imagelight_gray_woolライトグレイの羊毛
359imagecyan_woolシアンの羊毛
3510imagepurple_wool紫の羊毛
3511imageblue_wool青の羊毛
3512imagebrown_wool茶色の羊毛
3513imagegreen_wool緑の羊毛
3514imagered_wool赤の羊毛
3515imageblack_wool黒の羊毛
450imagebrickレンガ
640imageoak_doorオークのドア
850imagefenceフェンス
1070imagefence_gateフェンスゲート
3550imagebedベッド