11/8の課題(2011)

ユニークな模様を描くプログラム IroiroRandom.java をつくる

EventRandom4.java(またはEventRandom2.java)を元にいろいろ変更して IroiroRandom1.java IroiroRandom2.java IroiroRandom3.java などと作っていき、一番の出来を IroiroRandom.javaとして保存してください。(必ず java IroiroRandom で実行できるようにしておくこと)

EventRandom4.javaから改変して IroiroRandom1.java を作る場合、4箇所の EventRandom4 を IroiroRandom1 に変えることを忘れないように。

また、IroiroRandom1.java IroiroRandom2.java IroiroRandom3.java などから一番の出来を IroiroRandom.javaとしするときにも、4箇所の IroiroRandom? を IroiroRandom に変えることを忘れないように。

元になるプログラムは EventRandom4.java として下に示してあります。今回はこの中のどんな図形をどこに描くかを示すdrawRdm次に描く図形の色を設定するnextColorを変更することでプログラムを完成させます。

変更例をあげますが、このなかから好きなものを選ぶのではなく、必ず変更を加えてユニークな模様にしなければなりません。

元になるプログラム

これはすでに作ってあるはずですが、そうでない人はここからコピーできるようにもう一度書きました。

ファイル名 EventRandom4.java (既にある人はそれを使う)

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.*;

public class EventRandom4 extends JFrame implements ActionListener{
    JButton mybtn;
    MyPanel mypnl;

    public EventRandom4() {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(400,300);
        setTitle("BufferedImageで描く");
        mypnl = new MyPanel(400,300);
        mybtn = new JButton("draw");
        setLayout(new BorderLayout());
        add(mypnl, BorderLayout.CENTER);
        add(mybtn,BorderLayout.SOUTH);
        mybtn.addActionListener(this);
        setVisible(true);

    }
    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == mybtn) {
            mypnl.drawRdm();
            mypnl.repaint();
        }
    }
    public static void main(String[] args){
        EventRandom4 myframe = new EventRandom4();
    }

    public class MyPanel extends JPanel{
       Color c = new Color(0,0,0);  //楕円の色と初期値
       Color bc = new Color(255,255,191);
       int dc = 51;  //色の変化の大きさ
       int dx = 50;  //位置の変化の大きさ
       BufferedImage buffimg;
		 Graphics bfg;
       public MyPanel(int w,int h){
          buffimg = new BufferedImage(
             //getSize().width,
             //getSize().height,
             w,h,BufferedImage.TYPE_INT_RGB);
          bfg = buffimg.createGraphics();
          bfg.setColor(bc);
          bfg.fillRect(0, 0, w, h);
       }
       @Override
       public void paintComponent(Graphics myg){
          super.paintComponent(myg);
          myg.drawImage(buffimg, 0, 0,getSize().width, getSize().height,this);
       }
       public void drawRdm() {
          for(int i=0; 10>i; i++){
                nextColor();
                int x = (int)(400*Math.random());
                int y = (int)(300*Math.random());
                int h = (int)(50*Math.random()+5);
                bfg.fillOval(x-h/2,y-h/2,h,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);
          bfg.setColor(c);
       }
    }
}

400*Math.random()は0から400までのでたらめな数を用意します。

(int)(数式)は計算するとdoubleの数になるものを整数に変換します。

fillOvalなどは引数が整数でないとコンパイルが通りません。

このまま実行して10回ほどクリックすると、こうなります

作成例

もう一度いいますが、以下の作成例のなかから好きなものを選ぶのではなく、必ず変更を加えてユニークな模様にしなければなりません。

例1

元になるプログラムから、IroiroRandom1.java を作ります。

まず EventRandom4.java を IroiroRandom1.java として「別名で保存」し、4箇所の EventRandom4 を IroiroRandom1 に変えて再び保存します。

この中のnextColor()の部分だけを次のように書き換えます。

ファイル名 IroiroRandom1.java の一部

public void nextColor(){
   int r=c.getRed();
   int g=c.getGreen();
   int b=c.getBlue();
   r = (int)(r + dc*Math.random());
   if (r > 255){
      r = 0;
   }
   g = (int)(g + dc*Math.random());
   if (g > 255){
      g = 0;
   }
   c = new Color(r,g,b);
   bfg.setColor(c);
}

