プチコンmkII

プチコンmkII 初心者講座

サンプルプログラム3(前)

プログラマーからひとこと

配列変数のことはもう大丈夫ですか?
もはやこの章ではあたりまえのように配列がFOR文といっしょに使われています。
一歩ひきかえすのもいいかもしれません。何度も読んだり、自分で打ってみて、ついでにちょっと書き換えたりしてみて、自分のものになることもあるものです。

心配のしすぎだったでしょうか。

前回はかなりプログラムっぽいことをやったので、今回はちょっと方向をかえてリアルタイムのキー入力や、十字ボタンの操作なんてやってみます。
「リアルタイム」というのは、まあいろいろ意味はあるんですが、いまは「押したらすぐ動く」みたいなものと思っていいんじゃないでしょうか。
けっこうゲームっぽいですね。

そういう意味ではけっこう大事なことをまなぶサンプルかもしれません。
けっこう長くなっているので、今回と次回の2つにわけて見ていきましょう。

あと、BEEP命令で音を出すヒントもちょっとついてますよ。

SYSBEEP変数

ハカセ「サンプルプログラム3は、まあちょっとした楽器プログラムじゃな。」
LOAD”SAMPLE3”
RUN
画面
インテリ「これを読んでいるPCなどの前のみんなも、サンプルをRUNしてためしてみよう! 前も言ったけど。
今回はプログラムリストをDSiで見ながら読むとわかりやすいよ!
」
神崎「ピアノ風のキーボードが1オクターブと、ドラムが4音使えるんだね。」
ハカセ「実はもっとエキスパート向きのMMLという音楽機能もプチコンmkIIにはあるのじゃが……まあ、最初のウチはあっさり目におぼえるのがよかろう。」
ワンパク「ツーバスやハイハットを考えてねェあたり好感がもてるぜ。だがピアノなんざ資産階級のオモチャじゃねえか! いただけねえな!」
ハカセ「ワンパク君はいささか音楽的にかたよったエイキョウばかり受けている気がするんじゃが、まあピアノがイヤならプログラムを改造するというコトもできるぞい。」
インテリ「プログラムをサイショから見ていこうか。まず気になるのはどこかな?」
神崎「1~21行まではだいたいおなじみの画面表示だね。7行目が引っかかるなあ。
0007#. SYSBEEP=FALSE
「=」を使ってるってことは、変数?
」
インテリ「いいところに気がついたね。このSYSBEEPは「システム変数」という、変数の一種なんだ。システム変数はプチコンの動作にかかわるデータが入るようになっているよ。」
ワンパク「ウンザリだぜ! 配列変数をやっとオボえたってのに、また変数のバリエーションかよ!」
インテリ「今はこんがらがりそうだから変数のことは考えずに、命令として丸暗記しておいた方が早いかもしれないね。
「SYSBEEP=FALSE」と書くと、プチコンのシステム音が鳴らなくなるんだよ。
」
神崎「オボエるのがそれだけなら、まあカンタンかな。このプログラムでキーボードを打っても、いつもの「ポツッ」ていう音が出なかったのはSYSBEEPを使ったからなんだね。」
ワンパク「そういやBEEPはサウンドを鳴らす命令だったな。SYSBEEPの「SYS(シス)」ってのはシステムの「シス」ってコトか?」
神崎「「FALSE(フォールス)」は「まちがった」って意味だと思ったけど……」
ハカセ「プログラムの世界ではちょっと意味が変わって「偽(ぎ)」などと言うのじゃが、どう見てもイッパンテキではないのう。おおざっぱなオボエかたじゃが、アリ・ナシの「ナシ」がFALSE、とオボエると今後なにかとワカりやすいぞい。」
ワンパク「システムのBEEPが「ナシ」、つまりシステム音を鳴らさない、ってコトか……ワカりやすいが、じゃあ鳴らすようにモドすにはどうすりゃイイんだ?」
ハカセ「イッキにプログラムのサイゴになるが、89行で使っておるな。
0089#. SYSBEEP=TRUE
「TRUE(トゥルー)」は「真(しん)」と言うが、これも「アリ」とオボエておけばよかろう。
」
ワンパク「ワカモノコトバをムリに使ってるカンジもするが、ワカりやすいことはタシカだな!」
ハカセ「それ、ワシに言っとるのかの……?」

インデント

