fx-5800P【ゲーム】:もぐら叩き~まとめ~

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


fx-5800P で作る「もぐら叩き」ゲームのまとめ
コード修正 2014/03/20
fx-FD10 proに関する記述追加 2014/09/28
コード誤記修正 2016/05/12
  fx-CG20 に関する記述修正 2017/01/04
 


普通のプログラム作成の記事と異なり、多少冗長な内容になっており、(1)~(8)で、徐々にプログラムを作ってゆく様子を複数の記事で紹介した。


最終的なプログラムは、本ページの一番下に掲載した。


一連の連載は開発ストーリーになっている。

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

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

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

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

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

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

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

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



fx-5800P に搭載されているプログラミング言語は、Casio Basic というカシオの味付けをした BASIC言語 だ。

特に、もぐら叩きのようなゲームを作る際に特に重要かつ必要なものは、以下の機能だろう。
1) 広い表示画面
2) Getkeyコマンドによる、リアルタイムキー入力監視機能
3) Locateコマンドによる、柔軟な表示機能


さらに、昔のプログラム電卓に搭載されていた BASIC と異なり、構造化 BASICである点も特筆できる。昔のプログラム電卓やポケコンに搭載されていた BASIC は行番号と GOTO コマンドでプログラムの流れを作っていたが、現在の Casio Basic は Goto コマンドを使わずに制御構造を作れるので、ブロック構造による 構造化プログラミングができるようになっている。

これらの機能が、fx-5800P を魅力的にしている。


CASIOの電卓の中で、上記を満たすプログラミング言語を搭載されているのは、私が入手しているマニュアルを調べる限り、下記の4機種程度で、比較的限られている。

・fx-9860G: グラフ関数電卓(生産終了)
 取扱説明書

・fx-9860G II: グラフ関数電卓(現行品)
 メーカーサイト / 取扱説明書

・fx-CG20 / fx-CG10: グラフ関数電卓(現行品)
 メーカーサイト / 取扱説明書

・fx-FD10 pro 土木測量向けプログラム関数電卓 (現行品)
 メーカーサイト / 取扱説明書

・fx-5800P: プログラム関数電卓(現行品)
 メーカーサイト / 取扱説明書


fx-FD10 pro fx-FD10 pro


fx-9860GIIfx-9860G II 
fx-CG20fx-CG20 

fx-5800P-3fx-5800P 


上で紹介した機種には、新世代の CASIO BASIC が搭載されている。fx-5800Pが最も機能制限されていて、他はfx-5800Pのほぼ上位互換となっている。

完全互換でないのには理由がある。電卓の機種が異なると、ハードウェアの違いからキー配置が異なる。従って、Getkeyで得られるキーコードが異なるため、ソースレベルでの互換性は無い。これを除けば fx-5800Pのプログラムからの移植性は比較的高いと(旧来の命令の互換性については、少し注意が必要だ⇒こちらを参照)。

上で紹介したもの以外の、過去のグラフ関数電卓や、プログラム関数電卓では、上記の3つの条件を同時に満たすものは無い。グラフ機能の無いプログラム関数電卓としては、2006年発売の fx-5800P が唯一上記3つの条件を満たす。しかし、fx-72F、fx-71F 、fx-3600P、fx-3950Pなどはプログラム機能が十分でないので 魅力的な新世代 Casio Basic を搭載していないので、推奨機種から除外する。

fx-9860GII、fx-CG20、fx-FD10 Pro は、1万円以上の価格だ。

一方で、fx-5800P は 6千円台前半 (2017/01/01時点の Amazon価格) と格段に手軽な価格だ。この価格で、上記3つの条件を満たす言語を搭載しているのだから、改めて魅力的なマシンと言える。

※ 興味があれば、最近のCasio プログラム電卓の価格動向 を参照ください。


当初は、fx-5800P のような電卓で、遊べるアクションゲームを作れるとは思っていなかった。いきさつは、以下の記事に書いた。

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

たまたま、Goto~Lbl コマンドで、カウントタイマーを作ってみると、意外に速いことから、実際に遊べるレベルのアクションゲームを作れるかどうかを試したくなったのが、もぐら叩きを作り始めた動機だった。

パソコンで作るゲームと異なり、最初にゲーム仕様を作るのではなく、機能を追加した時にゲームとしてのスピード感を損なわないように探りつつ、様子を見ながらゲーム仕様を作っていった。実際に私自身が考えたり試したりした事柄を、時系列で実況中継風に書いた結果、冗長な記事となってしまった。

その結果、そこそこの出来映えとなったと思っている。

実力の有る方なら、一気にスイスイとプログラムを作れるのだろうが、そこは私のスキルレベルに読者の皆さんを付き合わせてしまった。


できあがったゲームは、バリバリのゲーマーには物足りないのだが、普段からあまりゲームで遊ばない人間(=私)には、少しすつスキルアップして、得点が増えてゆくのが愉しい。


ご興味の有る方は、是非一度プログラムを入力して、遊んでみて欲しい。


もぐら叩きが意外にうまくいったので、最近はシューティングゲームができないものか?と、色々と動きのあるルーチンを作って遊んでみている。ひょっとしたら、何かシューティングゲームができるのかも知れない。

