fx-5800P【ゲーム】もぐら叩き(5)

fx-5800Pでもぐら叩き
e-Gadget


fx-5800P【ゲーム】もぐら叩き(4) の続き


以下の機能を追加して、より遊べるゲームに改造することにする。

1) 間違ったモグラを叩いた時にペナルティーとしてLIFEを減らす
2) たまには、モグラでないものが顔を出し、それを叩くとペナルティーとしてLIFEを減らす



今回追加及び削除した部分を、赤文字で以下に示す。


fx-5800P用プログラム
もぐら叩きゲーム 改造版
==================
10→DimZ              :変数の初期化
35→Z[1]:36→Z[2]
37→Z[3]:21→Z[4]
22→Z[5]:23→Z[6]
31→Z[7]:32→Z[8]
33→Z[9]
17→D:25→E:0→P

For 1→B To 3           :初期画面表示
Locate 1,B,"[ ][ ][ ]"
Next
Locate 11,2,"PRIZE"
Locate 12,3,P
Locate 1,4,"LIFE:"
Locate 6,4,L

Lbl 0                  :ゲームメインループ(始まり)

RanInt#(1,9)→T         :モグラ出現のタイミングと座標
RanInt#(1,3)→X
RanInt#(1,3)→Y
RanInt#(1,4)→Z
9+X-3Y→N
If P≧200 And Z=0
Then 1→Q
Else 0→Q:IfEnd


Lbl 1                  :モグラ出現のカウントタイマー
Dsz T
Goto 1

0→C                  :モグラを出現させ、叩くまでの処理
If Q=1:Then
Locate 3X-1,Y,"X"
Else
Locate 3X-1,Y,"O"
IdEnd
Do
Isz C
If C>E:Then
P-25→P
Break:IfEnd
Getkey→K
LpWhile K=0
Locate 3X-1,Y," "

If Q=0:Then            :モグラを叩いた後の判定
If C≦D And K=Z[N]
Then:P+20-C→P
Else L-1→L
If C>E:Then
P-25→P:IfEnd
Else
If C≦E:Then
L-1→L:IfEnd

IfEnd

Locate 12,3,"      "       :リアルタイム表示
Locate 12,3,P
Locate 6,4,L

L⇒Goto 0              :ゲームメインループ(終わり)

0→DimZ               :ゲーム終了時の処理
For 1→A To 3
For 1→B To 3
Locate 3B-1,A,"Q"
Next:Next
Locate 1,2,"GAME OVER"
==================


変更・追加点の説明:

1.偽モグラを "X" で表示し、PRIZEが200以上の時、さらに RanInt#(0,4)→Z で Zが0になった時に、偽モグラを出現させる。偽モグラ出現率は約20%。偽モグラ出現時は、フラグQを1にする。

2.タイムアウト時のPRIZE減点処理を、Do ループの外に出した。偽モグラ出現時はタイムアウトにする必要がある。偽モグラかどうかの判定を Do ループ内で行うと、スピードが遅くなるのて、偽モグラかどうか、および減点処理を Do ループの外に出したわけだ。

3.間違ったモグラや偽モグラを叩いた時に、L-1→L を処理してLIFEを1つ縮める。

コードを追いかけると、上記の具体的な処理が分かると思う。軽微な変更で、簡単に機能追加できた。


持ち点20点、タイムアウト条件やその他の設定は、現在のところ固定されている。これらを変更することで、難易度を変更できる。


そこで、難易度を変更できるようにして、一旦ゲームの完成としようと思う。


つづく...

⇒ もぐら叩き(6)



応援クリックをお願いします。励みになるので...

人気ブログランキングへ


FC2ブログランキングへ



keywords: fx-5800Pゲームプログラミングもぐら叩きプログラム関数電卓

リンク集 | ブログ内マップ
関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

fx-5800P【ゲーム】:もぐら叩き(4)

fx-5800Pでもぐら叩き
e-Gadget


fx-5800P【ゲーム】:もぐら叩き(3)の続き...

今回で暫定的にゲームを完成させ、次回以降でゲームのクオリティを上げてゆく。


前回までに作ったプログラム:


10→DimZ
35→Z[1]:36→Z[2]
37→Z[3]:21→Z[4]
22→Z[5]:23→Z[6]
31→Z[7]:32→Z[8]
33→Z[9]

17→D:0→P
For 1→B To 3
Locate 1,B,"[ ][ ][ ]"
Next
Locate 11,2,"PRIZE"
Locate 12,3,P
Locate 1,4,"LIFE:"
Locate 6,4,L

Lbl 0           : 一番下のGoto 0からジャンプしてくる

RanInt#(1,4)→T
RanInt#(1,3)→X
RanInt#(1,3)→Y
T^(3)→T
9+X-3Y→N

Lbl 1
Dsz T
Goto 1


0→C
Locate 3X-1,Y,"O"

Do
Isz C
Getkey→K
LpWhile K≠Z[N]

Locate 3X-1,Y," "


If C≦D:Then
P+20-C→P
Else
L-1→L
IfEnd

Locate 12,3,"    "
Locate 12,3,P
Locate 6,4,L

L⇒Goto 0        : 上のLbl 0へジャンプして繰り返す、L=0 ならジャンプせず終了
0→DimZ



ここまで作って遊んでみると、気に入らない点が出てきた。モグラへの反応をしないでいると、プログラムはモグラを叩くのをズ~ッと待っているのだ。これではゲームとしてはマズイ。

プログラムで何が起きているかと言えば、入力キーの判定を行う Do ~ LpWhileループ でモグラを叩くためのキー入力を待ち続けている状態になっている。

そこで、タイムアウト機能を追加して、モグラを叩くキー入力を少し待って、入力が無い時には、このループから強制的に出て、次の処理へ進むように変更しようと思う。


そこで、改めてゲームの仕様を変更することにした。



10.ゲームの暫定仕様を変更する

タイムアウトの基準を変数Eに格納しており、タイムアウトした時はPRIZE(総合点)とLIFEを供に減らすことにする。

1)持ち点について:
モグラを1匹相手にするたびに、持ち点をもらう: 持ち点 = 20とする
2)COSTについて:
COST は変数 C に格納する(偶然だが、既にそうなっている、ちょっとコジツケ)
モグラを速く叩くと COST が小さくなり、遅いとCOSTが大きくなる
3)得点について:
モグラへの反応が速ければ得点が多くなり、遅ければ得点は少ない
モグラ1匹を叩く際、最初にもらった持ち点=20から C を引いた結果が得点
得点: 20-C
・C≦17 の時(モグラへの反応が速い時): 得点 = 20-C を得る
C>18 の時(モグラへの反応が遅い時): 得点 = 0、さらに LIFE が1つ下がる
この境目の17を変数Dに格納して、判定させるようにする。
4)PRIZE(総合点)について:
獲得した得点を足し合わせたものを PRIZE(総合点)とする。
PRIZE を変数 P に格納する
PRIZE をリアルタイム表示する
PRIZEの計算: P+20-C→P
5)Time-out処理について:
モグラへの反応が非常に遅ければ、モグラが引っ込み、PRIZEとLIFEの双方が減らされる。
・タイムアウト条件: E=25
・C>E の時(モグラへの反応が非常に遅い時): 総合点が25点減り(P-25→P)、LIFEが1減る(L-1→K)
6)LIFE(ゲーム継続権利)について
ゲーム開始時に、LIFE をもらう: LIFE=5 とする
LIFE を変数 L に格納する
LIFE をリアルタイム表示する
C>18 の時(モグラへの反応が遅い時): LIFE が1減る
LIFE が0になると、ゲーム終了



11.タイムアウト処理をコードに反映させる

モグラが叩かれる判定処理は、Do ~ LpWhileループで処理している。

Do
Isz C
Getkey→K
LpWhile K≠Z[N]


このループ内で、C がE (=25) を超える場合は、強制的にループを抜ける処理を書く。

fx-5800Pでは、ループから強制的に外に出る時に役立つコマンドが準備されている。Breakコマンドだ。Breakコマンドは、Do ~ LpWhileループ、While ~ WhileEndループ、For ~ Next ループで使える。

では、タイムアウト時のコードを書く。

Do
Isz C
If C>E:Then
P-25→P
Break:IfEnd

Getkey→K
LpWhile K≠Z[N]


追加した部分を赤い文字で示す。


さて、Do ループを抜けると、その下に続いている処理が実行される。その部分を見てみる。


Locate 3X-1,Y," "

If C≦D:Then
P+20-C→P
Else
L-1→L

IfEnd

Locate 12,3,"    "
Locate 12,3,P
Locate 6,4,L


L⇒Goto 0            : 上のLbl 0へジャンプして繰り返す、L=0 ならジャンプせず終了
0→DimZ


この部分は、特に変更が不要なことがわかる。

オレンジ色のコードに注目してみると、Do ループから抜けた後、Cは25よりも大きいのだから、If C≦D の条件には 合わない。従って、Elseへ移って、L-1→L が実行される。つまり、LIFEが1つ減らされる。

このままで、仕様通りの処理ができる。

ところで、タイムアウトの条件を決めるEの初期化処理を、忘れずに行っておく。変数DやPの初期化を行っているプログラム冒頭部分に、25→E を追加しておく。



12.暫定仕様のプログラムを仕上げる

