プログラミングII

       report#8


目次


(1)課題:Java Applet/AWTについて学び、Java Appletのオリジナルプログラムを作成し解説せよ。
(2)反省・感想



(1)課題:Java Applet/AWTについて学び、Java Appletのオリジナルプログラムを作成し解説せよ。
[1]プログラム
import java.awt.*;
import java.awt.image.*;    //画像を扱うクラスをインポート
import java.applet.AudioClip;  //音声を扱うクラスをインポート
import java.awt.event.*;
import java.applet.*;

public class Puzzle9 extends Applet implements MouseListener {


  int appWidth;
  int appHeight;
Image orgimg;
  Image image[];
  int data[];
  int xp[];
int yp[];
  int status;
  int movefr;
  int count;
  boolean b1_flag;
  boolean b2_flag;

  AudioClip drag;
  AudioClip good;
  AudioClip shuffle;
  AudioClip reset;

Image offimg;
  Graphics offscr;

final int MS = 3; //マスの数(一辺の)
  final int MSS = 50;  //マスのサイズ
  final int AKI = 8; //空いている増すの数(画像を読み込むマス)

  final Font FONT1 = new Font("Dialog", Font.BOLD, 20);
  final Font FONT2 = new Font("Courier", Font.BOLD, 16);
  final Font FONT3 = new Font("Courier", Font.BOLD, 24);


  public void init() {

appWidth = getSize().width; //アプレットのサイズを取得
    appHeight = getSize().height;

    image = new Image[MS*MS]; //イメージを分割する数

    data = new int[MS*MS]; //データの数
for (int i = 0 ; i < MS*MS ; i++) {
      data[i] = i;
    }

		     status = 0; //ステータスの初期化
		     count = 0;//カウント(ボタンをクリックした数)の初期化
		     b1_flag = true;//ボタン1の初期化
    b2_flag = true; //ボタン2の初期化

    xp = new int[MS*MS]; //x座標の配列
    yp = new int[MS*MS]; //y座標の配列

    int cell = 0; 
    for (int i = 0 ; i < MS ; i++) {
      for (int j = 0 ; j < MS ; j++) {
        xp[cell] = (20+1) + ((MSS+1)*j); //左20空けてマスのx座標を指定
        yp[cell] = (30+1) + ((MSS+1)*i); //上30空けてマスのy座標を指定
        cell++;
      }
    }

    String param = null;
    param = getParameter("tani.jpg"); //画像読み込み
    if (param != null) {
      orgimg = getImage(getDocumentBase(), param);
    } else {
      orgimg = makeDefalut(); //画像データがなかったらmakeDefalut()をイメージにする
    }

    makeImages();

    drag = getAudioClip(getDocumentBase(), "drag.au"); //音声データを読み込む
    good = getAudioClip(getDocumentBase(), "good.au");
    shuffle = getAudioClip(getDocumentBase(), "shuffle.au");
    reset = getAudioClip(getDocumentBase(), "reset.au");

    if (drag != null) drag.play(); //音声を再生
    if (drag != null) drag.stop();
    if (good != null) good.play();
    if (good != null) good.stop();
    if (shuffle != null) shuffle.play();
    if (shuffle != null) shuffle.stop();
    if (reset != null) reset.play();
    if (reset != null) reset.stop();

    setBackground(new Color(200,200,255)); //背景色を指定

    offimg = createImage(appWidth, appHeight); //スクリーンのイメージ
    offscr = offimg.getGraphics(); //スクリーンに描画するためのオブジェクト

			   addMouseListener(this);//MouseListenerをアプレット自身に登録

  }