電卓の遅い処理速度、完全シングルタスク、広いといっても16×4 しかない画面で、動きやロジックを試しながら、遊べそうなゲームを模索してみようと思っている。


おしまい( ^o^)ノ



以下は、プログラムコード: [2016/05/15 誤記修正]

もぐら叩き: Wack -a-Mole by やす(Krtyski)

Wack-a-Mole_src 





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

人気ブログランキングへ


FC2ブログランキングへ


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

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

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

fx-5800P のキーコード 【修正あり】

【2013/11/3 修正】
fx-5800Pのキーコード取得プログラムのソースに、1行抜けがあったので、それを修正。同時に、若干のスリム化をした。 お詫びして以下に修正を加える。

[2015/12/07 修正]
Casio Basicを使いこなす前に書いた記事だが、その後多くのプログラムを書いて Getkeyコマンドの有用性が分かってきたので、それに伴う修正を行った。



パソコンのプログラミング経験者は、キーボードのキー1つひとつに、固有の番号が割り当てられていることをご存じだろう。
この番号をキーコードと言う。

fx-5800P-3 

カシオプログラム関数電卓 FX-5800P-N

fx-5800Pもプログラミングでキーコードを使えるようになっている。
特定のキーが押されたかどうかを監視することができるわけだ。

fx-5800Pの専用プログラミング言語には、Getkey と言うコマンドが用意されている。

Getkeyコマンド
・引 数:なし
・戻り値:取得したキーコード
・動 作:Getkeyが実行された時、最後に押されたキーのキーコードを返す。何も押されていない場合は0を返す。

なお、[AC/ON]キーは例外で、それ以外の全てのキー(49個)のキーコードを取得できる。


直前に押されたキーのコードを取得することから、パソコンと同様に、キーバッファからキーコードを取得するようになっているのだろう。

※ fx-5800Pの取扱説明書:以下からPDFファイルをダウンロードできる
http://support.casio.jp/manualfile.php?cid=004007004



Getkeyを使う場面


Getkeyが有用なのは、プログラムが何か処理をしている時に押したキーに応じて処理を割り込ませる場合だ。テンキー以外のキーを使うメニュー処理にも有用だ。

そこで、[9]をキー入力してメニュー選択を行うプログラム作ってみる。

試しにGetkeyを使わないプログラムを作ってみると、以下のようになる。
ここでは、[9]を入力した時、入力した数字を表示させることにする。

======================
"INPUT NUMBER"?→K
"THE NUMBER = ":K◢ 

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

このプログラムを実行すると、

------------------
INPUT NUMBER ?
------------------


と表示され、「9」を入力すると、

------------------
INPUT NUMBER ?
9
------------------

と表示され、一旦処理が止まる。

ここで、[EXE]キーを押すと、次の処理へ進んで、「入力した内容を表示する」処理が実行される。

------------------
INPUT NUMBER ?
9
THE NUMBER =   9
------------------

Getkeyを使わずに入力命令「?」を使うと、必ずプログラムが一旦停止するので、先へ進むにはどうしても [EXE]キーを押す必要がある。メニュー選択で余計なキー操作が必要だ。それでもテンキーを使ったメニュー処理なら、この方法は簡単ではある。


次に、Getkeyを使って、[9]を押してメニュー選択すると、[9]のキーコードを表示するプログラムを作ってみる。

======================
"INPUT NUMBER ?"
Do
Getkey→K
LpWhile K≠33
"THE NUMBER =":K◢ 

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


キーが押されたかどうかを監視するには、Getkeyコマンドとループ処理と組み合わせる必要がある。

Do~LpWhile ループ処理では、キー入力監視を行い、数字キー[9]に相当するキーコードを取得しない限り、ル-プが回り続ける。キーコード33が取得されると、ループを脱出して、次の表示処理へ進む。

プログラムを実行すると、

--------------------
INPUT NUMBER ?   ■
--------------------

と表示される。

右端の■は、プログラムが動いていることを示す。つまり、ループが回り続けているわけだ。

ここで、[9]キーを押すと、

------------------
INPUT NUMBER ?
THE NUMBER =
            33
------------------

と[9]のキーコードである33が表示された。


Getkeyコマンドを使うと、メニュー選択のために何かキーを押すと、直ちに次の処理を行えることが分かる。さらに、テンキー以外のキーを使うには、Getkey を使うしかない。


キーコード取得プログラム
fx-5800Pの取扱説明書には、各キーのキーコードが記載されている。

Getkeyを利用するプログラムを書いている時、手元に取説が無いことが結構ある(私の場合は、通勤電車で電卓プログラミングを愉しんでいるので、こういうことになってしまう)。

そこで、キーコードを調べて表示するプログラムを作ってみた。

fx-5800P専用
キーコード取得プログラム:2013/12/20 修正
===============================
"Get KEYCODE"
Locate 6,3,"HIT ANY KEY"
Locate 8,4,"
:QUIT"
Lbl 0
Do
Getkey→K
LpWhile K=0
Cls
Locate 1,1,"KEYCODE =   "
Locate 11,1,K
Goto 0

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


これを実行すると、

----------------
  GET KEYCODE

   HIT ANY KEY
     :QUIT
----------------

と、プログラムの説明を表示。