ゲームが終了した時、やはり GAME OVER の表示や、ちょっとした動きが欲しくなった。

そこで、次のような表示を考えて、その機能を追加してみる。


 [  ][  ][  ]
 [  ][  ][  ] PRIZE
 [  ][  ][0]  1618
 LIFE:0


LIFEがゼロになった。ここでゲーム終了となる。

先ずは、口を手で押さえてウフフ笑いのモグラ「Q」が、次々に全部の穴から顔を出させる。


 [Q][Q][Q]
 [Q][Q][Q] PRIZE
 [Q][Q][Q]  1618
 LIFE:0


続けて、GAME OVER の表示が出る。

 [Q][Q][Q]
 GAME OVER PRIZE
 [Q][Q][Q]  1618
 LIFE:0




この処理を追加するには、モグラの穴に Q を順次表示させ、続いて "GAME OVER"を表示すれば良い。

For 1→A To 3
For 1→B To 3
Locate 3B-1,A,"Q"
Next:Next
Locate 1,2,"GAME OVER"



これで、暫定仕様がひとまず完成した。


10→DimZ
35→Z[1]:36→Z[2]
37→Z[3]:21→Z[4]
22→Z[5]:23→Z[6]
31→Z[7]:32→Z[8]
33→Z[9]
17→D:0→P

For 1→B To 3
Locate 1,B,"[ ][ ][ ]"
Next
Locate 11,2,"PRIZE"
Locate 12,3,P
Locate 1,4,"LIFE:"
Locate 6,4,L

Lbl 0

RanInt#(1,4)→T
RanInt#(1,3)→X
RanInt#(1,3)→Y
T^(3)→T
9+X-3Y→N

Lbl 1
Dsz T
Goto 1

0→C
Locate 3X-1,Y,"O"
Do
Isz C
If C>E:Then
P-25→P
Break:IfEnd
Getkey→K
LpWhile K≠Z[N]
Locate 3X-1,Y," "

If C≦D:Then
P+20-C→P
Else
L-1→L
IfEnd

Locate 12,3,"      "
Locate 12,3,P
Locate 6,4,L

L⇒Goto 0

0→DimZ
For 1→A To 3
For 1→B To 3
Locate 3B-1,A,"Q"
Next:Next
Locate 1,2,"GAME OVER"



13.ゲームで遊んでみる

作ったゲームで遊んでみた。徐々に上達してきて、1000 PRIZE 程度を出せるようになった。

ところで、我が家にはゲーマーが2人いるので、遊んで貰った。いきなり 3000 PRIZE 以上をたたき出した。そして評価を聞いてみたところ、もっとスピードが無いとつまらないと言う。

そこで、モグラの顔を出すタイミングを決める処理;

RanInt#(1,4)→T
T^(3)→T

の部分がスピードを落としている原因なので、以下のように変更しスピードアップさせた。

RanInt#(1,9)→T


そして、このスピードアップは満足してもらて、面白くなったと言う。そして、さらに遊んで貰ったところ、ついに30005 PRIZE をたたき出した。

現状では、5桁のPRIZEに対応していないので、PRIZEの値Pを表示する前の空白4個で埋める部分を、空白6個で埋めるように変更した。

ゲームらしくなってきた。



fx-5800P用プログラム
もぐら叩き 暫定仕様
==================
10→DimZ              :変数の初期化
35→Z[1]:36→Z[2]
37→Z[3]:21→Z[4]
22→Z[5]:23→Z[6]
31→Z[7]:32→Z[8]
33→Z[9]
17→D:0→P

For 1→B To 3           :初期画面表示
Locate 1,B,"[ ][ ][ ]"
Next
Locate 11,2,"PRIZE"
Locate 12,3,P
Locate 1,4,"LIFE:"
Locate 6,4,L

Lbl 0                  :ゲームメインループ(始まり)

RanInt#(1,9)→T         :モグラ出現のタイミングと座標
RanInt#(1,3)→X
RanInt#(1,3)→Y
9+X-3Y→N

Lbl 1                  :モグラ出現のカウントタイマー
Dsz T
Goto 1

0→C                  :モグラを出現させ、叩くまでの処理
Locate 3X-1,Y,"O"
Do
Isz C
If C>E:Then
P-25→P
Break:IfEnd
Getkey→K
LpWhile K≠Z[N]
Locate 3X-1,Y," "

If C≦D:Then            :モグラを叩いた後の判定
P+20-C→P
Else
L-1→L
IfEnd

Locate 12,3,"      "       :リアルタイム表示
Locate 12,3,P
Locate 6,4,L

L⇒Goto 0              :ゲームメインループ(終わり)

0→DimZ               :ゲーム終了時の処理
For 1→A To 3
For 1→B To 3
Locate 3B-1,A,"Q"
Next:Next
Locate 1,2,"GAME OVER"
==================


fx-5800Pでは、上のような注記(コメント)を挿入することが出来ないので、上の注記は実際に入力していない。注記を見てみると、スッキリと処理が軽くなるように作ったことが、分かると思う。


このゲームを作るきっかけは、電卓でどの程度のアクションゲームが出来るかと言う興味からであったが、この程度の遊べるゲームなら作れることが分かった。



より面白いゲームにするための我が家のゲーマー達からのアドバイスは、以下のようなものだった。

1) 間違ったモグラを叩いた時にペナルティーとしてLIFEを減らす
2) たまには、モグラでないものが顔を出し、それを叩くとペナルティーとしてLIFEを減らす


