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の時にループを抜けることができ、Do ~ 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





さて、この If を用いたコードを工夫します(実は、これがメインテーマです!)。
以下に、同じことを行うための簡潔なコードを紹介します。ここでは僅か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)

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

この考え方は、プログラムで利用できるので、覚えておくと便利だと思います。特に動作の遅い fx-5800P のようなプログラム電卓では、プログラムが速くなるのでお勧めです!

※ 剰余系 を数学的に厳密に説明すると、とたんに馴染みにくい、分かりにくい説明となります(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 等を用いた条件分岐が多くなると、式を用いた方が間違いなく処理速度が早くなるので、私は式によるアプローチを好んで使っています。



脱線してしまいました。

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




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


 


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

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

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

コメントの投稿

非公開コメント

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

やす (Krtyski)

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


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

プログラム電卓を実際に使って気づいたこと、自作プログラム、電卓での Casio Basic, C.Basic そして Casio Python プログラミングについて書いています。

なお管理人はカシオ計算機の関係者ではありません。いつでもどこでもプログラミングができるプログラム電卓が好きな1ユーザーです。


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

リンク
月別アーカイブ
Sitemap

全ての記事を表示する

ブロとも申請フォーム

この人とブロともになる

QRコード
QR