fx-5800P:コマンドの処理速度【再編集】

2013/12/27:
Kenさんのご指摘で、測定がおかしいことが分かり、結果が大幅に間違っていたので、再度測定を行い、内容を再編集した。
Kenさんありがとうございます。


2014/2/5:
fx-5800P の電池を新しくして測定をしたところ、If 文の処理時間が大幅に速くなった。電池の電圧の影響があるようだ。測定値を更新した。




これまで、fx-5800Pで、素因数分解もぐら叩きゲーム を作ってみている。

特に、fx-5800Pのような、最低必要限のコマンドを備え、さらに比較的処理速度の遅い電卓でもぐら叩きのようなアクションゲームでは、アルゴリズムや各コマンドの処理速度が重要になってくる。


そこで、幾つかのよく使うコマンドの処理速度を調べてみた。


以下のようなプログラムを作って、処理時間の差から、各コマンドに要するおおよその時間を推定した。

なお時間測定には、ぎょういちろうさん作のフリーソフトウェア SGウォッチ を使用した。


1) Goto 文でのカウントループ
1000→A
Lbl 0
Dsz A
Goto 0
"DONE"▲


処理時間: 6秒



2) If [式] 文を追加したループ
1000→A
Lbl 0
If A≠0:Then
Dsz A
Goto 0
IfEnd
"DONE"▲


処理時間: 16秒


1) のプログラムとの違いは、If [式] ~ Then ~ IfEnd コマンド の有無であり、それにより処理時間が10秒増加している。ループ回数は 1000回なので、If [式] 文実行には 10ミリ秒かかっていると推定される。

If [式] 実行時間: 10ms



3) If [変数] を追加したループ
1000→A
Lbl 0
If A:Then
Dsz A
Goto 0
IfEnd
"DONE"▲


処理時間: 10秒 【修正】

1) のプログラムとの違いは、追加された If [式] ~ Then ~ IfEnd であり、それにより処理時間が4秒増加している。ループ回数1000回なので、If [変数] 文実行には 4ミリ秒かかっている。

If [変数] 実行時間: 4ms



4) Dsz の代わりに A-1→Aにしたループ
1000→A
Lbl 0
A-1→A
If A≠0:Then
Goto 0:IfEnd
"DONE"▲


処理時間: 24秒 【修正】

2) と 4) の処理速度は、Dsz A を A-1→A に置き換えると、8秒遅くなっている。速度を速くしたい場合は、Dsz コマンドを使えば良いことが分かる。こではループ1000回の結果なので、1回の処理の時間差は、8ミリ秒となる。

Dsz A は、A-1→A よりも 8ms 速い



5) If [式] 文の代わりに [式]⇒ にしたループ
1000→A
Lbl 0
A≠0⇒Dsz A
Goto 0
"DONE"▲


処理時間: 15.5秒

1) のプログラムとの違いは、A≠0⇒ が追加されている点であり、処理時間は9.5秒増えている。これは1000回ループの結果なので、A≠0⇒ 1回の実行は15.5ミリ秒。

A≠0⇒ 実行時間: 15.5ms

2) のプログラムよりも5.5秒程度速い。これは1000回ループの結果なので、1回の実行時間は5.5ミリ秒程度速いことが分かる。

[式]⇒ は If [式] 文よりも、5.5ms 速い




6) If [変数] 文の代わりに [変数]⇒ にしたループ
1000→A
Lbl 0
A⇒Dsz A
Goto 0
"DONE"▲


処置時間: 9秒 【修正】

1) のプログラムとの違いは、A⇒ が追加されている点で、処理時間は3秒増えている。これは1000回ループの結果なので、A⇒ 1回の実行は3ミリ秒。

A⇒ 実行時間: 3ms


3) のプログラムよりも9秒速い。これは1000回ループの結果なので、A⇒ は If A 文よりも 1回の実行は9ミリ秒速いことがわかる。

[変数]⇒ は If [変数] よりも 9ms 速い



条件分岐のコマンド If と ⇒ を比べると、⇒ が速いことが分かった。

If 文に比べて、[式]を評価する場合は⇒ 命令の方が、5.5ms 速い。[変数]を評価する場合は、⇒命令は9msとかなり速くなる。


また、デクリメント (変数を1つ減らす) 場合は、A-1→A よりも Dsz A が圧倒的に速いことが分かった。





7) For ループ
For 1000→A To 0
Step -1
Next
"FOR DONE"▲