ここで、いきなり好きなキー(調べたいキー)を押す。

例えば、[DEL]キーを押すと、

-------------------
KEYCODE = 34    ■
    HIT ANY KEY
            :QUIT
-------------------

と表示される。

ここで表示されているキーコード34は、動作開始で押した[DEL}キーのキーコードだ。

さらに、好きなキーを押すと、そのキーコードが次々に表示される。 結構重宝している。




keywords: fx-5800PGetkeyコマンドキーコード, keycodeプログラミングプログラム関数電卓

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

続きを読む

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

Casio 関数電卓の素因数分解

  追記 2015/06/18

これまで、素因数分解プログラムについて取り上げています。

 ・ fx-5800P で素因数分解
 ・ fx-5800P で素因数分解再び
 ・ fx-5800P 素因数分解 - バグ修正と表示変更
 ・ fx-9860GII への移植 - 素因数分解
 ・ VBAで素因数分解

これらの記事の発端は、カシオのスタンダード関数電卓 fx-995ES に因数分解機能が搭載されたことに始まります。
素因数分解機能が内蔵されたのなら、プログラム電卓で作ってみようと思ったわけです。但し、自作プログラムは、逆立ちしたって内蔵機能よりも速く計算できません。これは、チョット気になっていました。

そこで、今回は、素因数分解のアルゴリズムの話題です。

実は、すけっぴぃ様から、素因数分解アルゴリズムの効率化に関するコメント(ここ)を頂いており、すぐには役に立つ情報を返信できなかったのですが、心の隅に引っかかっていたこともあって、この話題を少し掘り下げてみます。


 
私の手持ちの電卓で素因数分解ができるのは、最初から機能が内蔵されている fx-995ESfx-JP900、それに作ったプログラムが走る fx-5800P と fx-9860GII の4機種。
Int_fx-995ES Int_fx-JP900 Int_fx-5800P Int_fx-9860GII 
順に、fx-995ESfx-JP900、fx-5800P、fx-9860GII

最近、fx-JP900 を入手し、素因数分解機能を試したところ、fx-995ES よりも大幅に計算が速くなっていて、さらに得られる素因数の桁数が増えています。

幾つかの素因数分解結果を、fx-995ES、fx-JP900、fx-5800P のプログラム、カシオの高精度計算サイトKe!san で行った結果の一覧表を再掲載します。← Casio fx-JP900 (その3) から抜粋

整数fx-955ESfx-JP900fx-5800PKeisan
1,234,567127x(9721)127x9,721127x9721127x9721
98,765,43223x37x(333667)
(1.7秒)
23x37x333,667
(0.4秒)
23x37x333667
(27秒)
23x37x333667
9,516,208,47332x172x(3,658,673)32x172x(3,658,673)32x172x365867332x172x3658673
123,456,78932x(13717421)32x(13,717,421)32x3607x380332x3607x3803

因数分解できない場合は ( ) 付きで表示される仕様で、そこは fx-955ES も fx-JP900 も同じ。
但し、fx-995ES は素因数が4桁以上で ( ) 付きになっていましたが、fx-JP900 では素因数の桁数制限が大幅に緩和され、上の例ですと6桁まではOK。

また、fx-JP900 の取扱説明書17ページを見ると、素因数が 1,018,081 以上の素因数を持つ時は計算エラーになると書かれていますが、上の1つめ、2つめ、3つめの例では、( ) 付きで結果が表示されています。これ以上計算できないが、たまたまそれが素因数だったと解釈すれば良さそうです。( ) 付きの場合は、それが正しいかどうかの保証が無いと言うことでしょう。

4つめの例では、( ) 付きの結果は、さらに因数分解できるが、これ以上計算できないことを示しています。

[2015/06/18 追記]
コメント欄での sentaro様とのやりとりから、求める素因数の桁数を制限すること、そしてCPUの演算速度の簡単な比較から、2と3以上の奇数で順次割り算する単純なロジックても、それぞれの実行時間をほぼ説明できそうだ、と今のところの結論です。(追記終わり)



素数は整数論の一分野で研究されていて、素数が無限個存在することは、紀元前300年頃に証明されています。しかし、未だに素数を求める公式が見つかっていないし、素数の密度を求める式も見つかっていません。ケースバーケースの近似的な式があるだけです。それだけ神秘的な数が素数と言えるのですが、だからこそ素数は暗号通信の要として、実用上極めて重要なものになっています。応用工学で重要な素数だからこそ、数学教育において素数は重要だと考え、カシオは素因数分解機能を内蔵したのかも知れません。

ところで、遅いCPUを搭載した fx-5800P で走らせた素因数分解プログラムは、処理が遅いので、あまり凝ったアルゴリズムを実装できません。それに比べて内蔵機能の計算が桁違いに速いことが、気になっていました。

そんなとき、fx-JP900 の評価をしていて、正しく計算する条件として求める素数の桁数に制限があることを改めて考えてみました。桁数の制限をかけるアルゴリズムがあって、それを使えば Casio Basic でも速いアルゴリズムを実装できるかもしれないと思いました。そこで、具体的なプログラムにするには、まだ不完全ですが、取りあえず書いてみます。