このようにすると、より緊張感が増すので、面白くなる....なるほど、確かにそうだ(´д`)


ここまできたので、もう少し面白くしようと思う。



まだ、つづく...

⇒ もぐら叩き(5)



応援クリックをお願いします。励みになるので...

人気ブログランキングへ


FC2ブログランキングへ



keywords: fx-5800Pゲームプログラミングもぐら叩きプログラム関数電卓

リンク集 | ブログ内マップ

関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

fx-5800P【ゲーム】:もぐら叩き(3)

fx-5800Pでもぐら叩き
e-Gadget


【2013/11/24、誤植を修正】


fx-5800P【ゲーム】:もぐら叩き(2)
の続き...

前回までに作ったプログラム:

10→DimZ
35→Z[1]:36→Z[2]
37→Z[3]:21→Z[4]
22→Z[5]:23→Z[6]
31→Z[7]:32→Z[8]
33→Z[9]

For 1→B To 3
Locate 1,B,"[ ][ ][ ]"
Next

Lbl 0

RanInt#(1,4)→T
RanInt#(1,3)→X
RanInt#(1,3)→Y
T^(3)→T
9+X-3Y→N

Lbl 1
Dsz T
Goto 1

Locate 3X-1,Y,"O"

Do
Getkey→K
LpWhile K≠Z[N]


Locate 3X-1,Y," "

[ 新たなコードは、主にここに追加する ]

Goto 0
0→DimZ


軽くおさらいすると、Lbl 0 ~ Goto 0 の間で処理が繰り返される、ループ構造になっている。Do ~ LpWhile のループで叩かれたモグラの判定を行い、命中した時にこのループを抜けて、下へ処理が進む構造だ。

従って、今後追加するコードは、主に判定結果に応じた処理になるので、上に注記したように Do ~ LpWhile ループの後から Goto 0 の前までの間に、新たな処理を追加することになる。


もぐら叩きは反応の速さを競うゲームだから、反応速度を測定する機能が不可欠になる。先ずは、反応速度を調べる機能を追加する。

次に、その結果に基づいて、プレイヤーの頑張りを点数に置き換える機能が必要になる。加えて、ゲーム終了の条件も作らなくてはいけない。ユーザーのプレイをちょっと妨害する機能があれば、さらに面白くなりそうだ。


このあたりでゲーム設計をきちんと決めておく必要がありそうだ



6.モグラが顔を出してから叩くまでの反応時間を測る

プレイヤーの頑張りを点数に反映させるために、モグラが顔を出してから、叩いて命中させるまでの反射時間の測定をできるだけ簡潔な処理で組み込みたい。

モグラが顔を出し、叩かれて顔を引っ込めるまでは、

Locate 3X-1,Y,"O"
Do
Getkey→K
LpWhile K≠Z[N]
Locate 3X-1,Y," "


この部分が制御している。プレイヤーの反射時間はこのループが回る回数に相当するわけだ。


そこで、上のDo~LpWhile ループの中に、

Isz C

を追加する。

Isz C は、本来はCを1つづつ増やしながら(インクリメントしながら)Cが0になったとき、次の処理をスキップして、次の次の処理へジャンプするコマンドだ。但し、インクリメントだけを行う時にも使える。

但しCがゼロにならないことが大前提になる。もし何かの都合で、Cが0になってしまうと、次の次のコマンドへジャンプしてしまい、予期せぬ動作をするから、ここは注意が必要だ。従ってCの初期値は0以上でないといけない。

Isz Cは、先にCを1つ増やしてから(インクリメントしてから)、ジャンプするかどうかの判定を行うので、最初にCが0であっても問題はない。しかし万一Cが-1の場合は、1回インクリメントするとC=0となってしまい、ジャンプするので、必要な処理が飛ばされるので、プログラムは誤動作してしまう。

Isz C の代わりに、C+1→Cとしても良い。全く問題ない。ただ Isz C の方が動作速度が速いように感じているので、ここではIsz C を使うことにする。Isz C の処理速度については、まだきちんと検証してないことを付け加えておく。
ここで忘れてはいけないのが、Do~LpWhileループに入るまでに、変数Cを初期化して0にしておくことだ。

0→C
Locate 3X-1,Y,"O"
Do
Isz C
Getkey→K
LpWhile K≠Z[N]
Locate 3X-1,)," "



これで、プレイヤーの反射時間が C で分かるようになった。Cが小さければ速く反応したことになるし、Cが大きければ時間がかかったことになる。

10→DimZ
35→Z[1]:36→Z[2]
37→Z[3]:21→Z[4]
22→Z[5]:23→Z[6]
31→Z[7]:32→Z[8]
33→Z[9]

For 1→B To 3
Locate 1,B,"[ ][ ][ ]"
Next


Lbl 0             : 一番下のGoto 0からジャンプしてくる

RanInt#(1,4)→T
RanInt#(1,3)→X
RanInt#(1,3)→Y
T^(3)→T
9+X-3Y→N

Lbl 1
Dsz T
Goto 1


0→C             : 追加点
Locate 3X-1,Y,"O"

Do
Isz C             : 追加点
Getkey→K
LpWhile K≠Z[N]

Locate 3X-1,Y," "


[ 新たなコードは、主にここに追加する ]


Goto 0            : 上のLbl 0へジャンプして、繰り返す
0→DimZ



[ 新たなコードは、主にここに追加する ]のところに、Locate 11,3,C を追加して、Cの値をリアルタイム表示させて、このプログラムを実行して遊んでみると、一回モグラを叩くたびにCが10程度であった。



7.ゲームの暫定仕様を決める

実際にプログラムを走らせてみて、1回もぐらを叩くのにCが10程度になったことを参考にして、ゲームの暫定仕様を決めようと考えた。

そもそも、モグラを素早く退治すれば得点を大きくしないといけない。そこで考えたのが持ち点制。持ち点から反応時間 C を引いたものを得点とすれば、速く反応した方が得点が大きくなる。今のプログラムだと、もぐらを叩くのにC=10程度なので、持ち点を20とした。

[ 得点 ] = 20-C

一回あたり、10点程度が得られる。

この得点計算だと、Cが20を超えるとマイナス得点になって面白そうだが、それではノンビリと待ちすぎなように思ったので、Cが18以上になると、もう得点を与えないようにした。マイナスにはならないが、増えない。このほうが面白そうだ。


次に考えたのが、一回の得点は浮き沈みがあるから、それを合計してゲーム全体の点数にした方が良さそうだと言うこと。そしてその総合点をリアルタイムで表示すると楽しそうだ。総合点が大きい方がよいと言うことだ。


但し、ゲームが延々と続くのは退屈だし面白くない。どうやってゲームを終わらせるかをチョット考えた。戦闘力が高くてもスタミナが無いとそれを発揮できないと言うのがゲームの定番だ。攻撃を受けてスタミナがゼロになったら死んでしまってゲーム終了と言うのが多い。

そこで、LIFEを設定して、これが減って行きゼロになったらゲーム終了にしよう。LIFEを減らすのは、Cが18以上になった時にしてみた。得点は減らないが、確実に寿命が縮むと言うのは良さそうだ。最初に与えるLIFEは、取りあえず 5 にした。


そんな感じで、脳内シミュレーションしてみた。なんとなくゲームらしくなったかな?


具体的に、以下のように COST、PRIZE、LIFE を導入して、ゲーム進行を定義した。
1)持ち点について:
モグラを1匹相手にするたびに、持ち点をもらう: 持ち点 = 20とする
2)COSTについて:
COST は変数 C に格納する(偶然だが、既にそうなっている、ちょっとコジツケ)
モグラを速く叩くと COST が小さくなり、遅いとCOSTが大きくなる
3)得点について:
モグラへの反応が速ければ得点が多くなり、遅ければ得点は少ない
モグラ1匹を叩く際、最初にもらった持ち点=20から C を引いた結果が得点
得点: 20-C
・C≦17 の時(モグラへの反応が速い時): 得点 = 20-C を得る
C>18 の時(モグラへの反応が遅い時): 得点 = 0、さらに LIFE が1つ下がる
この境目の17を変数Dに格納して、判定させるようにする。
4)PRIZE(総合点)について:
獲得した得点を足し合わせたものを PRIZE(総合点)とする。
PRIZE を変数 P に格納する
PRIZE をリアルタイム表示する
PRIZEの計算: P+20-C→P
5)LIFE(ゲーム継続権利)について
ゲーム開始時に、LIFE をもらう: LIFE=5 とする
LIFE を変数 L に格納する
LIFE をリアルタイム表示する
C>18 の時(モグラへの反応が遅い時): LIFE が1減る
LIFE が0になると、ゲーム終了

あまり複雑だと、一度に機能を追加するのが面倒なので、先ずはこの程度で機能を組み込むことにする。



8.得点の機能を組み込む

得点加算の機能を追加する。

上の仕様では、C≦17 の時に 20-C の得点が得られる。そうでない場合は、得点はなくて、さらに LIFE が1つ減る。この判定の境目の17を、変数Dに入れておく。こうすると、あとで条件を変更するのが楽だ。

これをコードに表現すると、

If C≦D:Then
P+20-C→P
Else
L-1→L
IfEnd


但し、Pを0で初期化しておく必要がある。

0→P

これは、ゲームの最初の部分に置く。3x3 のモグラの穴を表示する前に書くことにする。

変数Dの初期化も、同じところに書いておく。

17→D



さて、PEIZE(総合点)とLIFEをリアルタイム表示する仕様なので、表示部分も追加しておく。

 [  ][  ][  ]
 [  ][  ][  ] PRIZE
 [  ][  ][0]  0
 LIFE:5


こんな感じの表示にしてみる。

先ずは、ゲームが始まった時の表示は、3x3 のモグラの穴の表示に続けて書く。

Locate 11,2,"PRIZE"
Locate 12,3,P

Locate 1,4,"LIFE:"
Locate 6,4,L



ゲーム進行時のリアルタイム表示は、

Locate 12,3,P
Locate 6,4,L

となる。

これらの表示は、Cの判定が終わってそれをスグに反映して表示するので、上の If C≦D:Then のブロックのスグ下に書けば良い。

If C≦D:Then
P+20-C→P
Else
L-1→L
IfEnd
Locate 12,3,P
Locate 6,4,L



ところが、実はチョット問題がある。

例えば、PRIZEが105となると、

 [  ][  ][  ]
 [  ][  ][  ] PRIZE
 [  ][  ][0]  105
 LIFE:5


次に、PRIZEが90になった場合、

 [  ][  ][  ]
 [  ][  ][  ] PRIZE
 [  ][  ][0]  905
 LIFE:5


となってしまう。

1桁目の「5」が残っているのだ。

そこで、PRIZEの値を表示する前に、一旦空白を書き込んで「105」を消しておけば良い。空白は書き込めるだけ書き込めば安全なので、今回は4個の空白を書き込む。

Locate 12,3,"    "

そこで、上のコードを以下のように修正する。

If C≦D:Then
P+20-C→P
Else
L-1→L
IfEnd
Locate 12,3,"    "
Locate 12,3,P
Locate 6,4,L




少しづつ機能追加をしてゆけば楽だ。しかし、変数の初期化や初期表示は、肝心のコードとは離れたところに書くので、これを忘れがちだ。


ここで、一旦プログラムのコードをまとめる。


10→DimZ
35→Z[1]:36→Z[2]
37→Z[3]:21→Z[4]
22→Z[5]:23→Z[6]
31→Z[7]:32→Z[8]
33→Z[9]

17→D:0→P
For 1→B To 3
Locate 1,B,"[ ][ ][ ]"
Next
Locate 11,2,"PRIZE"
Locate 12,3,P
Locate 1,4,"LIFE:"
Locate 6,4,L

Lbl 0             : 一番下のGoto 0からジャンプしてくる

RanInt#(1,4)→T
RanInt#(1,3)→X
RanInt#(1,3)→Y
T^(3)→T
9+X-3Y→N

Lbl 1
Dsz T
Goto 1


0→C
Locate 3X-1,Y,"O"

Do
Isz C
Getkey→K
LpWhile K≠Z[N]

Locate 3X-1,Y," "


If C≦D:Then
P+20-C→P
Else
L-1→L
IfEnd

Locate 12,3,"    "
Locate 12,3,P
Locate 6,4,L


Goto 0            : 上のLbl 0へジャンプして、繰り返す
0→DimZ


赤い文字が、今追加した部分だ。



9.ゲーム終了機能を追加する

LIFEがゼロに、つまり L=0 になると、Goto 0 をスキップして、処理をその下へ進めるように、コードを書き換える。

fx-5800P などのカシオの電卓には、それらに特有な独特な条件分岐コマンド「⇒」がある。これを使う。

取扱説明書にあるコマンドの例が分かりやすいので、転載する。

Lbl 1
?→A
A≧0 ⇒ √ ̄(A)◢:Goto 1


負の数の平方根はとれないのでエラーになる。
そこで、平方根を取るAが正か負かを先に調べて負でないなら平方根の計算をする必要がある。

このプログラム例では、⇒ の左が正しい(真)なら、次の処理を行い、正しくない(偽)なら、次の次までジャンプする機能をうまく使っている。

A がゼロ以上(負でない)なら、⇒ の次の処理「√ ̄(A)」を実行し、A がそうでないなら、次の次の処理 Goto 1 へジャンプする。

さて、取扱説明書に書いていないが、次のような使い方もできる。

Lbl 1
?→A
A⇒1÷A◢:Goto 1


これは、1÷A を計算するプログラムだが、A = 0 だと割り算できない、と言うかしてはいけない。もしA がゼロの時に1÷A を計算させるとエラーになる。そこで、A がゼロの時は、次の処理をスキップして、次の次の処理へジャンプさせる。これが上のプログラムだ。

A⇒1÷A◢:Goto 1

⇒ の左には変数だけがある。このように使う時、A がゼロ以外の時「真」となり、A がゼロの時「偽」となる。⇒ にはこのような性質がある。この性質は取扱説明書には書いていない。

この性質は、If A:Then...、Do ~ LpWhile A、While A ~ WhileEnd などでも使えるので、便利なことがある。



今のプログラムに話を戻すと、

プログラムコードの最後から2行目の Goto 0 を 

Goto 0
0→DimZ




L⇒Goto 0
0→DimZ


と書き換えるだけで、目的が達成できる。

L がゼロでない時は「真」なので、⇒ の次の Goto 0 が実行される。

もし、L がゼロになると「偽」になるので、⇒ の次の次の処理へジャンプする。つまり Goto 0 をスキップして、次の処理 0→DimZ へジャンプして、プログラムが終了する。

⇒ コマンドは、実に便利なコマンドで、色々な局面で多用できるので、覚えておくと便利だ。



暫定仕様の機能を組み込んだプログラムをまとめると、以下のようになる。

10→DimZ
35→Z[1]:36→Z[2]
37→Z[3]:21→Z[4]
22→Z[5]:23→Z[6]
31→Z[7]:32→Z[8]
33→Z[9]

17→D:0→P
For 1→B To 3
Locate 1,B,"[ ][ ][ ]"
Next
Locate 11,2,"PRIZE"
Locate 12,3,P
Locate 1,4,"LIFE:"
Locate 6,4,L

Lbl 0             : 一番下のGoto 0からジャンプしてくる

RanInt#(1,4)→T
RanInt#(1,3)→X
RanInt#(1,3)→Y
T^(3)→T
9+X-3Y→N

Lbl 1
Dsz T
Goto 1


0→C
Locate 3X-1,Y,"O"

Do
Isz C
Getkey→K
LpWhile K≠Z[N]

Locate 3X-1,Y," "


If C≦D:Then
P+20-C→P
Else
L-1→L
IfEnd

Locate 12,3,"    "
Locate 12,3,P
Locate 6,4,L

L⇒Goto 0            : L=0の時Goto 0をスキップしてゲーム終了
0→DimZ




つづく...

⇒ もぐら叩き(4)




応援クリックをお願いします。励みになるので...

人気ブログランキングへ


FC2ブログランキングへ



keywords: fx-5800Pゲームプログラミングもぐら叩きプログラム関数電卓

リンク集 | ブログ内マップ
関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

fx-5800P【ゲーム】:もぐら叩き(2)

fx-5800Pでもぐら叩き
e-Gadget


fx-5800P【ゲーム】:もぐら叩き(1)の続き...

前回までに作ったプログラム:

For 1→B To 3
Locate 1,B,"[ ][ ][ ]"
Next

Lbl 0

RanInt#(1,4)→T
RanInt#(1,3)→X
RanInt#(1,3)→Y
T^(3)→T

Lbl 1
Dsz T
Goto 1

Locate 3X-1,Y,"O"

Goto 0



このプログラムは、Lbl 0 と Goto 0 の間でループにして、ランダムな時間とランダムな位置にモグラの顔を出させる動作を繰り返す。

このプログラムを実行すると、モグラが顔を一旦出すと、二度と引っ込まない。そのうち全ての穴がモグラで一杯になって、それ以上の変化がなくなる。

モグラを引っ込める(=消す)処理を書いていないから、当然ではある。顔を出したモグラをく叩いた(命中した)かどうかを判定する処理を追加し、そのタイミングでモグラを消す処理を追加するつもりだ。

消す処理は簡単だ。モグラは Locate 3X-1,Y,"O" で表現した。消すには、同じところに空白 " " を書き込めば良い。

Locate 3X-1, Y, " "


では、次へ進む...



5.モグラ命中の判定ロジックを考える

さて、ピョコピョコ顔を出すモグラは出来たが、これを叩いて、さらに命中したかどうかの判定を作れば、ゲームの動きの中心部分が完成だ。どのような理屈で、この判定ロジックを実現しようか...


モグラの穴を 3x3 の配列にしたのは、fx-5800Pの1~9の数字キーも 3x3 の並びになっていて、モグラの位置に対応した数字キーを押して、モグラを叩く動作にしようと考えているから...

 [  ][  ][  ]
 [  ][  ][O]
 [  ][  ][  ]


例えば、このモグラを叩いて命中させるには、[6]キーを押せばよいわけだ。

数字キーの並びは、このようになっている。

 [7][8][9]
 [4][5][6]
 [1][2][3]


そこで、モグラの位置を決める1組の数 X と Y に対して、1~9の数字を対応させる法則が分かれば、つまり式が見つかれば話は簡単になる。

この数字キーの並び方は、電卓やパソコンのテンキーではみな同じになっている。一方、携帯を含めた電話機の数字の並びは異なっている。ちょっと調べてみた。

パソコンのテンキーの配列は ISO (国際標準委員会)で決めた規格に従っており、電卓はその流れを汲んでいる。一方、電話機はCCITT (国際電信電話諮問委員会)の規格に従っていて、それらの規格が異なっていると言う背景がある。電話機についてはアメリカのAT&Tが作ったプッシュホンの配列を追認したようだ。

パソコンについてはよく使う0や1が下に来るようになっていると聞くが、おそらくそのような考えで作ったどこかの(多分アメリカの)メーカーの社内規格が標準規格として採用されたのだろうと勝手に想像している。

今作っているプログラムをスマホ上のプログラムに移植する時は、ソースコードの一部を変更する必要が出てくるわけだ。


1) モグラの位置に対応する数字キーを求める

fx-5800P は省電力が最優先事項だからCPUのクロックをかなり落としている筈で、そのためにプログラムの動作が遅くなっていると想像される。従ってアクションゲームを作るには、如何に少ない手順で処理を行うかがポイントだと思う。

そこで、モグラの位置を数字キーに関連付けるのも、数式1つで解決し、If 文などの条件分岐を使わない方法にしたい。

まず以下のようなメモを書いてみた。

X Y  N
------------
1 1
1 2
1 3
------------
2 1
2 2
2 3
------------
3 1
3 2
3 3
------------


X と Y の全ての組み合わせを書き出した。続いてそれぞれのX と Y にに対応する数字キーを、Nの下に書き込んでみた。

X Y  N
------------
1 1  7
1 2  4
1 3  1
------------
2 1  8
2 2  5
2 3  2
------------
3 1  9
3 2  6
3 3  3
------------


これを、じぃ~っと眺めていると、ひらめいた\(^_^)/

9+X-3Y = N

検算してみると、確かに正しい( ^o^)ノ

モグラの座標から対応する数字キーNへの簡潔な公式が見つかった。


2) 数字キーの判定 = モグラ命中の判定

押されたキーを知るには、Getkeyコマンドを使う。

余談だが、fx-5800Pに限らず、最近のカシオ製のグラフ関数電卓 fx-CG20 も Getkeyコマンドを備えており、fx-986GII と fx-CG20 のキーコードと完全んい互換性がある。ただし、これら2機種のキーコードは fx-5800P と互換性はない。参考までに、シャープのグラフィック関数電卓 EL-9900では、取扱説明書を読む限りではあるが、テンキーと矢印キーのみを取得できる KEY コマンドはあるが、他のキーを調べる手段は提供されていないようだ。

さて、[1]キーが押された時、Getkey が 1を返してくれたら話は簡単なのだが、実際はそう都合よくなっていない。

fx-5800Pの Getkey は、以下のような2桁のキーコードを返す。

[1] ⇒ 35
[2] ⇒ 36
[3] ⇒ 37
[4] ⇒ 21
[5] ⇒ 22
[6] ⇒ 23
[7] ⇒ 31
[8] ⇒ 32
[9] ⇒ 33

数字キーの数とキーコードには、簡単な式で表現できる関連性が見つからない。今度は、いくらじぃ~っと眺めていても、分からない。

そこで、数字キーの1~9の数字とキーコードを強引に関連付けるために、配列変数を使って、Nのキーコードを Z[N] に入れて初期化しておく。具体的には、

35 を Z[1] に
36 を Z[2] に
37 を Z[3] に
21 を Z[4] に
22 を Z[5] に
23 を Z[6] に
31 を Z[7] に
32 を Z[8] に
33 を Z[9] に

入れて、初期化すれば良い。つまり、配列変数 Z[N]N にテンキーの数字を入れると Z[N] がキーコードが返すようにする作戦だ。


以上をまとめると、モグラ命中の判定は以下のような流れになる。

乱数でモグラの位置を決める ⇒ X, Y のペアが決まる。
          ↓
X, Y のペアから N が決まる ⇒ 9 + X -3Y = N
          ↓
N に対応するキーコードが分かる ⇒ Z[N]
          ↓
実際に押された数字キーのキーコードと Z[N] を比較する ⇒ 判定



キーコードを取得する時は、

押されたキーを確実に拾うためにループをグルグル回しておいて、探しているキーが入力されない限りループを回し続け、目的のキーが入力された時にループを終了して、次へ進む...


といった処理が Casio Basic では良さそうだ。上の流れに従ってコードを書くと...


[ Z[1]~Z[9]をキーコードで初期化するコードをここに書く ]
RanInt#(1,3)→X
RanInt#(1,3)→Y
9+X-3Y→N

Do
Getkey→K
LpWile K≠Z[N]



ところで、配列変数 Z[ ] を使う時は、変数の確保と初期化が必要だ。今回は、10→DimZ として10個の配列変数を確保する。本来は9個確保すれば良いが、キリの良いところで、10個にした。深い意味は無い。

配列変数が確保されると、全て0に初期化されるので、改めて対応するキーコードを入れておく必要がある。なおプログラムの最後で、確保した配列変数を解放しておく。解放するには、0→DimZ と書く。

ここまでをまとめると、以下のようなコードになる。

10→DimZ
35→Z[1]:36→Z[2]
37→Z[3]:21→Z[4]
22→Z[5]:23→Z[6]
31→Z[7]:32→Z[8]
33→Z[9]

For 1→B To 3
Locate 1,B,"[ ][ ][ ]"
Next

Lbl 0

RanInt#(1,4)→T
RanInt#(1,3)→X
RanInt#(1,3)→Y
T^(3)→T
9+X-3Y→N

Lbl 1
Dsz T
Goto 1

Locate 3X-1,Y,"O"

Do
Getkey→K
LpWhile K≠Z[N]

Locate 3X-1,Y," "

[ 新たなコードは、主にここに追加する ]

Goto 0
0→DimZ



押されたキーが、正しいキーでないと Do~LpWhileのループが回り続ける。つまり、モグラに命中した時に初めて、次の処理へ進むようにしている。

今回の冒頭で、判定処理の後に、顔を出したモグラを消す処理を追加すると書いたように、上のコードには、Locate コマンドを用いてモグラを消す処理を追加してある。

叩いたモグラの判定処理までできた。今後、判定結果に応じた処理を追加してゆく。


さて、このプログラムを実行すると、モグラが顔を出して、それを叩いたらモグラが引っ込む、と言う動作を軽快に楽しめる。この程度の処理では、電卓といえどもサクサク動いていてくれる。


つづく...

⇒ もぐら叩き(3)



応援クリックをお願いします。励みになるので...

人気ブログランキングへ


FC2ブログランキングへ



keywords: fx-5800Pゲームプログラミングもぐら叩きプログラム関数電卓

リンク集 | ブログ内マップ
関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

fx-5800P【ゲーム】:もぐら叩き(1)

fx-5800Pでもぐら叩き
e-Gadget


fx-5800Pでモグラ叩きゲームを作ってみる。


きっかけは、カウントタイマーを色々作ってみたことだ。

Lbl 1
Dsz C
Goto 1


ふむ、これが最も軽く動きそうだ。

Dsz C の使い方は、Cを1減らして、0になったら次のコマンドをスキップして、次の次のコマンドへジャンプする、条件分岐の一種のコマンドだ。但し、単純にCをデクリメント(減らす)だけにも使える。

このソースコードは、Dsz の本来の使い方だ。予め1以上の数値を変数 C に格納しておくと、Goto 1 ~ Lbl 1の間をぐるぐる回りながら、Cを1つづつ減らしてゆく。いずれ C は0になる。0になったら、次のコマンドである Goto 1 をスキップして、さらに次のコマンドまでジャンプする。つまり、GOto 1 ~ Lbl 1のループを抜け出すわけだ。

Cの値を大きくすれば、ループは長い間回り続ける。つまり、カウントタイマーの時間制御はCの値で行う。



パソコンに比べて処理速度が遅い fx-5800Pでアクションゲームを作ろうとは思って折らず、実際作ったことも無かった。

ところが、ふと、モグラ叩きゲームを作ろうと思った。プログラム電卓だとどんな感じになるのか、ちょっと興味があった。



fx-5800P は表示にアルファベットしが使えず、日本語を使えない。
ゲームのタイトルは、MOGURA TATAKI と ローマ字でも良いが、ちょっと格好をつけて英語にした。「モグラ叩き」は英語で、Whack-a-Mole と言うようなので、プログラム名: Whack-a-Mole (ワッカモウ、と聞こえるのだ) と決定した。

いよいよプログラム作成開始だ。実際の私が考えたこと、作業したことを、順を追って、実況中継風にして、少しづつできあがるところを、紹介したいと思う。



0.プログラム作成の概略

先ず、必要になりそうな基本構成を考えてみた。

1) モグラ叩きの画面

2) モグラが顔を出す時の処理
  ・モグラが顔を出すランダムなタイミング作り
  ・モグラが顔を出すランダムな場所の決め方

3) とにかくモグラを叩いた時の処理
  ・命中したかどうかの判定方法

4) モグラに命中した時の処理
  ・顔を出してから命中するまでの時間測定
  ・一定時間内に命中した時の点数計算方法と表示
  ・タイムアウト時に次のモグラの顔を出す処理

5) ゲーム全体のチューニング


こんな感じで、少しずつ作ってみることにした。



1. 先ず、画面を作ってみた

 [  ][  ][  ]
 [  ][  ][  ]
 [  ][  ][  ]


この3X3の穴のどれかから、モグラが顔を覗かせるわけだ。
まぁ、こんな感じで良いだろう。
モグラは、O で表現すれば良さそう...


For 1→B To 3
Locate 1,B,"[ ][ ][ ]"
Next


このように書けばOK。




2.もぐらが頭を出すタイミングを作る

冒頭のカウントタイマーを使って、ランダムな時間差でタイミングを作る。

カウントタイマーは、以下を使う


Lbl 1
Dsz T
Goto 1


ここでは、変数に T を使う。タイマーの「T」だ。


ランダムな時間差を作るには、T にランダムな整数を格納すれば良い。そこで、fx-5800Pに備わっている「整数乱数発生関数」を使うことにする。

RanInt#(1,4)→T

さて、この関数の表記は、1~4までの整数をランダムに発生させるというものだ。発生する乱数は、1, 2, 3, 4 のいずれかだ。時間差の最小が1、最大が3になる。あまり時間差が無い。もっと大きな時間差があった方がゲームは面白いだろう。

この時間が短いと、アクションゲームとして忙しくなるが、変化が少ないので、飽きてしまいそうだ。速いだけではなくて、緩急の差を付けようと思った。

そこで、T x T x T = T3 としてみた。そうすると、1, 8, 27, 64 になる。時間差の最小が 7で、最大は 63となる。かなり劇的な時間差になった。プログラムでT3 は、T^(3)と書く。[ ^ ]記号を使う。

これで、ランダムに時間差を大きく変化させるカウントタイマーができた。

RanInt#(1,4)→T
T^(3)→T
Lbl 1
Dsz T
Goto 1


なお、ここの T の設定は、実際にゲームで遊んでみてからチューニングする時に、もう一度考えることにする。



3.モグラがランダムな位置に顔を出す処理を考える

 [  ][  ][  ]
 [  ][  ][O]
 [  ][  ][  ]


こんな感じで、「O」がモグラだ。

そこで、モグラの位置を、X と Y を使って、座標で決めることにする。
fx-5800P の画面は(一般にパソコンの画面も同じだが...)、原点が左上、X は右向き、Y は下向きに増えるように座標が決められている。モグラの位置もこの決まりに従うことにする。

上の例では、モグラの位置は X=3 (3列目)、Y=2 (2行目) となる。

つまり、X と Y と言う2つの数字が決まれば、モグラの位置が決まる。
なお、今は横3個、縦3個の穴なので、X = 1, 2, 3、Y=1, 2, 3 のいずれかになるようにする。

X と Y をランダムに決めるには、T と同じように 整数乱数関数を使う。
つまり、

RanInt#(1,3)→X
RanInt#(1,3)→Y 


とすると、モグラの顔が出るランダムな位置が決まる。



4.モグラが実際に顔を出す処理を作る

座標が決まっただけでは、実際にモグラが顔を出せない。

 [  ][  ][  ]
 [  ][  ][O]
 [  ][  ][  ]


モグラを「O」で表現する。
穴の並びが既に表示してあって、そこへモグラだけを追加表示したい。そこで、Locateコマンドを使って、特定の位置に文字を表示する。

つまり、

Locate A,B,"O"

と書く。

次に、この A と B をどうすれば良いかを考える。

モグラの位置は、プログラム上では、既に上で X と Y で決まるようにした。従って、実際のLocateコマンドで使う A と B を X と Y を使って表せば良いことになる。

A は横の並びを決めるのだった。

A = 3X -1
B = Y


これでよい。ちょっと考えて思いついたのでラッキーだ。

例えば、上のモグラの例だと、X=3、Y=2 なので、A= 8、B=2 となるから、モグラを表示するには、

Locate 3X-1,Y,"O"

と書けば良い。これは、1~3のどのような X と Y でも正しい。

以上をまとめると、ランダムな場所、なおかつランダムなタイミングで、モグラに顔をださせるソースコードは次のようになる。


For 1→B To 3
Locate 1,B,"[ ][ ][ ]"
Next
RanInt#(1,4)→T
RanInt#(1,3)→X
RanInt#(1,3)→Y
T^(3)→T
Lbl 1
Dsz T
Goto 1
Locate 3X-1,Y,"O"



このソースコードの先頭のモグラの穴の表示の直後に Lbl 0 を、最後に Goto 0 を追加して、実際に実行してみると、モグラがピョコピョコ顔を出すのが見られる。

私がfx-5800Pで初めて作った、動きのあるプログラムだ。


For 1→B To 3
Locate 1,B,"[ ][ ][ ]"
Next

Lbl 0

RanInt#(1,4)→T
RanInt#(1,3)→X
RanInt#(1,3)→Y
T^(3)→T

Lbl 1
Dsz T
Goto 1

Locate 3X-1,Y,"O"

Goto 0



つづく...

⇒ もぐら叩き(2)



応援クリックをお願いします。励みになるので...

人気ブログランキングへ


FC2ブログランキングへ



keywords: fx-5800Pゲームプログラミングもぐら叩きプログラム関数電卓

リンク集 | ブログ内マップ
関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

プログラミングが中学の技術家庭科で必修に

昨日、中学でプログラミングが必修になったと知った。⇒こちら

平成24年度からと言うので、既に始まっているわけだ。良いことだと思うが、一体何をどのように教えるのか、大変気になる。いままでの数学の教え方の延長線上にあるなら、教員の負担が増えるわりには効果が少ないのではないか、と大きなお世話を焼きたくなる。

一般人が手軽にプログラミングを行わず、ソフトウェア開発力で海外の遅れをとっているから、中学でプログラミングを必修にしようと考えたのだろう。

おそらく、最も安価に手に入り、手軽にプログラミングができる環境は、プログラム関数電卓だ。


電卓の用途

本ブログでは、今のところ fx-5800Pと言う国産のカシオ製品を開発プラットフォームとしてあげているが、内蔵されているプログラミング言語は、かなりの割り切りの産物だと感じている。これはPCでのプログラミングとの対比での感想である。

一方で関数電卓での計算を補助するためのプログラムなら、必要以上のものが仕様として揃っている。他社のプログラム関数電卓については、残念ながらまだよく知らない。見聞きしている範囲では、シャープなどの国産製品はカシオと大きく変わらないようだ。

カシオから手帳サイズでプログラム可能な関数電卓が最初に発売されたのが1979年。その後1981年にFX-602Pが、そしてプログラム互換性のある最後のモデル FX603Pが発売されたのが1990年だ。グラフ機能のある関数電卓を別として、FX-603Pの後継モデルが 2007年発売の fx-5800P となる。つまり17年間新モデルが登場していない。

国内他社製品についても似たようなもので、つまりプログラム関数電卓の国内市場は、新製品を投入するだけの広がりを見せていないようだ。カシオはプログラム機能のあるグラフ関数電卓を発売しているが、海外専用モデルがあることから分かるように海外市場を重視していることは明らかだ。日本では、ユーザーが携帯生の高いハードウェアでプログラムを作るニーズが少ないのだろう。

海外へ目を移すと、HP や TI のプログラム関数電卓は、国産とはかなり異なった設計と製品展開を行っているようだ。私自身は海外製品はまだ使ったことが無いが、akatuki氏が運営しているブログ:電卓情報では主にHP製のプログラム関数電卓の話題を読むことができる。また、電卓マニアの部屋でも、TIやHPの関数電卓についての記事がある。とね日記ではTIの製品の記述がみられる。

これらのサイトを拝見する限り、HPやTIは教育向けに電卓を開発・販売していて、高度な機能をもつ電卓が中学生向けの商品設定になっているなど、驚かされる。アメリカでは、数学や物理の授業で積極的に電卓を使っているようだ。さらに、CASといって、数式の変換を行う機能もある。これを授業で使うわけだから、数式の変換そのものではなくて、別のことを教えていることになる。より本質的なことなのか、あるいはより応用面なのか、いずれにせよ暗記できるもの以外を教えているのだろうと想像される。

日本では、中学や高校で電卓の使い方を教えないようだ。むしろ電卓の使用を禁止していると聞く。
最近はネット上のQ&Aで、「因数分解のできる電卓はありませんか?」 とか、「宿題で困っているので、2時方程式が解ける電卓を紹介して欲しい」などの書き込みを見て、強烈な脱力感に襲われる。日本の授業で電卓を使わせると、学習が進まないと言う話を耳にするが、そんな学生ばかりだと、確かにそうかも知れないと納得しそうになる。

しかし、待てよ。電卓で解けるようなことばかり教えていて、本質を教えていないのではないか?むしろ教える側に問題はあるまいか? そんな風にも思える。公式を暗記して、それを使った演習問題をして、ハイ終わり、そんな授業をしていないだろうか?



プログラミングの習得について

プログラミングは、中学の技術家庭科の授業で必修とのことだが、アルゴリズムを教えているのだろうか?

そうあるべきと思っている。特定のハードウェアやOS特有の子細なことのみを教えて、手順を覚えましょう、暗記したら少し演習をして、テストをして、ハイ終わり....ではないことを祈る。

アルゴリズムこそが、コンピュータを応用する基本だし、開発プラットフォームやOSに左右されない最も本質だ。単に論理的な思考といっても、コンピュータ向けのアルゴリズムはかなり特殊だ。アルゴリズムを分かっている教員がどれほどいるのだろうか?

私などは、再帰的な処理を初めて知った時の感動を今でも覚えている。こういう感動を与えられるような授業であって欲しい。

一見無駄を含んでいるようで、間違いない問題解決にはその無駄が必要だという感覚も大切だ。問題を確実に解決するアルゴリズム以外に、解決速度を優先させたアルゴリズムだってある。アルゴリズムを工夫する経験が中学性のような若い頭に最も有用だと思うわけだ。



エンドユーザー・プログラミング

電卓情報のakatuki氏と以前ディスカッションしていた際に出てきた言葉「ユーザーエンド・プログラミング」は、自分が今必要な処理のために、とりあえずプログラムを作って使ってみる、と言うことだ。パソコンを使っても良いし、電卓だって使えるのなら良いわけだ。そこでプログラミングが必要なら、手軽に作れば良い。私自身はプログラミングに縁の無い仕事であるが、仕事でもプライベートでも、Windowsと電卓の両方で、必要に応じて手軽にプログラミングして活用しており、その便利さを享受している。

一方で、誰かが作ったソフトやプログラムがネットには沢山ある。それを探して使うのは手軽だが、計算結果の責任は誰が持つのか? 計算精度はどうなのか? 内部でどのような処理を行っているのか? 分かって使うのは良いが、分からずに使うのは問題だろう。

ユーザーエンド・プログラミングがあって初めてユーザーエンド・コンピューティングがまともに機能するわけだ。

このブログを始めてから教えて頂いた、無償で入手可能なスマホ上のプログラミング環境:BASIC! などもユーザーエンド・プログラミングの有効なツールだ。これについては、まだ使用経験が無いが、仕様書を見る限り強力な開発系だと思う。誰でも持ち歩いている携帯端末でプログラミングが出来ると言う点は、極めて重要だ。

Windowsベースで言えば、私は ActiveBasicを挙げたいと思う。これも無料だが、CやC++ 並の柔軟性と能力を持ったWinidows上の開発環境だ。

プログラミングが中学での必修になったことに呼応して、プログラミング教室ビジネスも動き出している。学校で教わるよりも良いのだろうか?子供向けのビジネスだが、大人向けのプログラミング教室は寡聞にして知らない。金のあるところに湧き出たビジネスではあるが、今後どのように普及していくのか、あるいはしないのか?興味はある。


今後、様子を見てゆきたいと思う。




応援クリックをお願いします。励みになるので...

人気ブログランキングへ




keywords: プログラミングプログラム関数電卓

リンク集 | ブログ内マップ
関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

fx-5800P【プログラミング】:配列変数

fx-5800Pのプログラミング言語には、配列変数が用意されている。

プログラム内で、

100→DimZ

とすると、100個の配列変数が確保され、全ての要素が初期化され0が格納される。つまり、

Z[1] = Z[2] = Z[3] = ・・・ = Z[100] = 0

となる。

これを解放するには、

0→DimZ

とすれば良い。

配列の名前は、Z に固定されているのが特徴だ。

配列は、プログラムを格納するメモリ領域から切り取られるので、28500バイトの中から、プログラムに使われていない容量を配列変数に使える。電卓のプログラムでそれほど多くの変数を使うとは考えにくいので、実質無制限に使えると思って良いだろう。

配列なので、例えば変数Cを使って、Z[C] といった使い方ができる。つまり、ループコマンドの中で、Cをインクリメント(増やす)したりデクリメント(減らす)しながら、Z[C] を使って様々な処理ができるので、プログラムの記述を効率化できる。

fx-5800Pの配列 Z[ ] には、ちょっと癖がある。

・要素数に0を使えない
Z[C]の Cは1以上の整数しか使えず、0を使えない。C=0 の時はエラー(Argument ERROR:引数エラー)となる。

プログラミングに慣れた方なら、配列の要素数をついつい0から始めてしまう。私も fx-5800Pの配列に慣れるまで、何故エラーになるのか、何度か悩んだ。

・For文の制御変数(カウンタ)に使えない
試しに、以下のようなコードを書いてみるとエラーになる。

For 0→Z[1] To 10
<何かの処理>
Next


しかし、

For 1→C To 10
Z[C]+C→Z[C+1]

Next


ならOKだ。

実は、上のエラーは2重のエラーである。For 文も制御変数に 0 を使えないのだ。


そこで、fx-5800Pに備わっている3種類のループ(繰り返し)コマンドを使って、テストプログラムを作ってみた。

fx-5800P専用
配列変数テストプログラム
====================
100→DimZ
1→C
Do
Z[C]+C→Z[C+1]
IsZ C
LpWhile Z[C]<50
C▲
Z[C]▲
0→DimZ

100→DimZ
1→C
While Z[C]<50
Z[C]+C→Z[C+1]
Isz C
WhileEnd

C▲
Z[C]▲
0→DimZ

100→DimZ
For 1→C To 11
Z[C]+C→Z[C+1]
Next

C▲
Z[C]▲
0→DimZ

====================


Doループ、Whileループ、Forループのいずれも、C=11、Z[C]=55 の結果が得られる。

ところで、配列変数とは直接関係無いが、fx-5800PのFor文の癖も、似たようなところがある。制御変数は1以上の整数を使わないとダメだ。ついつい0からスタートするコードを書くとエラーとなる。


配列変数に話を戻す。

入れ子の配列 Z[Z[C]+1] も使えるので、ある程度の使いではありそうだ。
何層まで入れ子が可能かは、まだ試していないが、ソースコードが非常に読みづらくなるので、私は2重入れ子までしか使わないと思う。



また脱線だが、ソースコードの読みやすさについて言えば、インデント(字下げ)を使いたくなる。例えば上記のソースコードはインデントを使うと以下のようになって、非常に見やすくなる。

fx-5800P専用
配列変数テストプログラム
====================
100→DimZ
1→C
Do
  Z[C]+C→Z[C+1]
  IsZ C
LpWhile Z[C]<50

C▲
Z[C]▲
0→DimZ

100→DimZ
1→C
While Z[C]<50
  Z[C]+C→Z[C+1]
  Isz C
WhileEnd

C▲
Z[C]▲
0→DimZ

100→DimZ
For 1→C To 11
  Z[C]+C→Z[C+1]
Next

C▲
Z[C]▲
0→DimZ

====================


fx-5800Pでは、このようにインデントを入れると Syntasx ERROR となる。

コメントを付けることもできない。但し、上記のような改行は問題ない。長々と複雑なソースコードを書かず、サブルーチンを使った方が良さそうだ。

電卓プログラムに可読性まで求めるのは、贅沢なのだろうが...




応援クリックをお願いします。励みになるので...

人気ブログランキングへ


FC2ブログランキングへ

keywords: fx-5800Pプログラミング配列変数プログラム関数電卓

リンク集 | ブログ内マップ

関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

fx-5800P【ゲーム】:Hit&Blow


Hit&Blow と言うゲームをご存知だろうか?

フジテレビのNumer0nでの元になるもので、古くからある数当てゲームだ。

最初に、互いにN桁の数を決める。数の決め方には決まりがある。
・0から9までの数を使い、
・各桁は異なる数とする
・一番左の桁を0として良い

あなたが推測した数を相手に伝える。そして相手は、「2ヒット1ブロー」といったように、ヒット数とブロー数を答える。
・桁と数の両方が一致すれはヒット
・桁は違うが数だけ一致しればブロー



そこで、fx-5800PHit&Blow を作ってみた。

ところで、fx-5800Pで素因数分解プログラムを作った時、処理速度の遅いことが骨身にしみている。そこで、電卓が出題した3桁の数を当てるゲームとした。

プログラム作成時に、主に以下の2点を考えた:
・16桁x4行の画面内で遊べるように、全てをうまく配置できるか?
 私なりのガイドライン(使いやすいプログラム参照)に従って、うまく配置してみた。

・HIT数とBLOW数の判定をどうするか?
 ここが、多分一番肝心なところ。2通りのロジックを試してみた。



プログラムの仕様
1) 試行10回以下で正解すればOKとする。
 ・この時、「VERY GOOD」と褒めてあげる。

2) 試行11回目以降でも、ゲーム継続を可能とする。
 ・但し、「QUIT?」(止めるか?)と表示する。
 ・ここで止めたら、「YOU GAVE UP」と釘をさして、正解を表示する。

3) 試行11回目以降で正解すれば、一応ねぎらう。
 ・「Good」と言葉をかける。

4) 正解を出した時は、試行回数を表示する。
 ・一応「YOU WIN」と認定してあげる。

4)  デバッグ目的で、ゲーム開始時に正解を見られるようにする
 ・秘密のキー入力で正解が分かるようにする。



ゲームの実行画面

こんな感じで完成した。

先ずは、メニューリストから、「HITBLOW」を選ぶ。

ManuList 



ゲームが起動した時の画面:

HB-Start 
 
ガイドラインに従って、メニュー表示をした。
< ? >は秘密のキーだ(ここでは、まだナイショ)。
ここで、[EXE]キーを押して、ゲーム開始。




HB-1 

ゲーム開始早々、405 で 2HIT だ!
右上の :1 は試行回数を示す。



さらに [EXE] キーを押すと...

HB-2 

試行2回目、ここまでくれは、こっちのものだ!!
[EXE]キーを押して...次は決まるか?



ぶぅ~~(´д`)