インテリ「23~43行は、配列とFOR~NEXT、READ・DATAを使ったおなじみのプログラムだね。」
ワンパク「配列変数N$()にキーボードを左から順に入れてるのはだいたいワカったゼ。たぶん、そのウチこの変数を使うんだろ。」
神崎「40行で使っている変数KCNTは何なんだろう?
0040#. KCNT=20
0041#. FOR I=0 TO KCNT-1
」
ハカセ「ケンバンの数、すなわち20コと考えてもらえばいいかの。「Kenban(ケンバン)」の「CouNT(カウント)」じゃからKCNTじゃ。変数の名前を決めるのはけっこうナヤむところじゃわい。」
ワンパク「おっと待った、こういうコトにはオレはうるさいゼ! わざわざ変数にしなくても、FOR I=0 TO 19でいいんじゃねェか!?」
ハカセ「う、ウム。このアトにも1回しか使っておらんし、そうとも言えるのう。じゃが、コレはケンバンの数をふやす改造をするトキにベンリなように作っておるのじゃよ。」
インテリ「39行でDIM N$(20)と変数を使わずに配列宣言をしているから、カンペキじゃないけどね。
0039#. KCNT=20
0040#. DIM N$(KCNT)
となっていればもっと良かったんじゃないかな。
」
ハカセ「インテリ君のレイセイなシテキは、ときどきワシの心をスルドクえぐるぞい……。」
ワンパク「まァそのヘンはいいとしてもよォ、42行で1文字スペースがあいてんのはナンかイミあんのか?
0041#. FOR I=0 TO KCNT-1
0042#.  READ N$(I)
0043#. NEXT I
」
ハカセ「これはプログラム用語で「インデント」というヤツじゃな。カンタンに言えば、FORやGOTOで「くり返しているナカミ」のブブンだけ、1文字スペースを空けておるのじゃ。
これはまだ1行じゃからあまりイミはないが、ナカミが何行もあったりFORの中にFORがあったりするトキには、なかなか見やすくなっててイイものじゃぞい。
」
インテリ「「’」のコメントもそうだけど、プログラムがどう動いているのか、リストを他人が見てもすぐわかるように書くのはダイジだよね。
そのわりに次の46~47行の変数のイミが分かりづらいけど……
0046#. F=4096/12
0047#. V=22
」
ハカセ「インテリ君は上げてから落とすのがウマいのう……。」

BEEP命令のピッチ

0046#. F=4096/12
0047#. V=22
ハカセ「この変数のイミを教えるには、まずBEEP命令についてもっとクワしく説明がヒツヨウじゃな。
BEEP 22でピアノの音を鳴らす、ココまでは知っておるハズじゃな?
」
神崎「このプログラムでも使っている音色ですね。」
インテリ「その先はボクが説明しようか。BEEP命令にはもっとフクザツな使い方があって、ピッチを決めることもできるんだ。」
ワンパク「ビ……?」
インテリ「「PITCH(ピッチ)」は「音高」とも言うんだけど、カンタンに言えば音の高さのことだね。」
ワンパク「音の……タカ……?」
インテリ「ワンパク君は音楽にはくわしいと思っていただけに、さすがにその反応にはオドロキを隠せないよ。
たとえばドレミの「ミ」の音は「ド」より「高い」という言い方をするよね。ドからレ、レからミ、ファソラシド……と先に行くほどピッチが高くなる、と思えばだいたいマチガイじゃないよ。
」
ワンパク「音楽リロンを気にしてるようじゃパンクじゃねーゼ! もっとストレートにセツメイしやがれ!」
インテリ「たとえばBEEP 22,0はピアノのドの音が鳴って、BEEP 22,682でレの音になると言えば実感できるかな?」
神崎「「,」の後の数字がピッチになっているんだね。」
インテリ「ちょっとセンモン的な話になるけど、ピッチが-8192だと2オクターブ下、8192で2オクターブ上になるよ。つまり半音は4096÷12という……」
ワンパク「それイジョウ難しいコトをさえずるようなら、オレのベースが火をふくゼ!」
神崎「ワンパク君にとってのベースギターは人をナグる武器だからなあ。」
インテリ「うーん、じゃあこう説明しよう。ドレミをセイカクに言うと「ド・ド#・レ・レ#・ミ・ファ・ファ#・ソ・ソ#・ラ・ラ#・シ」だね。最初の「ド」がピッチ0だと考えて、ひとつ右に行くごとにピッチの数字が4096/12ずつ増えるとおぼえるといいんじゃないかな。」
ワンパク「フーム……まったくリクツがワカった気はしねえが、そういうモンだとわりきってオボエればいいってコトだな!」
神崎「(ワンパク君のロックと、ボクらが知ってるロックは少しちがうのかもしれない……)」
ハカセ「ハナシはワカったようじゃな。そこで46行目にモドるが、F=4096/12というのはまさにピッチを増やすキジュンの数、V=22はピアノの音色の番号というワケじゃ。あとあとBEEP命令でこの変数を使っておるからオボエておいてくれい。」
ワンパク「つまり変数Vの数を変えればピアノ以外の音も出せるってワケだな。V=20なんかロックでいいんじゃねェか?」
インテリ「ここを読んでるみんなも数字を変えてRUNしてみよう!」