処理時間: 7秒 【修正】


8) Do ループ
1000→A
Do
Dsz A
LpWhile A
"DONE"▲


処理時間: 6秒


9) While ループ
1000→A
While A
Dsz A
WhileEnd
"DONE"▲


 
処理時間: 6秒


上記3種類のループコマンドでは、Do ループと While ループが For 文を僅かに抑えて最も速いことが分かった。



10) Do ループ(ループ終了判定に式を使用)
1000→A
Do
Dsz A
LpWhile A≠0
"DONE"


処理時間: 12.5秒


11) While ループ(ループ終了判定に式を使用)
1000→A
While A≠0
Dsz A
WhileEnd
"DONE"


処理時間: 12.5秒
 
Do ループや While ループの終了判定に式を用いると、処理時間が大幅に長くなることが分かった。



以上まとめると、


1. Goto ループは高速処理に使える

特に、Dsz、Isz、[変数]⇒ と組み合わせるのが良い。

   Lbl 0
   [何かの処理]
   Dsz A
   Goto 0


   Lbl 0
   [何かの処理]
   Isz A
   Goto 0


   Lbl 0
   [何かの処理]
   Dsz A
   A⇒Goto 0



2.条件分岐は、⇒命令が速い

さらに、
   A⇒[変数] が A⇒[式]よりもかなり速い


3.ループコマンドは、Do 文、Whiler 文が速い

For 文もほぼ同等だが、若干遅い。


4.Do ループ、While ループは、Goto ループと同等の速さ

Goto ループは、いわゆるスパゲティープログラムになりやすい。コードの可読性も低下する。
従って、無理して Goto ループを使わずとも、Do ループや While ループを使えば良く、それによる速度低下は機にしないで良い。

但し、終了条件にはできるだけ [変数] を用いること。[式]を用いると処理時間が長くなる。


5.Dsz、Isz はループ終了判定に有効

デクリメント(A-1→A) やインクリメント (A+1→A)には、積極的に Dsz や Isz を使うと良い。


これで、fx-5800P 特有の CASIO BASIC のコマンドの選択がはっきりした。




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

人気ブログランキングへ


FC2ブログランキングへ


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

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

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

UCF連動: キーコードの秘密

fx-5800P:同時にキーを押してみる で紹介したように、キーを押すと本来2桁のキーコードが得られるが、条件のあった複数のキーを同時に押すと、1桁のキーコードが得られることを偶然見つけた。

このネタが、プログラム関数電卓が好きな人の間では、よく知られていることなのか? そしてこの現象について何か面白い話が無いものか、気になっていた。


ところで、 Universal Casio Forum (UCF) と言うカシオのプログラム関数電卓のファンが集まって情報交換するフォーラムを最近見つけた。世界の(主にアメリカ)のプログラム関数電卓ファンとの情報交換を始めてみている。

そこで、キーの同時押しと同じ内容を UCF でトピックスを立ててみた。 "fx-5800P: Secret Of Keycode" (キーコードの秘密)と言うタイトルにして、先ずはキーコードが一桁になる条件がある...と、ここまでの内容を書いた。

このフォーラムでは、Krtyski と言う名前を使っている。このブログと同じ写真を使っているので、私と同一人物だと分かると思う。


fx-5800P: Secret Of Keycode はこちら

ここでは、以下のキーコード取得プログラムを紹介した。

1-GetKeycode  

2-GetKeycode 


 srcGetKeycode 



どのようなコメントが貰えるのか、楽しみにしている。面白い話が聞けたら、本エントリーへのコメントとして紹介しようと思っている。

もしご興味があって、UCF に参加したいと言う方がいらっしゃれば、楽しみにお待ちしています。どうぞお越しください。




2013/12/30: UCFでの反応の第一報をコメントに掲載した → こちら

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

人気ブログランキングへ


FC2ブログランキングへ


keywords: fx-5800Pキーコードkeycodeキーの同時押しプログラム関数電卓

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

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

情報を求めて

プログラム関数電卓に関する情報源は、割合限られていることから、このブログを立ち上げたのですが、海外に情報を求めて、時間のある時に色々と探しています。

その中で、割合面白そうなフォーラムを見つけました。

Universal Casio Forumこちら

こちらでは、Krtyski と言う名前でアカウントを作りました。(国籍不明な名前でしょ?)


これからゆっくりと見てみようと思っていますが、fx-5800P に関して結構面白い話題があります。