fx-995ES では3桁以内の素因数に分解して表示することができるのですが、正しい計算が保証できるときの素因数が3桁と言うのは、どういうことか? 例えば、何十個かの素数の表をメモリ内に持っていて、それを使って計算すれば、かなり計算量が節約できるかも知れません。3桁つまり1~999の範囲にある素数は168個で、最大の素数は 997 です。168個程度のデータならメモリに入れておくのは現実的です。与えられた自然数をこの168個の素数で次々と割り算してゆけば、2と奇数で順次割り算するよりも、遙かに計算量が少なそうです。

ある整数の素因数分解を行う時、素因数はその整数の平方根以下になることを使い、さらに2と奇数を順に割り算して素因数を求める計算を、fx-5800P や fx-9860GII 用に書いたプログラムで行っています。このとき、3桁の素数で最大は 997 なので、9972 = 994009 以下の素因数分解は、メモリに保存された168個の素数で順割り算すれば、かなり計算量は節約できます。fx-5800P や fx-9860GIi で作ったプログラムでは、2と奇数で割り算するので、499個の数で割り算しています。つまり、計算量は 168÷499 = 0.3367 つまり 約33%、1/3 にに抑えられます。
Casio Basic での変数参照や配列参照のアクセスに比べて、関数計算する際のテーブル参照は遙かに速いと考えられるので、これで内蔵機能が速いことが説明できそうです。この方法を Casio Basic のプログラムに反映する際は、算術演算に 1~1.5ms 程度かかり、配列変数や行列へのアクセスに20ms程度かかること、そしてこの差を考慮して、本当に速くなるのかどうかを検討する必要があります。


一方 fx-JP900 は、1,018,081 以上の素因数を持っている整数ではエラーになる仕様です。ちなみに 1,018,081 は素数でなくて、これを素因数分解すると 10092 です。fx-5800P のプログラムで計算してみると、1,018,081 未満で最大の素数は、1,018,057 だと分かります。1,000,000 (100万)までの素数は 78,498個あるので、8万個近くある素数の表を不揮発メモリに持っておくのは、関数電卓としてはあまり現実的ではないでしょう。1,018,081 以上でエラーになることから、ひょっとしてこれを実装していることも考えられますが、素因数分解だけのために原価を押し上げるメモリを使うのは疑わしいわけです。

そこで、メモリに保存された素数テーブルを使わず、完全ではないものの、素数を計算して、それで順次割り算してゆく方法は、うまくすると計算量を減らして、高速化できるのかも知れません。或いは、メモリ上の素数テーブル参照と計算の併用も現実的な折衷案かも知れません。

素数の計算については、以下の式が非常に効率よく素数を計算するものとして知られています。
オイラの素数の式 
これはオイラーが見つけた、素数 p を求める式です。全ての素数をもれなく見つけることはできません。
ただ、この式の面白いのは、x  が 0 から 39 の時に得られる数が全て素数だと言う点にあります。但し、x=39 の時得られる素数 1601 以下には、この式で得られない素数が沢山あります。1601 以下の全ての素数を算出できるわけではありません。

さらに、 が 0 から 60 の時は、x = 40, 41, 42, 44, 49, 50, 57 の7個の x 以外で、 p は素数になります。素数を算出する効率は、x が 0 から 60 で計算した61個の値のうち88.5% が素数になります。繰り返しますが、これで得られる3071 以下には、この式の結果以外に多くの素数があります。

xpxpxp
0411322326743
1431425127797
2471528128853
3531631329911
4611734730971
57118383311033
68319421321097
79720461331163
811321503341231
913122547351301
1015123593361373
1117324641371447
1219725691381523
391601
 ・・・・・・
603701
10081017113

ちなみに、x = 1009 の時 p = 1,019,131、x = 1008 の時 p = 1,017,113 となります。つまり、x = 1008 で得られる1,017,113 がこの式でエラーにならない最大素因数 1,018,057 に最も近いものだと分かります。この式では、100万までの素数の47.5% が求められることが調べられていて、効率は半分以下に落ちます。しかし、現在 fx-5800P や fx-9860GII に実装しているプログラムのロジック「2と奇数で約 50万回近く割り算する」よりも、1000回程度の割り算をする方が、計算量が 1/500程度になります。仮に3分かかっていた計算は1秒以下になりそうです。

与えられた整数に対して、先ず先に、このオイラーの式で得られる計算値から素数を選んで、それで順次割り算して、残った余りについて、2と奇数で順次割り算して計算すると言うアルゴリズムが考えられます。オイラーの計算値から少ない計算量で素数を見つけられれば、テーブルと計算の併用で、高速化の可能性があります。x をどの範囲まで使うのか、38 までとするか、60 とするか、1008 までとするか、その中間のどこかにするか、も実際の計算量とコマンドの処理速度から最適点を検討する必要があります。仮に、x = 1000 まで使うなら、1000の47.5% に相当する 475 個の素数で順次割り算するので、500 / 500,000,000 = 0.001% となり、他の計算量と計算時間を低く抑えられれば、大幅な高速化ができるかも知れません。

プログラムの実装は、そのうちやってみようと思います。もし先にプログラムを作られた方は、是非コメント欄で発表してください。お待ちしております。



ところで、余計な話になりますが、

