fx-5800P:矢印キーの活用

fx-5800P用のゲーム Hit&Blow を、3~5桁に自由に変更して遊べるバージョンを作りました。

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

3桁に固定したHit&Blowの最初の画面は以下のようでした。
HB-Start 


この限られた表示の中で、3~5桁を自由に変更できるようにするため、以下のようにして空いている1行を活用します。

hb_Start4 hb_Start5 hb_Start3 

空いた1行には、桁数を表示させ、上矢印[▲]キーと下矢印[▼]キーで、3桁、4桁、5桁と自由に選べるようにしました。

  <UP:DN>

は、矢印キーを使って変更することを示しています。[▲]キーを押せば桁数の数字が増えますが、5 の時に[▲]キーを押すと 3 に戻ります。一方、[▼]キーは桁数を減らしますが、3 の次は 5 になります。このように 3、4、5 を循環します。 

矢印キーで、3、4、5、のいずれかを選んでもらうインターフェースは、3~5以外を設定される心配がなく、プログラムの中で入力チェックが不要になり、想定外の入力に対する再入力の処理も不要になります。

限られた表示スペースで効率的なインターフェールを実現するには、矢印キーは有用で、出来たプログラムの品質も向上します。

今回は、矢印キーを活用して、使いやすく動きのあるプログラムを作るメリットを紹介します。



桁数選択の仕様

最初は3桁の設定にするので、最初の画面では以下のように表示します。

 3 DIGITS  <UP:DN> 

ここで、[↑]キーを押すと、桁数を増やして、表示を

 4 DIGITS  <UP:DN>

と変化させます。

ここで、[↓]キーを押すと、桁数が減るようにして、表示を

 3 DIGITS  <UP:DN>

に戻るようにします。


さて、表示が以下のように5桁になっている場合、

 5 DIGITS <UP:DN> 

[▲]キーを押すたとき、6にはならず、3に戻したいので、

3  ⇒ 4 ⇒ 5 ⇒ 3 ⇒ 4 ⇒ 5・・・

と循環して変化させます。

[▼]キーでも同様に、

3 ⇒ 5 ⇒ 4 ⇒ 3 ⇒ 5 ⇒ 4・・・

と循環させます。

これを実現するための、プログラムの例を紹介してゆきます。



プログラムの構造

先ず、矢印キーを押したことをリアルタイムで知る必要があります。これには Getkeyコマンドが有用です。

※ Casio Basic の優れている点の一つが Getkeyコマンドを使いこなせるところにあります。


[▲]のキーコードは84、[▼]のキーコードは85なので、

If 文を用いて、


Getkey→K

If K=84:Then
[必要な処理]
IfEnd

If K=85:Then
[必要な処理]
IfEnd



といった、記述をすれば、それぞれのキーを押した時に異なる処理をさせられます。ここでは、Getkeyで得られたキーコードを変数Kに入れておき、それを If 文で 判別して必要な処理を行います。

リアルタイムで[▲]キーと[▼]キーが押された事を検知して、リアルタイム処理を行うためには、ループ(繰り返し)処理と組み合わなければいけません。ここでは、Do ~ LpWhile と組み合わせてみます。


Do

Getkey→K

If K=84:Then
[必要な処理]
IfEnd

If K=85:Then
[必要な処理]
IfEnd

LpWhile [ループ継続条件]



※ LpWhileは、おそらく Loop While の略です。英語のWhileには 「~している間は」 と言う意味がありますから、LpWhile [ループ継続条件] となります。英語の意味さえ分かれば Basic の理解に役立ちます。


ここで留意すべきは、このDo~LoWhileのループが回っている間は、[▲]キーと[▼]キーを押した時の処理のみが行えると言うことです。矢印キーを押す以外にリアルタイムで必要な処理を行う必要がある場合は、その処理を Do ~ LpWhile ループ内に記述しなければなりません。

普通は、矢印キーで必要な選択を行わせ、選択が終了すると、その選択を確定させるために、何かキーを押させるようなユーザーインターフェースを考えます。

そこで、ここでは [EXE] キーを押した時に選択を確定することにします。つまり、この Do ~ LpWhileのループでは、[▲]キーと[▼]キーに加えて、[EXE]キーが押されることを監視するようにします。

[EXE]キーのキーコードは47なので、キーコード K が47でない場合はループを継続するようにしておけば、Kが47の時にループを抜けることができ、Dp ~ LpWhile ループの次の処理へ移ることができます。


Do

Getkey→K

If K=84:Then
[必要な処理]
IfEnd

If K=85:Then
[必要な処理]
IfEnd

LpWhile K≠47





あとは、各矢印キーが押された時の処理を書けば終わりです。

今回は、この処理の工夫がメインテーマです。