HB-3 

あとは、組み合わせの問題....もうちょい...



で...

HB-4 

試行6回目で、当たり!!\(^_^)/

さらに [EXE]キーを押すと...




HB-YouWin 

試行6回で YOU WIN の表示。
ここで、[0]キーを押すと、最初の画面へ戻って、新たに出題される。 



ところで、最初の画面で秘密のキーを押すと...

HB-Sneak 

こんな感じで、正解がわかる...




プログラムの構造

メインルーチンと4つのサブルーチンを作った。

・メインルーチン:
 プログラム全体の流れを記述する。細かい作業はサブルーチンに任せる。

fx-5800P専用プログラム
プログラム名: HITBLOW

====================
Lbl 0

0→C:0→D:→E            :初期化と初期画面表示
Cls
Locate 2,1,"Hit And BLOW"
Locate 2,3,":START"
Locate 2,4,"< ? >:ANSWER"

Do                    :秘密のキーを押した時
Getkey→F                
fx-5800P:同時にキーを押してみる を参照
If F>0 And F<10
Then 1→D
Break:IfEnd
LpWhile Getkey≠47
                         :この2行が肝心
Prog "S2HB3"              :正解出題ルーチン
Prog "S3HB3"               :ゲームの中心部分

Cls                       :結果表示
If D=1:Then               
"   YOU GAVE UP"            :正解できなかった時 D=1
"THE ANSWER ="
Locate 14,2,A
Else
Locate 5,1,"YOU WIN"        :正解時の処理
Locate 3,2,"IN"
Locate 6,2,C
Locate 8+Int(log(C)),2,"TRIES" :関数電卓ならではの処理
IfEnd                      ⇒ 別記事で紹介予定
Locate 1,4,"<0>:TRY AGAIN"