たとえは、プログラム容量は、1コマンド、1文字、1命令、全て1バイトと言うものです。Getkey なんてコマンドは1バイト。2.5 と言う数は、3文字あるからそれだけで3バイト...といった具合です。またプログラムのヘッダに35バイト、プログラム名に12バイト、といったなかなか面白い情報があります。


「もぐら叩き」を紹介しました。→ こちら




keywords: fx-5800PCASIOプログラム関数電卓

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

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

fx-5800P【ゲーム】:もぐら叩き(8):修正あり

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


2013/12/28 修正:
コマンド実行時間について、大きな間違いがあったので、修正する。
条件分岐処理で、⇒命令よりも If 文の方が速いとしていたが、これが大きく間違っていた。⇒命令の方が速いことが確認されたので、それに従ってプログラムコードを修正した。お詫びして訂正させて頂きたい。

2014/03/20 修正
If 分を ⇒ に変更することで実行速度が向上すると書きながら、徹底していなかったので、修正した。


2015/02/17 修正
プログラムコードで Locate の表示文字列から <AC> や <EXE> が抜けていた、記載ミスを修正した。 



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


色々と工夫するところがまだ有りそうだが、前回までに作ったゲームのメインルーチンを土台にして、ゲームとしてまとめようと思う。


そこで、ゲームコンセプトを、「もぐら退治の賞金稼ぎ」とする。

◆ゲーム開始時に、LIFE をもらう。
◆モグラ退治が遅い場合や間違って退治すると、LIFE が減り、それがゼロになるとゲーム終了
◆モグラ1匹あたり、定額の資金をもらう。
◆モグラ退治に時間がかかるほど、費用がかさむ
◆モグラを素早く退治すると、退治費用が節約でき、資金の残りが賞金となる
◆限られたLIFEで、どこまで賞金(PRIZE) を稼げるか、がんばろう!!



◆モグラが出現すると FUND (資金)を貰う
◆モグラを叩くと、反応時間分のCOST(費用)が減る
◆モグラ退治が速いほど、FUND - COST 分の儲け(得点)が多くなり、PRIZE(賞金)が増える
◆モグラ退治に時間がかかると、BURST となり LIFE が減る。
◆モグラを取り逃がすと、TIME-OUTとなり、 LIFE が減るだけでなく、 PRIZE がごっそり減る
◆ゲームが進むと、FAKE モードが発動される
FAKE ONE モードは、偽モグラが出現する。これは放置。手を出すと LIFE が減る
FAKE TWO モードは、偽モグラと本物モグラが同時に出現する。本物を退治すると儲けがあるが、偽モグラを退治すると LIFE が減る。



ゲームの内部仕様を、以下のようにする。これまで作ったロジックはそのままにして、上の仕様に併せて、分かりやすい変数名になるように、変数を一部変更する。

1)持ち点について:
・モグラが出現するごとに、持ち点(資金=fund)をもらう
・ 持ち点は、設定変更できる
・持ち点を "FUND" と呼び、変数 F に格納する
変数Fデフォルトを 20 とする
2)モグラを叩くまでの手間 (COST):
COST は、モグラが出現すると時間とともに増えてゆく
・正しいモグラを叩くと、その時点で COST が確定する。
・モグラを叩くのに時間がかかれば、それだけCOSTが多いことになる
COST変数C に格納する
3)得点について:
・モグラが出現する際に貰う持ち点から、COST を差し引いたものが得点
得点 = [ FUND (F) ] - [ COST (C) ]
・モグラへの反応が速ければ得点が多くなり、遅ければ得点は少ない

