前回の私のブログ記事の最後に、「今回作ったプログラムの操作性をもっとよくできるはずだ。」みたいなことを書きました。画面上のウィンドウ内で、連立二元一次方程式を表す二行の文字列
?x+?y=?
?x+?y=?
の”?”の部分に数値を入れて、『xとyを求める』ボタンを押すという操作手順を、このプログラムを利用する時に、私たち人間は何度も繰り返すことでしょう。そう考えてみると、その操作手順がなるべく簡単で、ムダなキーボード操作が少ないと、使いやすいことがわかります。私たち人間が、コンピュータプログラムと数値などの情報(データ)をやり取りするための仕組み、すなわち、マン・マシン・インターフェース(Man-Machine Interface: 今回も、以下MMIと略します。)を工夫して、それを改善することが重要だということがわかります。
ところで、ウィンドウズでは、HTMLやVBスクリプト・Jスクリプトなどの簡易言語が標準装備されています。人によっては、そんな簡易言語など、CやJavaなどのちゃんとした言語処理システムと比較したならば、全然使い物にならないという意見の方もいらっしゃると思います。私は、その意見を否定するつもりはありません。ただ、私は、どんなコンピュータでも、それを利用するのに小さなプログラムで簡単に操作できる、そんなシステムがあると便利だと思っているだけなのです。私は、しばしば過去において、コンピュータのプログラミングが難しくて、「コンピュータ嫌い」や「コンピュータ離れ」になってしまいそうになりました。そんな窮地を救ってくれて、プログラミングを続けさせてくれたのが、ウィンドウズに標準搭載されていたそうした簡易言語だったのです。
私も、その使いたての最初のうちは、マニュアルに書いてある通りのプログラミングをしていました。簡易言語に普通に用意されていた命令やタグやオブジェクトなどを、決まりきった普通の使い方でプログラムを組むのに使っていました。そのうちに、私自身満足がいくものを作ってみようと考えた時に、どうしても既存の材料やその標準的な使い方では作れない、という困難に突き当たりました。そこで、マニュアルを事細かく調べたり、テストプログラムを作って実際に動かしてみたりして、あれこれできないかと考えるようになりました。
今回のプログラムにしても、”?”に数値を入れている部分を、HTMLのINPUTタグなどを使って、画面上のウィンドウ内に6個所の空欄枠付きの入力フィールドを作れば簡単です。それが、ごく普通の、いわゆる「標準的な」プログラミングです。けれども、私は、他の人がC言語で作った、画面上に多数の空欄枠付きの入力フィールドを並べたプログラムを見たことがありました。インターネットのサイトのベクターからダウンロードをしたフリーウェアのプログラムでした。それをキーボードで操作してみて、何か使いずらいなと私は思いました。別に、そのプログラムを作った人が悪いのではありませんが、標準的な入力枠付きフィールドが多数並んでいる、その画面レイアウトが何となく私には気に入りませんでした。(という私も、仕事でプログラマをやっていた20代の頃は、クライアント(顧客)や上司先輩の指示命令で、それと同じような画面レイアウトのプログラムを作っていました。)
そこで、「標準的な」入力枠付きフィールドをいっさい使わずに、数値を入れたい”?”の画面上の位置に矢印カーソルを移動させるだけ、という今回のスタイルにしてみたわけです。そのように、数値の取り込ませ方をなるべく簡略化することによって、従来のコンピュータの使いづらさや面倒くささを少しでも改善したかったわけです。
そのことは、”?”の箇所全部に数値を入れてから『xとyを求める』ボタンを押して、方程式の計算を開始させるという、操作の手順にも言えることでした。いっそのこと、そのボタンをなくしてしまおう、と私は次に考えました。キーボードからの打ち込みにより、”?”の箇所全部に数値が入ったそのタイミングで方程式の計算を開始すれば、マウスで毎回そのボタンを押す手間が省けます。些細なことに思われるかもしれませんが、毎回計算を始めるためにボタンを押さなくても、自動的に計算を始めてその結果を出してくれるのは、キーボードを打つ人間の利用者(ユーザ)側から考えてもお得な話です。まさに昔、電卓のCMのキャッチフレーズに使われた「答え一発。」という言葉そのままに、その便利さを実現できる仕組みと言えましょう。
実際にコンピュータでそのプログラムを動かしてみると、画面上のウィンドウ内から”?”が全部なくなったその瞬間、あるいは数値の変更があったその瞬間に、xとyの値が求まって、その計算結果が画面に出てきました。”?”が画面上から消えてなくなった後は、キーボードからのワンキー(one key)ごとの操作で新たな数値が定まって、刻々とその計算結果も変化してゆきました。これこそが、今回私が目指した操作性の向上あるいはMMIの改善でした。それでは、今回そのように作り変えたプログラムの内容を以下に示しましょう。
連立二元一次方程式v1.50.hta
<STYLE TYPE="text/css"> BODY { background-color:rgb(80%,70%,70%); overflow:auto; } SPAN { font-size:20pt; height:20pt; padding:4pt; margin:3pt 0pt; cursor:default; } .coef { font-size:24pt; } .fita { font-size:20pt; font-style:italic; } </STYLE> <HTA:Application Id=oHTA Scroll=no Contextmenu=no /> <BODY scroll=No> <SPAN CLASS=coef id=c1 >?</SPAN><SPAN CLASS=fita >x</SPAN> <SPAN> + </SPAN> <SPAN CLASS=coef id=c2 >?</SPAN><SPAN CLASS=fita >y</SPAN> <SPAN> = </SPAN> <SPAN CLASS=coef id=c0 >?</SPAN><BR> <SPAN CLASS=coef id=c1 >?</SPAN><SPAN CLASS=fita >x</SPAN> <SPAN> + </SPAN> <SPAN CLASS=coef id=c2 >?</SPAN><SPAN CLASS=fita >y</SPAN> <SPAN> = </SPAN> <SPAN CLASS=coef id=c0 >?</SPAN><P> <SPAN id=Mes ></SPAN> </BODY> <SCRIPT language="VBScript"> Option Explicit Dim target Call ResizeTo(400, 280) Document.Title = "連立二元一次方程式" Sub Document_Onmouseover Set target = Window.event.srcElement If target.classname = "coef" Then If target.style.color = "" Then target.style.color = "red" End If End If End Sub Sub Document_Onmouseout Set target = Window.event.srcElement If target.classname = "coef" Then If target.style.color = "red" Then target.style.color = "" End If End If End Sub Sub Document_OnkeyPress Dim tk, kc tk = Window.event.keyCode kc = Chr(tk) If kc = "?" Then Mes.InnerText = KeyinQMark() Exit Sub End If If target.classname <> "coef" Then Exit Sub If tk = 8 Then ' Backspace code? Mes.InnerText = KeyinBackspace() ElseIf kc = "-" Then Mes.InnerText = KeyinMinus() Else Mes.InnerText = KeyinNumber(kc) End If End Sub Private Function KeyinQMark() c1(0).InnerText = "?" c1(1).InnerText = "?" c2(0).InnerText = "?" c2(1).InnerText = "?" c0(0).InnerText = "?" c0(1).InnerText = "?" KeyinQMark = "" End Function Private Function KeyinBackspace() Dim wv If target.InnerText = "?" Then KeyinBackspace = "まず数値を入れてください。" Else wv = Abs(Eval(target.InnerText)) If wv < 10 Then target.InnerText = "?" Else target.InnerText = Cstr(wv \ 10) End If KeyinBackspace = TryAnswer() End If End Function Private Function KeyinMinus() Dim wv If target.InnerText = "?" Then KeyinMinus = "まず数値を入れてください。" Else wv = 0 - Eval(target.InnerText) If wv < 0 Then target.InnerText = "(" & wv & ")" Else target.InnerText = wv End If KeyinMinus = TryAnswer() End If End Function Private Function KeyinNumber(kc) Dim idx, wv idx = InStr(1, "0123456789", kc) If idx > 0 Then If target.InnerText = "?" Then wv = 0 Else wv = Eval(target.InnerText) * 10 End If target.InnerText = Cstr(wv + idx - 1) KeyinNumber = TryAnswer() Else KeyinNumber = "数値しか入りません。" End If End Function Private Function TryAnswer() If QMarkCheck() Then TryAnswer = "" Else TryAnswer = calcMatrix() End If End Function Private Function QMarkcheck() If c1(0).InnerText = "?" Or c1(1).InnerText = "?" Or _ c2(0).InnerText = "?" Or c2(1).InnerText = "?" Or _ c0(0).InnerText = "?" Or c0(1).InnerText = "?" Then QMarkcheck = True Else QMarkcheck = False End If End Function Private Function calcMatrix() Dim rstr, delta, elm_x, elm_y, d1(1), d2(1), d0(1) d1(0) = Eval(c1(0).InnerText) d1(1) = Eval(c1(1).InnerText) d2(0) = Eval(c2(0).InnerText) d2(1) = Eval(c2(1).InnerText) d0(0) = Eval(c0(0).InnerText) d0(1) = Eval(c0(1).InnerText) delta = d1(0) * d2(1) - d2(0) * d1(1) elm_x = d2(1) * d0(0) - d2(0) * d0(1) elm_y = d1(0) * d0(1) - d1(1) * d0(0) If delta = 0 Then rstr = "連立方程式ではありません。" Else rstr = "x = " & Reduce(elm_x, delta) & " , " &_ "y = " & Reduce(elm_y, delta) End If calcMatrix = rstr End Function Private Function Reduce(child, adult) Dim rstr, idx, clower, alower, prefix, surfix Dim chsg, adsg, chpv, adpv, rsig If child < 0 Then chsg = -1 chpv = Abs(child) Else chsg = 1 chpv = child End If If adult < 0 Then adsg = -1 adpv = Abs(adult) Else adsg = 1 adpv = adult End If If chpv = adpv Then Reduce = Cstr(child \ adult) Exit Function End If For idx = adpv to 2 step -1 If adpv mod idx = 0 Then If chpv mod idx = 0 Then Exit For End If End If Next clower = chpv \ idx alower = adpv \ idx rsig = chsg * adsg If alower = 1 Then rstr = Cstr(clower \ alower * rsig) Else If rsig = -1 Then prefix = "-(" surfix = ")" Else prefix = "" surfix = "" End If rstr = prefix & clower & " / " & alower & surfix End If Reduce = rstr End Function </SCRIPT>
前バージョン(連立二元一次方程式v1.00.hta)のプログラム内容と今回のバージョンを比較しますと、方程式の計算のプログラム部分は、全く変わっていません。つまり、プログラムで修正した部分は、ボタンの画面レイアウトとその処理に関わる部分だけです。『xとyを求める』ボタンが押された時に行われていた処理は、キーボードの打ちこみ毎の処理に変更しました。つまり、キーボードからの打ちこみで必要な数値が全てそろった直後に、その計算処理を開始します。そのような処理を、一つの関数(TryAnswerという関数)にまとめて、プログラム中の必要な箇所に配置しました。
また、画面レイアウト上からは、『xとyを求める』ボタンと共に『数値のクリア』ボタンもなくしました。数値を全てクリアする場合は、”?”キーを押します。すると、画面上のウィンドウ内は、初期状態の”?”だらけの連立方程式に戻ります。この”?”キーは、いわゆる隠れキーです。『数値のクリア』ボタンはなくなりましたが、それまでの処理は”?”キーを押した場合の処理に移しました。
もともと、それらのボタンはHTMLの標準で用意されているINPUTタグで作ったボタンでは実はありませんでした。私が、SPANタグにスタイルシートとVBスクリプトで細工をして作った『疑似ボタン(あるいは、言葉は悪いですが、フェイクなボタン)』でした。せっかく自作したのですが、今回のプログラムの操作性向上、すなわち、MMIの改善のために、お払い箱となりました。
これで、今回のプログラムのバージョンアップは終わりとなります。ただし、欲を言えば、さらなるバージョンアップが考えられます。それはどういうものかと申しますと、小数値が打ちこめるようにプログラムを修正することです。そんなの大したことないじゃないか、と思われるかもしれません。今のプログラムでは、整数の数値が扱えるように作ってあります。それを整数値から小数値にすればよいのですが、計算結果を分数で画面に出す時に、その分母や分子が小数になって、わかりにくい複雑な数値となってしまう場合があるようです。
それを解決する方法の一つは、次のとおりです。キーボードから打ちこまれた数値が小数であるならば、いったん分数に変換して、計算処理も分数で行うのです。もしも時間の余裕があったならば、この数式の実生活への応用範囲を広げるという意味でも、いつかそれにトライしてみたいと思っています。