Whle Getkey≠25            :もう一度遊ぶ
WhleEnd

Goto 0
====================



・サブルーチン(1):
 入力された3桁数を、各桁の数字に分解する。

fx-5800P専用プログラム
サブルーチン: S1HB3
入力された数字を各桁に分解し
変数 K、L、M に格納する
====================
Int(N÷100)→X               ⇒ 別記事で紹介するかも...
Int((N-100X)÷10)→Y
N-100X-10Y→Z
If X=Y Or Y=Z Or Z=X
Then 1→E:IfENd
====================



・サブルーチン(2)
 各桁の数字が同じにならないように、3桁数を作る。

fx-5800P専用プログラム
サブルーチン: S2HB3
各桁を重複しないように作り、
正解の変数、K、L、Mへ格納し、
正解の3桁数を変数Aに格納する
====================
RanInt#(0,9)→K

Do
RanInt#(0,9)→L
LpWhile L=K

Do
RanInt#(0,9)→M
LpWhile M=K Or M=L

100K+10L+M→A
If D=1:Then
"THE ANSWER =   "
Locate 14,1,A▲
IfEnd

====================



・サブルーチン(3)
 ゲームの核心の流れを記述する。

fx-5800P専用プログラム
サブルーチン: S3HB3
正解するか、諦めると
メインルーチンへ戻る
====================
10→DimZ
Do
0→E:Isz C