・COSTが一定以上になると(反応が遅い時)は、BURST してペナルティーが課される。
BURST になる COST"BURST LIMIT"と呼び、変数B に格納する。
・BURST LIMITは、設定変更できる。デフォルトを17とする。
・C≦B の時(モグラへの反応が速い時): 得点 = F-C を得る
・C>B の時(モグラへの反応が遅い時): 得点 = 0、さらに LIFE が1つ下がる
4)PRIZE(総合点)について:
獲得した得点を足し合わせたものを PRIZE(総合点)と表記し、を変数 P に格納する
PRIZE をリアルタイム表示する
PRIZEの更新: P+F-C→P
5)Time-outについて:
モグラへの反応が遅すぎると、モグラが逃げてしまい、PRIZELIFE の双方が減らされる。この時間を "TIME OUT"と呼び、変数E (End のE)に格納する。
・タイムアウト条件の設定を変更可能とする。
C>E の時(反応が遅く、モグラを逃した時)の減点を "SHAKE LOSS"と呼び、変数S に格納する。
変数Sデフォルトを25とする
SHAKE LOSS 発生時は、PRIZEが25点減り(P-S→P)、LIFEが1減る(L-1→L
(shake = 逃がす)
6)FAKEモードについて:
PRIZEが所定点数に達すると、FAKE機能を発動させる。
・FAKEが機能が発動する時の PRIZE (総合点)を "INVOKE FAKE" と呼び、変数V に格納する。
変数Vデフォルトを200とする。
・FAKE機能は、以下の2つ
FAKE ONE: (Q=2) 偽モグラのみを出現させる。何かを叩くとLIFEが1減る。放置してTIME-OUTにすれば良い。
FAKE TWO: (Q=1) 偽モグラと本物モグラを同時に出現させる。本物モグラ以外を叩くと、LIFEが1減る。
7)LIFEについて:
・ゲーム開始時に、LIFE をもらう
LIFEの初期値変数M に、ゲーム進行時にリアルタイム変化する LIFE を変数 L に格納する
・LIFEの初期値デフォルトを 7 とする。
・LIFE
をリアルタイム表示する
C>E の時(モグラへの反応が遅い時): LIFE が1減る、但し FAKE ONE モードは例外。
LIFE が0になると、ゲーム終了


【2013/12/18 修正】
ところで、fx-5800P【プログラミング】:コマンドの処理時間 で、主なコマンドの処理時間を調べてみた。

この結果を得るまでは、条件分岐として、If 文よりも ⇒ 命令の方が速いと思っていたが、実は逆だと言うことが分かった。具体的には If [式] [式]⇒ を比べると、If [式] のほうが速いのだ。

そこで、ここまで作ってきたプログラムコードで、[式]⇒ を使って記述しいたコードを、If [式] に書き換えて、少しでもスピード感を出そうと思う。



fx-5800P:コマンドの処理時間【再編集】で、幾つかのコマンドの処理時間を調べたところ、条件分岐には If 文よりも ⇒ 命令の方が速く、特に 変数の評価を行う場合は、⇒ が圧倒的に速いことが分かった。

If A:Then
[何か処理]
IfEnd


よりは、

A⇒[何か処理]

の方が圧倒的に速い。

一方、

If A=B:Then
[何か処理1]
Else
[何か処理2]
IfEnd


より、

A=B⇒[何か処理1]
A≠B⇒[何か処理2]


の方が時間がかかる。

従って、[変数]の評価では極力 ⇒命令を使うようにし、[式] の評価では Else を使わない場合は ⇒を 使ってプログラムコードを書く。

======ここまで修正 ======