BTRIG()命令

インテリ「プログラムリストは50行からメインループに入るね。」
ワンパク「その「メインループ」ってのはナンだ? メインなのはなんとなくオレにもワカるけどよォ、ループするってコトは無限ループになったりすんのか?」
ハカセ「そうマチガっとるワケでもないぞい。じゃが、やってはならない無限ループとちがって、これはヒツヨウなループなのじゃ。」
神崎「ちょっと実感がわかないけど、先を読むとわかってくるのかな。」
ワンパク「まずドラムが、54~63行目か。
0054#. ’--- ト゛ラム
0055#. B=BTRIG()
0056#. IF B AND 1 THEN BEEP 52
0057#. IF B AND 2 THEN BEEP 53
0058#. IF B AND 4 THEN BEEP 62
0059#. IF B AND 8 THEN BEEP 25
0060#. IF B==64 GOTO @EXIT
ワカらねえコトだらけで、ドコから手をつければいいのかもワカらねえぜ!
」
インテリ「そういうことなら、まず56行目のB=BTRIG()がポイントだね。こう書くと、DSiの何ボタンが押されたか、変数Bに入るようになっているんだ。」
神崎「ボタンっていうと、DSiのAボタンみたいな?」
インテリ「DSiのボタンはひととおり全部だね。この表を見てごらん。
十字ボタン↑1Aボタン16Lボタン256
十字ボタン↓2Bボタン32Rボタン512
十字ボタン←4Xボタン64START1024
十字ボタン→8Yボタン128SELECT2048
たとえば十字ボタンの上を押したときは、変数Bには1が入る。右ボタンなら4だね。
」
ワンパク「ナンだってこんなハンパな数なんだ? 2の次は3でいいじゃねェか! ジュンバンに数字をふれば1~12ですむハナシだろ?」
インテリ「じゃあ十字ボタンの左上を押したときを考えてごらん。左は4、上は1だね。だから4+1で、変数には5が入ることになるんだ。」
神崎「同時押しされた時を考えて、わざと数字に間をあけてるってコト?」
インテリ「フツウはまずないことだけど、上と下が同時に押されれば1+2で3、さらに左も押せば3+4で7だね。こういうふうにどんな組み合わせで何個ボタンを押しても、同じ数字が出てこないようにできてるんだよ。もともとはビット演算という考えかたが……」
ワンパク「おっと、ヤヤコシそうなハナシはゴメンだぜ! とにかくシクミはワカッたぜ。タブンその後のIF文で変数Bにあわせた音を鳴らしたりしてんだろ?」
ハカセ「たしかにほぼそのトオリじゃ。ワンパク君のいろいろすっとばしたリカイリョクには、野生のたくましさを感じるのう。」

メインループ