Lbl 0
Cls
Locate 12,1,":"
Locate 13,1,C
"3 DIGITS"?→N
Prog "S1HB3"

If E=1:Then
Locate 12,2,"ERROR"
Locate 6,3,"SAME NUMBER"
Locate 2,4,"FOUND IN DIGITS"▲
0→E:Goto 0
IfEnd

Prog "S4HB3"

If D=1:Then
Break:IfEnd
LpWhile H≠3

0→DimZ

Return
====================



・サブルーチン(4)
 回答を判定して、△HIT、◇BLOW を表示する

 2つの異なるロジックで作ってみた。


サブルーチン(4-1):桁数の拡張性を考えたロジック

For 文と配列変数Z[ ]を利用した。


fx-5800P専用プログラム
サブルーチン: S4HB3
ヒット数を Hへ、ブロー数をBへ
格納してサブルーチン S3HB3へ戻る

====================
0→S:0→T
0→H:0→B:0→D
X→Z[1]:Y→Z[2]
Z→Z[3]:K→Z[6}
L→Z[7]:M→Z[8]

For 1→S To 3
If Z[S]=Z[S+5]
Then Isz H
IfEnd:Next

For 1→S To 3
For 1→T To 3
If Z[S]=Z[T+5]
Then Isz B
IfEnd:Next:Next

