天天看點

JAVA實作拼圖遊戲

效果圖如下:

源碼如下:

package org.test;

/**

* <p>Title: LoonFramework</p>

* <p>Description:拼圖圖像處理[未優化]</p>

* <p>Copyright: Copyright (c) 2007</p>

* <p>Company: LoonFramework</p>

* @author chenpeng    

* @email:[email][email protected][/email] 

* @version 0.1

*/

import java.awt.Canvas;

import java.awt.Color;

import java.awt.Event;

import java.awt.Frame;

import java.awt.Graphics;

import java.awt.Image;

import java.awt.MediaTracker;

import java.awt.image.BufferedImage;

import org.loon.framework.game.helper.ImageHelper;

public class BlockImage extends Canvas {

        /**

         * 

         */

        private static final long serialVersionUID = 1L;

        private Image _img;

        private Image _img2;

        private Graphics bg;

        private Image backimage;

        private int blocks[];

        private boolean isEvent;

        private MediaTracker mt;

        private int _width;

        private int _height;

        private int _RS;

        private int _CS;

        private Image screen = null;

        private Graphics later = null;

        private int _objWidth;

        private int _objHeight;

        private int _COUNT;

         * 析構函數,内部調用init方法。

         * @param bImage

         * @param overImage

         * @param cs

         * @param rs

        public BlockImage(Image bImage, Image overImage, int cs, int rs) {

                init(bImage, overImage, cs, rs);

        }

         * 初始化拼圖參數。

