小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Android拼圖游戲開發(fā)全紀(jì)錄3

 水與火604 2016-03-13

今天我們要繼續(xù)開發(fā)Android游戲拼圖,今天同樣是做一些準(zhǔn)備工作,昨天我們把界面的準(zhǔn)備工作做好了,今天呢,我們想想,要完成一個(gè)拼圖,我們還需要做哪些準(zhǔn)備。

首先,我們需要一個(gè)工具類,去獲取屏幕的相關(guān)信息,讓我們的程序去自動(dòng)適應(yīng)不同分辨率大小的屏幕:

  1. package com.xys.xpuzzle.util;  
  2.   
  3. import android.content.Context;  
  4. import android.util.DisplayMetrics;  
  5. import android.view.Display;  
  6. import android.view.WindowManager;  
  7.   
  8. /** 
  9.  * 屏幕工具類:實(shí)現(xiàn)獲取屏幕相關(guān)參數(shù) 
  10.  *  
  11.  * @author xys 
  12.  *  
  13.  */  
  14. public class ScreenUtil {  
  15.   
  16.     /** 
  17.      * 獲取屏幕相關(guān)參數(shù) 
  18.      *  
  19.      * @param context 
  20.      * @return DisplayMetrics 屏幕寬高 
  21.      */  
  22.     public static DisplayMetrics getScreenSize(Context context) {  
  23.     DisplayMetrics metrics = new DisplayMetrics();  
  24.     WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);  
  25.     Display display = wm.getDefaultDisplay();  
  26.     display.getMetrics(metrics);  
  27.     return metrics;  
  28.     }  
  29. }  

下面我們要開始設(shè)計(jì)一個(gè)實(shí)體bean,去封裝我們的拼圖,這里的方法有很多,我只是舉個(gè)磚頭。

我們知道,拼圖時(shí)會(huì)把圖片分割成NXN個(gè)方塊,移動(dòng)方塊以完成拼圖,所以我將每個(gè)分割后的方塊做成一個(gè)對(duì)象,我們所有的實(shí)體bean都是基于每個(gè)分割后的方塊,所以自然的我們可以抽象出一個(gè)實(shí)體bean:

  1. package com.xys.xpuzzle.bean;  
  2.   
  3. import android.graphics.Bitmap;  
  4.   
  5. /** 
  6.  * 拼圖Item邏輯實(shí)體類:封裝邏輯相關(guān)屬性 
  7.  *  
  8.  * @author xys 
  9.  *  
  10.  */  
  11. public class ItemBean {  
  12.   
  13.     // Item的Id  
  14.     private int itemId;  
  15.     // bitmap的Id  
  16.     private int bitmapId;  
  17.     // bitmap  
  18.     private Bitmap bitmap;  
  19.   
  20.     public int getItemId() {  
  21.     return itemId;  
  22.     }  
  23.   
  24.     public void setItemId(int itemId) {  
  25.     this.itemId = itemId;  
  26.     }  
  27.   
  28.     public ItemBean() {  
  29.     }  
  30.   
  31.     public int getBitmapId() {  
  32.     return bitmapId;  
  33.     }  
  34.   
  35.     public void setBitmapId(int bitmapId) {  
  36.     this.bitmapId = bitmapId;  
  37.     }  
  38.   
  39.     public Bitmap getBitmap() {  
  40.     return bitmap;  
  41.     }  
  42.   
  43.     public void setBitmap(Bitmap bitmap) {  
  44.     this.bitmap = bitmap;  
  45.     }  
  46.   
  47.     public ItemBean(int itemId, int bitmapId, Bitmap bitmap) {  
  48.     this.itemId = itemId;  
  49.     this.bitmapId = bitmapId;  
  50.     this.bitmap = bitmap;  
  51.     }  
  52.   
  53. }  

bean里面封裝了

1、方塊對(duì)應(yīng)在NXN格中的序號(hào)

2、分割后的圖片的ID和對(duì)應(yīng)的圖片