Locate1,3,H
Locate 3,3,"HIT"
Locate 1,4,B-H
Locate 3,4,"BLOW"

If H≠3 And C>10
Then
Locate 12,3,"QUIT?"
Locate 12,4,""
IfEnd

If H=3:Then
If C>10:Then
Locate 13.3."GOOD"
Else
Locate 8,3,"VERY GOOD"
IfEnd:IfEnd

Do
Getkey→F
If F=34:Then
1→D:Break:IfEnd
LpWhilr F≠47

====================



処理速度が少し遅いように思われた。 For 文の実行分と、配列変数へのアクセスに多少余計に時間がかかるのかも知れない。配列変数に関しては単なる思い込みの可能性もあるが...

[2014/03/09:追記] 速度低下の主要因は配列変数へのアクセスが非常に遅いためである。通常変数に比べてアクセス速度が3倍近くかかるようだ。



サブルーチン(4-2):処理速度向上を狙って、If 文のみのロジック

2者択一の If文 は処理が速いと考え、それでも桁数拡張がしやすいロジックにしてみた。


fx-5800P専用プログラム
サブルーチン: S4HB
ヒット数を Hへ、ブロー数をBへ
格納してサブルーチン S3HB3へ戻る

====================
0→S:0→T:0→U
0→H:0→B:0→D