最後に、FAKEモードで、偽モグラを [Q] で表現してたが、[0] (斜め線の入ったゼロ (fx-5800Pではオーとゼロを区別するために、ゼロのフォントは斜め線が入っている)を使うことにする。本物と偽のモグラを紛らわしくする作戦だ。

これに併せて、GAME OVER 表示の際に用いていた偽モグラ も、Qから0(斜め線付き)に変更する。


各種設定を変更するルーチンを、メインルーチンとし、ゲーム本体をサブルーチンとする。そしてメインルーチンからゲーム本体を呼び出す構造にする。


先ずは、実行画面から紹介しよう。

[FILE] キーを押して、プログラム リストから WHACK-A-MOLEを実行すると、もぐら叩きゲームの初期画面が表示される。

wam-menu    

[0] キーを押すと、デフォルトの設定変更だ。
[EXE] キーを押せば、ゲームスタート。
[AC] を押せば終了。


[EXE] キーで、もぐら叩きの画面登場!

wam-Start   

[0] キーで GO(ゲーム開始)!


wam-mole  

モグラが出現する。

モグラの位置対応するテンキー[1]~[9]を、素早く押す!


PRIZEが200になると、FAKE モード発動!

 wam-fake1 

偽モグラは、O (オー)ではなくて、ゼロ なので、間違えやすいので、要注意!

間違えると、LIFE が減ってしまう、慎重に...


wam-fake2  

偽物と本物モグラの両方も出現する。

本物を、素早く叩くのだ...


wam-gameover   


ついに、LIFE がゼロになって、GAME OVER ...

右下の表示に従って [EXE] キーを押すと、終了メニューが現れる。

wam-gameover_menu  

GAME OVER メニュー:

[0] キーで、最初のゲームタイトル画面へ戻る。

[RCL] キーで、同じ条件でゲーム開始!



最後に、完成したプログラムコードをまとめる。


先ずは、ゲーム本体(サブルーチン)の完成版は次のようになる。赤文字は、今回追加・変更した部分だ。

fx-5800P用プログラム
もぐら叩きゲーム Ver 1
ゲーム本体
プログラム名:"WAM"
==================
Lbl 2
M→L
:0→P:0→Q          :変数の初期化
Cls                    :メインルーチンで他の初期化を行う
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→I To 3           :初期画面表示
Locate 1,I,"[ ][ ][ ]"      :For の制御変数をBからIに変更
Next
Locate 11,2,"PRIZE"
Locate 12,3,P
Locate 1,4,"LIFE:"
Locate 6,4,L
Locate 11,4,"GO:<0>"    :もぐら叩き開始
While Getkey≠25
WhileEnd
Locate 11,4,"      "        :スペースが6個


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

RanInt#(1,9)→T         :モグラ出現のタイミングと座標
RanInt#(1,3)→X
RanInt#(1,3)→Y
RanInt#(0,3)→Z
RanInt#(1,3)→W
9+X-3Y→N
If P≧V:Then            :FAKEモード発動
Z=0⇒2→Q
Z=1⇒1→Q
Z≧2⇒0→Q

Else 0→Q:IfEnd

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

0→C                  :本物/偽モグラを出現させる
If Q=2:Then            :FAKE ONE モード
Locate 3X-1,Y,"0"        :斜め線のあるゼロ
Else                   :FAKE TWO モード
Q=1Locate 3W-1,X,"0"  :斜め線のあるゼロ
Locate 3X-1,Y,"O"
IdEnd

Do                    :モグラを叩くまでのカウンタ
Isz C                  :C (COST)が増える
If C>E:Then
Break:IfEnd

C>E⇒Break
                                  :2014/03/20 修正
Getkey→K
LpWhile K=0

                      :モグラを消す
Q=1Locate 3W-1,X," "   :スペース1個
Locate 3X-1,Y," "         :スペース1個

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

C>E⇒P-S→P
                                :2014/03/20 修正
IfEnd
Else
If C≦E:Then
L-1→L:IfEnd

C≦E⇒L-1→L
                                : 2014/03/20 修正
IfEnd

Locate 12,3,"      "       :リアルタイム表示(スペース6個)
Locate 12,3,P
Locate 6,4,L

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

0→DimZ               :ゲーム終了時の処理
For 1→I To 3            :For 文の制御変数をA, Bから I, J に変更
For 1→J To 3
Locate 3J-1,I,"0"         :0に斜め線のゼロ
Next:Next
Locate 1,2,"GAME OVER"

Locate 10,4," <EXE> "◢  :[EXE]キーで終了メニュー表示
Cls
Locate 1,2,"GAME OVER"
Locate 2,3,"<0> :GO BACK"
Locate 1,4,"<RCL>:TRY AGAIN"
Do                        :キー入力待ち
Getkey→K
If K=25 Or K=41
Then Break
IfEnd
K=25 Or K=41⇒Break
              : 2014/03/20 ついでにココも修正、コードが見やすくなる
LpWhile 1
If K=41:Then            :[RCL]キーで同じ条件でゲーム再開
Goto 2:IfEnd
K=41⇒Goto 2
                               : 2014/03/20 ついでにココも修正、コードが見やすくなる
If K=25:Then            :[0]キーでメインルーチンへ戻る
Return:IfEnd

K=25⇒Return
                               : 2014/03/20 ついてにココも修正、コードが見やすくなる
==================


ゲームが終了すると、以下の画面になる。

wam-gameover 

画面上でのこれまでとの違いは、右下にの表示が増えているところだ。

ここで[EXE]キーを押すと、ゲーム終了時メニューが現れる。

wam-gameover_menu  


ここで、[RCL] を押すと、同じ条件でゲーム開始の画面になる。

wam-Start 


ゲーム終了時メニューで、[0] キーを押すと、プログラムを起動した時の最初の画面に切り替わる。ここで、各種デフォルト設定を変更できる。

wam-menu 

最初にゲームを起動した時と同じ画面だ。[0]キーと[EXE]キーは、Getkeyコマンドでキーコードを取得し、If 分による条件分岐で必要な処理を行う。

この処理を行うプログラム(メインルーチン)は今回新たに作った。具体的には、以下のようになる。


fx-5800P用プログラム
もぐら叩きゲーム Ver 1

メインルーチン
プログラム名:"WHACK-A-MOLE"
==================
7→M:17→B:25→E        :各種デフォルト設定
20→F:25→S:200→V

Lbl 0
Cls
" WHACK-A-MOLE"          :ゲームタイトル
Locate 5,2,"<0>:SETTINGS"   :メニュー表示
Locate 6,3,"<EXE>:START"
Locate 8,4,"<AC>:QUIT"

Do                    :キー入力待ち
Getkey→K
If K=25:Then
Break:IfEnd
LpWhile K≠47

If K=25:Then Cls         :[0]キーで設定変更
"LIFE"?M
"BURST LIMIT"?B
"TIME-OUT"?E
"FUND"?F
"SHAKE LOSS"?S
"INVOKE FAKE"?V
Goto 0:IfEnd

Prog "WAM"             :ゲーム本体を呼出す
Goto 0

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



これで、しばらく遊んでみている。

今のところ、徐々にスキルが上がって、PRIZE(総合点)が向上している。
我が家のゲーマーも、まぁまぁだ、と言ってくれている。

少なくとも、私自身はやるたびに PRIZE が増えてゆくので、今は愉しい。


つづく...

⇒ もぐら叩き~まとめ~



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

人気ブログランキングへ


FC2ブログランキングへ


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

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

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

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

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


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


前回、機能追加して、少し遊んでみたところ、幾つかの問題が出てきた。

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



これら3つの機能追加を行ったのだが、以下のような問題がはっきりした。

問題1: 偽物モグラが連続して出続けるので、ゲームが退屈になる

問題2: 偽物モグラと本物モグラの出現位置のパターンがある程度固定されてしまっている。



※ モグラ叩きゲーム作成については、実際に行った内容を、順次紹介している。


そこで下記のように、上記問題を解消させた。


偽物モグラが連続して出続ける

原因は、以下のプログラムコードの中にあった。

If P≧200:Then
Z=2⇒2→Q
Z=1⇒1→Q
Else 0→Q:IfEnd


PRIZEが200以上になった時、上記の追加機能が発動する設定にしている。
一旦、偽物モグラ出現モードになると(Q=2)、Qが2のままになる。明らかなバグだ。

そこで、この部分を以下のように修正した。

If P≧200:Then
Z=0⇒2→Q
Z=1⇒1→Q
Z≧2⇒0→Q
Else 0→Q:IfEnd


なお、モグラの出現モードを決定する Z については、

RanInt#(0,3)→Z

と変更し、

・Z=2 の時: 偽物モグラのみ出現のモード(Q=2)
・Z=1 の時: 偽物モグラと本物モグラ両方出現のモード(Q=1)
・Z=0 の時: 本物モグラのみ出現のモード(Q=0)


と変更した。これにより、

・Z=2、Z=1 になるのが、それぞれ30%程度

となる。実際に遊びながら、この程度が面白いので、上記の設定とした。


本物モグラと偽物モグラの出現位置のパターンが固定される

本物モグラは、乱数で得られる X と Y から、座標(3X-1, Y) の位置に出現させている。
これに対して、偽物モグラを、座標(3Y-1, Z) の位置に出現させているのが、この問題の原因だ。

そこで、新たに乱数 W を得るように変更し、偽物モグラの出現位置の座標を(3W-1, X) にした。これにより、偽物モグラはほぼ全てのパターンで出現するようになった。


以上の変更を反映させた、プログラムコードは以下のようになる。

今回追加・変更した部分を、赤文字で以下に示す。


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:0→E

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#(0,3)→Z
RanInt#(1,3)→W
9+X-3Y→N
If P≧200:Then
Z=0⇒2→Q
Z=1⇒1→Q
Z≧2⇒0→Q

Else 0→Q:IfEnd

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

0→C                  :モグラを出現させ、叩くまでの処理
If Q=2:Then
Locate 3X-1,Y,"X"
Else
Q=1⇒Locate 3W-1,X,"X"
Locate 3X-1,Y,"O"
IdEnd
Do
Isz C
C>E⇒Break
Getkey→K
LpWhile K=0
Q=1⇒Locate 3W-1,X," "
Locate 3X-1,Y," "
If Q≦1:Then            :モグラを叩いた後の判定
If C≦D And K=Z[N]
Then P+20-C→P
Else L-1→L
If C>D:Then
P-25→P:IfEnd
IfEnd
Else
If C≦D: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"
==================


つづく...

⇒ もぐら叩き(8)



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

人気ブログランキングへ


FC2ブログランキングへ



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

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

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

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

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


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


前回紹介した機能追加は、我が家のゲーマー達には最初は面白いが、しばらくすると慣れてしまって面白くないと言う。

前回は、下記の機能を追加している:

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



そこで、さらに緊張感を追加するために、

3) 偽物のモグラだけでなく、同時に本物のモグラを出し、本物以外を叩くとペナルティーとしてLIFEを減らす