こうなります

緑だけでなく赤の成分も変化させるように nextColor() メソッドに書き加えました。さらに青も加えることもできます。

例2

元になるプログラムのdrawRdm()の部分を次のように書き換えます。nextColor()の部分は例1のようにしても、元のままでも、青がからむようにしてもそれぞれ違いが楽しめます。

ファイル名 IroiroRandom2.java の一部

public void drawRdm() {
   for(int i=0; 10>i; i++){
      nextColor();
      int x1 = (int)(400*Math.random());
      int y1 = (int)(300*Math.random());
      int x2 = (int)(400*Math.random());
      int y2 = (int)(300*Math.random());
      bfg.drawLine(x1,y1,x2,y2);
   }
}

こうなります

円の代わりにdrawLineで線を引いています。

色を緑と青を変えるようにしました(プログラムは省略。赤と緑を参照)。あまり面白くありません。

例2-b

元になるプログラムのdrawRdm()の部分を次のように書き換えます。nextColor()の部分は例1のようにしても、元のままでも、青がからむようにしてもそれぞれ違いが楽しめます。

ファイル名 IroiroRandom2.java の一部

public void drawRdm() {
   for(int i=0; 10>i; i++){
      nextColor();
      int x1 = (int)(400*Math.random());
      int y1 = (int)(300*Math.random());
      int x2 = (int)(400*Math.random());
      int y2 = (int)(300*Math.random());
      bfg.drawLine(x1,y1,x2,y2);
      bfg.drawLine(x1+1,y1,x2+1,y2);
      bfg.drawLine(x1+2,y1,x2+2,y2);
      bfg.drawLine(x1+3,y1,x2+3,y2);
      bfg.drawLine(x1+4,y1,x2+4,y2);
      bfg.drawLine(x1+5,y1,x2+5,y2);
      bfg.drawLine(x1+6,y1,x2+6,y2);
      bfg.drawLine(x1+7,y1,x2+7,y2);
      bfg.drawLine(x1+8,y1,x2+8,y2);
   }
}

こうなります

drawLineを重ねました。いまいちです。完全にランダム(偶然まかせ)はあまり面白くないのでしょう。

例2-c

元になるプログラムのdrawRdm()の部分を次のように書き換えます。nextColor()の部分は例1のようにしても、元のままでも、青がからむようにしてもそれぞれ違いが楽しめます。

ファイル名 IroiroRandom2.java の一部

bfg.drawLine(x1,y1,x2,y2);
nextColor();
bfg.drawLine(x1+1,y1,x2+1,y2);
nextColor();
bfg.drawLine(x1+2,y1,x2+2,y2);
nextColor();
bfg.drawLine(x1+3,y1,x2+3,y2);
nextColor();
bfg.drawLine(x1+4,y1,x2+4,y2);
nextColor();
bfg.drawLine(x1+5,y1,x2+5,y2);
nextColor();
bfg.drawLine(x1+6,y1,x2+6,y2);
nextColor();
bfg.drawLine(x1+7,y1,x2+7,y2);
nextColor();
bfg.drawLine(x1+8,y1,x2+8,y2);

こうなります

例2-bのプログラムを少し変更し、線を描く前にいちいち色を変えます。単色の帯が連続して色が変化する帯になります。

例3

元になるプログラムのdrawRdm()の部分を次のように書き換えます。nextColor()の部分は例1のようにしても、元のままでも、青がからむようにしてもそれぞれ違いが楽しめます。

ファイル名 IroiroRandom3.java の一部

public void drawRdm() {
   dx = 20;
   int x = (int)(400*Math.random());
   int y = (int)(300*Math.random());
   for(int i=0; 100>i; i++){
       int xx = (int)(dx*Math.random()*2-dx); //-dx から dx までの値
       nextColor();
       x += xx;
       y += xx;
       int h = (int)(20*Math.random()+5);
       bfg.fillOval(x-h/2,y-h/2,h,h);
   }
}