矢印キーが押された時の処理を考える

ここで記述する処理は大きく分けて2つあります。

・表示

・桁数の循環を実現する
 [▲]キーを押した時、3⇒4⇒5⇒3⇒4⇒5・・・・・・
 [▼]キーを押した時、3⇒5⇒4⇒3⇒5⇒4・・・・・・



ここでは、桁数を格納する変数と G とし、Gの初期値を3とします。すると初期表示は、

 HIT And Blow
3 DIGITS <UP:DN>
 <EXE>:START
 < ? >:ANSWER


となります。

では、Gの初期値を3とし、上の表示を含めると、以下のようなプログラムになります。


3→G
Cls
Locate 2,1,"HIT And BLOW"
Locate 1,2,G
Locate 3,2,"DIGITS"

Locate 2,3,"<EXE>
:START"
Locate 2,4,"< ? >:ANSWER"

Do

Getkey→F
If F=84:Then
[必要な処理]
IfEnd

If F=85:Then
[必要な処理]
IfEnd

LpWhile F≠47




ここで、上から2行目のCls は、画面表示を全てきれいに消去(クリア)します。Cls は Clear Screen から来ています。

次に、[必要な処理] の具体的な内容は、次の2つです。
(既に上で述べていますが、念のため...)

・リアルタイムに桁数を循環させる
・リアルタイムにGの値の表示を変更する


Gの値は、3、4、5が順に変化するので、矢印キーを1回押した時、基本的にはG+1 か G-1 をすれば良い。そして、循環させるために、5から3へ変化させる、或いは3から5へ変化させるところを工夫すれば良いわけです。

最も簡単な方法は、If 文の利用です。

[▲]キーを押した時の処理として、
If G≧5
Then 3→G
Else G+1→G
IfEnd


[▼]キーを押した時の処理として、
If G≦3
Then 5→G
Else G-1→G
IfEnd


そして、Gの表示を更新するには、

Locate 1,2,G

を上記のそれぞれのIf文の中に追加すれば終わりです。

If ~ Then ~ Else ~ IfEnd で出てくる ThenElse は、その英語の意味が分かっていれば、非常に分かりやすくなります。Then は 「そうならば...」と言う意味があり、Else は 「それ以外」 と言う意味があります。
もし G≦3 ならば、5→G (5をGに入れ)、それ以外の場合は G-1→G (Gから1を引き算して G に入れる) と言う理屈を、そのまま英語で表現しただけです。このように Basic は英語の意味さえ分かれば、非常に理解が楽になります。



※ "→" 命令は、Casio Basic 独特の代入命令です。パソコンの Basic では、代入命令に "=" を使って、G=5 などと記述します。


Locateコマンドは、必要な位置に必要な表示を行えるので、他の表示はそのままで桁数だけを書き直すことが出来る、大変便利なコマンドです。

※ Casio Basic の優れている点の1つに、Locateコマンドによる柔軟な表示能力があります。


3→G
Cls
Locate 2,1,"HIT And BLOW"
Locate 1,2,G
Locate 3,2,"DIGITS"

Locate 2,3,"<EXE>
:START"
Locate 2,4,"< ? >:ANSWER"

Do

Getkey→F
If F=84:Then
If G≧5
Then 3→G
Else G+1→G
IfEnd
Locate 1,2,G

IfEnd

If F=85:Then
If G≦3
Then 5→G
Else G-1→G
IfEnd
Locate 1,2,G

IfEnd

LpWhile F≠47





もう一つ、同じことを行うための別のプログラムを紹介します。いきなり例を挙げますが、ここでは僅か2行で [必要な処理] を実現しています。

個人的には、この方がエレガントなので、好きです。


3→G
Cls
Locate 2,1,"HIT And BLOW"
Locate 1,2,G
Locate 3,2,"DIGITS"

Locate 2,3,"<EXE>
:START"
Locate 2,4,"< ? >:ANSWER"

Do

Getkey→F
If F=84:Then
4+G-3Int((G+1)÷3)→G
Locate 1,2,G

IfEnd

If F=85:Then
2+G-3Int((G-1)÷3)→G
Locate 1,2,G

IfEnd

LpWhile F≠47



循環する桁数を 式として表現できるので、このようなプログラムも可能になるわけです。

この式の基本的な考え方は、「どんな整数でも3つの連続した整数にグループ分けすること出来る」 ことに基づいています。ここでは「剰余系」と言う考え方を利用しています。どんな整数でも3で割った時の余りは、0、1、2のどれかになります。これを3の剰余系と言います。

※ 5つにグループ分けしたい場合は、5の剰余系、つまり5で割った時の余りの数で分類すれば良いので、汎用性のある考え方です。


