円(ボール)が2個以上のときの問題

どんな問題か

ボールが複数ある時にはその中の一つが上下左右の壁に当たって進行方向を変えると全部のボールが進行方向を変えてしまいます。クリックで進行方向を変える改造をする前は、各ボールは別々に跳ね返っていました。

moveDisk

これはクリックして進行方向が変わることを各ボールに伝えるためdx, dyをグローバル変数、つまり全部のボールに共通な変数にしてしまったことによります。

ボールの動きを見るだけならこれはこれでおもしろいかもしれませんが、ボールが多くなると動く範囲が狭くなってしまいますし、せっかく独立させた動きが一体で動くように見えてしまいます。

解決策1

dxとdyを個別のスレッドの変数にもどして、クリックされたことを別の方法で知らせることを考えます。

今回はスレッドに名前がついていませんからスレッドを特定して呼びかけるわけにはいきません。スレッドの方から共通な変数にアクセスするという制約で考えます。

greenやblueのクリック数をグローバル(共通な)変数として導入します。クリックがあるとこの値を増やします。それぞれのボールでこの変数の値をローカル(共通でない)変数にコピーし、2つの値が異なっていればdx,dyを操作して変数もコピーしなおします。変数の値が同じであれば新しいクリックがなかったものとしてなにもしません。

MoveDisk6.javaをもとに変更していきます。

ファイル名 MoveDisk7.java の概要図

MoveDisk7のフィールドからdx, dyを取り除き、moveDiskクラスに移します。

MoveDisk7のフィールドに緑ボタンのクリック数、青ボタンのクリック数を記録する変数をいれます。

ローカルにも必要なのグローバル変数をgctgrn.gctbluとし、ローカルをctgrn,ctbluとします

class MoveDisk7{
    int gctgrn = 0;
    int gctblu = 0;
    //int dx = 0;
    //int dy = 10;
    actionPerformed(){...}
    main(){...}
    class MyPanel{
        paintComponent(){...}
        drawRdm(){...}
        nextColor(){...}
    }
    class moveDisk{
        int dx = 0;
        int dy = 10;
        int ctgrn;
        int ctblu;
        run(){...}
    }
}

ファイル名 MoveDisk7.java のMoveDiskのコンストラクタ

MoveDiskのコンストラクタにgctgrn,gctbluのコピーを加えます。これは必須ではありません書かない場合は最初からdx,dyの処理が入るということになるだけです。

//constructor
public moveDisk(MyPanel pn, BufferedImage im) {
    this.pnl   = pn;
    this.image = im;
    //y = (int)(image.getHeight()*Math.random());
    y = 100;
    x = (int)(image.getWidth()*Math.random());
    ctgrn = gctgrn;
    ctblu = gctblu;
}

ファイル名 MoveDisk7.java のMoveDiskのrunメソッド中のwhile

カウントが等しくない時はdx,dyの交換をします。そのあとでローカルのカウントをグローバルに合わせます。

while ( true  ){
    if (gctgrn != ctgrn) {
         int tmp = dx;
         dx = dy;
         dy = tmp;
         ctgrn = gctgrn;
    }
    if (----??----) {
        //blueについても同様に
    }
    thg.setColor(bc);
    thg.fillOval(lx-d/2,ly-d/2,d,d);

ファイル名 MoveDisk7.java のactionPerformed

actionPerformed にはいままでdx,dyの交換がありましたが、今回はカウンタgctgrn,gctbluの値を増やすだけです。

public void actionPerformed(ActionEvent e) {
    // ..................
    if (e.getSource() == gbtn) {
        gctgrn++;
    }
    if (e.getSource() == bbtn) {
        gctblu++;
    }

moveDisk

課題

1.

MoveDisk6.javaをもとにします

上記の様に働くようにし、動作を確認しなさい。

ファイル名 MoveDisk7.java

もくじ

聖愛高等学校
http://www.seiai.ed.jp/
Last Modified