ように追加した。


余計な機能を追加しても、スピードを極力落とさないようにしたいところだ。
本物モグラの座標は、乱数で X と Y を求めて、座標(3X-1、Y)に出現させている。にそこで、偽物モグラが出る座標は、X と Y を入れ替えて、座標(3Y-1、X)に出現させることにする。これにより、偽物モグラのための乱数取得を行わずに済む。



あとは、モグラ出現の処理と、判定処理のスピード低下を極力減らすようにすれば良い。



モグラ出現の処理

今回の機能追加で、モグラの出現モードが3つになった。出現モードは変数 Q で管理している。これまでは、Q は 0 か 1 だったが、今回からは 0、1、2 の3通りになる。

・Q=0: 本物モグラが1匹だけ出現する
・Q=1: 本物モグラと偽物モグラが1匹づつ同時に出現する
・Q=2: 偽物モグラが1匹だけ出現する


なお、Q=1のモードの時は、意地悪く偽物モグラを一瞬先に出すことにする。
ところで、今回追加した出現モードを、Q=1 としたのは、モグラ判定処理のスピード低下防止に関連する。本物モグラが出現するモードを Q=0Q=1 にすると、判定の計算処理を、If Q≦ 1: Then で一括処理できるからだ。




モグラ判定の処理

モグラ出現モードを上記のように設定すると、変更は1カ所で済み、それによるスピード低下は If Q=0 から If Q≦1 への変更に伴う変化のみに依存する。



