パソコン活用研究5番街(Visual Basic、Excel(VBA)、BASIC プログラミング研究)
キーボード入力
キーボードからの入力に関する命令、関数というと、INPUT,
LINE INPUT, INKEY$, INPUT$,
KEY, ON KEY GOSUBといったところでしょうか。
INPUT および INKEY$の基本的な使い方については、BASIC超基本 、 BASIC超基本2 にて
とりあげました。また、リアルタイムゲーム作制のための実践的なキーボード入力に関するノウハウ
は、リアルタイムキースキャン でとりあげております。
ここでは、上記でとりあげた以外のキーボード入力に関する基本的なノウハウをまとめてみました。
1 キー入力待ちはINPUT$(n) が便利
INPUT,INPUT$,INKEY$
の違いはよろしいでしょうか。
キー入力待ち | 押されたキーを画面に表示 | 備考 | |
INPUT | 有 (リターンキーで入力確定) | 有 | 複数の変数(数値、文字)入力可 |
INPUT$(n) | 有 | 無 | 指定した文字数 (n) の入力 特殊キー入力可 |
INKEY$ | 無 | 無 | 1文字(1byte)のみ入力 特殊キー入力可 |
例えば、INPUT$(3)
とすると、3文字入力されるまで入力待ちします。
使い途といしては、いったんGAMEが終了して、もう一回やるかどうかを、"y"
か "n"で答えさせるような
場合に一番適しているでしょう。
簡単な例をあげておきます。
<Input0.bas>
10 a$=input$(1) 20 if a$="Y" or a$="y" then goto 100 30 if a$="N" or a$="n" then goto 200 40 goto 10 100 print "Contine":goto 10 200 print "end": end |
2 キー入力による条件分岐 INSTRの使用
先ほどでてきた、 <Input0.bas>
では、入力されたキーを IF文で判定して、それぞれの分岐先に
とばしていました。入力されるキーの種類がこれぐらいなら、まあいいでしょうが、5種類ぐらいのキーを
使い分けるゲーム、といったことになると、IF
文を5個並べることになります。そういう場合に、昔から
これぞBASICの定石といわれてきたのが、INSTR関数
の利用です。
簡単に INSTR の書式をあげておきます
INSTR ([<サーチ位置>], <文字列1>,
<文字列2>) [ ]は省略可 文字列1 の中から 文字列2を捜します。サーチ位置には、文字列1の中で捜しはじめる位置を指定します。 INSTRは、文字列2が見つかればその位置を、見つからなければ0を関数値として返します。 |
以下に<input0.bas>をINSTR で書き換えたものをあげます。
10 a$=input$(1) 20 on instr("YyNn",a$) goto 100,100,200,200 40 goto 10 100 print "Contine":goto 10 200 print "end": end |
これぐらいのコードを書くと、素人のBASICプログラマとしては、「ちっとはBASIC知ってるな」とかコメント
されたものです。(大昔、アマチュアのBASICプログラムの雑誌への投稿が盛んだった時代の話。
いつかって?ウーム、パソコン進化の歴史からすると、縄文、弥生時代とでもいうべきか)
3 INSTRは早いか
BASICの場合は、やっぱり処理スピードが早いかどうかもきになります。
INSTR関数をつかって「お主、少しはやるじゃねーか」と言われても、スピードダウンになったんじゃ
お話になりません。それで、いちおう処理スピードについても検証してみました。
<inputsp0.bas>
N88互換BASIC for Win 22秒 | Qbasic 22秒 |
10 width 80,20 20 cls 25 a$="" 30 t=val(right$(time$,2)) 40 for i=0 to 1000 50 if a$="Y" or a$="y" then gosub 200 55 if a$="N" or a$="n" then gosub 210 60 next i 100 t1=val(right$(time$,2)) 110 if t1<t then t1=t1+60 120 print t1-t :end 130 ' 22 200 return 210 return |
10 'WIDTH 80, 20 20 CLS 25 a$ = "" 30 t = VAL(RIGHT$(TIME$, 2)) 40 FOR i = 0 TO 300000 50 IF a$ = "Y" OR a$ = "y" THEN GOSUB 200 55 IF a$ = "N" OR a$ = "n" THEN GOSUB 210 60 NEXT i 100 t1 = VAL(RIGHT$(TIME$, 2)) 110 IF t1 < t THEN t1 = t1 + 60 120 PRINT t1 - t: END 130 ' 22 200 RETURN 210 RETURN |
<inputsp1.bas>
IF文を1つにしてみました
N88互換BASIC for WIN 13秒 | QBASIC 18秒 |
10 width 80,20 20 cls 25 a$="" 30 t=val(right$(time$,2)) 40 for i=0 to 1000 50 if a$="Y" or a$="y" then gosub 200 60 next i 100 t1=val(right$(time$,2)) 110 if t1<t then t1=t1+60 120 print t1-t :end 130 ' 13 (for nextループは5秒くらい) 200 return 210 return |
10 'WIDTH 80, 20 20 CLS 25 a$ = "" 30 t = VAL(RIGHT$(TIME$, 2)) 40 FOR i = 0 TO 300000 50 IF a$ = "Y" OR a$ = "y" THEN GOSUB 200 60 NEXT i 100 t1 = VAL(RIGHT$(TIME$, 2)) 110 IF t1 < t THEN t1 = t1 + 60 120 PRINT t1 - t: END 130 ' 18 (for__ next 13seconds) 200 RETURN 210 RETURN |
<inputsp2.bas>
INSTR関数使用
N88互換BASIC for WIN 15.5秒 | QBASIC 16秒 |
10 width 80,20 20 cls 25 a$="" 30 t=val(right$(time$,2)) 40 for i=0 to 1000 50 on instr("YyNn",a$) gosub 200,200,210,210 60 next i 100 t1=val(right$(time$,2)) 110 if t1<t then t1=t1+60 120 print t1-t :end 130 ' 15.5 200 return 210 return |
10 ' WIDTH 80, 20 20 CLS 25 a$ = "" 30 t = VAL(RIGHT$(TIME$, 2)) 40 FOR i = 0 TO 300000 50 ON INSTR("YyNn", a$) GOSUB 200, 200, 210, 210 60 NEXT i 100 t1 = VAL(RIGHT$(TIME$, 2)) 110 IF t1 < t THEN t1 = t1 + 60 120 PRINT t1 - t: END 130 ' 16 200 RETURN 210 RETURN |
ええとですね、これぐらい単純なプログラムだと、For
... Next のループ自体にかかる時間が無視できない
レベルにあるので、For ... Next
ループ自体にかかる時間を考慮して下表のようにまとめてみました。
N88互換Basic for Win | QBASIC | |
For ... Nextループ | 5 秒 | 13 秒 |
IF文 2個(Inputsp0.bas) | 17 秒 | 9 秒 |
IF文 1個(Inputsp1.bas) | 8 秒 | 5 秒 |
INSTR関数(inputsp2.bas) | 10.5 秒 | 3 秒 |
人それぞれ、いろんな評価があるでしょうが、実用上
INSTRを使うことは速さの点でも有益だと
言えましょう。ことにQBASICでの利用価値は高いと言えます。
蛇足ながら、N88互換BASIC と
QBASIC
でループの回数は300倍違います。ご注意。
4 LINE INPUT の利用
INPUTで文字列を入力する場合、カンマ(,)は、区切り記号として使うので、データとして入力できません。
カンマもデータとして入力したい場合は、LINE
INPUTを使えばO.K.です。
LINE INPUT はリターンキーが押されるまでの文字列を全てデータとして入力します。
(本来、LINE INPUTはファイルからの読み込みの方でよく使われる)
以下に、入力された文字列を、カンマのところでばらばらに区切って表示するプログラムを
あげておきます。他に、MID$, RIGHT$, LENなど文字列関連の関数も使った例になってますので
Very Short
な中に、濃い内容がつまったプログラムです。ビタミン剤のようなプログラムですから、
BASICはじめたバカリダヨーという人は、じっくり味わって消化して下さい。
<LINPUT.bas>
5 position=1:p=1 10 line input a$ 20 while p 30 p=instr(position,a$,",") 35 if p=0 then goto 60 40 print mid$(a$,position,p-position) 50 position=p+1 60 wend 70 print right$(a$,len(a$)-position+1) |
QBASIでの実行結果
C:\QBASIC>qbasic kasai,tsuyoshi,age,25,year,1995 kasai tsuyoshi age 25 year 1995 |
5 入力されたキーのアスキーコードの取得
入力されたキーのアスキーコードを利用したい場合というのがあります。
例えば、[Esc] キー や ->
のような矢印キーの入力の判定といった場合です。
このような時は、ASC関数を使います。
下のプログラムは何をやってるかと言うと、テキストファイルを読み込んで、画面に表示されない特殊キー
は[ ]内にアスキーコードを表示するというプログラム。75行に注目。
それから、80行は、読み込んだデータがラインフィード(LF アスキーコード10)だったら改行させている。
MS-DOSのTYPE コマンドにプラスαの機能をつけた感じのもの。
<KTYEPE.bas> QBASIC用
10 cls:key(1) on 20 on key(1) gosub 120 'N88互換BASIC用には on key gosub 120 でよい 30 on error goto 100 40 input "File Name :",file$ 50 open file$ for input as #1 60 while not(eof(1)) 70 a$=input$(1,#1) 75 if asc(a$)>31 then print a$; else print "["+str$(asc(a$))+"]"; 80 if asc(a$)=10 then print 90 wend 100 close 110 key(1) off:end 120 return 100 |
これも、QBASICの実行例をいちおうつけときます。自らを読みこんでみました。
File Name :ktype.bas 10 cls:key on[ 13][ 10] 20 on key gosub 120[ 13][ 10] 30 on error goto 100[ 13][ 10] 40 input "File Name :",file$[ 13][ 10] 50 open file$ for input as #1[ 13][ 10] 60 while not(eof(1))[ 13][ 10] 70 a$=input$(1,#1)[ 13][ 10] 75 if asc(a$)>31 then print a$; else print "["+str$(asc(a$))+"]";[ 13][ 10] 80 if asc(a$)=10 then print[ 13][ 10] 90 wend[ 13][ 10] 100 close[ 13][ 10] 110 key off:end[ 13][ 10] 120 return 100[ 13][ 10] [ 13][ 10] |
6 KEY, ON KEY
プログラム実行中に、キーを押して、割り込みをかけたい場合に使います。
上述の<KTYPE.bas>の10、20、110行目をみて下さい。
上述のプログラムでは、長いファイルを読みこんでいる時に、もう途中であきた、中断したいというケース
を想定して、ファンクションキー1(F1)を押せば、プログラムが終了するようにしてあります。
それが、10、20、110行目です。
KEY ON, KEY OFF は割り込みの許可、解除をします。
プログラム終了前に必ず KEY OFFする必要があります。さもないと、本来のファンクションキーの
機能がつかえないままとなります。
ON KEY GOSUB 割り込みルーチンの開始行の定義をしますが、N88互換BASIC
for WIN と
QBASIC で若干書式と機能が異なります。
N88互換BASIC for WIN
KEY [(キー番号)] ON [ ]は省略可 キー番号には1から10までのファンクションキーの番号を指定する。省略すると全てのキーを指定した ことになる。 ON KEY GOSUB 行番号, [行番号], .... [ ]は省略可 行番号には、割り込みのかかった時に分岐させたいルーチンの開始行を指定する。 行番号は、はじめから順に、F1,F2,F3・・・を押した場合に対応する形になる。 |
QBASIC
QBASICの場合は
キー番号が若干異なる。また、KEY( ) ON, OFFでキー番号を省略することは
できないようだ。
キー番号は 1から10がファンクションキー(これは同じ)、11が上矢印、12が左、13が右、14が下と
なっている。0を指定すると、全てのキーを指定したことになる。
また、割り込み開始行の定義は、ON KEY(キー番号)
GOSUB という形で、必ずキー番号を指定
する形になる。
*今回とりあげたプログラムは<KTYPE.bas>以外は、N88互換BASIC
for WIN 、QBASIC
ともに共通です。