The Asahi Shinbun Blobe - 数学という力 というサイトでは、素数と円周率の関係、素数と宇宙の真理の関係について解説されていて、なかなか面白いです。素数は現代数学の花形の1なのですね。

ゼータ関数 
これは、リーマンと言う数学者が名付けたゼータ関数というものです。一番右の項は、オイラー積という総積計算で、素数 p がしっかり出てきます。

この式で、s=2 の時は、
ゼータ関数(s=2) 
となって、素数 p のオイラー積 と円周率 π が結びつくことが発見された歴史的な式をゼータ関数で表したものです。素数と円周率の関係式をより一般化したゼータ関数で表現することで、より深く調べることができるというわけです。上の記事によれば、この式を巡った素数の熱い研究が進められているようですね。簡単に素因数分解できる公式が存在するのかどうか?まだよく分かっていません。そのうち見つかる筈と言う人もいれば、存在しないかも知れないと言う人もいます。あまり簡単に計算できると、インターネットなどで使われている暗号が簡単に破られることに繋がるので、大問題です。

脱線すると、このゼータ関数で s=-1 の時は、
ゼータ関数(s=-1) 
なんて、なってしまいます。自然数を無限に足すと、-1/12 になる、なんとも受け入れられない結果です。実は、ゼータ関数は複素数の世界のものなので、一見あり得ない結果に見えるわけです。

カシオの高精度計算サイト Ke!san のココでも取り上げられています。
ここでは、明確に書かれていませんが、s=-1 で、実数の世界を複素数の世界に拡張(解析接続)しています。ゼータ関数の性質として、これはやっても良いこと(s=1 以外で解析接続できてしまう)なので、間違っちゃいないのですが、紛らわしいですね。

1+2+3+4+・・・  は実数の世界と誰でも思うので、自然数の無限和が負の数である -1/12 に収束するなどと言うのは、実数の世界では間違いです。でも複素数の世界では収束するので、ゼータ関数は物理の計算で重宝されているわけです。

素数は大きくなると、まばらになるのか?その密度はどうなっているのか? これもはっきりと分からない問題でしたが、2014年には素数は極端な偏りがなく万遍なく分布することが発見されました。→ こちら


素数の性質の研究は、非常にホットな分野ですね。まぁそれだけ分からないからこそ、暗号に使われるわけです。
深淵な研究は数学者に任せるとして、取りあえずプログラム電卓で素因数分解の高速化が出来るかも知れないということで、一旦区切ることにします。




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

人気ブログランキングへ


FC2ブログランキングへ

 

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

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

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

fx-5800P でピタゴラス数

最終:2015年3月11日

プログラムにバグがあったので修正しました [2014/12/03]


a2 + b2 = c2 となる自然数の組 (a, b, c) をピタゴラス数といいます。(3, 4, 5) がピタゴラス数と言うのは、直角三角形の3平方の定理で有名です。

そこで、ピタゴラス数を調べる Casio Basic プログラムを fx-5800P で作ってみました。

実際の計算には、以下のようなピタゴラス数の性質を利用しました。

ピタゴラス数の性質 

例えば、(3, 4, 5)(6, 8, 10) は、いずれもピタゴラス数ですが、1つめを2倍すると2つめになり、これらは同じと見なすことにするので、「a, b, c の最大公約数は 1」と言う条件を付けています。(6, 8, 10) の最大公約数は、2 なので、条件から外れます。最大公約数が 1 の (a, b, c) を原始ピタゴラス数と言います。

m n の組み合わせに重複がなければ、全ての原始ピタゴラス数が重複なく得られると言うのが特長なので、この性質を利用して上の条件に合うような、mn を探して、見つかった mn からピタゴラス数 (a, b, c) を計算する作戦です。

先に M を決めて、そこから条件に合う N を探索し、N が 1 になった時はNの探索を終えて、次の M を決めて条件に合う N を探索する....これを繰り返します。



1) 最初、M を 3 とし、N を 1 とする。

2) 現在の M N からピタゴラス数を計算し、表示する

3) N 0 にならない範囲で 2 減らして、M÷N が割り切れないとき(MN が互いに素のとき)、その N を採用。割り切れる時は 3) を繰り返す。割り切れるかどうかは、M÷N の小数部分が 0 かどうかで判定。但し N が0 になると M÷N でエラー(0 で割り算できない)ので、その1歩手前の N が 1 の時には、Nの探索を終了する。

4) N0 以下になるとき、M を 2 つ増やし、M-2N に代入して、3) に戻り、正しい MN が見つかるまで 3) を繰り返す。

5) 2) へ戻る。 

文章よりも、2) ~ 4) のプログラムを見た方が分かりやすいでしょう。

Do
N-2→N
If N<0:Then
M+2→M:M-2→N
IfEnd
N=1⇒Break
LpWhile Frac(M÷N)=0




ピタゴラス数プログラム
3→M:1→N:1→D     (初期化処理)
Locate 1,2,"A="    
(初期画面表示)
Locate 1,3,"B="
Locate 1,4,"C="

Lbl 0

(M2-N2)÷2→A       
(ピタゴラス数の計算)
MN→B
(M2+N2)÷2→C