インテリ「このままプログラムリストの先に進んでもいいけど、その前にさっきもちらっと出てきた「ループ」の考え方を知っておくほうがよさそうだね。」
ワンパク「ナンだかフクザツなハナシのヨカンを感じるぜ。」
インテリ「いやいや、フクザツにならないための予習さ。ちょっと実行モードでNEWと打ってごらん。」
NEW
OK
ワンパク「これがナンだってんだ?」
神崎「あ、編集モードにすると……」
画面
ワンパク「プ、プログラムリストがゼンブ消えてるじゃねェか!」
神崎「プログラムリストを消すのがNEW命令なのか……マチガって使ったらコワいね。」
インテリ「サンプルプログラムはまたLOADしなおせばいいけど、自分のプログラムは消す前にSAVEを忘れずにね!
じゃあループの話にもどって、このプログラムを打ってみよう。プログラムのイミは分かるかな?
0001#. INPUT”ニュウリョク”;A
0002#. PRINT”コタエハ”;A
」
神崎「またずいぶんシンプルな……。」
ワンパク「オレをバカにしてんのか? ヨウするにINPUTで変数Aを入れさせて、それをPRINTしてるだけじゃねェか!」
RUN
ニュウリョク?
1
コタエハ1
OK
インテリ「その通り。じゃあ、BUTTON()命令を使って同じことをするにはどうすればいいかな?」
ワンパク「1行ふえちまうが、こういうコトだな?
0001#. PRINT”ニュウリョク”
0002#. A=BTRIG()
0003#. PRINT”コタエハ”;A
」
RUN
ニュウリョク
コタエハ0
OK
神崎「あれ? なにもしないうちにプログラムが終わっちゃったよ。」
ワンパク「どういうコトだチクショー! ボタンを押してねェんだからそりゃ「コタエハ0」だろうぜ!」
インテリ「そこだよ! INPUT命令とちがって、BTRIG()命令では「ボタンを押してない」ことも入力のウチなんだ。だからRUNしたとたんに終わっちゃうんだね。」
ワンパク「じゃあどうすりゃボタンを押すまで待ってもらえるってんだ、ナットクできねえぞ!」
神崎「何回でもBTRIG()命令をやり直すってことだよね。こうすればいいのかな?
0001#. PRINT”ニュウリョク”
0002#. @LOOP
0003#. A=BTRIG()
0004#. PRINT”コタエハ”;A
0005#. GOTO @LOOP
……あ、これじゃダメだ……。
」
画面
神崎「やっぱり。PRINT文もループの中に入ってるからどんどん書き続けちゃう……」
インテリ「でもなかなか悪くないよ。ボタン入力の結果をPRINTするのはデキてるからね。」
ワンパク「タシカに、ボタンを押したシュンカンだけは「コタエハ」の後にちゃんと数字が入ってる……ような気がする……チクショウ、見づれえんだよ!
ボタンを押すと同時にSELECTボタンで止めてやる!
」
画面
ワンパク「……ン?」
神崎「なんだかヘンだね。ボタンは押しっぱなしなのに、これだと何度もボタンを押してるような……?」
インテリ「そこに気が付いたか。そうBTRIG()命令なら、本当はボタンを押したその時だけ変数に数字が入る命令だったよね。」
ワンパク「うまく動いてねえじゃねェか!」
インテリ「そこで、ちゃんとBTRIG()命令が動くように、もう1つ命令を入れるよ。
0005#. VSYNC 1
」
神崎「VSYNC……?」
ワンパク「読みカタすらもワカらねェぜ!」
ハカセ「タシカに読みづらいが、これは「ブイ・シンク」と読むのがイッパンテキじゃな。
もともとは「ヴァーティカル・シンクロナイゼーション(Vertical SYNCronization)」のことで……
」
ワンパク「よしワカッた、そのセツメイはいらねェ!」
ハカセ「まあそんなトコじゃろうな……。
ザックリ言えば、プログラムを一時停止する命令じゃ。VSYNC 1なら60分の1秒だけ止まり、VSYNC 60ならピッタリ1秒止まるコトになっとるぞい。
」
神崎「つまり、この行でも60分の1秒だけプログラムを止めてるってこと……?」
ワンパク「プログラムが止まると、BTRIG()命令がうまく動くってのが、よくワカんねェな……。」
インテリ「プチコンはすごいスピードでプログラムを動かしているよね。特にこんな短いループなんかは、こうしてちょっとだけスローダウンさせておかないと、BTRIG()命令が終わる前にもう1回BTRIG()命令がはじまっちゃう……ような、そんなカンジかな。」
ワンパク「フーム……そのセツメイはわからないでもねェが、そのワリにスッキリと言いきらねえじゃねェか。」
インテリ「すごくおおざっぱに説明したから、プログラムにくわしい人にはツッコミどころなんだよね。まあ深く考えずに、BTRIG()命令のループにはVSYNCをセットで入れるようにしておくとうまく動くよ!」
神崎「そう言われるとわかりやすいけど、話はすっとばしたなあ。」
ハカセ「この命令はアクションゲームなんかによく使われておる。今はまだこのテイドしか使うところがないが、そのウチずいぶん助かる命令になるじゃろう。」
神崎「そんなものかなあ……あれ? BTRIG()命令がうまく動くと、うまく動いてるかどうかがよく見えなくなるね……。」
インテリ「一瞬で通りすぎちゃうから、見づらいどころじゃないかな? BTRIG()命令のかわりにBUTTON()を使ってみよう。
0001#. PRINT”ニュウリョク”
0002#. @LOOP
0003#. A=BUTTON()
0004#. PRINT”コタエハ”;A
0005#. VSYNC 1
0006#. GOTO @LOOP
」
神崎「BUTTON(ボタン)って、そのまんまボタンって意味?」
インテリ「そのまんまさ。BTRIG()命令はボタンを押したシュンカンだけ、変数に数字が入ったよね。BUTTON()命令ではとにかくボタンが押してあれば、いつでも変数に数字が入るんだ。プログラムをRUNして見てみよう!」
画面
ワンパク「ナルホド。ボタンを押してる間はずっと変数Aのナカミに数字が入るってワケか。」
インテリ「ここまででわかったけど、このタイプの命令は何回もくり返さないと思ったように動かないね。そのためにはGOTOでループを作らないといけないんだ。」
ハカセ「さよう。こういうリアルタイムで入力を待つプログラムは、入力を待っているとアッというまに終わってしまうので、ループを作って入力を待ち続けるのがキホンじゃな。」
ワンパク「ハハーン、それが「メインループ」になるってワケか!」
インテリ「ジッサイにはこれ以外にもすぐ通りすぎちゃう命令や、くり返さないとイミがないコトもプログラムにはたくさんあって、そういうのをまとめてひとつのループにするのが「メインループ」になるね。
まあ、プログラムをおぼえていくうちに自然に身につくハズさ。
」
神崎「今つくったプログラムは無限ループだったけど、本当にやりたかったように作るとどうなるの?」
インテリ「まだ見おぼえのない書き方もまじるけど、これでいいんじゃないかな。
0001#. PRINT”ニュウリョク”
0002#. @LOOP
0003#. A=BUTTON()
0004#. IF A!=0 THEN PRINT”コタエハ”;A:END
0005#. GOTO @LOOP
みんなも打ってみてね!
」
ワンパク「ウゥ……マジで見たことねェ書き方しやがって、ヨウシャのねえヤロウだぜ!」