  public void paint(Graphics g) {

    offscr.setColor(getBackground());
    offscr.fillRect(0,0, appWidth, appHeight);

    offscr.setColor(Color.white); //タイトルを書いている(色を白に指定)
    offscr.setFont(FONT1);
    offscr.drawString("9 Matrix Puzzle", 70,20);

    offscr.setColor(Color.gray);
    for (int i = 0 ; i <= MS ; i++) {
      offscr.drawLine(20,30+(MSS+1)*i, 20+(MSS+1)*MS,30+(MSS+1)*i); //マス目(線で)を書いている
      offscr.drawLine(20+(MSS+1)*i,30, 20+(MSS+1)*i,30+(MSS+1)*MS);
    }

			  for (int i = 0 ; i < MS*MS ; i++) { //イメージをマス内に表示
      if (data[i] == AKI) {
        offscr.setColor(Color.lightGray);
        offscr.fillRect(xp[i],yp[i], MSS,MSS);
      } else {
        offscr.drawImage(image[data[i]],xp[i],yp[i], this);
      }
    }

    offscr.setColor(Color.black); //クリック回数を表示
    offscr.setFont(FONT2);
    offscr.drawString("COUNT: " + Integer.toString(count), 190,114);

					       if (status == 2 && cmpData() == true) {//完成したらGood!!を表示
      offscr.setColor(Color.magenta);
      offscr.setFont(FONT3);
      offscr.drawString("Good!!", 190,142);
    }

    offscr.setColor(Color.pink); //ボタン1の状態を指定
    offscr.fill3DRect(190,30, 85,54, b1_flag);
    offscr.setColor(Color.black);
    offscr.setFont(FONT2);
    int offset1 = b1_flag ? 0 : 1;
    offscr.drawString(" Start ", (198 + offset1),(46 + offset1));
    offscr.drawString("   &   ", (198 + offset1),(62 + offset1));
    offscr.drawString("Shuffle", (198 + offset1),(78 + offset1));

    offscr.setColor(Color.pink); //ボタン2の状態を指定
    offscr.fill3DRect(200,158, 60,22, b2_flag);
    offscr.setColor(Color.black);
    offscr.setFont(FONT2);
    int offset2 = b2_flag ? 0 : 1;
    offscr.drawString("Reset", (208 + offset2),(174 + offset2));

					       g.drawImage(offimg, 0,0, this);

  }


  public void update(Graphics g) {

    if (status == 1) { //ボタン1でのマウスイベント

      shuffle(); //シャッフル
      count = 0; //カウントを0にする
      if (shuffle != null) shuffle.play(); //シャッフルの音を実行
      status = 2;

    }

    if (status == 3) { //ボタン2のマウスイベント

      for (int i = 0 ; i < MS*MS ; i++) { //データを初期化
        data[i] = i;
      }
      count = 0; //カウントを0にする
      if (reset != null) reset.play(); //リセットの音を実行
      status = 0; //ステータスを0にする

    }

			   if (status == 4) {//マス目内部のマウスイベント処理
			   
      int moveto = 999;

      if ((movefr % MS) > 0 && data[movefr - 1] == AKI) { //左への処理
        data[movefr - 1] = data[movefr];
        data[movefr] = AKI;
        moveto = movefr - 1;
      }

      if ((movefr % MS) < MS-1 && data[movefr + 1] == AKI) { //右への処理
        data[movefr + 1] = data[movefr];
        data[movefr] = AKI;
        moveto = movefr + 1;
      }

      if ((movefr / MS) > 0 && data[movefr - MS] == AKI) { //上への処理
        data[movefr - MS] = data[movefr];
        data[movefr] = AKI;
        moveto = movefr - MS;
      }

      if ((movefr / MS) < MS-1 && data[movefr + MS] == AKI) { //下への処理
        data[movefr + MS] = data[movefr];
        data[movefr] = AKI;
        moveto = movefr + MS;
      }

      if (moveto != 999) {
        if (drag != null) drag.play(); //ドラッグ音を実行
        count++; //カウント(クリック回数)を数える
        if (cmpData()) { //完成したら
          if (good != null) good.play(); //good音を実行
        }
      }

      status = 2;

    }

    paint(g);

  }


  public void mousePressed(MouseEvent e) {

    int x = e.getX();
    int y = e.getY();

    if (status == 0 || status == 2) {
      if ( 190 < x && x < (190 + 85) && 30 < y && y < (30 + 54)) {
        b1_flag = false;
      }
    }

    if (status == 2) {
      if ( 200 < x && x < (200 + 60) && 158 < y && y < (158 + 22)) {
        b2_flag = false;
      }
   }
    if (status == 2) {
      for (int i = 0 ; i < MS*MS ; i++) {
        if ( xp[i] < x && x < xp[i] + MSS && yp[i] < y && y < yp[i] + MSS) {
          movefr = i;
          status = 4;
        }
      }
    }

    repaint();
    return;

  }