Locate 1,1,D        (見つかった回数の表示)
Locate 3,2,"       " (スペース14個)
Locate 3,2,A        
(ピタゴラス数の表示)
Locate 3,3,"       " (スペース14個)
Locate 3,3,B        (ピタゴラス数の表示)
Locate 3,4,"       " (スペース14個)
Locate 3,4,C        (ピタゴラス数の表示)

Locate 7,1,"EXE:Next"◢  
(操作法表示&プログラム一時停止)

Do               
(次の M と N を探す)
N-2→N
If N<0:Then
M+2→M:M-2→N
IfEnd
N=1⇒Break
LpWhile Frac(M÷N)=0
Isz D             
(見つかった回数を1つ増やす)

Goto 0


このプログラムは、Lbl 0 / Goto 0 の無限ループが基本構成ですので、終了するには [AC] キーを押します。

プログラムを起動すると、画面は以下のようになります。

Pytha1 

最初の原始ピタゴラス数 (4, 3, 5) が表示されています。
※ 左上: 探したピタゴラス数の個数。起動時なので 1
※ 右上: [EXE] キーを押すと次のピタゴラス数を探す


ここで、[EXE] キーを押すと、以下のように2つめのピタゴラス数がわかります。

Pytha2 

さらに、[EXE] キーを押すと、3つめのピタゴラス数を探します。

Pytha3 
※ 画像修正



今のプログラムだと、[EXE] キーを叩き続けなければ、大きなピタゴラス数が分からず、ちょっと物足りない。

そこで、[EXE] キーを長押しすると、ピタゴラス数の探索&表示を連続して行うように機能追加しました(連続モードの追加)。


※ 動画修正



使い方:
・起動すると、最初に作った「ステップモード」で、右上に EXE:Next  と表示。
[EXE] キーを押すと、次のピタゴラス数を計算して、表示します。

[EXE] キーを長押しすると「連続モード」になり、右上に (-): Stop と表示。
・連続モードでは、次々とピタゴラス数を計算して表示し続けます。
[(-)] キーを押すと「ステップモード」に戻り、右上の表示が EXE:Next に戻ります。

右上に EXE:Next と表示されていると、ステップモードだと分かります。(-):Stop と表示されていると、連続モードだとわかります。


連続表示のまま、しばらく置いておくと、以下のようになります。


※ 動画更新

ピタゴラス数が次々と表示されるのを見ていると、チョット面白いですね。


さて、キー長押しで機能選択する方法は、これまでも紹介していますが、今回のプログラムでも利用しています。この方法を知っていると、とても便利です。連続モードの機能追加には、[(-)] キーの通常押しの検出、[EXE] キーの長押しの検出を追加し、連続モードなら変数 E=0 、通常モードだと E=1 とし、表示を E の値に従って変更するようにしました。

これらのキー入力検知は以下のプログラムで処理します。

Getket=57⇒1→E
0→K
While Getkey=47
Isz K:K=7⇒Break
WhileEnd:K=7⇒0→E


次の短いプログラムを入力して、実際に遊んでみてください。

ピタゴラスの綴りが PYTHAGORAS なので、そのままファイル名としました。

(プログラム修正)

Pythagoras_Source 

※ Locateコマンドの空白は16個




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

人気ブログランキングへ


FC2ブログランキングへ


keywords: プログラム関数電卓、fx-5800P、キー長押し、CasioBasic、 ピタゴラス数

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

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

fx-5800P 素因数分解 - バグ修正と表示変更

2014/11/15: 掲載プログラムの転記ミスを修正しました。


素因数分解再び の記事で紹介したプログラムについて、すけっぴぃさんから、バグの報告 (「素因数分解再び」のコメント) を頂きました。

素因数分解した結果に、素数の2乗が含まれる時、その素数の2乗が素数に分解されず、そのまま残って、素数でないのに素数として結果表示されると言う問題です。

例えば、45 ( = 32 × 5) の素因数分解の結果が 9 × 5 となってしまうが、135 ( = 33 × 5) は、正しく結果表示されると言う問題です。


かなり前に頂いたご指摘なのに、すぐに対処できないまま時間が経ってしまい申し訳ありません。最近時間に余裕が少しできたので、調べたところ、原因が分かりました。


本文にあるコードの赤文字の部分の1行目(あるいは以下のプログラムの10行目)にある

Y≦D



Y<D

に変更することで、バグの解消ができました。


これまでのプログラムは、素因数を見つけるたびに表示するようにしていましたが、実はこの仕様にしっくりきていませんでした。
そこで、素因数分解の計算を終了後、まとめて結果を表示するように変更してみました。


プログラムを起動した時の画面:

素因数分解Startup


数を入力する:

素因数分解Input 


素因数分解を最後まで計算したあとで、結果を表示:

素因数分解DisplayResult 

1行表示されたら [EXE] キーを押して次の行を表示させます。
これを繰り返して、上のように <EXE> が表示されたらそれが最後の素因数です。
ここで、 [EXE] キーを押せば最初の入力画面に戻ります。

4行を超える結果になる場合は、再び1行目から上書きします。


プログラムは以下のようにしました。かなりヒドイ転記ミスがありましたので、修正したものを再掲載します [2014/11/15]

 素因数分解_改造版ソース 
 