接下來(lái)就是對(duì)圖片的分割:

  1. package com.xys.xpuzzle.util;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import com.xys.xpuzzle.R;  
  7. import com.xys.xpuzzle.activity.PuzzleMain;  
  8. import com.xys.xpuzzle.bean.ItemBean;  
  9.   
  10. import android.content.Context;  
  11. import android.graphics.Bitmap;  
  12. import android.graphics.BitmapFactory;  
  13. import android.graphics.Matrix;  
  14.   
  15. /** 
  16.  * 圖像工具類:實(shí)現(xiàn)圖像的分割與自適應(yīng) 
  17.  *  
  18.  * @author xys 
  19.  *  
  20.  */  
  21. public class ImagesUtil {  
  22.   
  23.     public ItemBean itemBean;  
  24.   
  25.     /** 
  26.      * 切圖、初始狀態(tài)(正常順序) 
  27.      *  
  28.      * @param type 
  29.      * @param picSelected 
  30.      * @param context 
  31.      */  
  32.     public void createInitBitmaps(int type, Bitmap picSelected, Context context) {  
  33.     Bitmap bitmap = null;  
  34.     List<Bitmap> bitmapItems = new ArrayList<Bitmap>();  
  35.     // 每個(gè)Item的寬高  
  36.     int itemWidth = picSelected.getWidth() / type;  
  37.     int itemHeight = picSelected.getHeight() / type;  
  38.     for (int i = 1; i <= type; i++) {  
  39.         for (int j = 1; j <= type; j++) {  
  40.         bitmap = Bitmap.createBitmap(picSelected, (j - 1) * itemWidth, (i - 1) * itemHeight, itemWidth, itemHeight);  
  41.         bitmapItems.add(bitmap);  
  42.         itemBean = new ItemBean((i - 1) * type + j, (i - 1) * type + j, bitmap);  
  43.         GameUtil.itemBeans.add(itemBean);  
  44.         }  
  45.     }  
  46.     // 保存最后一個(gè)圖片在拼圖完成時(shí)填充  
  47.     PuzzleMain.lastBitmap = bitmapItems.get(type * type - 1);  
  48.     // 設(shè)置最后一個(gè)為空Item  
  49.     bitmapItems.remove(type * type - 1);  
  50.     GameUtil.itemBeans.remove(type * type - 1);  
  51.     Bitmap blankBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.blank);  
  52.     blankBitmap = Bitmap.createBitmap(blankBitmap, 0, 0, itemWidth, itemHeight);  
  53.   
  54.     bitmapItems.add(blankBitmap);  
  55.     GameUtil.itemBeans.add(new ItemBean(type * type, 0, blankBitmap));  
  56.   
  57.     GameUtil.blankItemBean = GameUtil.itemBeans.get(type * type - 1);  
  58.     }  
  59.   
  60.     /** 
  61.      * 處理圖片 放大、縮小到合適位置 
  62.      *  
  63.      * @param newWidth 
  64.      * @param newHeight 
  65.      * @param bitmap 
  66.      * @return 
  67.      */  
  68.     public Bitmap resizeBitmap(float newWidth, float newHeight, Bitmap bitmap) {  
  69.     Matrix matrix = new Matrix();  
  70.     matrix.postScale(newWidth / bitmap.getWidth(), newHeight / bitmap.getHeight());  
  71.     Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);  
  72.     return newBitmap;  
  73.     }  
  74. }  

這個(gè)工具類主要完成這兩件事:

1、切圖、初始狀態(tài)(正常順序)

2、處理圖片 放大、縮小到合適位置

根據(jù)上一篇講的算法,我們需要將圖片進(jìn)行分割,然后生成一個(gè)切好圖后的Items集合,當(dāng)然,還要對(duì)要拼圖的圖片進(jìn)行下大小的處理,因?yàn)槲覀兂擞心J(rèn)的圖片,還可以自定義圖片


