コンピュータは正確な図形を描くという印象がありますが、ランダム関数を使って描くたびに違う絵、意外性のある絵を描かせることができます。
Math.random() や for の使い方。メソッドの作り方の復習もします。
最初は色だけにして、あとで円の大きさや、描画位置もランダムに変えていくことを考えます。
import java.awt.*; import javax.swing.*; public class PaintRandom extends JFrame{ public PaintRandom() { setDefaultCloseOperation(EXIT_ON_CLOSE); setSize(400,300); setTitle("ランダム関数を使った模様"); MyPanel mypnl = new MyPanel(); mypnl.setSize(400,300); mypnl.setBackground(Color.white); setLayout(new BorderLayout()); add(mypnl, BorderLayout.CENTER); setVisible(true); } public static void main(String[] args){ PaintRandom myframe = new PaintRandom(); } public class MyPanel extends JPanel{ int w=40; //楕円の幅 int h=40; //楕円の高さ Color c = new Color(0,0,0); //楕円の色 int dc = 16; //色の変化の大きさ int dx = 50; //横位置の変化の大きさ public void paintComponent(Graphics myg){ super.paintComponent(myg); for(int x=0; 400>x ; x=x+dx){ for(int y=0; 300>y; y=y+4){ nextColor(); myg.setColor(c); myg.fillOval(x-w/2,y-h/2,w,h); } } } public void nextColor(){ int r=c.getRed(); int g=c.getGreen(); int b=c.getBlue(); g = (int)(g + dc*Math.random()); if (g > 255){ g = 0; } c = new Color(r,g,b); } } }
実行すると次のように円をたくさん表示します。場所はforによって一定の間隔でずれますが、色はだんだん明るい青になりますがその速さはランダム関数でわざとずらしています。
int w=40; //楕円の幅
int h=40; //楕円の高さ
Color c = new Color(0,0,0); //楕円の色
int dc = 16; //色の変化の大きさ
int dx = 50; //横位置の変化の大きさ
Color c に注目してください。java では色がクラスとして指定できます。ここでは、RGBの3原色の成分で表していますが、透明度を持たせることもできます。
「色の変化の大きさ」: RGBの成分は各色 0 から 255 までの 256 段階ありますが、このプログラムでは dc の値を加えていって、だんだんと色を変化させ、グラデーションを作っています。
「横位置の変化の大きさ」: このプログラムでは縦に円を少しずつずらしながら描いて柱のようにしたものを、さらに横位置を変えて繰り返して描きます。その横位置の変化の大きさです。
色を少しずつ変化させるのは作業手順が多いのでメソッドにして独立させました。Color のインスタンス c を dc を使って変化させています。
public void nextColor(){
int r=c.getRed();
int g=c.getGreen();
int b=c.getBlue();
g = (int)(g + dc * Math.random());
if (g > 255){
g = 0;
}
c = new Color(r,g,b);
}
c.getRed() は Color クラスの c の赤の成分を取り出す Color のメソッドです。
ここでは色の緑成分だけを dc ずつ明るくするようにしていますが、いつもおなじ dc ずつでなくするために、Math.random() を掛けています。Math.random() は 0以上、1未満の double の値です。平均すると 16/2 ずつ明るくなるはずです。
(int) は計算の結果が double になっているので、これを int に代入する時に int の値に変換するものです。キャストといいます。他にもやり方があるのですが、この方が簡単です。
if の所では、緑の成分 g が255以上にならないように、255を越えたら0にもどすようにしています。
new Color(r,g,b) は前にもでていますが、r,g,b の成分の色を作っています。
public void paintComponent(Graphics myg){ for(int x=0; 400>x ; x=x+dx){ for(int y=0; 300>y; y=y+4){ nextColor(); myg.setColor(c); myg.fillOval(x-w/2,y-h/2,w,h); } } }
2つの for を使っています。for(int y=0; y<300; y=y+4) で縦に4ずつずらしながら円を描いています。
円を描くにあたり、nextColor() で色を変化させ、変化した色 c を myg.setColor(c); で描画色に設定し、 myg.fillOval(x-w/2,y-h/2,w,h); で円を描きます。
myg.fillOval(横位置,縦位置,幅,高さ) です。-w/2 などはここではいらないのですが、後で幅を変化させた時に、円の中心が縦に揃うようにしています。
w, h を同じにしているので、楕円が円になります。
int xx; for(int x=0; x<400; x=x+dx){ xx = (int)(x + dx*Math.random()); for(int y=0; y<300; y=y+4){ nextColor(); myg.setColor(c); myg.fillOval(xx-w/2,y-h/2,w,h); } }
作業変数の x はさわると危険なので、別の変数 xx を定義して、現在の x より、dx*Math.random() だけ 右よりの位置にします。dx を足してからさらに dx*Math.random() を足しているので、全体として、足しすぎなのですが、影響ありません。
dxを小さくすると重なりが多くなって壁の様になります。
円の大きさもランダムに変えると次のようなものになります。
円の横位置を左から右に移していくのではなく、ランダムな位置に置くとまた違った印象になります。
上記プログラムをつくりなさい。
独自の変わった模様を描けるプログラムをつくりなさい。