今回追加・変更した部分を、赤文字で以下に示す。


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:0→Q

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#(0,9)→Z
9+X-3Y→N
If P≧200:Then
Z=2⇒2→Q
Z=1⇒
1→Q
Else 0→Q:IfEnd

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

0→C                  :モグラを出現させ、叩くまでの処理
If Q=2:Then
Locate 3X-1,Y,"X"
Else
Q=1⇒Locate 3Y-1,X,"X"
Locate 3X-1,Y,"O"
IdEnd
Do
Isz C
If C>E:Then
Break:IfEnd
Getkey→K
LpWhile K=0
Q=1⇒Locate 3Y-1,X," "
Locate 3X-1,Y," "
If Q≦1:Then            :モグラを叩いた後の判定
If C≦D And K=Z[N]
Then P+20-C→P
Else L-1→L
If C>D:Then
P-25→P:IfEnd
IfEnd
Else
If C≦D: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"
==================


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


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


つづく...

⇒ もぐら叩き(7)



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

人気ブログランキングへ


FC2ブログランキングへ



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

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

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

fx-5800Pで素因数分解再び

【2014/10/29 再修正】
【2013/12/04 修正】
【2014/12/05 誤字修正】


以前、fx-5800Pで作った素因数分解のプログラムを紹介した。

以前の記事は、fx-5800Pで素因数分解を参照。



素因数を見つけるループの1回の実行時間を推定したところ、45ミリ秒ほどかかっていることが分かった。全ての自然数を検索する方法では実測値が[素因数の] × 45ミリ秒 の計算値とほぼ一致したことから、このループの実行時間はほぼ45ミリ秒程度とと考えている(その後、奇数のみを調べるようにプログラムを変更している)。



これを読んで下さったKENさん(長野県)からコメント(非公開)を頂き、「条件にもよるが大幅に高速化できる」という具体的なプログラムソースの改善案を頂いた。

=========================
ある数Xの素因数をするときにはsqrtXまで調べれば十分であることを使いました。(例えば51を素因数分解するのに、7まで調べたら9以上は調べる必要がない)
以下Lp Whileの前後に追加したソースです。
---
If C=0 And D>Y
Then 0→Y
If End
Lp While Y≧1
If Y=0 And X≠1
Then X⊿
"TO THE":1⊿
If End

