−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
応用数学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.さあ,好みの時計を作ろう
ということで,基礎はおしまい。これらを改良して,自分の気に入った時計を作ってみ
てください。