比較演算子

神崎「この行がモンダイなんだね。
0004#. IF A!=0 THEN PRINT”コタエハ”;A:END
今までの話から、これが「もしも変数Aがゼロじゃなければ~する」ってIF文だとはなんとなく分かるんだけど……
」
インテリ「気になるのは「変数!=数字」のカタチだよね。」
神崎「「==」もビックリだったけど、「!=」だって初めて見るよ!」
ハカセ「ほっほっほ。ソコはそうムズカシいモノでもないぞ。いわゆる「≠(ノットイコール)(等号否定)」と同じイミで、まあ右と左が「ちがう」というくらいのことじゃな。」
ワンパク「まさか、またムカシのコンピューターに「≠」の字がなかったから「!=」と書いたとか、そんなことじゃねェだろうな……。」
ハカセ「それでだいたい合っておるそうじゃ。」
ワンパク「コ、コンピューターにタイするゲンソウがどんどんウシナわれていくぜェ……。」
ハカセ「ほかにも「<(小なり)」「>(大なり)」を使うこともあるが、「≦(小なりイコール)」は「<=」、「≧(大なりイコール)」は「>=」と書くのじゃ。」
ワンパク「そんなのばっかりか! なんかもう、コンカイはオレもいろいろダキョウしてる気がするぜェ……。」
インテリ「そろそろ元気がなくなってきたかな。色々おぼえたし、いったん一休みしよう!」

今回のまとめ

インデント
行の先頭に空白スペースを入れることを「インデント」といいます。プログラムの動作には関係ありませんが、リストを見やすくするのに使います。FOR~NEXTの中に使うのがいちばん一般的ですね。
NEW命令
NEW
実行モードで使います。プログラムが消去されます。
SYSBEEP変数
SYSBEEP=FALSE
SYSBEEP=TRUE
FALSEならシステム音を消し、TRUEならシステム音が鳴るようになります。
BEEP命令のピッチ
BEEP (音色),(ピッチ)
ピッチ0が基本の音、-8192だと2オクターブ下、8192で2オクターブ上になります。おおざっぱに「ドレミで半音上げるには、ピッチを4096/12だけ増やす」とおぼえておくといいでしょう。
BTRIG()命令
変数=BTRIG()
ボタンが押された瞬間、変数に押されたボタンの情報が入ります。
十字ボタン↑1Aボタン16Lボタン256
十字ボタン↓2Bボタン32Rボタン512
十字ボタン←4Xボタン64START1024
十字ボタン→8Yボタン128SELECT2048
たとえば左上に押せば4+1で5が、何も押さなければ0が入ります。
VSYNC命令
VSYNC (数)
プログラムを一時停止します。VSYNC 60で1秒、VSYNC 1なら60分の1秒だけ遅くなります。
BUTTON()命令
変数=BUTTON()
BTRIG()命令とよく似ています。
ボタンが押されている間ずっと、変数に押されたボタンの情報が入ります。
比較演算子
IF~THEN命令の条件文で使います。
変数AとBを比べる場合
A==BAとBの内容が同じ
A!=BAとBの内容が違う
A<BAよりBが大きい
A<=BAよりBが大きいか、同じ
A>BAよりBが小さい
A>=BAよりBが小さいか、同じ
IF (変数)!=(数) THEN (命令)
変数と数が一致しないときだけ命令を実行します。