こうなります

円を直線上に配置します。x,yに同じ数を加えるので右下か左上に動きます。進み具合をランダムにしています。

例3-b

元になるプログラムのdrawRdm()の部分を次のように書き換えます。nextColor()の部分は例1のようにしても、元のままでも、青がからむようにしてもそれぞれ違いが楽しめます。

ファイル名 IroiroRandom3.java の一部

public void drawRdm() {
   dx = 8;
   int x = (int)(400*Math.random());
   int y = (int)(300*Math.random());
   int xx = (int)(dx*Math.random()*2-dx);
   int yy = (int)(dx*Math.random()*2-dx);
   for(int i=0; 100>i; i++){
      nextColor();
      x += (int)(xx+dx*Math.random()-dx/2);
      y += (int)(yy+dx*Math.random()-dx/2);
      int h = (int)(20*Math.random()+5);
      bfg.fillOval(x-h/2,y-h/2,h,h);
   }
}

こうなります

円を直線上に配置し、角度と進み具合をランダムにしています。

クリック数を多くするとまた印象が変わります。

例4

ヒントだけ。線と円、四角を組み合わせたり、文字を使うという手もあります。

例の2から3まで同じnextColor()を使っています。これも変えるとまた違ったものになります。

例5

元になるプログラムのdrawRdm()の部分を次のように書き換えます。nextColor()の部分は例1のようにしても、元のままでも、青がからむようにしてもそれぞれ違いが楽しめます。

ファイル名 IroiroRandom5.java の一部

public void drawRdm() {
    int x = (int)(400*Math.random());
    int y = (int)(300*Math.random());
    for(int i=255; i>0; i--){
       nextColor();
       int h = i;
       bfg.fillOval(x-h/2,y-h/2,h,h);
    }
}

こうなります

円の中心をランダムに設定し、半径を255から順に1ずつ小さくして同心円を描いています。

例6

元になるプログラムのdrawRdm()の部分を次のように書き換えます。nextColor()は使いませんので変更してもしなくても変わりません。

ファイル名 IroiroRandom6.java の一部

public void drawRdm() {
    int x = (int)(400*Math.random());
    int y = (int)(300*Math.random());
    int rgb = (int)(3*Math.random()); // rgb=0 or 1 or 2
    for(int i=255; i>0; i--){
       if (rgb==0) c = new Color(255-i,0,0);
       if (rgb==1) c = new Color(0,255-i,0);
       if (rgb==2) c = new Color(0,0,255-i);
       bfg.setColor(c);
       int h = i;
       bfg.fillOval(x-h/2,y-h/2,h,h);
    }
}

こうなります

nextColorを使わず、半径に応じて色が明るくなるように直接色を指定します。Color(255-i,0,0)はiが小さくなると明るい赤になります。赤緑青のどれになるかはrgbの値が0,1,2のどれかになることを利用してifで判断します。

nextColor(rgb);をnextColor(rgb,255-i);にすることで色をランダムでなくiを使った色に指定しています。255-iでなくただのiにすると中央部が明るい円になります。

例7

元になるプログラムのdrawRdm()の部分を次のように書き換えます。nextColor()は使いませんので変更してもしなくても変わりません。

ファイル名 IroiroRandom7.java の一部

public void drawRdm() {
    int x = (int)((400-140)*Math.random());
    int y = (int)((300-140)*Math.random());
    int rgb = (int)(3*Math.random()); // rgb=0 or 1 or 2
    for(int i=255; i>0; i--){
       if (rgb==0) c = new Color(255-i,0,0);
       if (rgb==1) c = new Color(0,255-i,0);
       if (rgb==2) c = new Color(0,0,255-i);
       bfg.setColor(c);
       int h = (int)(i/2);
       bfg.fillOval(x,y,h,h);
    }
}

こうなります

例6のh=iをh = (int)(i/2) にしています。つまり大きさが半分。円の中心を合わせるための x-h/2,y-h/2 を ただの x,y にするとこの様な形ができます。

もくじ

Javaプログラミング
聖愛中学高等学校
http://www.seiai.ed.jp/
Nov.2010
Nov.2011