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:取得したキーコード




応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 



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

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

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

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

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




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 の時(反応が遅く、モグラを逃した時)の減点を "BURST LOSS"と呼び、変数S に格納する。
変数Sデフォルトを25とする
BURST 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 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)が増える
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
C>E⇒P-S→P
                                  :2014/03/20 修正
IfEnd
Else
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
K=25 Or K=41⇒Break
 
LpWhile 1
K=41⇒Goto 2
                                  : [RCL] キーで同じ条件でのゲーム再開
K=25⇒Return
                                  : [0] キーでメインルーチンへ戻る
==================


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

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 が増えてゆくので、今は愉しい。


つづく...

⇒ もぐら叩き~まとめ~



応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 


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 になるのが 50%程度、Z=1 になるのが 25%程度、Z=0 になるのが 25% 程度

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


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

本物モグラは、乱数で得られる 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)



応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 



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)



応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 



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 に内蔵されている素因数分解の計算速度には及ばない。



応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 



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

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

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

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)



応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 



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)



応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 



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 の処理速度については検証済みだ [2017/08/06 追記・修正]

fx-5800P:コマンドの処理速度【再編集】
fx-5800P:変数アクセス、比較・論理演算、条件分岐の速度比較


さてここで忘れてはいけないのが、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)




応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 



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-FD10 Pro やグラフ関数電卓 fx-9860G シリーズ、fx-9860GII シリーズ、fx-CG20 や fx-CG50 も Getkeyコマンドを備えており、これらのキーコードは完全に互換性がある。ただし 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 コマンドを用いてモグラを消す処理を追加してある。

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


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


つづく...

⇒ もぐら叩き(3)



応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 



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)



応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 



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

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

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

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

やす (Krtyski)

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


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

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

なお管理人はカシオ計算機の関係者ではなく、Casio Basicが面白いと感じる1ユーザーです。


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

リンク
月別アーカイブ
Sitemap

全ての記事を表示する

ブロとも申請フォーム

この人とブロともになる

QRコード
QR