If X=K:Then
Isz H:1→S:IfEnd
If X=L:Then
Isz H:1→T:IfEnd
If Z=M:Then
Isz H:1→U:IfEnd

If X=L And T=0
Then Isz B:IfEnd
If X=M And U=0
Then Isz D:IfEnd
If Y≠X:Then
If Y=K And S=0
Then Isz B:IfEnd
If Y=M And U=0
Then Isz B:IfEnd
IfEnd
If Z≠X And Z≠Y:IfEnd
If Z=K And S=0
Then Isz B:IfEnd
If Z=L And T=0
Then Isz B:IfEnd
IfEnd

Locate 1,4,"                "
Locate1,3,H

Locate 3,3,"HIT"
Locate 1,4,B
Locate 3,4,"BLOW"

If H≠3 And C>10
Then
Locate 12,3,"QUIT?"
Locate 12,4,""
IfEnd

If H=3:Then
If C>10:Then
Locate 13.3."GOOD"
Else
Locate 8,3,"VERY GOOD"
IfEnd:IfEnd

Do
Getkey→F
If F=34:Then
1→D:Break:IfEnd
LpWhilr F≠47

====================



思った通り、配列変数とFor文で作ったサブルーチン(4-1)よりも、If 文だけで作ったサブルーチン(4-2)の方が、処理が速かった。

ちなみに、if 文が実行される回数を比較してみた:

(4-1):12回 (おそい)
(4-2):10回 (はやい)

if文が2回多いだけだ。

あきらかに体感できる範囲で、確実に速度差を感じる。If分の実行回数に違いがないとすると、やはりFor分の実行による時間が体感の違いの原因だろう[2014/12/14 追記]: 動作の非常に遅い配列変数を使ったことが主な原因だ。

fx-5800Pで素因数分解プログラムを作った時、Doループの実行速度を簡易的に計測して、ループが1回だけ回るのに45m秒程度かかっていることが分かっている。処理時間は、当然ループ内の処理内容に依存するわけだが、それでもパソコンに比べると恐ろしく遅い。

仮に、今回のFor文のループが1回だけ回るのに50m秒かかるとすると、0.05 x 12 = 0.6(秒) かかるわけだが、体感とほぼ合う。なんとなく納得できる範囲だ。

fx-5800Pは、単4電池1本で、1日に1時間使用したとして1年の寿命と仕様に記載されている。消費電力を抑えることをかなり高い優先度としていると思われる。消費電力抑制の効果的な方策の1つに、MPUのクロックを落とすことがある。つまりその分処理速度は遅くなるわけだ。

いずれ、検証してみたいと思う。 [2014/12/14 追記]: For 文と Lbl / Goto ループの速度差は無視できるほど小さい。非常に遅い配列変数を使ったことが主要因だと判明している。


また、ソースコードの詳細については、プログラミング入門向けに別の記事で取り上げる予定だ。




応援クリックをお願いします。励みになるので...

人気ブログランキングへ


FC2ブログランキングへ

keywords: fx-5800PゲームプログラミングHit & Blowプログラム関数電卓

リンク集 | ブログ内マップ
関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

fx-5800P【プログラミング入門】:プログラム作成から実行までの操作

fx-5800Pプログラミング
e-Gadget

fx-5800Pプログラミング入門のための CasioBasic入門連載中



fx-5800Pを初めて使う方のための操作手順です。

fx-5800P以外でも、プログラムを作して実行する操作法は、必ず取扱説明書で説明されている。


さて、以下のプログラムを作って、実行してみよう。
================
"N = "?→N

================

操作手順

1.電源ON (ここから全ては始まる)

2.[MODE] [5] (プログラムモードへ入り、Program Menu が表示される)

3.[1] (1:NEWを選択)

4.ここでプログラムのファイル名つける: 例えば INPUT1 とでもしよう

5.[EXE]を押すと、File Mode の選択画面が現れるので、ここでは[1](1:COMP)を選ぶ


これで、プログラムを書き込むことができる。
慣れれば、ここまでの作業は5秒以内!


6.続けて、上記の1行だけのプログラムを書き込む。

・「"」や「N」は、[ALPHA]キーを押した後、対応するキーを押せば良い

・「?」や「→」は、[FUNCTION]キーを押し、[3] (3:PROG)を押したら現れるメニューから選ぶ。メニューは複数画面にわたるので、矢印キーの上と下を押して、探しているものを見つけ、その番号を押す。



7.プログラムの入力が終われば、[EXIT]キーを2回押して、Program Manu に戻ろう。


これでプログラム作成完了となる。


では、作ったプログラムを動作させよう。

8.Program Menu で [2] (2:RUN)を押すと Prog List  が現れる

9.リストから、今作ったプログラムファイル INPUT1 にカーソルを合わせて [EXE]を押す


以上が、電源ONから、プログラムを作り、実行するまでのプロセスだ。


パソコンでプログラムを作って実行するのに比べると、とても手順が少ない。



プログラムが実行されると、以下の画面が現れる。


----------------
N = ?



----------------


ここで、2013 と入力すると
----------------
N = ?

2013


----------------

となる。

次に、[EXE]を押して、入力を確定する。

----------------
N = ?
2013
                 2013

----------------

と表示される。

「?」命令により入力した時は、[EXE]キーでの確定が必要になる。



ここまで分かれば、あとは実際にプログラムをどのように作るかを考えるのみだ。

fx-5800P でプログラムを作るためのより具体的な操作方法や、超入門向けプログラム作成については、以下から連載を始めています。
 ⇒ Casio Basic入門38

Casio Basic入門では、取扱説明書では絶対に分からないCasio Basic 使いこなしを紹介しています。Casio Basicの命令やコマンドの使い方の詳細を、実用に使えるプログラム作成を題材にして進めています。
 ⇒ Casio Basic入門1

Casio Basicはどういうものか?を私なりに紹介してものは、以下にあります。
 ⇒ Casio Basicの勧め



応援クリックをお願いします。励みになるので...

人気ブログランキングへ


FC2ブログランキングへ

 

keywords: fx-5800Pプログラミング入門プログラム関数電卓

リンク集 | ブログ内マップ
関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

電卓以上、パソコン未満。


プログラム関数電卓を一言で表現したら、どう言えば良いのだろうか?

以前から、そんなことを考えることがよくあった。



ふと、頭の上で電球が灯った....\(^_^)



電卓以上、パソコン未満。


これだっ、これだよ


機能を考えても、その通りだ。

要求されるプログラミング能力も、その通りだ!

心の中のモヤモヤが一気に晴れた。


「、」と「。」を加えて、このキャッチを差別化しておこう (。・ω・。)




応援クリックをお願いします。励みになるので...

人気ブログランキングへ




keywords: プログラム関数電卓

リンク集 | ブログ内マップ
関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

最新記事
最新コメント
カテゴリ
C# (3)
検索フォーム
Visitors
Online Counter
現在の閲覧者数:
プロフィール

やす (Krtyski)

Author:やす (Krtyski)
since Oct 30, 2013


プログラム関数電卓は、プログラムを作り・使ってナンボ!

実際に触って気づいたこと、自作プログラム、電卓プログラミングについて書いています

おもしろい・役に立つならクリックしてください。励みになります。

人気ブログランキングへ


FC2ブログランキングへ


写真: 「4駆で泥んこ遊び@オックスフォード郊外」

リンク
月別アーカイブ
Sitemap

全ての記事を表示する

RSSリンクの表示
最新トラックバック
ブロとも申請フォーム

この人とブロともになる

QRコード
QR