home *** CD-ROM | disk | FTP | other *** search
/ Mac Power 1997 January / macpower199701.bin / MacPowerÉIÉäÉWÉiÉã / CafeJAVA / Puzzle15.java < prev    next >
Encoding:
Text File  |  1996-11-09  |  7.5 KB  |  281 lines

  1. //////////////////////////////////////////////////////////////////////////
  2. //
  3. //                    サンプルプログラム3「15パズル 改良版2」
  4. //                                    分割イメージの自動作成 完成度アップ
  5. //                                                Programmed By T.Tanabe
  6. //
  7. //                            BGMと画像の著作権: ⒞Aris Multimedia Entertainment, Inc. 1993
  8.  
  9.  
  10. // 各種インポート
  11. import java.applet.*;
  12. import java.awt.*;
  13. import java.util.Random;
  14. import java.awt.image.CropImageFilter;
  15. import java.awt.image.FilteredImageSource;
  16. import java.awt.image.ImageFilter;
  17.  
  18. // メインアプレット
  19. public class Puzzle15 extends Applet implements Runnable {
  20.     String    sPuzzleFile = "DefaultPict";    // 指定の無いときのファイル名
  21.     int                iMoveCnt = 0;
  22.     AudioClip        auClick, auBgm;
  23.     Thread            thread = null;
  24.     PuzzleCanvas    PCanvas;
  25.     Label            lblMoveCnt;
  26.     
  27.     // 起動直後の初期化処理
  28.     public void init() {
  29.         String s;
  30.         
  31.         // パラメータの指定がある場合、ファイル名を変更する
  32.         if ((s = getParameter("file")) != null) { sPuzzleFile = s; };
  33.         
  34.         PCanvas = new PuzzleCanvas();
  35.         
  36.         // イメージの読み込み&設定
  37.         showStatus("Now Data Loading ...");
  38.         MediaTracker mt = new MediaTracker(this);
  39.         Image img = getImage(getDocumentBase(), "Images/"+sPuzzleFile+".gif");
  40.         mt.addImage(img, 0);
  41.         try {
  42.             mt.waitForID(0);
  43.         } catch(InterruptedException e) return;
  44.         PCanvas.setImage(img);
  45.         
  46.         // サウンドの設定
  47.         auBgm    = getAudioClip(getDocumentBase(), "Sounds/BGM.au");
  48.         auClick = getAudioClip(getDocumentBase(), "Sounds/Click.au");
  49.         
  50.         // 画面下部のカウント表示&ニューゲームボタンの設定
  51.         lblMoveCnt = new Label("Move Count = 0", Label.LEFT);
  52.         Panel pnl = new Panel();
  53.         pnl.setLayout(new GridLayout(1,2, 100, 0));
  54.         pnl.add(lblMoveCnt);
  55.         pnl.add(new Button("New Game"));
  56.         
  57.         setLayout(new BorderLayout());
  58.         add("Center", PCanvas);
  59.         add("South", pnl);
  60.     }
  61.     
  62.     // アプレット周囲の空白設定(インセット)
  63.     public Insets insets() {
  64.         return new Insets(10, 10, 10, 10);
  65.     }
  66.  
  67.     // アプレット開始&再開
  68.     public void start() {
  69.         if (thread == null) {
  70.             thread = new Thread(this);
  71.             thread.start();
  72.         }    
  73.     }
  74.     
  75.     // スレッド実行
  76.     public void run() {
  77.         if (auBgm != null)    auBgm.loop();
  78.     }
  79.     
  80.     // アプレット一時停止
  81.     public void stop() {
  82.         if (thread != null) {
  83.             auBgm.stop();
  84.             thread.stop();
  85.             thread = null;
  86.         }
  87.     }
  88.     
  89.     //アクションイベントの処理
  90.     public boolean action(Event evt, Object what) {
  91.         if (evt.target instanceof Button) {
  92.             // New Gameボタンが押されたらゲームを初期状態にする
  93.             PCanvas.InitAll();
  94.             PCanvas.repaint();
  95.             lblMoveCnt.setText("Move Count = 0");
  96.             iMoveCnt = 0;
  97.             showStatus("");
  98.             return true;
  99.         }
  100.         return false;
  101.     }
  102.  
  103.     // マウスダウンイベントの処理
  104.     public boolean mouseDown(Event evt, int x, int y) {
  105.         if (evt.target instanceof PuzzleCanvas && PCanvas.bClear == false) {
  106.             // マウスダウンがパズルエリアに対して発生(ゲーム中のみ)
  107.             int mx = x / PuzzleCanvas.PARTS_SIZE, 
  108.                 my = y / PuzzleCanvas.PARTS_SIZE;
  109.             
  110.             int bx = PCanvas.getBlinkX(), by = PCanvas.getBlinkY();
  111.             if ((mx == bx || my == by) && (mx - bx + my - by) != 0) {
  112.                 // X,Yのどちらか一方が一致したとき
  113.                 while(mx - bx + my - by != 0) {
  114.                     // 移動可能な限りブランクを移動する
  115.                     if (mx < bx)        PCanvas.MoveBlink(PuzzleCanvas.LEFT);
  116.                     else if (mx > bx)     PCanvas.MoveBlink(PuzzleCanvas.RIGHT);
  117.                     else if (my < by)     PCanvas.MoveBlink(PuzzleCanvas.UP);
  118.                     else if (my > by)     PCanvas.MoveBlink(PuzzleCanvas.DOWN);
  119.                     bx = PCanvas.getBlinkX(); by = PCanvas.getBlinkY();
  120.                 }
  121.                 PCanvas.repaint();
  122.                 iMoveCnt = iMoveCnt + 1;
  123.                 lblMoveCnt.setText("Move Count = " + iMoveCnt);
  124.                 auClick.play();
  125.                 // クリアチェック
  126.                 if (PCanvas.isClear()) {
  127.                     PCanvas.GameClear();
  128.                     showStatus("Game Clear!!");
  129.                 }
  130.                 return true;
  131.             }
  132.         }
  133.         return false;
  134.     }
  135. }
  136.  
  137. // パズルキャンバス用のクラス
  138. class PuzzleCanvas extends Canvas {
  139.     // 定数定義
  140.     static final int UP                = 0;
  141.     static final int RIGHT            = 1;
  142.     static final int DOWN            = 2;
  143.     static final int LEFT                = 3;
  144.     static final int PARTS_SIZE     = 60;
  145.     static final int PUZZLE_SIZE        = 4;
  146.     static final int PARTS_MAX        = PUZZLE_SIZE * PUZZLE_SIZE;
  147.     
  148.     static Random random = new Random();
  149.     Rectangle rc = new Rectangle(0, 0, 
  150.                         PARTS_SIZE * PUZZLE_SIZE, PARTS_SIZE * PUZZLE_SIZE);
  151.     Image    imgOrignal, imgParts[] = new Image[PARTS_MAX];
  152.     int        iArea[] = new int[PARTS_MAX];
  153.     int        iBlink;
  154.     boolean    bClear;
  155.     boolean bFirstDraw = true;
  156.     
  157.     // コンストラクタ
  158.     PuzzleCanvas() {
  159.         InitAll();
  160.     }
  161.     
  162.     public int getBlinkX() {    return iBlink % PUZZLE_SIZE;    }
  163.     public int getBlinkY() {    return iBlink / PUZZLE_SIZE;    }
  164.     public int indexToX(int n) {    return n % PUZZLE_SIZE;    }
  165.     public int indexToY(int n) {    return n / PUZZLE_SIZE;    }
  166.         
  167.     // パズルのイメージをセットするメゾット
  168.     public void setImage(Image img) {
  169.         imgOrignal = img;    
  170.         ImageFilter cropImg;
  171.         Graphics    g;
  172.         MediaTracker mt = new MediaTracker(this);
  173.         for (int i = 0; i < PARTS_MAX; i++) {
  174.             cropImg = new CropImageFilter(indexToX(i) * PARTS_SIZE, 
  175.                 indexToY(i) * PARTS_SIZE, PARTS_SIZE, PARTS_SIZE);
  176.                imgParts[i] = createImage(new FilteredImageSource(
  177.                                            img.getSource(), cropImg));
  178.             mt.addImage(imgParts[i], 1);
  179.            }
  180.         try {
  181.             mt.waitForID(1);
  182.         } catch(InterruptedException e) return;
  183.     }
  184.     
  185.     // 再描画のオーバーライト
  186.     public void update(Graphics g) {
  187.         g.clipRect(rc.x, rc.y, rc.width, rc.height);
  188.         paint(g);
  189.         bFirstDraw = true;
  190.     }
  191.     
  192.     // 描画処理
  193.     public void paint(Graphics g) {
  194.         g.drawImage(imgOrignal, 250, 0, 120, 120, this);
  195.         for (int i = 0; i < PARTS_MAX; i++) drawParts(g, i);
  196.     }
  197.     
  198.     // パズルのパーツを1つ描画する
  199.     public void drawParts(Graphics g, int pos) {
  200.         int x = indexToX(pos) * PARTS_SIZE,
  201.             y = indexToY(pos) * PARTS_SIZE;
  202.     
  203.         if (pos != iBlink || bClear)
  204.             g.drawImage(imgParts[iArea[pos]], x, y, this);
  205.         
  206.         if (bClear == false) {
  207.             if (pos != iBlink)
  208.                 g.drawRect(x, y, PARTS_SIZE - 1, PARTS_SIZE - 1);
  209.             else
  210.                 g.fillRect(x, y, PARTS_SIZE, PARTS_SIZE);
  211.         }
  212.     }
  213.     
  214.     //全て初期化
  215.     public void InitAll() {
  216.         for (int i = 0; i < PARTS_MAX; i++) iArea[i] = i;
  217.         iBlink = Math.abs(random.nextInt() % PARTS_MAX);
  218.         Shafull();
  219.         bClear = false;
  220.         bFirstDraw = true;
  221.         rc.reshape(0, 0, PARTS_SIZE * PUZZLE_SIZE + 130, PARTS_SIZE * PUZZLE_SIZE);
  222.     }
  223.     
  224.     // パズルパーツをシャッフルする
  225.     public void Shafull() {
  226.         for (int i = 0; i < 500; i++)
  227.             MoveBlink(Math.abs(random.nextInt() % 4));
  228.     }
  229.     
  230.     // ブランクカーソルの移動処理
  231.     public void MoveBlink(int iDir) {
  232.         int movOfs[] = {-PUZZLE_SIZE, 1, PUZZLE_SIZE, -1};
  233.         
  234.         if (isMoveOK(iDir)) {
  235.             if (bFirstDraw) {
  236.                 // 表示後、始めの描画はクリップのための初期設定
  237.                 bFirstDraw = false;
  238.                 rc.reshape(getBlinkX() * PARTS_SIZE, 
  239.                         getBlinkY() * PARTS_SIZE, PARTS_SIZE, PARTS_SIZE);
  240.             } else {
  241.                 // 2回目以降は、以前の範囲に追加
  242.                 rc.add(new Rectangle(getBlinkX() * PARTS_SIZE, 
  243.                         getBlinkY() * PARTS_SIZE, PARTS_SIZE, PARTS_SIZE));
  244.             }
  245.             int tmp = iArea[iBlink + movOfs[iDir]];
  246.             iArea[iBlink + movOfs[iDir]] = iArea[iBlink];
  247.             iArea[iBlink] = tmp;
  248.             iBlink = iBlink + movOfs[iDir];
  249.             rc.add(new Rectangle(getBlinkX() * PARTS_SIZE, 
  250.                         getBlinkY() * PARTS_SIZE, PARTS_SIZE, PARTS_SIZE));
  251.         }
  252.     }
  253.     
  254.     // ブランクカーソルの指定方向が移動可能か調べる
  255.     boolean isMoveOK(int dir) {
  256.         switch(dir) {
  257.         case LEFT:    return getBlinkX() != 0;
  258.         case RIGHT:    return getBlinkX() != (PUZZLE_SIZE - 1);
  259.         case UP:    return getBlinkY() > 0;
  260.         case DOWN:    return getBlinkY() < (PUZZLE_SIZE - 1);
  261.         }
  262.         return false;
  263.     }
  264.     
  265.     // パズルが完成したかどうかを調べる
  266.     public boolean isClear() {
  267.         for (int i = 0; i < PARTS_MAX; i++) {
  268.             if (iArea[i] != i) return false;
  269.         }
  270.         return true;
  271.     }
  272.     
  273.     // パズルが完成したときの処理
  274.     public void GameClear() {
  275.         bClear = true;
  276.         rc.reshape(0, 0, PARTS_SIZE * PUZZLE_SIZE, PARTS_SIZE * PUZZLE_SIZE);
  277.         repaint();
  278.     }
  279. }
  280.  
  281.