Casio Basic入門14
Casio Basic入門
誤字脱字・記載ミスや分かりにくい表現は随時追記・修正します
最終: 2015/01/11 Casio Basic 特有の問題について重要な追記を一番最後に行いました
最終: 2015/01/11 Casio Basic 特有の問題について重要な追記を一番最後に行いました
4. CasioBasicを使ってみる(続き)
Chapter 2 - 初級
◆ Chapter 2 の目標: 動きのあるプログラムを作る
簡単なアクションゲームを作る
前回: Casio Basic入門13
Chapter 2-9 で、ゲーム機能の実装が終わりました。
プログラム名 CH2-9
While 1
0→P:3→T:0→B
Locate 1,1,"P:0"
Locate 1,3,"L:"
Locate 10,1,"TRY:"
Locate 14,1,T
Locate 1,4,"B:0"
Lbl M
0→E
TankInt#(7,25)→L
Locate 3,3," " (スペース4個)
Locate 3,3,L
Locate 6,4,"<EXE>:START"◢
Locate 6,4," <(-)>:STOP" (頭にスペース1個)
Locate 1,2," " (スペース16個)
RanInt#(2,50)→C
Do
If C-4Int(C÷4)≦1
Then
Locate 8,2,"×"
Else
Locate 8,2,"+"
IfEnd
Getkey=57⇒1→E
Dsz C
LpWhile E=0
Locate 8,2," " (スペース1個)
0→C
Do
E=1⇒Break
C>L⇒Break
Isz C
LpWhile Getkey≠57
C>L⇒2→E
Locate 8,2,C
If E=2
Then
P-L→P:Dsz T
Locate 5,2,"TIME OUT"
Else If E=1
Then
P-L+C→P:Dsz T
Locate 3,2,"FALSE START"
Else If E=0
Then
P+L-C→P
If P≧50(B+1)
Then
Isz B:Isz T
Locate 3,4,B
IfEnd
IfEnd
IfEnd
IfEnd
Locate 3,1," "
Locate 3,1,P
Locate 14,1,T
T⇒Goto M
Locate 1,2," " (スペース16個)
Locate 4,2,"GAME OVER"
Locate 8,3,"<AC>:QUIT" (頭のスペースはない)
Locate 6,4,"<EXE>:RETRY"◢
Cls
WhileEnd
プログラムブロック構造
While 1 (大ループ)
[プログラム全体の初期化]
Lbl M
[繰り返し処理の初期化]
[アニメーション表示]
[反応速度の測定&表示]
[例外処理]
Goto M
[ゲームオーバー時の処理]
WhileEnd
チョットした動きを付けて「反射ゲーム」を完成させます。
Chapter2-10
For文とProgコマンドを使ってみる
CasioBasic入門では、Doループ、Whileループ そして Goto/Lbl ループを紹介してきました。今回は、Forループを紹介します。
例えば、ディスプレイの左から右へ "." を並べて表示しようと思います。
Locate 1,2,"."
Locate 2,2,"."
Locate 3,2,"."
・
・
・
Locate 15,2,"."
Locate 16,2,"."
とすれば良いわけですが、これではプログラムを書くだけでも大変です。
では、Locate I,2,"." をみてください。"." を表示する位置が、(x, y) = (I, 2) になっています。大文字の I を変数として使っています。
そして、I を 1~16まで変化させながら、Locate I,2,"." を実行すれば、単純作業を自動化できてプログラムらしくなります。これを実現するのが、For 文 です。
具体的な記法は、以下のようになります。
For 1→I To 16
Locate I,2,"."
Next
・I に1を代入 (I の初期化)
・I を 1から16まで変化させながらループをまわす
・ループの中では Locate I,2,"." を実行する
・I が16の時の処理が終わればループを抜ける
...と言う動作をします。
プログラムを入力する時、For や To そして Next は、Do や While と同じページのメニューから選べば入力できます。
ここで、使った変数 I を制御変数やインデックスと言うこともあります。
さて、実際に、プログラム実行してください。点が左から右へ増えてゆきます。fx-5800P は動作が遅いので、For文を使えばアニメの表示に使えるわけです。
では、次のプログラムを入力して、実行してみてください。
Program Menu で、1:NEW を選び、プログラム名を S1RE としてください。
プログラム名 S1RE
For 1→I To 7
Locate 8-I,2,"<"
Locate 9+I,2,">"
Next
どうですか?
画面中央から < > が広がってゆくアニメーション になっていますね。
このアニメーションを GAME OVER の表示に重ねてみることにします。
反射ゲームのゲームオーバー時に、Locate 4,2,"GAME OVER" を実行しています。そこで、この表示の直前に上のアニメーションを実行すると、< > が広がるアニメの後、真ん中に GAME OVER と表示されますね。
Casio Basicでは、他のプログラムを呼び出して使うことができます。呼び出すプログラムをサブルーチンと言います。
他のプログラムを呼び出すには、Prog コマンドを使って、呼び出すプログラム名を " " で挟みます。
Prog "S1RE"
と書くと、プログラム S1RE を呼び出し、S1RE の実行が終わると、この記述の直後へ戻ってきて、次の処理が続きます。
そこで、プログラムCH2-9 の [ゲームオーバー時の処理] ブロックを以下のように変更しましょう。
Locate 1,2," "
Prog "S1RE"
Locate 4,2,"GAME OVER"
Locate 8,3,"<AC>:QUIT"
Locate 6,4,"<EXE>:RETRY"◢
Cls
(追加した部分を赤文字で示した)
プログラムCH2-9 のゲームオーバー時:
もう1つ、動きのあるギミックを追加しようと思います。
プログラムの起動時に、プログラムの説明画面が現れることがありますが、これをスプラッシュ画面といいます。そこで、反射ゲームにも動きのあるスプラッシュを表示させて、Chapter 2 の仕上げとします。
先ずは、完成動画を見て下さい。
先ず、アニメーションで React!! と表示しています。そして、e-Gadget と by Krtyski と表示されます。
ここで、小文字のアルファベットを使っていることに注目してください。fx-5800P の Casio Basic では、普通にアルファベットを表示するには大文字に限られますが、それでは面白くない。
スプラッシュと小文字表示については、Ku さんによる 小文字表示プログラムのご提案があり、とても面白いので、 このアイディアを盛り込みました。小文字の表示方法についての詳細は、「楽屋裏 - スプラッシュ」のコメント欄を参考にしてください。e-Gadget と表示する具体的なプログラムの記載があります。
小文字を使うには、以下の方針で工夫すれば良いと思います。
・ 欲しい小文字を1文字目或いは2文字目に含んだ文字列を、探す
・欲しい小文字以外は、他の文字で上書きするかスペースで上書きして消す
スプラッシュ画面は、サブルーチン S2RE で作成し、プログラムCH2-9 から呼び出して使うことにします。
React!! の動画は以下のように、For 文を使っています。
3→W
For 1→I To 16
Locate 17-I,2,"R" ([Function] [4] [▼] [▼] [▼] [3])
Next
For 1→I To 15
Locate 17-I,2," "
Next
For 1→I To 15
Locate 17-I,2,"e^(" ([SHIFT] [In])
Next
For 1→I To 14
Locate 17-I,2," "
Next
For 1→I To 14
Locate 17-I,2,"ao" ([Function] [4] [5])
Next
For 1→I To 13
Locate 17-I,2," "
Next
For 1→I To 13
Locate 18-I,2,"co" ([Function] [4] [▼] [▼] [▼] [4])
Next
For 1→I To 12
Locate 17-I,2," "
Next
For 1→I To 12
Locate 17-I,2,"t" ([Function] [4] [▼] [▼] [▼] [▼] [6])
Next
For 1→I To 11
Locate 17-I,2," "
Next
For 1→I To 11
Locate 17-I,2,"!" ([i])
Next
For 1→I To 9
Locate 17-I,2," "
Next
For 1→I To 7
W→C
Lbl 0
Dsz C
Goto 0
Locate 8-I,2," "
Next
ここで、React!! の最初の文字 R のアニメーションを見てみましょう。
For 1→I To 16
Locate 17-I,2,"R"
Next
文字 R は、特殊文字を使っています。普通に 大文字の R でも良いのですが、次にくる e とのバランスを考えて、この文字にしているだけです。ここは好みの問題ですから、気にしないでくさだい。
For文が実行される時、
最初は、I=1 なので、17-I は 16 となり、Locate 16,2,"R" と同じことになります。
次に、I=2 になるので、17-I は 15 となり、Locate 15,2,"R" と同じ、
これを繰り返し、
最後に、I=16 になるので、17-I は 1 となり、Locate 1,2,"R" と同じになります。
ここで、For文が終わります。
このアニメーションの視覚効果は、R を2行目の1番右に表示し、次に1つ左に表示し、さらに1つ左に表示...と繰り返し、1桁目に表示するまで繰り返しています。この表示が終わった段階では、2行目の左端から右端まで R がズラズラと並んでいます。
次に、以下のFor文で、右から R を順に消してゆき、最後の1文字を残します。
For 1→I To 15
Locate 17-I,2," "
Next
この For文が実行されると、
最初は、I=1 なので、17-I は 16 となり、Locate 16,2," " と同じになります。
次に、I=2 になるので、17-I は 15 となり、Locate 15,2," " と同じ、
これを繰り返し、
最後に、 I=15 になるので、17-I は 2 となり、Locate 2,2," " と同じになります。
ここで、For文が終わります。
全ての文字が同じように動くと、視覚的には、右から文字がやってきて、React!! ができあがるようなアニメーションに見えます。
React!! をアニメーションで表示した後、2ブロック目のFor文で、右から1文字づつ消すアニメーションにしています。
文字を右から順に消すのは、Locate 8-I,2," " で順にスペースで上書きしています。
ここでは、以下のループを使って待ち時間を作っています。時間はカウンタCで決まります。
Lbl 0
Dsz C
Goto 0
For文をまわるたびに、Cを初期化する必要があり、Wの値で初期化しています。Wの値はプログラムの一番最初で3にしています。
以上がアニメーション部分です。
上のプログラムの1つめのブロックと2つめのブロックの間で、
e-Gadget と by Krtyski の表示を入れます。そのプログラムは以下のようになります。
Locate 8,1,"e^(" ([SHIFT] [In])
Locate 11,1,"ao" ([Function] [4] [5])
Locate 12,1,"d/dX(" (Function] [1] [2])
Locate 13,1,"g" ([Function] [1] [▼] [▼] [▼] [▼] [3])
Locate 14,1,"e^(" ([SHIFT] [In])
Locate 9,1,"-G" (普通に "-G")
Locate 15,1,"t" ([Function] [1] [▼] [▼] [▼] [▼] [6])
Locate 16,1," " (普通にスペース)
Locate 6,4,"Abs(" ([Function [1] [▼] [1])
Locate 6,2," " (普通にスペース)
Locate 6,4,"yσn" ([Function] [7] [2] [6])
Locate 9,4," " (普通にスペース)
Locate 10,4,"K" (普通に"K")
Locate 11,4,"re" ([Function [4] [▼] [3])
Locate 12,4,"t" ([Function] [4] [▼] [▼] [▼] [▼] [6])
Locate 13,4,"yσn" ([Function] [7] [2] [6])
Locate 14,4,"sin(" ([sin])
Locate 15,4,"k" ([Function] [1] [▼] [▼] [▼] [6])
Locate 16,4,"i" ([i])
以上のアニメーションと表示が終わると、最後に画面をクリア(消去)する必要があります。そこで、Cls コマンドを使います。
このプログラムはサブルーチンとして呼び出されるので、終了すると呼び出された位置へ戻ります。
一方、Returnコマンドを実行しても、サブルーチンを強制終了して、呼び出された位置へ戻ります。
今後、このサブルーチンを変更する可能性を考えて、最後に明示的に Return を書いておきます。このままですと、特にReturnは不要ですが、念のためです。
※ CasioBasicコマンドリファレンス
- Cls
- Return
スプラッシュ画面表示のプログラムをまとめます。
プログラム名 S2RE
3→W
For 1→I To 16
Locate 17-I,2,"R" ([Function] [4] [▼] [▼] [▼] [3])
Next
For 1→I To 15
Locate 17-I,2," " (スペース1個)
Next
For 1→I To 15
Locate 17-I,2,"e^(" ([SHIFT] [In])
Next
For 1→I To 14
Locate 17-I,2," " (スペース1個)
Next
For 1→I To 14
Locate 17-I,2,"ao" ([Function] [4] [5])
Next
For 1→I To 13
Locate 17-I,2," " (スペース1個)
Next
For 1→I To 13
Locate 18-I,2,"co" ([Function] [4] [▼] [▼] [▼] [4])
Next
For 1→I To 12
Locate 17-I,2," " (スペース1個)
Next
For 1→I To 12
Locate 17-I,2,"t" ([Function] [4] [▼] [▼] [▼] [▼] [6])
Next
For 1→I To 11
Locate 17-I,2," " (スペース1個)
Next
For 1→I To 11
Locate 17-I,2,"!" ([i])
Next
For 1→I To 9
Locate 17-I,2," " (スペース1個)
Next
Locate 8,1,"e^(" ([SHIFT] [In])
Locate 11,1,"ao" ([Function] [4] [5])
Locate 12,1,"d/dX(" (Function] [1] [2])
Locate 13,1,"g" ([Function] [1] [▼] [▼] [▼] [▼] [3])
Locate 14,1,"e^(" ([SHIFT] [In])
Locate 9,1,"-G" (普通に "-G")
Locate 15,1,"t" ([Function] [1] [▼] [▼] [▼] [▼] [6])
Locate 16,1," " (スペース1個)
Locate 6,4,"Abs(" ([Function [1] [▼] [1])
Locate 6,2," " (スペース1個)
Locate 6,4,"yσn" ([Function] [7] [2] [6])
Locate 9,4," " (スペース1個)
Locate 10,4,"K" (普通に"K")
Locate 11,4,"re" ([Function [4] [▼] [3])
Locate 12,4,"t" ([Function] [4] [▼] [▼] [▼] [▼] [6])
Locate 13,4,"yσn" ([Function] [7] [2] [6])
Locate 14,4,"sin(" ([sin])
Locate 15,4,"k" ([Function] [1] [▼] [▼] [▼] [6])
Locate 16,4,"i" ([i])
For 1→I To 7
W→C
Lbl 0
Dsz C
Goto 0
Locate 8-I,2," " (スペース1個)
Next
Cls
Return
ここで作ったスプラッシュプログラム S2RE をメインプログラムから呼び出します。
プログラム CH2-9 の1番最初で、スプラッシュプログラムを呼び出すので、プログラムの1番上に
Prog "S2RE"
を追加します。
これで、反射ゲームが完成です。
これまで作ってきた反射ゲームを React!と命名しましょう。そこで、プログラム名 CH2-9 を REACT に変更します。
Program Menu で、3:EDIT を選ぶ(2;RUN でも良い)と、Program List が表示されます。そこで、CH2-9 にカーソルを合わせ([EXE]キーは押さずに...)、[FUNCTION]キーを押すと、File Commands 画面が現れます。ここで 2:Rename を選び、File Name を REACT に変更します。
プログラム名 REACT
Prog "S2RE"
While 1
0→P:3→T:0→B
Locate 1,1,"P:0"
Locate 1,3,"L:"
Locate 10,1,"TRY:"
Locate 14,1,T
Locate 1,4,"B:0"
Lbl M
0→E
RanInt#(7,25)→L
Locate 3,3," " (スペース4個)
Locate 3,3,L
Locate 6,4,"<EXE>:START"◢
Locate 6,4," <(-)>:STOP" (頭にスペース1個)
Locate 1,2," " (スペース16個)
RanInt#(2,50)→C
Do
If C-4Int(C÷4)≦1
Then
Locate 8,2,"×"
Else
Locate 8,2,"+"
IfEnd
Getkey=57⇒1→E
Dsz C
LpWhile E=0
Locate 8,2," " (スペース1個)
0→C
Do
E=1⇒Break
C>L⇒Break
Isz C
LpWhile Getkey≠57
C>L⇒2→E
Locate 8,2,C
If E=2
Then
P-L→P:Dsz T
Locate 5,2,"TIME OUT"
Else If E=1
Then
P-L+C→P:Dsz T
Locate 3,2,"FALSE START"
Else If E=0
Then
P+L-C→P
If P≧50(B+1)
Then
Isz B:Isz T
Locate 3,4,B
IfEnd
IfEnd
IfEnd
IfEnd
Locate 3,1," "
Locate 3,1,P
Locate 14,1,T
T⇒Goto M
Locate 1,2," " (スペース16個)
Prog "S1RE"
Locate 4,2,"GAME OVER"
Locate 8,3,"<AC>:QUIT" (頭のスペースはない)
Locate 6,4,"<EXE>:RETRY"◢
Cls
WhileEnd
プログラムブロック構造
[スプラッシュ呼び出し]
While 1 (大ループ)
[プログラム全体の初期化]
Lbl M
[繰り返し処理の初期化]
[アニメーション表示]
[反応速度の測定&表示]
[例外処理]
Goto M
[ゲームオーバー時の処理]
WhileEnd
そこそこ遊べる「反射ゲーム」になったと思います。
スピードが必要なところは、コンパクトなループにし、ゲームの得点計算などは別のところで行う作戦にしたので、機能追加してもスピードが犠牲になっていないと思います。
皆さんは、どのくらいの最高得点になりますか?
簡単すぎる、あるいは難しすぎる場合は、タイムアウトカウンタ L を決める RanInt#(7,25)→L を調整したり、ボーナスポイントを貰える条件( If P≧50(B+1) : 50点おき)を変更すると良いでしょう。
CasioBasicのコマンド類を覚えてもらいながら、ブロック構造でプログラムを作るメリットも紹介してきました。慣れないうちは、プログラムコードを紙やエクセルなどに書いて全体を眺めるほうが、分かりやすいと思います。
プログラムの保存
fx-5800P はメモリ内にしかプログラムを保存できません。もう一台fx-5800Pを持っていれば、オプションのリンクケーブルを使ってプログラムを転送してバックアップできます。
私は、いつもエクセルに書いて保存しています。スペースの数を確認できる、色々なメモを書いておけるのがその理由です。
フォントには、電卓のフォントに近い Consolas を使っています。このフォントでは、0(ゼロ)は斜め線がついて、O(オー)との区別が明確なので、お勧めです。
私は、いつも変数のメモを付けるようにしています。
必要に応じて、プログラムの構造のメモなども追加しています。




重要な追記 2015年1月11日
Do ループや While ループからの脱出に Dsz 命令や Isz 命令、⇒ 命令を使うと異常動作の可能性があります。
具体的には、以下の条件を満たす記法が異常動作の可能性の条件となります;
Dsz/Isz/⇒で偽の場合に、次のコマンドをスキップするという
仕様のため、次の条件の場合にSynERRORとなります。
・条件1: DoやWhileを用いたループがあること
・条件2:ループ脱出に Dsz/Isz/⇒を利用すること
・条件3:Dsz/Isz/⇒ の次のコマンドが、LpwileかWhileEndであること
これは、カシオお客様センターに確認したもので、ユーザーから見ればバグですが、メーカーとしては非公開の内部実装に沿った仕様通りの動作ということです。その背景には、古い命令である Dsz, Isz, ⇒ に慣れ親しんだユーザーへの配慮から、敢えてこれら古い命令を残したということです。
但し、必ずエラーになるかといえば、そうではないことは今回のプログラムが正常動作することが示しています。
この部分です;
RanInt#(2,50)→C
Do
If C-4Int(C÷4)≦1
Then
Locate 8,2,"X"
Else
Locate 8,2,"+"
IfEnd
Getkey=57⇒1→E
Dsz C
LpWhile E=0
Locate 8,2," "
細かいことをいえば、ループ構造を正しく制御するためには、ループが継続される時と継続されない時で、ジャンプ先が異なるので、プログラムの内部動作として、スタックという特殊なメモリを使ってジャンプ先アドレスの管理を行っています。このスタック制御に関して、古い Dsz / Isz / ⇒ 命令と後から追加した Do / While ループで整合性がとれていないのが、現在の Casio Basic です。古くからのユーザーが慣れ親しんだ古い命令を敢えて残した際、後から追加した Do / While ループとの整合性が不完全なままになっていると言うことは、確認がとれています。
逆に言えば、制御構造のスタック管理を意識して使えば、今回のように必ずしもエラーとはならないわけです。
カシオが正常動作を保証している記法に準拠して、一番簡単に書き直すのなら、上記のコードの場合は
Dsz C
を
C-1→C:C=0⇒Break
に修正することになり、これで万全なプログラムとなります。
この問題については、改めて別エントリーにまとめていますので、ご参照ください。
⇒ 楽屋裏 - Dsz によるループ脱出
これで、Chapter 2 を終了します。
初級者の方は、次に Chapter 7 Casio Basic入門 38 へ進むことを勧めます。
Chapter 7 の次には Chapter 8 Casio Basic入門 43 へ進んでください。
次の Chapter 3 では、論理演算、配列変数、サブルーチンの使いこなしなどを紹介する予定です。
これまでに、CasioBasicに備わっている入力命令:? や、リアルタイム入力ができる Getkey コマンドを紹介しています。Getkey については、使いこなしを紹介してきましたが、入力命令 ? の使い方はあまり紹介していません。
と言うのも、入力命令:? が使いにくいからです。画面の中の好きな位置で入力させることはできないし、入力した結果は勝手に改行して表示される、などと、その動作が自由にならないからです。
Locate コマンドを使えばとても柔軟に出力できるのに、残念ながら柔軟な入力コマンドがありません。そこで、Chapter 3 では自由自在に入力できる方法を紹介する予定です。特製の入力コマンドをサブルーチンで作ってしまおうと言う計画です。
つづく...
⇒ CasioBasic入門15 / 目次
応援クリックをお願いします。励みになるので...