サンプルプログラム3(後)
サンプルプログラム3を見ていくのも後半になりました。
と言っても、前回までで難しいところはだいたいおさえたので、今回はわりとスルスルいくような気がします。
中にはかなりおおざっぱな説明も出てきますが、リクツ付けはそのうち、レベルが上がってきたころにやるので、それまでは「こーゆーもんなんだな」という感じでおぼえてください。
ないしょですが、プログラマーでもそうやっておぼえた事というのは、けっこうあります。
ちなみに私も前回ここで指摘されるまで、「フォールス」または「フォルス」と読む「False」を「ファルス」と間違って読みつづけていました。あんがいそういうものです。
さて、メインループの話からダイブずれてしまったようじゃな。そろそろLOAD”SAMPLE3”でサンプルプログラムにモドるとするかの。
それにしたってよォ、ここで出てくるIF文はケッキョクまだココまででオボエたやり方じゃセツメイつかねェぞ!
いちばん多く使われてるのは、このタイプの文だね。
0058#. IF B AND 1 THEN BEEP 52
今まで習ったことのフンイキから、「上ボタンを押したら52番の音色でBEEP」ということはわかるけど……
「IF B AND 1 THEN」ってナンだよコンチクショー! おかしいにもホドがあるじゃねえか!
これはリクツは気にせず丸ごとおぼえた方が早いかなあ。BUTTON()したバアイ、「IF B AND 1」と書くと、「Bの中に1がまじっている」というイミになるんだ。
「まじっている」?
とくに十字ボタンの入力なんかにベンリな使いかただね。たとえば押されたボタンが右上だったとしよう。すると変数に入る数字は1+8で
9だよね。
十字ボタン↑ | 1 |
十字ボタン↓ | 2 |
十字ボタン← | 4 |
十字ボタン→ | 8 |
そうなるとコマるのは、「
IF B==1」じゃヒットしないことだね。
ところが「
IF B AND 1」や「
IF B AND 8」と書くと、ちゃんとヒットするんだ。フシギだね。
これをセツメイするには、まず「ビット演算」についてセツメイせねばならん。ならんのじゃが、あんまりムズカしいのでヒトにオシエづらいのじゃあああああ
ショシンシャ向きのサンプルプログラムなのに、ちょくちょくフクザツなコトをしようとするよな。セツメイできねェなら、サイショからやるなよ!
まあまあ。こういうベンリな使いかたがあるんだから、ふかく考えずに使えばいいのさ。
テメーのワリキリもなんだかスゲエな……。
まだ57行目が残ってるね。
0057#. IF OLDB!=0 GOTO @DSKIP
「
IF~
GOTO」っていうカタチも初めてだけど……
「IF~THEN」のGOTOバージョンだと考えていいよ。そんなに違いはないよね。
それにしたって、イミがワカらねえぜ! 変数OLDBがゼロじゃなければ@DSKIPのある行に飛ぶ。そりゃナンのタメだ?
ソレならちょっと前までモドって55行を見るのじゃ。
0055#. OLDB=B
変数
Bはもちろん押されているボタンの番号じゃな。もしも十字ボタン上が押されておれば、変数
Bはスナワチ
1というコトになる。
ということは変数OLDBにも、変数Bと同じ1が入るということですね。
さよう! 変数のナマエOLDBは、「OLD(古い)」Bというイミで付けたのじゃよ。
今までは「変数=数字」のカタチを使っていたけど、「変数=変数」というように書いてもいいってコトだね。
フーム、変数もオクがフカいぜ……。
イヤ、ちょっと待て! 57行のイミがまだワカるようでワカらねえままだぜ!
そうだね、たとえば上ボタンを押したときで考えてみようよ。
はじめに55行に来たときには変数Bはまだゼロだから変数OLDBもゼロのままだね。
そして56行のB=BUTTON()で初めて変数Bに1が入ることになる。
オウ。ナンドもやったコトだから、ソコはまあワカるぜ。
OLDBがゼロだから57行は飛ばしていい。58行でIF B AND 1になってるから、BEEP 52と音を鳴らすよね。
まあトウゼンだな。アトのIF文はひっかからねェからドンドンすっトバすぜ。
途中ははぶくけど、79行でGOTO @LOOPしているから、また52行からのループになるね。
フム……? すると55行でOLDB=Bするから、変数OLDBは1になるな。
まだ上ボタンをはなさずに押しっぱなしだと考えるよ。56行でB=BUTTON()してもやっぱり変数Bは1だね。
で、57行のIF OLDB!=0がキいて、GOTO @DSKIPするワケだ……オイオイ、58行を飛ばしちまうってのか?
ソコじゃ! もしこのまま58行に行くと、またもやBEEP 52するコトになるのう。ソレでは「ドン」と鳴る音がレンゾクして「ドドン」と鳴りっぱなしになってしまうじゃろ。
ソレはソレでロックじゃねェか?
そ……そういうモンダイじゃないんじゃないかな。
ためしに57行の先頭に「
’」をつけてみよう。
0057#. ’IF OLDB!=0 GOTO @DSKIP
これでこの行は使われなくなったよね。
RUNしてドラムを鳴らしてごらん。
ウ……ウォオー! コレはコレでロックだとしても、このプログラムでやりたかったのはこういうコトじゃねー!
そういうコトさ。カクニンできたらさっきの「’」は消しておこうね。
先頭に「’」をつけてとりあえずテストしてみる、というのはタンジュンじゃが、ダイジなテクニックじゃな。
プログラム用語では「コメントアウト」と言うのじゃが、このキカイにおぼえておくといいぞい。
66行から、気になることが書いてあるね。
0066#. ’--- FOR-NEXT テ゛
0067#. ’--- トチュウカラヌケルト
0068#. ’--- ナイフ゛メモリカ゛ヘルノテ゛
0069#. ’--- GOTO ヲツカッタル-フ゜
う、うむ。ソコはちょっとヤッカイなモンダイなのじゃが、ひとまずその先の72行から片づけてもらおうかの。
0072#. K$=INKEY$()
カタチはなんとなくBUTTON()命令と似ているね。
そう! INKEY$()命令は、BUTTON()命令のキーボードバージョンだと考えていいだろうね。「IN KEY」つまりキー入力というコトだね。
ツマリ、72行だと変数K$に押したキーの……ナニが入るんだ?
あ、それはBUTTON()命令よりカンタンだね。押した文字がそのまま変数に入るんだ。Aキーを押していたら、K$にはAという文字が入るよ。
チッ、フカヨミしすぎたか! しかし、おかげで73行目のやってるコトはよくワカッたぜ。
0073#. IF K$==”” GOTO @LOOP
変数
K$がカラ……つまりキーが押されてなければ、おなじみの
@LOOPに飛んでくり返しってことだな!
このあたりまではBUTTON()命令と本当によく似ているね。問題はこの後だけど……
ゴホン。ここはヒトアシさきに、カンタンに書き直したプログラムの方を見てもらおうかの。
0074#. FOR I=0 TO KCNT-1
0075#. IF K$==N$(I) GOTO @PLAY
0077#. NEXT
これを読めば、ナニをしとる行かはワカるはずじゃの?
……たしか配列変数N$()には(0)~(19)まで、ケンバンに使う字が入ってたハズだな。
変数KCNT-1はケンバンの数をコンピューター風に数えて、19のはずだよね。
変数K$に入ってるのは押されたキー。つまり……20回ブンN$()を変えながらくり返しチェックして、どこかで押されたキーがケンバンのキーと同じだったら@PLAYに飛ぶ、ってコトだな!
おお……ワンパク君、すっかりリッパになったのう……。
そりゃいいんだけどよォ、ジッサイのサンプルはこうじゃねェよな。マズいコトでもやったのか?
おお……ズバズバ言うトコは変わっとらんのう……。
0074#. I=0
0075#. @KLOOP
0076#. IF K$==N$(I) GOTO @PLAY
0077#. I=I+1
0078#. IF I<KCNT GOTO @KLOOP
0079#. GOTO @LOOP
よーく見なおしてもらえばワカると思うが、ココで書いているコトはFOR~NEXT文で書いたコトと同じなのじゃ。
77行目の「I=I+1」てのが初めて見るパターンだが……
変数のルールにそって考えると、なんとなく分かるね。バケツIに、それまでのIの中身プラス1を入れるってことでしょ?
そういうこと。こういうふうに変数の中では、同じ変数を使った計算もできるんだけど、なれないとピンとこないかもね。
もしも変数Iのナカミが0だったときにI=I+1すると、0+1で1が変数Iのナカミになるね。
FOR~NEXT文も、変数に1ずつプラスしてくワケだしな。
よし、このブブンがFOR~NEXTと同じコトをやってるのはワカッた。で、なんでそんなコトすんだ? FOR~NEXTの方がカンタンじゃねェか!
ココがムズカしいトコロでのう……。
押されたキーとケンバンのデータがマッチすれば@PLAYに飛ぶのはワカッとるな?
じゃがFOR~NEXTのくり返しが終わらないウチにトチュウで飛び出して、またFOR~NEXTをゼロからくり返しはじめて……、とやっておると、プログラムの中に「トチュウで止まったままのFOR文」がドンドンたまっていくのじゃよ。
つまり、いわゆるスタックがたまってメモリをアッパクするんですね。
???
まあモノはためしじゃ、サンプルをFOR~NEXT方式に書きかえて、ジャンジャンキーボードをたたいてみい。
ウオォー! オレのレンシャが火をふくゼェー!
Out of memory (74, FOR)
OK
ゼエ、ゼエ……た、タシカにエラーが出たな。
メッタにないコトではあるんじゃが……。とにかくFOR~NEXTをトチュウで抜け出すのはあまりコンピューターにやさしくないというコトと、もし自作のプログラムでOut of memoryエラーが出たらコレをうたがってもいい、とはココロのスミでおぼえておいていいかもしれんのう。
さあ、ここまで来たらもうあとはキーボードどおりに音を鳴らすだけだね!
なんだかんだで、けっこう長かったなあ。
0082#. @PLAY
0083#. P=F*(I)-4096
0084#. BEEP V,P
0085#. GOTO @LOOP
84行で使っている変数
Vは最初のほうで出てきた
BEEP命令の音色、変数
Pは
BEEP命令の「ピッチ」だね。
その変数
Pを決めてるのが83行目ってワケだな。もうずいぶんサカノボるが、変数
Fは46行目で決めてたんだったか。
0046#. F=4096/12
1音ずらす数字が「4096/12」なんだったね。そして変数Iは0がキーボードの「’」、1がキーボードの「A」、……と対応してるから……
Aキーを押せばF*1、つまりフダンより1音上のピッチになるってコトだ!
……あれ?
-4096って何だろう?
0083#. P=F*(I)-4096
ウム。P=F*(I)のままじゃと、ちょっと音がカルいかと思ってのう。-4096してちょうど1オクターブだけ下げておいたのじゃ。
重低音……ってホドじゃねェが、そこはワカるぜ。いっそ-40960くらいにしたらどうなるんだ?
Out of range (84, BEEP)
OK
ウウ……BEEP命令のピッチは-8192~8192までがゲンカイなのじゃよ……。
「Out of range」というのは「ハンイからはずれた」という意味のエラーメッセージだね。
インテリ君のすばやい進行は、ときにザンコクじゃ……。
88行目からは、ラベル
@EXITだね。
0088#. @EXIT
0089#. SYSBEEP=TRUE
0090#. END
@EXIT……。そんなラベル、どっかで見たような……見てねェような……
ははは。
BUTTON()命令を使ったところで、ボタン判定をしていたじゃないか。
0062#. IF B==64 GOTO @EXIT
オゥ、これだ! そういやあの時はドラムのコトばっかり考えてて、このGOTOのコトはすっかり忘れてたぜ! オレとしたことが!
BUTTON()命令で64が入ったということは、たしかXボタンを押したってことだったよね。
さよう。このプログラムでは、Xボタンでプログラム終了じゃったな。と言えばあとはワカるじゃろう?
さすがにラクショーだぜ! 89行でSYSBEEP=TRUEして音を元にモドして、90行でENDだな!
ポイントは、Xボタンを押すことで、50~80行目の間をグルグル回っていたメインループからぬけ出しているコトだね。
そういうコト! ハッキリ言えば90行目のENDはなくてもいいんだけど、ループから飛びだしてプログラムを終わらせるにはピッタリだね。
それはモチロンじゃし、この後にラベルを増やして新しいキノウを増やすときにはますます
ENDがダイジになるじゃろうな。
0088#. @EXIT
0089#. SYSBEEP=TRUE
0090#. END
0091#. @USO
0092#. SYSBEEP=FALSE
たとえばこういうプログラムじゃと、90行目に
ENDがなければ91行から先まで勝手に進んでしまうわい。
フーム……。ラベルでループを使ったプログラムじゃ、ループを抜け出すのと、そこでENDするのがダイジになるワケだな……。
ワ、ワンパク君! どうしたんじゃそのリッパなまとめぶりは……!
さすがに長びいたからよォ、このヘンでENDっぽく終わらせるのがイイ気がしたんだゼ。ノーフューチャー!
いつも通りだったね。
- コメントアウト
- 行の先頭に「’」と書くだけで(あたりまえですが)その行がなかったことになります。プログラムの動作テストのときなどに便利です。
- INKEY$()命令
- (文字変数)=INKEY$()
変数に押されたキーが入ります。
- ビット演算子
- むずかしいので、使い方だけおぼえましょう。BUTTON()命令で使う変数なら、この形が使えます。
IF (変数) AND (数) THEN (命令)
変数がボタンに対応した数を含んでいるときだけ、命令を実行します。
BUTTON()命令以外でもこれが使えると思ったら大まちがいです。
- FOR~NEXT文からの脱出とスタック溜まり
- くわしいことをはぶくと、FOR~NEXT文の中からGOTOで飛び出して、またFOR~NEXT文の中から……とくり返すのは、あんまりコンピューターに優しくなく、激しくやりすぎると「Out of memory」エラーが出ることもあります。めったにないことですが、このサンプルプログラムの方法で回避はできますよ。