−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
   応用数学II                        1995.12.07-08
   16.実践 −気分転換に時計を作ろう−             飯島
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

16−0.はじめに

 おもいもかけず,風邪を引いてしまい,12/7は休講となってしまった。そこで,2班の 人にとって,やらなくてもあまり影響のないような内容で,その気があれば,読んで練習 すればものにできそうな内容をすることにしました。課題は,                  時計を作ろう ということです。

16−1.一番簡単な時計

 時計を作るためには,時刻を取得しなければなりません。逆に,時刻さえ取得できるの ならば,こんなことは簡単です。BASIC系の言語では,TIME$というのが,時刻 を表す文字列を得る関数なので,次のようにして,最も簡単なプログラムを作ることがで きます。 CLS DO   LOCATE 1, 1   PRINT TIME$;   A$ = INKEY$ LOOP UNTIL A$ <> "" どうして,A$という変数を使っているか分かりますか。これがないと,いつまでたっても ,「止めることができない」のです。また,LOCATE 1,1 という命令がどうして入ってい るか分かりますか。分からない人は,      疑問を持ったら,それを「消す」ことによって役割を調べよう。 「消す」ためには,  (1) 文字通り消す方法 の他に,  (2) 行頭に「' 」あるいは,「REM 」を挿入する方法 つまり,  ' A$ = INKEY$   あるいは,   REM  A$ = INKEY$ があります。

16−2.アナログ時計

 しかし,これだけでは,「芸がない」ですね。時計と言えば,アナログ時計とデジタル 時計がありますが,まずはアナログ時計を作ってみましょう。  要するに,時刻を数値に変換し,短針,長針,秒針の示すべき角度を計算し,それぞれ の大きさに従って,それを描画すればいいということです。 COMMON SHARED pi pi = ATN(1) * 4 SCREEN 12 MaxOfX = 15 CLS MaxOfY = MaxOfX * 480 / 640 dp = MaxOfX / 320 WINDOW (-MaxOfX, MaxOfY)-(MaxOfX, -MaxOfY) CLS CIRCLE (0, 0), 7 FOR M = 0 TO 360 STEP 6   t = M / 360 * 2 * pi   IF M MOD 30 = 0 THEN l = 6 ELSE l = 6.4   p1x = COS(pi / 2 - t) * l   p1y = SIN(pi / 2 - t) * l   p2x = COS(pi / 2 - t) * 7   p2y = SIN(pi / 2 - t) * 7   LINE (p1x, p1y)-(p2x, p2y) NEXT DO t$ = TIME$ LOCATE 1, 1   PRINT t$   Sec = VAL(RIGHT$(t$, 2))   Min = VAL(MID$(t$, 4, 2)) + Sec / 60   Hour = VAL(LEFT$(t$, 2)) + Min / 60   CALL DrawHour(OldH, 0)   CALL DrawMin(OldM, 0)   CALL DrawSec(OldS, 0)   CALL DrawHour(Hour, 7)   CALL DrawMin(Min, 7)   CALL DrawSec(Sec, 7)   OldH = Hour   OldM = Min   OldS = Sec a$ = INKEY$ LOOP UNTIL a$ <> "" SUB DrawHour (H, clr)   t = H / 12 * 2 * pi   px = COS(pi / 2 - t) * 3   py = SIN(pi / 2 - t) * 3   LINE (0, 0)-(px, py), clr END SUB SUB DrawMin (M, clr)   t = M / 60 * 2 * pi   px = COS(pi / 2 - t) * 5   py = SIN(pi / 2 - t) * 5   LINE (0, 0)-(px, py), clr END SUB SUB DrawSec (M, clr)   t = M / 60 * 2 * pi   px = COS(pi / 2 - t) * 6   py = SIN(pi / 2 - t) * 6   LINE (0, 0)-(px, py), clr END SUB  この中で,注意してほしいのは,次の行です。   Sec = VAL(RIGHT$(t$, 2))   Min = VAL(MID$(t$, 4, 2)) + Sec / 60   Hour = VAL(LEFT$(t$, 2)) + Min / 60 今まで,文字列の操作は全くしなかったので,この手のものは初めてです。さて,時刻の 文字列TIME$ は,                   hh:mm:ss の形式で与えられます。ということは,  時間の文字列=左の2文字  分の文字列 =左から4文字を先頭とする2文字  秒の文字列 =右の2文字 で得られます。これらをプログラムとして表記すると,  時間の文字列=RIGHT$(t$, 2)  分の文字列 =MID$(t$, 4, 2)  秒の文字列 =LEFT$(t$, 2) です。しかし,これらは「文字列」であって,「数値」ではありません。そこで,数値に 変換する関数である,VALを使い,上記のようなものにしました。  そうそう,工夫はそれだけではありませんね。どうして,   Min = VAL(MID$(t$, 4, 2)) + Sec / 60   Hour = VAL(LEFT$(t$, 2)) + Min / 60 なんていうのを付け加えているんでしょうね。 そう,疑問を思ったら,やっぱり,調べてみましょう。   Min = VAL(MID$(t$, 4, 2)) ' + Sec / 60   Hour = VAL(LEFT$(t$, 2)) ' + Min / 60 というような「' 」を挿入すると,それ以降を無視します。