圖片工具類完成后,接下來(lái)我們就要在一個(gè)工具類中實(shí)現(xiàn)這些算法,同時(shí)還要做一些對(duì)游戲的封裝:

  1. package com.xys.xpuzzle.util;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import com.xys.xpuzzle.activity.PuzzleMain;  
  7. import com.xys.xpuzzle.bean.ItemBean;  
  8.   
  9. /** 
  10.  * 拼圖工具類:實(shí)現(xiàn)拼圖的交換與生成算法 
  11.  *  
  12.  * @author xys 
  13.  *  
  14.  */  
  15. public class GameUtil {  
  16.   
  17.     // 游戲信息單元格Bean  
  18.     public static List<ItemBean> itemBeans = new ArrayList<ItemBean>();  
  19.     // 空格單元格  
  20.     public static ItemBean blankItemBean = new ItemBean();  
  21.   
  22.     /** 
  23.      * 判斷點(diǎn)擊的Item是否可移動(dòng) 
  24.      *  
  25.      * @param position 
  26.      * @return 能否移動(dòng) 
  27.      */  
  28.     public static boolean isMoveable(int position) {  
  29.     int type = PuzzleMain.type;  
  30.     // 獲取空格Item  
  31.     int blankId = GameUtil.blankItemBean.getItemId() - 1;  
  32.     // 不同行 相差為type  
  33.     if (Math.abs(blankId - position) == type) {  
  34.         return true;  
  35.     }  
  36.     // 相同行 相差為1  
  37.     if ((blankId / type == position / type) && Math.abs(blankId - position) == 1) {  
  38.         return true;  
  39.     }  
  40.     return false;  
  41.     }  
  42.   
  43.     /** 
  44.      * 交換空格與點(diǎn)擊Item的位置 
  45.      *  
  46.      * @param from 
  47.      * @param blank 
  48.      */  
  49.     public static void swapItems(ItemBean from, ItemBean blank) {  
  50.     ItemBean tempItemBean = new ItemBean();  
  51.     // 交換BitmapId  
  52.     tempItemBean.setBitmapId(from.getBitmapId());  
  53.     from.setBitmapId(blank.getBitmapId());  
  54.     blank.setBitmapId(tempItemBean.getBitmapId());  
  55.     // 交換Bitmap  
  56.     tempItemBean.setBitmap(from.getBitmap());  
  57.     from.setBitmap(blank.getBitmap());  
  58.     blank.setBitmap(tempItemBean.getBitmap());  
  59.     // 設(shè)置新的Blank  
  60.     GameUtil.blankItemBean = from;  
  61.     }  
  62.   
  63.     /** 
  64.      * 生成隨機(jī)的Item 
  65.      */  
  66.     public static void getPuzzleGenerator() {  
  67.     int index = 0;  
  68.     for (int i = 0; i < itemBeans.size(); i++) {  
  69.         index = (int) (Math.random() * PuzzleMain.type * PuzzleMain.type);  
  70.         swapItems(itemBeans.get(index), GameUtil.blankItemBean);  
  71.     }  
  72.     List<Integer> data = new ArrayList<Integer>();  
  73.     for (int i = 0; i < itemBeans.size(); i++) {  
  74.         data.add(itemBeans.get(i).getBitmapId());  
  75.     }  
  76.     // 判斷生成是否有解  
  77.     if (canSolve(data)) {  
  78.         return;  
  79.     } else {  
  80.         getPuzzleGenerator();  
  81.     }  
  82.     }  
  83.   
  84.     /** 
  85.      * 是否拼圖成功 
  86.      *  
  87.      * @return 是否拼圖成功 
  88.      */  
  89.     public static boolean isSuccess() {  
  90.     for (ItemBean tempBean : GameUtil.itemBeans) {  
  91.         if (tempBean.getBitmapId() != 0 && (tempBean.getItemId()) == tempBean.getBitmapId()) {  
  92.         continue;  
  93.         } else if (tempBean.getBitmapId() == 0 && tempBean.getItemId() == PuzzleMain.type * PuzzleMain.type) {  
  94.         continue;  
  95.         } else {  
  96.         return false;  
  97.         }  
  98.     }  
  99.     return true;  
  100.     }  
  101.   
  102.     /** 
  103.      * 該數(shù)據(jù)是否有解 
  104.      *  
  105.      * @param data 
  106.      * @return 該數(shù)據(jù)是否有解 
  107.      */  
  108.     public static boolean canSolve(List<Integer> data) {  
  109.     // 獲取空格Id  
  110.     int blankId = GameUtil.blankItemBean.getItemId();  
  111.     // 可行性原則  
  112.     if (data.size() % 2 == 1) {  
  113.         return getInversions(data) % 2 == 0;  
  114.     } else {  
  115.         // 從底往上數(shù),空格位于奇數(shù)行  
  116.         if (((int) (blankId - 1) / PuzzleMain.type) % 2 == 1) {  
  117.         return getInversions(data) % 2 == 0;  
  118.         } else {  
  119.         // 從底往上數(shù),空位位于偶數(shù)行  
  120.         return getInversions(data) % 2 == 1;  
  121.         }  
  122.     }  
  123.     }  
  124.   
  125.     /** 
  126.      * 計(jì)算倒置和算法 
  127.      *  
  128.      * @param data 
  129.      * @return 該序列的倒置和 
  130.      */  
  131.     public static int getInversions(List<Integer> data) {  
  132.     int inversions = 0;  
  133.     int inversionCount = 0;  
  134.     for (int i = 0; i < data.size(); i++) {  
  135.         for (int j = i + 1; j < data.size(); j++) {  
  136.         int index = data.get(i);  
  137.         if (data.get(j) != 0 && data.get(j) < index) {  
  138.             inversionCount++;  
  139.         }  
  140.         }  
  141.         inversions += inversionCount;  
  142.         inversionCount = 0;  
  143.     }  
  144.     return inversions;  
  145.     }  
  146. }  

可以看到,游戲工具類中,我們主要有以下幾個(gè)功能:

1、判斷點(diǎn)擊的Item是否可移動(dòng):主要難點(diǎn)是判斷需要分同行與不同行,否則會(huì)出現(xiàn)上一行的最后一個(gè)和本行的第一個(gè)可以移動(dòng)的BUG

2、交換空格與點(diǎn)擊Item的位置:實(shí)際上是交換GridView中的某2個(gè)Item的背景

3、生成隨機(jī)的Item:根據(jù)上一篇講的算法,打隨機(jī)打亂分割后的圖片

4、判斷是否拼圖成功:根據(jù)上一篇講的算法的結(jié)論判斷

5、判斷該數(shù)據(jù)是否有解:根據(jù)上一篇講的算法的結(jié)論判斷

6、計(jì)算倒置和算法:算法的核心注意要踢出空格


到目前為止,我們的準(zhǔn)備工作就基本結(jié)束了,很多人可能會(huì)說(shuō)開始的時(shí)候準(zhǔn)備這么多干嘛,其實(shí)這是我真實(shí)的思考順序,剛開始項(xiàng)目的時(shí)候,一定要先把項(xiàng)目整體規(guī)劃一下,而不是上手就做,當(dāng)你有了一個(gè)清晰的思路后,coding只是一個(gè)體力活而已。所以,工欲善其事,必先利其器,畫竹需要成竹在胸。


ps : 需要源碼的朋友請(qǐng)留言。



    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多