LpWhile Y≧1 の下に、表示のための処理を追加してみました。
 
また、17行目、Do ループの中に表示のために必要な配列変数への代入処理を入れています。

配列変数は、通常の変数よりもアクセスにかなり時間がかかることが分かっていますので、今回の改造で、全体の計算速度が低下する筈です。

そこで、計算速度を、前回のプログラムと比較してみました。

入力した自然数結果前回プログラムでの計算時間今回プログラムでの計算時間
123453 x 5 x 8232.5秒2.2秒
12345626 x 3 x 6433秒2.6秒
1234567127 x 972176.5秒
123456782 x 32 x 47 x 145938秒6.6秒
12345678932 x 3607 x 38033分2分43秒
98765432132 x 172 x 37972133秒28秒
9876543223 x 37 x 33366743秒27秒
98765433 x 227 x 1450312秒11秒
9876542 x 3 x 97 x 16976.5秒5秒
987655 x 197538秒7秒
987622 x 3 x 8233秒2秒

それほど大きな違いは出ていません。結果として、Doループを何度も回る時間に比べて配列変数アクセスによる速度低下が無視できる程度だと思います。

fx-5800P は同じ計算でも計算時間に結構なバラツキがあることが、最近分かってきました。これについては、クロック回路に起因する可能性が考えられるとの情報があり、その場合はクロック精度が数%バラツクのも説明できそうで、温度の影響もありそうです。

このあたりは、こちら (fx-5800Pの速度差) (fx-5800P プログラムのバックアップ のコメント) が 情報源です。

従って、今回の測定から、処理速度はほぼ同じ、と言うべきでしょう。但し、1234567 の素因数分解だけは、どうもよく分からない結果ですね。

手元で測り直したら7秒程度でした。本エントリーはボロボロでした(-_-;)

ご指摘頂いた santaro様、ありがとうございます。



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

人気ブログランキングへ


FC2ブログランキングへ



カシオプログラム関数電卓 FX-5800P-N カシオプログラム関数電卓 FX-5800P-N
(2006/09/22)
CASIO(カシオ)

商品詳細を見る



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

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


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

fx-5800P:Hit&Blow【完成版】

以前 fx-5800P【ゲーム】:Hit&Blow で取り上げ、fx-5800P で3桁の数字を当てる仕様で実際にプログラムを作りました。

その後、桁数を3桁、4桁および5桁に自由に変えて遊べる Hit&Blow を作って遊んでみました。

3桁が一番面白く、4桁は難易度が高くなりますがそれなりに面白いと思います。5桁バージョンは、難し過ぎてゲームとしてはつまらないかも知れません。


そこで、桁数を自由に変えて遊べる Hi&Blow を紹介します。




ゲームの仕様

ゲーム開始画面
1.ゲーム開始時に、数字の桁数を、3、4、5から選択・設定する
2.開始画面には、以下を表示する
  ・HIT And BLOW のゲームタイトル
  ・3~5の桁数の選択機能
  ・
:START、< ? >:ANSWER
3.開始画面で、秘密のキー(キーの同時押し)で正解を表示する


hb_Start4hb_Start5hb_Start3 
※ 桁数の選定は、矢印キー [▲] と [▼] で3~5が順次変化するようにする。
fx-5800P の16桁X4桁画面をフルに活かした画面設計にする。

ゲーム進行画面
4.電卓が出題する正解数を、△HIT、◇BLOW と言うヒントを元に当ててゆく
5.正解数は、各桁0~9各の異なる数字とし、一番左の桁は0であっても良い
6.入力する数字の桁に同じ数字があると、エラーを表示して正しい入力を促す
7.入力する数字の桁が、最初に指定した桁より多いと、エラーを表示して正しい入力を促す
8.何回目の回答かを、表示する
9.10回以内に正解すると、EXCELLENT と表示する
10.10回を超えても正解しない時は、QUIT? と表示する。
11.10回を超えて正解すると、GOOD と表示する。

hb_3d_3hb_4d_4hb_3d_bingo  

※ ゲーム進行画面は、既に作っている Hit&Blowと基本的に同じになる。


ゲーム終了画面
12.正解すると、終了画面で YOU WIN IN xx TRIES と正解するまでの回答数を表示する
13.正解できず、QUIT? の表示で[DEL]キーを押すと、終了画面で正解を示す
14.正解できずに終了すると、終了画面で YOU GAVE UP   ANSWER = xxxxx と表示する
15.終了画面では、
:QUIT、<0>:TRY AGAIN とメニューも併せて表示する

hb_FInish_win 



プログラムコード

以下の4つのルーチンから構成します。
ルーチン種別プログラム名説明
メインルーチンHIT AND BLOWプログラムの流れと表示を主に行う
サブルーチン1S1HB345入力数を各桁の数に分解する
サブルーチン2S2HB345正解の数を生成する
サブルーチン3S3HB345回答を入力させる、ゲーム本体の処理を行う
サブルーチン4S4HB345入力した数の判定及びその結果表示を行う

fx-5800P はパソコンとの通信機能が無いので、コードを手で入力するしかありません。チョット長いコードになりますが、入力して遊んでみてください。

今回のプログラムに関連した、幾つかのプログラミングTIPS を今後紹介する予定です。何かリクエストやご提案があれば、是非お聞かせください。