16−3.ちょっと修正

 さて,使ってみる,何か変なことがないですか。そうですね。修正したいところはいろ いろあるけれど,ここでは最低限の修正として,次のことをしましょう。   Sec = VAL(RIGHT$(t$, 2))   Min = VAL(MID$(t$, 4, 2)) + Sec / 60   Hour = VAL(LEFT$(t$, 2)) + Min / 60   IF OldS <> Sec THEN         ←−−−−−−−+     CALL DrawHour(OldH, 0)              |この2行を追加する     CALL DrawMin(OldM, 0)              |     CALL DrawSec(OldS, 0)              |     CALL DrawHour(Hour, 7)              |     CALL DrawMin(Min, 7)               |     CALL DrawSec(Sec, 7)               |   END IF                ←−−−−−−−+   OldH = Hour   OldM = Min   OldS = Sec  さあ,これでどういう効果があるでしょう。

16−4.デジタル時計

 さて,アナログ時計をもっと改良することも一つの課題にはなるけれど,それは後回し にして,ここではデジタル時計を作ることを考えましょう。  もっとも,一番簡単な時計もデジタル時計と言えばそうですが,もう少し改良するには ,やっぱり,字を大きくしたいですね。ということは,最大の問題点は,               「大きな数字を表示する」 ことです。  たとえば,次のようなプログラムを作ってみましょう。 COMMON SHARED pi pi = ATN(1) * 4 SCREEN 12 MaxOfX = 15 CLS MaxOfY = MaxOfX * 480 / 640 dp = MaxOfX / 320 WINDOW (-MaxOfX, MaxOfY)-(MaxOfX, -MaxOfY) DO t$ = TIME$ LOCATE 1, 1   PRINT t$   Sec = VAL(RIGHT$(t$, 2))   IF OldS <> Sec THEN      CALL DrawTime(Oldt$, 0)      CALL DrawTime(t$, 7)   END IF   Oldt$ = t$   OldS = Sec a$ = INKEY$ LOOP UNTIL a$ <> "" SUB DrawNum (n, clr, x, y)   n1 = INT(n / 10)   n2 = n MOD 10   CALL DrawNum2(n1, clr, x, y)   CALL DrawNum2(n2, clr, x + 2, y) END SUB SUB DrawNum2 (n, clr, x, y) SELECT CASE n CASE 0   LINE (x, y)-(x + 1.5, y - 3), clr, B CASE 1   LINE (x + .5, y - .2)-(x + 1, y), clr   LINE (x + 1, y)-(x + 1, y - 3), clr   LINE (x + .5, y - 3)-(x + 1.5, y - 3), clr CASE ELSE   LINE (x, y)-(x + 1.5, y - 3), clr   LINE (x + 1.5, y)-(x, y - 3), clr END SELECT END SUB SUB DrawTime (t$, clr)   Sec = VAL(RIGHT$(t$, 2))   Min = VAL(MID$(t$, 4, 2))   Hour = VAL(LEFT$(t$, 2))   CALL DrawNum(Hour, clr, 0, 0)   CALL DrawNum(Min, clr, 5, 0)   CALL DrawNum(Sec, clr, 10, 0) END SUB  さて,それぞれ下請けのサブを作っているのが分かりますか。           「同じような仕事」はサブを作って共有する という方針を理解してください。  ところで,「変」ですね。そう,そりゃ変です。だって,「×」がいっぱいなんだから 。例として,0と1を作っただけだから,後は自分で作ってください。つまり, SUB DrawNum2 (n, clr, x, y) SELECT CASE n CASE 0   LINE (x, y)-(x + 1.5, y - 3), clr, B CASE 1   LINE (x + .5, y - .2)-(x + 1, y), clr   LINE (x + 1, y)-(x + 1, y - 3), clr   LINE (x + .5, y - 3)-(x + 1.5, y - 3), clr CASE 2 CASE 3 CASE 4 CASE 5 CASE 6 CASE 7 CASE 8 CASE 9 END SUB と拡張し,その中身を具体的に試行錯誤しながら作ってみてください。「0」のケースを 見ればわかると思うけど,このサブでは,            (x,y)−(x+1.5,y−3) の範囲の中で数字を書くことにしています。同様にして作ってください。  また,「:」の表示が必要だったら,そういうサブも作ってください。

16−5.さあ,好みの時計を作ろう

 ということで,基礎はおしまい。これらを改良して,自分の気に入った時計を作ってみ てください。