        public void init(Image bImage, Image overImage, int cs, int rs) {

                // 列數

                _CS = cs;

                // 行數

                _RS = rs;

                // 加載拼圖用圖像。

                _img = bImage;

                // 獲得實際窗體寬。

                _width = _img.getWidth(null);

                // 獲得實際窗體高。

                _height = _img.getHeight(null);

                // 獲得單塊圖像寬。

                _objWidth = _width / _CS;

                // 獲得單塊圖像高。

                _objHeight = _height / _RS;

                // 本程式直接使用backimage上一塊圖形區域緩沖選擇項,是以實際背景圖像高=圖形高+額外圖塊高。

                backimage = new BufferedImage(_width, _height + _objHeight, 1);

                // 獲得生成的圖形

                later = backimage.getGraphics();

                // 再建立一塊圖像區域,作為圖像緩存用。

                screen = new BufferedImage(_width, _height, 1);

                // 獲得緩存的圖形

                bg = screen.getGraphics();

                // 獲得等同圖檔總數的數組。

                _COUNT = _CS * _RS;

                blocks = new int[_COUNT];

                // 初始化為非點選。

                isEvent = false;

                // 加載完成拼圖的顯示圖。

                _img2 = overImage;

                // 初始化圖塊參數。

                for (int i = 0; i < _COUNT; i++) {

                        blocks[i] = i;

                }

                // 載入MediaTracker,用以跟蹤圖像狀态。

                mt = new MediaTracker(this);

                // 加載被跟蹤的圖像。

                mt.addImage(_img, 0);

                mt.addImage(_img2, 0);

                // 同步載入。

                try {

                        mt.waitForID(0);

                } catch (InterruptedException interruptedexception) {

                        return;

                // 随機生成圖像面闆内容。

                rndPannel();

         * 描繪窗體圖像。

        public void paint(Graphics g) {

                // 檢查圖像載入。

                if (mt.checkID(0)) {

                        // 描繪底層背景。

                        bg.drawImage(backimage, 0, 0, null);

                        // 判斷是否觸發完成事件。

                        if (!isEvent) {

                                // 設定背景色。

                                bg.setColor(Color.black);

                                // 循環繪制小圖檔于背景緩存中。

                                for (int i = 0; i < _CS; i++) {

                                        for (int j = 0; j < _RS; j++)

                                                bg.drawRect(i * _objWidth, j * _objHeight, _objWidth,

                                                                _objHeight);

                                }

                        }

                        // 僅當完成事件觸發并且有勝利圖檔時,載入完成提示。

                        if (isEvent && _img2 != null) {

                                bg.drawImage(_img2, 0, 0, null);

                // 舉凡繪制圖像時,應遵循顯示圖像僅繪制一次的基本原則,一次性的将背景繪制到窗體。

                // 簡單來說,也就是采取[雙緩存]的方式,所有複雜操作皆在緩存區完成,也隻有這樣才能避免産生延遲閃爍。

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

                g.dispose();

         * 變更圖像。

        public void update(Graphics g) {

                paint(g);

         * 滑鼠點選事件。

        public boolean mouseDown(Event event, int i, int j) {

                if (isEvent)

                        return true;

                // 換算點選位置與小圖檔。

                int k = i / _objWidth;

                int l = j / _objHeight;

                copy(0, 0, 0, _RS);

                copy(k, l, 0, 0);

                copy(0, _RS, k, l);

                int i1 = blocks[0];

                // 換算選中圖檔存儲區。

                blocks[0] = blocks[l * _CS + k];

                blocks[l * _CS + k] = i1;

                int j1;

                for (j1 = 0; j1 < _COUNT; j1++) {

                        if (blocks[j1] != j1) {

                                break;

                if (j1 == _COUNT)

                        isEvent = true;

                repaint();

                return true;

        public boolean mouseUp(Event event, int i, int j) {

        public boolean mouseDrag(Event event, int i, int j) {

         * copy換算後的圖像區域。

         * @param i

         * @param j

         * @param k

         * @param l

        void copy(int i, int j, int k, int l) {

                later.copyArea(i * _objWidth, j * _objHeight, _objWidth, _objHeight,

                                (k - i) * _objWidth, (l - j) * _objHeight);

         * 事件觸發狀态。

         * @return

        public boolean isEvent() {

                return isEvent;

        public void setEvent(boolean isEvent) {

                this.isEvent = isEvent;

         * 随機生成面闆圖檔。

        void rndPannel() {

                later.drawImage(_img, 0, 0, this);

                for (int i = 0; i < (_COUNT * _CS); i++) {

                        int j = (int) ((double) _CS * Math.random());

                        int k = (int) ((double) _RS * Math.random());

                        int l = (int) ((double) _CS * Math.random());

                        int i1 = (int) ((double) _RS * Math.random());

                        copy(j, k, 0, _RS);

                        copy(l, i1, j, k);

                        copy(0, _RS, l, i1);

                        int j1 = blocks[k * _CS + j];

                        blocks[k * _CS + j] = blocks[i1 * _CS + l];

                        blocks[i1 * _CS + l] = j1;

        public static void main(String[] args) {

                Frame frm = new Frame("簡單的JAVA拼圖效果實作[由Loonframework架構提供]");

                frm.setSize(480, 500);

                frm.setResizable(false);

                /**

                 * PS:ImageHelper.loadImage為Loonframework架構中helper下方法,為不依賴于javax擴充包而開發。

                 * 可使用ImageIO相關方法代替。

                 */

                // 加載圖像。

                Image backImage = ImageHelper.loadImage("C:/backimage.jpg", true);

                Image overImage = ImageHelper.loadImage("C:/over.gif", true);

                // BlockImage中參數分别為 用于分解的拼圖,完成後顯示文字,拆分圖檔為分幾列,分拆分圖檔為幾行。

                //建議使用正方形圖檔作為背景圖。

                frm.add(new BlockImage(backImage, overImage, 4, 4));

                backImage = null;

                overImage = null;

                // 顯示窗體。

                frm.setVisible(true);

}

詳細操作參見源碼注釋,所用圖檔如下(也可自由選取圖形):

本代碼算法支援自由成比例分隔圖像行列,效果若下:

本文轉自 cping 51CTO部落格,原文連結:http://blog.51cto.com/cping1982/116705