メインルーチン: "HIT AND BLOW" (41行)

HB345_Code_main   

サブルーチン: "S1HB345" (24行)
HB345_Code_sub1   

サブルーチン: "S2HB345" (27行)
HB345_Code_sub2       

サブルーチン: "S3HB345" (32行)
HB345_Code_sub3       

サブルーチン: "S4HB345" (38行)
HB345_Code_sub4   



プログラムの基本構成と簡単な説明

メインルーチン: "HIT AND BLOW"
 初期設定
   ↓
 Lbl 0
   ↓
 開始画面表示
   ↓
 桁数選択と決定
   ↓
 正解数を決める <---> 正解数生成サブルーチン: "S2HB345"
   ↓
 回答の入力 <------> 回答サブルーチン: "S3HB345"
   ↓             Lbl 0
 終了画面          回答数の桁分解 <-> 桁分解サブルーチン: S1HB345"
   ↓            入力エラー処理
 Goto 0             回答数の判定 <--> 回答判定サブルーチン: S4HB345"
                 正解でない時 Goto 0
                 正解すればメインルーチンへ戻る


このように、メインルーチンと4つのサブルーチンからプログラム全体を構成します。


メインルーチン: HIT AND BLOW"
ゲーム全体の流れの制御と主なメニュー表示を行い、正解数決定サブルーチン(S2HB345) と  回答サブルーチン(S3HB345) を呼び出す。

最初の画面の<?>:ANSWER のメニューで正解を知るための秘密のキーは、キーコードが1桁になるようなキー入力をすれば良い。そのためには、複数のキーの同時押しを行う。例えば[4]と[7]のキーを同時押しする。詳しくは
ここ を参照してください。

最初の画面で決めた桁数は変数Gに格納される(G = 3, 4, 5)。

回答サブルーチン で正解表示フラグが1 (D=1) になってメインルーチンへ戻ってきた場合は、"YOU GAVE UP" の表示及び正解表示 "ANSWER = xxx" を行う。


正解数作成サブルーチン: "S2HB345"
決定された桁数(3、4、5桁)に従って、正解数を決定する。全ての桁が異なる数になるようにするところがポイント。

桁数(G)に応じた桁数で正解を生成する。整数乱数を生成する関数 IntRan#()を使用し各桁ごとに任意の1桁の数を得る。ここではDoループを用いて、各桁で同じ数になる場合はDoループ回し続け、全ての桁が異なる数になる時にDoループを抜ける。

メインルーチンで<秘密のキー>を押すと変数Dに1が入り、このルーチンにおいてD=1の時には正解を表示する。


回答サブルーチン: "S3HB345"
ゲーム進行画面を表示し、数字の入力をさせ、各桁の数を得るための桁分解サブルーチンと、入力された数の回答判定サブルーチンを呼び出す。正解が得られるまで処理を繰り返し、正解が得られたらメインルーチンへ戻る。

入力したn桁(n = 3, 4, 5)の数で同じ数が含まれる場合は、桁分解サブルーチンがエラーグラフEに1を格納する。このルーチンでは E=1 の時、「同じ数が含まれている(ERROR SAME NUMBER FOUND IN DIGITS)」とエラー表示をして、再入力させる。

このルーチン全体をDoループの中に収める。桁数Gでヒット数がGになれば正解となるので、H≠Gである限り、Doループで回答サブルーチンを回し続け、H=Gになった場合だけメインルーチンへ戻る(return)。つまり、このルーチンがゲーム本体となる。


桁分解サブルーチン: "S1HB345"
入力された数を、各桁の数に分解する。桁数(G)に応じた3つのルーチンを含む。入力したn桁(N = 3, 4, 5)の数で同じ数が含まれる場合は、エラーフラグ(変数E)に1を格納する。


回答判定サブルーチン: "S4HB345"
入力された数に対して、HIT数とBLOW数の判定を行い、その結果を表示する。結果が表示されたら、[EXE]キーを押させて 回答サブルーチン(S3HB345)へ戻る。

10回以内で正解が得られると "EXELLENT" と表示する。11回以上で正解が得られると "GOOD" と表示する。11回以上で正解が得られない時は "QUIT?"(やめますか?) "<DEL>"と表示する。[DEL]キーを押すと正解表示フラグ(変数D)に1を格納してメインルーチンへ戻る。



主な変数

G:桁数(3,4,5のいずれか)

A:正解のn桁数
K:数Aの1番左の桁の数
L:数Aの左から2桁目の数
M:数Aの左から3桁目の数
I:数Aの左から4桁目の数
J:数Aの左から5桁目の数

N:回答するn桁数
X:数Nの1番左の桁の数
Y:数Nの左から2桁目の数
Z:数Nの左から3桁目の数
V:数Nの左から4桁目の数
W:数Nの左から5桁目の数

H:ヒット数
B:ブロー数

C:回答回数
D:正解表示フラグ:
 D=0:正解表示をしない
 D=1:正解表示する
E:回答数エラーフラグ:
 E=0:エラーなし
 E=1:同じ数の桁があるエラー

K:取得したキーコード




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

人気ブログランキングへ


FC2ブログランキングへ


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

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

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

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