目次 | 索引 |
---|---|
前回の授業では、コマンドライン引数を用いて、Javaアプリケーションにデータを渡しました。 コマンドライン引数と同様に、アプレットに対してもデータを渡すことができます。 このデータを アプレット・パラメタ ( applet parameter ) とよびます。 「引数」と「パラメタ」は同じ概念だと思ってください。
次のプログラムは、正方形の左上の座標を受け取り、縦横50ピクセルの正方形を描くアプレットです。
/* 1*/ import java.applet.*; /* 2*/ import java.awt.*; /* 3*/ /* 4*/ public class DrawSquare extends Applet { /* 5*/ public void paint (Graphics g) { /* 6*/ int x = Integer.parseInt(getParameter("cornerx")); /* 7*/ int y = Integer.parseInt(getParameter("cornery")); /* 8*/ g.drawRect(x, y, 50, 50); /* 9*/ } /*10*/ }
<body style="background-color: white"> <hr> <applet code="DrawSquare.class" width="300" height="200"> <param name="cornerx" value="50"> <param name="cornery" value="50"> </applet> <hr> <applet code="DrawSquare.class" width="300" height="200"> <param name="cornerx" value="200"> <param name="cornery" value="100"> </applet> <hr> </body>
Netscape: |
---|
File Edit View Go Window Help |
![]() ![]() |
Applet BlackBox running |
アプレットに渡すデータは、HTMLドキュメントの中に書きます。
その際に、データには名前をつける必要があります。
ここでは、正方形の左上の
x
座標を
cornerx
、
y
座標を
cornery
とします。
HTMLドキュメントでは、
<param>
タグを用い、
<param name="name" value="value">
という形式で、名前とデータの対応を表します。 この例では、座標が (50, 50) ですので、
<param name="cornerx" value="50"> <param name="cornery" value="50">
となります。
なお、
<param>
タグに終了タグはありません。
最後に、これを
<applet>
タグで囲みますと、HTMLドキュメントが完成します。
アプレットでデータを受け取るには、式
Integer.parseInt(getParameter("name"))
を用います。
上記のプログラムの6行目と7行目で、変数
x
と
y
に、正方形の左上の
x
座標と
y
座標が格納されます。
前回の授業では、選択というプログラムの構成要素を紹介しました。 今日は、 反復 ( iteration ) について説明します。 反復を表す文は、 繰返し文 ( repetitive statement ) 、または ループ文 ( loop statement ) とよばれます。
反復にはいくつか種類がありますが、「何々が成り立つ間、何々を繰り返す」というものが基本です。
この種の反復には
while文
(
while statement
)
を使います。
while
文は以下の形をとります。
while (condition) { statement; ... }
条件
condition
が成り立っている間、文
statement
;
...
が繰り返し実行されます。
ここで、Good morning!と10回出力するプログラムを考えます。
はじめは数え上げ方式です。
これは、変数
i
に0を代入しておき、Good morning!と一回出力するごとに
i
の値を1増やすということを、
i
の値が10未満の間繰り返すものです。
/* 1*/ class TenMornings { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ i = 0; /* 5*/ while (i < 10) { /* 6*/ System.out.println("Good morning!"); /* 7*/ i++; /* 8*/ } /* 9*/ } /*10*/ }
b00a001@Ampere:~/java% java TenMornings Good morning! Good morning! Good morning! Good morning! Good morning! Good morning! Good morning! Good morning! Good morning! Good morning! b00a001@Ampere:~/java%
5行目から8行目までの
while
文は次のように実行されます。
i
の値は0。条件i < 10
が成り立つので、Good morning!と出力し、i
の値を1増やす。i
の値は1。条件i < 10
が成り立つので、Good morning!と出力し、i
の値を1増やす。i
の値は9。条件i < 10
が成り立つので、Good morning!と出力し、i
の値を1増やす。i
の値は10。条件i < 10
は成り立たないので、このwhile
文の実行を終える。
次はカウントダウン方式です。
これは、変数
i
に10を代入しておき、Good morning!と一回出力するごとに
i
の値を1減らすということを、
i
の値が正の間繰り返すものです。
/* 1*/ class TenMornings2 { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ i = 10; /* 5*/ while (i > 0) { /* 6*/ System.out.println("Good morning!"); /* 7*/ i--; /* 8*/ } /* 9*/ } /*10*/ }
5行目から8行目までの
while
文は次のように実行されます。
i
の値は10。条件i > 0
が成り立つので、Good morning!と出力し、i
の値を1減らす。i
の値は9。条件i > 0
が成り立つので、Good morning!と出力し、i
の値を1減らす。i
の値は1。条件i > 0
が成り立つので、Good morning!と出力し、i
の値を1減らす。i
の値は0。条件i > 0
は成り立たないので、このwhile
文の実行を終える。数え上げ方式とカウントダウン方式のどちらがよいかは、問題によって変わります。 数え上げ方式のほうがよく使われますが、カウントダウン方式が適切な場合もあります。
注意: 上記のプログラムで、7行目を書き忘れたとしましょう。
/* 1*/ class InfiniteMornings { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ i = 10; /* 5*/ while (i > 0) { /* 6*/ System.out.println("Good morning!"); /* 7*/ } /* 8*/ } /* 9*/ }
このプログラムを実行しますと、変数
i
の値は10のままですので、条件
i > 0
がずっと成り立ち、永遠にGood morning!と出力され続けることになります。
このような、いつまでも続く繰り返しを、
無限ループ
(
infinite loop
)
とよびます。
反復を使うときは、無限ループにならないように気をつける必要があります。
なお、誤って無限ループに陥ったときは、Ctrl-Cで強制終了してください。
反復の種類の中には、繰り返す回数が明確なものがあります。
この場合、
ループ制御変数
(
loop control variable
)
とよばれる変数を増加(あるいは減少)させながら繰り返すのが一般的です。
for文
(
for statement
)
を用いますと、このような反復をコンパクトに書き表すことができます。
for
文は次のような形をとります。
for (statement1; condition; statement2) { statement3; ... }
まず文
statement1
が一度だけ実行されます。
そして条件
condition
が成り立っている間、文
statement3
;
...
と
statement2
が繰り返し実行されます。
while
文を使ってこの
for
文を書きますと、次のようになります。
statement1; while (condition) { statement3; ... statement2; }
for
文を用いますと、Good morning!と10回出力するプログラムは次のように書けます。
数え上げ方式については、
/* 1*/ class TenMornings3 { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ for (i = 0; i < 10; i++) { /* 5*/ System.out.println("Good morning!"); /* 6*/ } /* 7*/ } /* 8*/ }
です。 カウントダウン方式は、
/* 1*/ class TenMornings4 { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ for (i = 10; i > 0; i--) { /* 5*/ System.out.println("Good morning!"); /* 6*/ } /* 7*/ } /* 8*/ }
となります。
while
文と
for
文には本質的な差はありません。
繰返しの回数がはっきりしているときには
for
文、そうでないときには
while
文を使うのがよいでしょう。
反復の使用例として、はじめに 1+2+…+100 の計算を行います。
この問題は、レジの計算をまねることで解決できます。 つまり、それまでの合計を表す変数 sum を用意して、初期値を 0 とします。 そして、 sum の値を 1 増やし、2 増やし、…と繰り返し、100 増やした時点の sum の値が答になるわけです。 アルゴリズムは次のようになります。
プログラムは以下のようになります。
/* 1*/ class Summation100 { /* 2*/ public static void main (String[] args) { /* 3*/ int i, sum = 0; /* 4*/ for (i = 1; i <= 100; i++) { /* 5*/ sum = sum + i; /* 6*/ } /* 7*/ System.out.println(sum); /* 8*/ } /* 9*/ }
b00a001@Ampere:~/java% java Summation100 5050 b00a001@Ampere:~/java%
次の例は、360 の約数をすべて求めるものです。
360 の約数が、1 から 360 までの間にあることは、数学的に分かっています。 したがって、1 から 360 までの数一つ一つに対して、360 がその数で割り切れるかどうかを判断すれば、約数がもれなく見つけられます。 アルゴリズムは次のようになります。
プログラムは以下のようになります。
/* 1*/ class Divisors360 { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ for (i = 1; i <= 360; i++) { /* 5*/ if (360 % i == 0) { /* 6*/ System.out.println(i); /* 7*/ } /* 8*/ } /* 9*/ } /*10*/ }
b00a001@Ampere:~/java% java Divisors360 1 2 3 4 5 6 8 9 10 12 15 18 20 24 30 36 40 45 60 72 90 120 180 360 b00a001@Ampere:~/java%
最後の例は、正方形のタイル模様を描くアプレットです。
アプレットの大きさは、幅300ピクセル、高さ200ピクセルとします。
正方形のサイズ(幅)は、アプレット・パラメタ(名前は
size
)を用いて与えます。
この模様は、正方形が敷き詰められているように見えます。 しかし、実際は垂直な線と水平な線が等間隔に描かれているだけです。 そこで、垂直な線を描く方法と水平な線を描く方法を考え、これを続けることでプログラムを完成させることにします。
垂直な線を等間隔に描くには、 x の値を増やしながら、座標 ( x , 0) と ( x , 200) を結ぶ直線を繰り返し描くとできます。 x の値は最初は0で、サイズ分だけ増やしながら、300未満の間繰り返します。 アルゴリズムは次のようになります。
size
の値とする。
プログラムは以下のようになります。
/* 1*/ import java.applet.*; /* 2*/ import java.awt.*; /* 3*/ /* 4*/ public class SquareTile extends Applet { /* 5*/ public void paint (Graphics g) { /* 6*/ int x = 0; /* 7*/ int s = Integer.parseInt(getParameter("size")); /* 8*/ while (x < 300) { /* 9*/ g.drawLine(x, 0, x, 200); /*10*/ x = x + s; /*11*/ } /*12*/ } /*13*/ }
<applet code="SquareTile.class" width="300" height="200"> <param name="size" value="20"> </applet>
垂直な線の場合と同様に、水平な線も描けます。 アルゴリズムは次のようになります。
size
の値とする。
プログラムは以下のようになります。
/* 1*/ import java.applet.*; /* 2*/ import java.awt.*; /* 3*/ /* 4*/ public class SquareTile extends Applet { /* 5*/ public void paint (Graphics g) { /* 6*/ int y = 0; /* 7*/ int s = Integer.parseInt(getParameter("size")); /* 8*/ while (y < 200) { /* 9*/ g.drawLine(0, y, 300, y); /*10*/ y = y + s; /*11*/ } /*12*/ } /*13*/ }
垂直な線を描いた後で水平な線を描くというアルゴリズムで、最終的にプログラムが完成します。 変数の宣言が最初にまとめられたことに注意してください。
/* 1*/ import java.applet.*; /* 2*/ import java.awt.*; /* 3*/ /* 4*/ public class SquareTile extends Applet { /* 5*/ public void paint (Graphics g) { /* 6*/ int x = 0; /* 7*/ int y = 0; /* 8*/ int s = Integer.parseInt(getParameter("size")); /* 9*/ while (x < 300) { /*10*/ g.drawLine(x, 0, x, 200); /*11*/ x = x + s; /*12*/ } /*13*/ while (y < 200) { /*14*/ g.drawLine(0, y, 300, y); /*15*/ y = y + s; /*16*/ } /*17*/ } /*18*/ }
HTMLドキュメントの
<param>
タグを変更し、正方形のサイズが変わることを確認してください。
以下のような、ひし形のタイル模様を描くアプレットを作成してください。
アプレットの大きさは、幅300ピクセル、高さ200ピクセルとします。
ひし形のサイズ(幅)は、アプレット・パラメタ(名前は
size
)を用いて与えます。
アルゴリズムは次のようにします。
(このアルゴリズムは、はみ出した部分は描かれないことを利用しています。)
size
の値とする。
余力のある人は、六角形のタイル模様を描いてください。 ひし形の場合と同様に、アプレット・パラメタは六角形のサイズ(幅)を表すものとします。 また、アルゴリズムは自由とします。 (ヒント: 六角形の幅を sx としますと、高さ sy は sx ×2/√3 で与えられます。
int sx = Integer.parseInt(getParameter("size")); int sy = (int) (sx * 2 / Math.sqrt(3));
と初期化するとよいでしょう。)
今日の演習5に従ってJavaプログラムを作成し、そのプログラムをkonishi@twcu.ac.jpあてにメールで提出してください。 メールには、学生番号、氏名、科目名、授業日(10/24)を明記してください。