バリアフリーのスロープはとても助かります.僕らは大量のタブレットを電車で運んでイベントに行くので1段でも段差があるとアウトなんですよね.渋谷駅の山手線のホームがなかなかすごくて,地上に出るには一度上の階に上がってから反対側のホームに出て,そこからエレベータに乗るという.そんな遠回りでもあると助かります.
プログラミングでもバリアフリーの考え方ができるのではないでしょうか.1ステップは誰でも簡単に作れます.それを延々と間違わないように積み上げて作ればいつかはちゃんとしたものができるという.
テトリスをビスケットで作るのとJavascriptで作るのを比べて,そう思いました.
ブロックが落ちるメガネは
のようになります.これは逆L型のブロックが4つの向きでの落ち方です.それぞれ形があるところより1マス分下に空白があるかどうかを調べて,空白があれば下に落ちて,上に空白ができるようになっています.
次は,ブロックが左に移動するメガネです.
いずれもタッチが入っていて「ブロックの左側を触った時」という条件になってます.同時にブロックの左側に空白があるかどうかを調べています.空白があれば,ブロックは左に移動して,右側には空白ができます.右に移動するメガネも同じように作ります.
ブロックの凸凹とどの方向に移動するかで,空白があるかどうか調べるべき場所が変わります.また,お気付きのようにこのプログラムは逆Lのブロックのみで,テトリスの他の形のブロック(全部で7種類)についても同じようなメガネが必要です.
ではJavascriptでかかれたテトリスはどのようになっているでしょうか.以下,本物のコードが出てきますが,ウゲッと思われる方は日本語のところだけ読んでくださればOKです.
コードレシピ 200行で作るテトリスのレシピ を例にします.こちらは2012年にDionysis Zindrosさんが教育目的で公開したテトリスのコードを元にしたそうです.
ブロックの形はこのように0と1を並べた配列で定義します.
[ 1, 1, 1, 0,
0, 0, 1 ],
他の形のブロックも同じように0と1を並べて作ります.
ブロックがある方向に動けるかどうかを判定する関数は
function valid( offsetX, offsetY, newCurrent ) {
offsetX = offsetX || 0;
offsetY = offsetY || 0;
offsetX = currentX + offsetX;
offsetY = currentY + offsetY;
newCurrent = newCurrent || current;
for ( var y = 0; y < 4; ++y ) {
for ( var x = 0; x < 4; ++x ) {
if ( newCurrent[ y ][ x ] ) {
if ( typeof board[ y + offsetY ] == 'undefined'
|| typeof board[ y + offsetY ][ x + offsetX ] == 'undefined'
|| board[ y + offsetY ][ x + offsetX ]
|| x + offsetX < 0
|| y + offsetY >= ROWS
|| x + offsetX >= COLS ) {
if (offsetY == 1 && offsetX - currentX == 0 && offsetY - currentY == 1) {
console.log('game over');
lose = true; // もし操作ブロックが盤面の上にあったらゲームオーバーにする
}
return false;
}
}
}
}
return true;
}
offsetX, offsetY に動く方向を指定して呼び出します.左に動けるかどうかのチェックはoffsetX=-1; offsetY=0で,下に動けるかどうかどうかのチェックは offsetX=0; offsetY=1 で呼び出します.このプログラムは4x4の任意の形のブロックに対して動くように作られています.テトリスで使われている7種類のブロックに限定されません.あと,このプログラムはゲームオーバーの判定も兼ねているので相当複雑です.やっていることは,4×4のますで,形があるところ(形の定義で1になっているところ)のoffsetX, offsetYだけずれた場所が空白かどうかとして調べています.
ブロックの回転をみてみましょう.タッチするとブロックが回転するメガネは
のようになります.回転したときに新たにブロックが移動する場所が空白であるかどうかしらべて,空白であれば回転して,今まで形があった場所に空白ができます.移動と同じく,他の形のブロックに対しても同じようなメガネを作らなければなりません.
javascriptでブロックを回転させるプログラムは
function rotate( current ) {
var newCurrent = [];
for ( var y = 0; y < 4; ++y ) {
newCurrent[ y ] = [];
for ( var x = 0; x < 4; ++x ) {
newCurrent[ y ][ x ] = current[ 3 - x ][ y ];
}
}
return newCurrent;
}
です.これには,回転が可能かどうかをチェックするプログラムは入っていませんが,さきほどのと組み合わせればできます.この回転プログラムも同じように4×4の任意の形のブロックを90度回転させることができます.
ビスケットのプログラムはすべて具体例を並べるだけで作られています.メガネの数は相当必要ですが,コツコツと作ればできます.そんなに難しくは作られていません.難しいというか間違えそうなのところは,メガネを作り忘れるということでしょうか.作り忘れてもゲームをやっていると途中で止まるのですぐにわかるのですが.
それに対してJavascriptのプログラムはその真逆です.テトリスで使われるブロック以外で任意の形の4×4のブロックに対して動くように作られています.とても汎用的に作られています.汎用的なのでプログラムは抽象的で,何が書かれているか読むのも大変ですし,作るのも大変です.記号で書かれたものから抽象的な世界での動作を頭の中で思い浮かべて,それでやっと読んだり書いたりできるのですから.
プログラミングの本質は抽象化であると主張する人がいます.これまでのプログラミングはどれもこのJavascriptのプログラムのような作り方をしますから,それをもって抽象化が本質であるというのはとても正しい主張です.
ではビスケットのように具体例をダラダラと並べたものはプログラミングとは言えないのでしょうか.どちらも違う意味で作るのは大変ですが,できたゲームは最終的にはどちらも同じ動きをします.違いを無理やり探してみると,たとえばブロックの種類を増やそうとしたら,Javascriptではデータを数行追加すれば良いだけなのに対して,ビスケットではさらに10個くらいのメガネを追加しなければなりません.
もしブロックの形をあらかじめ決めるのではなく,動きながら決めるということになった場合(たとえばカメラを接続して,そこに写っている形から次に落ちてくるブロックの形をその瞬間に作るとか),Javascriptではメインのプログラムはなにも修正することなくそのまま動きますが,ビスケットではメガネを実行中に追加することはできないので,作られる可能性のある4×4のブロック全部,つまり2の16乗で,4方向あるので1/4で大体1万種類分のメガネをあらかじめ用意しなければならないとか.もちろんそんなことはしないというか,実行中にブロックを追加するということは,コンピュータが得意なことの一つですけれど,パズルとしてはそれほど面白そうではないので.ビスケットに変換してみるととても大変なことだということを説明したかっただけです.
逆に言うと,テトリスでブロックの種類を増やすとか,動的に増やすとかなんてやらないということであれば,ビスケットのプログラムでもよい訳です.普通はそんなことやらないですよね.
Javascriptで作ったプログラムは,普通はやらないことまでも動いてしまうくらい高い能力をもったものです.そんなすごいものをたった数行で作ろうとしているのですから,このプログラムは読むのも書くのも難しいのです.すごさが凝縮したプログラムだと思います.プログラミングを勉強中の人にとって,この凝縮したソースコードを読むのはとても勉強になるでしょう.
それに対して,ビスケットは抽象化をしないで,具体例をダラダラ追加してゆくプログラミングなわけです.それでもいいと言い切れるでしょうか.
まず,コンピュータの特徴であるところの「一度プログラムを書いたら何度でも高速に正確に動く」という点はどちらもクリアしています.それから「プログラムさえ書けばどんなものも作れる」という点は,無限ななにか(カメラで落とすブロックを形を決めるテトリス)はビスケットでは無理ですが,実行の範囲を有限にする(ブロックの形を決める)ことで具体例だけのプログラムは遜色なくなります.
一方で,抽象化した世界でのプログラミングはとても難しく,トレーニングが必須です.記号のなかに深い意味が凝縮して入っているので,それを表面的に読んだところでなかなか深い意味にまで到達できません.それを自分で作りだすというのはもっと大変です.
プログラミング教育といったときに,大人の専門家を育てるためには,このような高度に抽象化されたものを作りだす能力が目標になります.ところが,コンピュータの特徴(一度書いたら... どんなものでも作れる...)を生かすのがプログラミング教育の目的であるならば,高い能力を育成しないで,具体例をダラダラと並べて作る方法でも問題はないと思いませんか?むしろ,トレーニングをすっとばして,コンピュータの良い部分を先取りできる良さがあります.
こういう,誰でも登れるスロープ的なアプローチをバリアフリープログラミングと呼ぶことにしました.
筋トレをしてどんなに段差が広い階段でも1回で登れる能力を身につけるのか,どんなに時間がかかっても特殊能力の訓練はせずにダラダラとやってつくるのを目指すのか.どっちもありだろうということです.で,普段は階段を登っているような人でも,重い荷物を持った時にはスロープが助かるように,抽象的にプログラミングができるような人でも,具体例ダラダラプログラミングが助かる時もあるはずです.実際に僕がそうですからね.
これからの課題ですが,具体例ダラダラで作れるプログラムの限界はどこかですね.
すでにわかっているのは動的とか無限は無理です.
対称性のある問題に関しても,具体例ダラダラではその対称性を生かすことができず,全部展開したものをダラダラつくらなければなりませんが,抽象的な方は変数を一つ増やしてとてもきれいなプログラムで解決できます.逆に対称性がない問題では抽象的な方はそれを生かすことができず,具体例ダラダラに接近されるでしょうね.
バリアフリープログラミングは新しいプログラミングのジャンルとして,今後説明に使って行きたいと思います.