これにより、ある程度複雑なプログラムがどのように動くかということを視覚 的に理解することにしたい。
program graphics_sample(input, output);
#include <xgraph.h>
var gdriver, gmode : integer;
xcen, ycen : integer;
begin
gdriver := detect; グラフィックス使用の準備
initgraph(gdriver, gmode, ''); グラフィックス使用の準備
cleardevice; 画面のクリア
clrscr; 文字画面のクリア
xcen := getmaxx div 2; 画面中心の x 座標の計算
ycen := getmaxy div 2; 画面中心の y 座標の計算
circle(xcen,ycen, 100); 円の表示
circle(xcen,ycen, 150); 円の表示
line(xcen-150,ycen-150,xcen+150,ycen-150); 線分の表示
line(xcen+150,ycen-150,xcen+150,ycen+150); 線分の表示
line(xcen+150,ycen+150,xcen-150,ycen+150); 線分の表示
line(xcen-150,ycen+150,xcen-150,ycen-150); 線分の表示
readln;
closegraph; グラフィックス使用の終了
end.
この例では、最初の #include 何とかというのは、グラフィックス関数を使
うということを宣言している。この #include というのは、PASCAL 言
語の機能ではなく、C という別の言語のコンパイラの機能であるが、とにかく
指定したファイルの中身をそこに読み込んでくる。実際のファイルは
/usr/include/xgraph.h のはずである。実行部の先頭の2行は、実際に絵を書くための 準備をする手続きを呼んでいる。これを呼ぶと新しいウインドウができる。
このウインドウは、 800 x 800 の点からできている。座標系は、 慣習により画面の左上が (0,0), 右下が (799,799) となっている。
このグラフィックスの手続きは、 IBM のパソコンでつかわれていた Turbo PASCAL (商品名)というコンパイラと(大体)同じように使えるようになっ ている。言語が違ったりすると、グラフィックスの手続きの細かいところはいろいろちがってくるが、まあ、線を書く、円を書く、文字を書く、色を変えるといったものがあるというのはどれも同じようなものである。
グラフィックス手続きについては、簡単なまとめをパスカルのグラフィックスに関する簡 単なまとめとしてつくっておいた
上のプログラムでは、circle と line が実際に円を書く、あるいは直線を引 く手続きである。従って、これらを追加したり、指定する数(引数)を変えた りすれば画面に出る絵が変わる。なお、手続きや関数で引数を2個以上必要と する場合(例えば circle では x 座標、 y 座標、 半径の3個)3個の数(あ るいは変数、式)をコンマで区切って並べる。並べたものの何番目がどれか(た とえばx、y 座標 と半径のうち)は、あらかじめ決まっている。このような方 式を、位置パラメータといい、現在のほとんどの計算機言語で使われている。
このやり方の代わりに、例えば circle(x_pos=xcen, y_pos=ycen, radius=100) というように指定することも考えられる。この方がわかりやす いが、プログラムが繁雑になるのを嫌うためかこの形式が使える計算機言語は 少ない。
なお、このプログラムを打ち込んで、そのままコンパイルしようとしてもうま くできない。これは、グラフィックスを使う関数がどこにあるか指定されてい ないからである。これは以下のように指定する。
pc graph1.pas -o graph1 -lXtc -lX11ここで、最後の2つの -l 何とかというのが、グラフィックスを使うた めのおまじないである。コマンドやファイル名には大文字と小文字の 区別がある。例えば -lxtc とか -lXTc とかではうまく動かない ので注意して欲しい。
program graphics_loop(input, output);
#include <xgraph.h>
var gdriver, gmode : integer;
xsize, ysize : integer;
n, i : integer;
dx, dy : real;
begin
write('How many lines? ');
readln(n);
gdriver := detect;
initgraph(gdriver, gmode, '');
cleardevice;
clrscr;
xsize := getmaxx ;
ysize := getmaxy ;
dx := xsize/n;
dy := ysize/n;
for i := 0 to n do line(0,round(i*dy), round(i*dx),ysize);
readln;
closegraph;
end.
for 変数 := 最初の値 to 最後の値 do 文;
は、まず変数に最初の値を入れて文を実行し、次に変数を1増やしてまた文を
実行し、以下同様に繰り返して変数が最後の値になったらおしまいにするという
ことになる(変数が最後の値になったときも文は実行される)。このような繰
り返し処理をループ処理という。上の場合では始点、終点が違う線分を指定し
た本数だけ引いてくれる。なお、 round は実数型の値を四捨五入した
整数に変換する関数である。もう少し高度な図形を書いてみよう。
program graphics_loop2(input, output);
#include <xgraph.h>
var gdriver, gmode : integer;
xcen, ycen : integer;
n,i,x,y : integer;
dx, dy : real;
begin
write('How many points? ');
readln(n);
write('Enter dx, dy: ');
readln(dx, dy);
gdriver := detect;
initgraph(gdriver, gmode, '');
cleardevice;
clrscr;
xcen := getmaxx div 2;
ycen := getmaxy div 2;
for i := 0 to n do begin
x := round(200*cos(i*dx))+xcen;
y := round(200*sin(i*dy))+ycen;
if i = 0 then
moveto(x,y)
else
lineto(x,y);
end;
readln;
closegraph;
end.
これはリサージュ図形(x方向とy方向が周期の違う単振動をする時にできる図
形)を描く。このプログラムでは、上のプログラムに比べて3つ新しいことを
している。一つは、 for で繰り返す中身が一文ではなく複数の文
のつながりであること、もう一つは i の値によって違うことをす
るために if ... then ... else ... というものを使っているこ
と、最後に line の代わりに moveto と
lineto を使っていることである。ループの中でいくつかの文のつながりを実行するためには、
for 変数 := 最初の値 to 最後の値 do begin
文;
......
文;
end;
というふうに、いくつかの文を begin と endで囲んでやる。
if 条件 do 文1
else 文2;
という構造は、 条件が成り立っていれば文1を、そうでなければ文2を実行せよという意味にな る。文2がない(条件が成り立っている時はなにかするがそうでなければ何も しない)ときには
if 条件 do 文1;
だけでいい。なお、 for の中に書いた、 begin 文; 文; ... end というまとまりのことを複文といい、一般に文が書けるところには複文も書け る。このため、 if ... then begin ..... end else begin .... end; というような風にすれば条件によって違ういくつかの処理をまとめてできる。
条件は、数値同士の比較式(大小、等 しい)と、複数の比較式からできる論理式などが書ける。
さて、繰り返し処理には for の他にもう一つの方法がある。それは、 「ある条件が成り立っているうちは繰り返す」というものである。
while 条件 do begin
文;
......
文;
end;
という構造は、 begin と endにかこまれた処理を条件が成り立っ ているあいだ繰り返せということになる。
program graphics_loop3(input, output);
#include <xgraph.h>
var gdriver, gmode : integer;
xcen, ycen : integer;
x,y, xmin,xmax : real;
dx, dy : real;
ix, iy, i : integer;
begin
write('xmax, dx ? ');
readln(xmax, dx);
xmin := -xmax;
gdriver := detect;
initgraph(gdriver, gmode, '');
cleardevice;
clrscr;
xcen := getmaxx div 2;
ycen := getmaxy div 2;
x := xmin;
i := 0;
while x <= xmax do begin
y := exp(-x*x) * sin(10*x);
ix := round(xcen + x*xcen/xmax);
iy := round(ycen - y*ycen/xmax);
if i = 0 then
moveto(ix,iy)
else
lineto(ix,iy);
x := x + dx;
i := i + 1;
end;
readln;
closegraph;
end.