  public void mouseReleased(MouseEvent e) {

    int x = e.getX();
    int y = e.getY();

    if (b1_flag == false) {
      if ( 190 < x && x < (190 + 85) && 30 < y && y < (30 + 54)) {
        status = 1;
      }
    }

    if (b2_flag == false) {
      if ( 200 < x && x < (200 + 60) && 158 < y && y < (158 + 22)) {
        status = 3;
      }
    }

    b1_flag = true;
    b2_flag = true;
    repaint();
    return;

  }

  public void mouseExited(MouseEvent e) {

    b1_flag = true;
    b2_flag = true;
    repaint();
    return;

  }

  public void mouseClicked(MouseEvent e) {
  }

  public void mouseEntered(MouseEvent e) {
  }


  public boolean cmpData() {

    boolean flag = true;

    for (int i = 0 ; i < MS*MS ; i++) {
      if (data[i] != i) flag = false;
    }

    return flag;

  }


  public void shuffle() { //シャッフルする

			 for (int i = 0 ; i < MS*MS ; i++) {
      data[i] = i;
    }

    int aki = AKI;
    int i = 0;
    int ii = 100 + (int)(Math.random() * 2);
    int work;

    while (i < ii) {
      switch ((int)(Math.random() * 4)) {
               case 0:
          if ((aki / MS) > 0) {
            work = data[aki];
            data[aki] = data[aki - MS];
            data[aki - MS] = work;
            aki = aki - MS;
            i++;
          }
          break;
					      case 1:
          if ((aki / MS) < (MS - 1)) {
            work = data[aki];
            data[aki] = data[aki + MS];
            data[aki + MS] = work;
            aki = aki + MS;
            i++;
          }
          break;
			   case 2:
          if (aki % MS > 0) {
            work = data[aki];
            data[aki] = data[aki - 1];
            data[aki - 1] = work;
            aki = aki - 1;
            i++;
          }
          break;
					      case 3:
          if (aki % MS < (MS - 1)) {
            work = data[aki];
            data[aki] = data[aki + 1];
            data[aki + 1] = work;
            aki = aki + 1;
            i++;
          }
          break;
      }
    }

  }


  void makeImages() { //イメージの分割

    int w = MSS;
    int h = MSS;

    for (int i = 0 ; i < MS ; i++) {
      for (int j = 0 ; j < MS ; j++) {

        int pixels[] = new int[w * h];
        PixelGrabber pg = 
                new PixelGrabber(orgimg, w*j, h*i, w, h, pixels, 0, w);
        try {
          pg.grabPixels();
        } catch (InterruptedException e) {
          System.out.println("interrupted waiting for pixels!");
        }
        ImageProducer ip = new MemoryImageSource(w, h, pixels, 0, w);
        image[(i * MS) + j] = createImage(ip);

      }
    }

  }


			   Image makeDefalut() {//指定したイメージがなかった場合

    Image di;
    Graphics dg;
    di = createImage((MSS * MS),(MSS * MS));
    dg = di.getGraphics();

    dg.setColor(Color.lightGray);
    dg.fillRect(0,0, (MSS * MS),(MSS * MS));
    dg.setColor(Color.blue); //フォントカラーは青
    dg.setFont(new Font("Courier", Font.BOLD, 46));
    char c[] = {'A','B','C','D','E','F','G','H',' '}; //ABCDEFGHをマスに記述
    int k = 0;
    for (int j = 0 ; j < MS ; j++) {
      for (int i = 0 ; i < MS ; i++) {
        dg.drawChars(c, k, 1, MSS*i + 10, MSS*j + 42);
        k++;
      }
    }

    return di;

  }


}



[2] 実行結果

パズル


  ・ルール
   左上から順番にABCDEFGHと並べるだけです。
反省・感想
  今回はパクったソースが長すぎた。考察するのが大変なので、簡単にすませた。本当は、イメージ
 に何か画像を張ろうとしたんだけど、どうしても貼付けることができなかったのであきらめてしまった。
 音がなったのにはちょっと感激。こんなこともできるのですね。
  後期のプログラミングIIでは、前期にくらべて、どうも粘りがなくなってしまっていた。若干手抜き
 なとこがあったり、提出期限に間に合わなかったり・・・反省すべき点がたくさんです。
  それと、どういうわけかMac版のInternet Explorerではこのアプレットが実行できてません。原因が
 わからなくて対処できませぬ。



参考文献
独習Java ジョゼフ・オニール著 SHOEISHA
浅煎り珈琲Javaアプリケーション入門 http://msugai.fc2web.com/java/index.html#awt