[▲]キーを押した時、基本的には G を1つ増やす、つまり G+1 とします。そして、この G+1 は、3、4、5のどれかに対応させるために、3の剰余系を利用しています。

整数 N を 3 で割った時の余りは、N - [3×Int(N ÷ 3)] で得られます。例えば、N=25 の時は、この式は 1 になります。


この式は、25÷3 = 8 余り 1 となることから、余りの 1 を求めています。少し細かくみていきます。

Int(N÷3)
は、253 で割って、整数部分を取り出しています。25÷3 = 8.3333333..... なので、整数部分は になります。余りの部分まで 3 で割っているので、.3333333.......と小数が現れています。そこで、8 を 3 倍して元に戻して、25 から引けば、余りが出てくるわけです。


或いは、中学レベルの数学の力を借りて、別の簡単な説明を試みます。

25 は、3の倍数 3A と 余り M を使えば、25 = 3A + M と現せます。
これを一般的に書くと、整数 N は、

N = 3A + M, (Aは整数)

この式を変形して、

M = N - 3A          [式1]

つまり、余りが求められます。

今、Mを求めたいのですが、A が何かは分かりません。但し、M0, 1, ,2 のいずれかです(これを利用します)。

N
3 で割り算すると、

N/3 = A + M/3

M0, 1, 2 のいずれかなので、M/3 は必ず 1 よりも小さい小数 0.xxxxx となります。つまり、
N/3 は、A.xxxxxxxx という小数になります。

そこで、N/3 の整数部を取り出せば、それは A となります。つまり、

A = Int(N÷3)         [式2]

となります。ここでは、M = 0, 1, 2 であることを利用しました。

[式1][式2] から、

M = N - 3×Int(N÷3)

と、余りが求められます。

このように、剰余系 と言う考え方は、プログラムで利用できるので、覚えておくと便利だと思います。

※ 剰余系 を数学的に厳密に説明すると、とたんに馴染みにくい、分かりにくい説明となります(Googleなどで検索すると、頭が痛くなる説明に出くわします、例えばここ)。要するに、整数はその余りによってグループ分けができると言うこと!! 3の剰余系は 0, 1, 2 の3つのグループ、5の剰余系は 0, 1, 2, 3, 4 の5つのグループに分けられて、どのグループに分けられるかは、簡単な式で現せる、ということです。



従って、G+1 を 3 で割った時の余りは、

(G+1) - 3Int( (G+1) ÷ 3)


で得られ、0、1、2 のどれかになります。これを 3、4、5 のどれかにするには、単純に 3 足せば良いですね。

よって、G+1 を 循環する 3、4、5 に対応させる式は、


3 + (G+1) - 3Int((G+1)÷3) = 4 + G - 3Int((G+1)÷3)


となるので、プログラムでは、この計算結果をGに代入します。



同様に、[▼]キーを押す時は、基本は G-1 となり、 その3の剰余系をを考えます。G-1 を3で割った時の余りは、

(G-1) - 3Int( (G-1) ÷ 3)

で得られ、0、1、2のいずれかになります。これを 3、4、5 のいずれかにするには、3を足せば良いので、G-1 を循環する 3、4、5に対応させる式は、

3 + (G-1) - 3Int(G-1)÷3) = 2 + G - 3Int((G-1)÷3)



となるので、プログラムでは、この計算結果をGに代入します。



If文を用いる方法式で計算する方法のどちらが良いかは、ケースバイケースです。

If文を使う方が、プログラムが分かりやすいので、バグが出にくいメリットがありそうです。式を使うと処理が速くなりそうですので、スピードが大切なゲームのプログラムでは、式を使った方が良いかも知れません。

今回の上記のプログラムの場合は、実際に比較してみると、処理速度はそれほど変わりません。If文による条件分岐が単純なのがその理由でしょう。処理速度が変わらないのならば、分かりやすい If 文を使った方が良さそうです。


プログラムによっては、If 等を用いた条件分岐が煩雑になると、明解な式を用いた時の処理速度が優位になる場合もありますので、私は式によるアプローチも試みるようにしています。



脱線してしまいました。

限られた画面スペースを有効に利用した入力方法には、矢印キーは非常に利用価値が有ることがお分かりだと思います。




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

人気ブログランキングへ


FC2ブログランキングへ


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

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

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

コメントの投稿

非公開コメント

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

やす (Krtyski)

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


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

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

おもしろい・役に立つならクリックしてください。励みになります。
にほんブログ村 IT技術ブログ 開発言語へ
にほんブログ村


人気ブログランキングへ


FC2ブログランキングへ


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

リンク
月別アーカイブ
Sitemap

全ての記事を表示する

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

この人とブロともになる

QRコード
QR