---
いかがでしょうか。
こうすることで特に(素因数分解の最後に残る)大きい素数が、一つだけ出てくるときに効果を発揮します。
12345の素因数分解(823の素数判定)はわずか1秒ほどで終わります。ただし、521×523=272483のように最大の素数とそれに次ぐ素数の差が小さいときは、ソースが増えた分、元のプログラムよりも数秒余計にかかってしまうようです。

3時間以上かかったという987654321は30秒で終わりました。
この案、是非いかがでしょうか。
=========================



ありがとうございます。改めてKENさんにお礼を申し上げます。


頂いたコンセプトに従って、具体的にプログラムの改良を試みたので紹介する。

元のプログラムソースに、赤で示した3行を追加することで、このコンセプトの追加ができた【修正】。

なお、元のプログラム名「Factorizing」は因数分解と言う意味で不適切だったので、素因数分解:Prime Decompositionから、プログラム名を「PRIME DECOMP」と変更した(青字で変更を示した)。

fx-5800P用
素因数分解改良プログラム
PRIME DECOMP
====================
Lbl 0
Cls
"PRIME DECOMP"
"INPUT INTEGER"?→A
0→C:2→D:A→X
Do
X÷D→Y

If C=0 And Y<D                 : 2014/10/29 修正
Then X→D:X÷D→Y
IfEnd

If Frac(Y)=0
Then Y→X:Isz C
Else
If C≠0
Then
D▲
"TO THE":C▲
0→C
IfEnd
If D=2
Then Isz D
Else Isz D:Isz D
IfEnd
IfEnd
LpWhile Y≧1
Cls
"COMPLETED"
""
"<->:TRY OTHERS"
":QUIT"
While Getkey≠67
WhileEnd
Goto 0
====================



KENさんのご提案よりも変更部分の少ない修正にしてみた(赤の部分)。

なお、この If C=0 And Y<D [2014/10/29 修正] による判定はループが回るたびに必ず1回実行されるが、中の Then x→D:X÷D→Y は1回しか実行されないので、ループの実行速度は、KENさんのご提案と変わらない。

この If 文の判定だが、If C=0 And Y≦√(X) としても良いが、123456789 の素因数分解では15秒ほど余計に時間がかかる。


平方根よりも小さくなる時、KENさんの案では Y を 0 にしている。私の案では D を X に変更することで、結果的に Y が 1 になる。いずれもDoループを抜けるための方策である。この点でも実行速度に大きな違いは無い。

私の案は、結果表示を新たに追加しないでプログラムを改造するという点にチョットこだわった。D を X に変更すると、結果的に Y が 1 になり、従って最後にもう一回ループが回ることから、Do ループを抜けた後に結果表示のコードを書く必要が無くなるわけだ。



この変更により、実行時間が以下のように大幅に改善された【修正】。

入力した自然数結果改造前の時間改造後の時間
123453 x 5 x 82320秒2.5秒
12345626 x 3 x 64320秒3秒
1234567127 x 97214分1秒
123456782 x 32 x 47 x 145936分8秒
12345678932 x 3607 x 3803約5分3分
98765432132 x 172 x 3797213時間以上33秒
9876543223 x 37 x 3336672.5時間43秒
98765433 x 227 x 145036分12秒
9876542 x 3 x 97 x 16977秒6.5秒
987655 x 197538分8秒
987622 x 3 x 82320秒3秒


目を見張るべき時間短縮となった( ^o^)ノ

KENさんのご指摘のように、大きな素因数が1つだけ出てくる場合に速度向上が顕著だ。しかし、32 x 3607 x 3803 のように似たような3桁の素因数が含まれる場合は、それほど大きな高速化はできない。√X の効果が出るまでに、D を2づつ増やすのに時間がかかるためと考えている。その証拠に一旦 3607 が出ると、次の 3803 がほぼ瞬時に得られる。


なお、今回の改善で計算速度は向上したが、 カシオの最新の関数電卓 fx-995ES に内蔵されている素因数分解の計算速度には及ばない。




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

人気ブログランキングへ


FC2ブログランキングへ


keywords: fx-5800Pfx-995ES、プログラム素因数分解プログラム関数電卓

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

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

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

やす (Krtyski)

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


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

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

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

人気ブログランキングへ


FC2ブログランキングへ


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

リンク
月別アーカイブ
Sitemap

全ての記事を表示する

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

この人とブロともになる

QRコード
QR