亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 1440 | 回復(fù): 0
打印 上一主題 下一主題

Android下實(shí)現(xiàn)一個(gè)簡單的俄羅斯方塊游戲 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2011-12-20 09:44 |只看該作者 |倒序?yàn)g覽
    前幾天看Android自帶的例子代碼,其中有個(gè)貪吃蛇的游戲,看了其代碼后覺得寫得非常好,同時(shí)又有了想寫一個(gè)俄羅斯方塊游戲的想法。俄羅斯方塊的游戲我以前曾經(jīng)用JAVA實(shí)現(xiàn)過,當(dāng)時(shí)實(shí)現(xiàn)得很復(fù)雜,而現(xiàn)在有了這個(gè)貪吃蛇的例子后,實(shí)現(xiàn)起來就簡單多了。在貪吃蛇游戲中有個(gè)類TileView.java,這個(gè)類基本實(shí)現(xiàn)了對(duì)單個(gè)方塊的操作,因此我就直接拿來用了,并沒有做任何的修改,這個(gè)類的代碼就不在這里貼出了。
    俄羅斯方塊游戲比貪吃蛇稍微復(fù)雜一些,其主要的難點(diǎn)主要有:
    1.實(shí)現(xiàn)方塊的旋轉(zhuǎn)。我們都知道在游戲中按上方塊是要旋轉(zhuǎn)的,我對(duì)方塊的旋轉(zhuǎn)就是選擇一個(gè)方塊作為中心,另外3個(gè)方塊都繞著它順時(shí)針旋轉(zhuǎn)90度。需要注意的一點(diǎn)就是田形的方塊是不需要旋轉(zhuǎn)的,如果按照我的方法旋轉(zhuǎn)田形方塊就會(huì)造成方塊平移的結(jié)果。
    2.邊界的判定。就是判斷一下方塊是否可以移動(dòng),這包含兩方面的內(nèi)容,一方面是水平方向的移動(dòng),這里需要注意的就是在邊界上旋轉(zhuǎn)方塊又可能使方塊旋轉(zhuǎn)出邊界,所以在旋轉(zhuǎn)前必要預(yù)先判斷一下旋轉(zhuǎn)后的方塊是否已經(jīng)超出了邊界;另一方面是往下移動(dòng),一旦不能移動(dòng)了就需要凍結(jié)方塊并產(chǎn)生新的方塊。
    3.消行。每落下一個(gè)方塊都需要判斷一下是否可以消行。而消行后上面的方塊又都要垂直下落,同時(shí)原來的位置也要被清空。

    下面說一下實(shí)現(xiàn)這個(gè)游戲的步驟:
    1.創(chuàng)建一個(gè)新的ANDROID工程,命名為Tetris,包名為com.test。
    2.創(chuàng)建一個(gè)activity類,命名為:Tetris.java。

    1. package com.test;

    2. import android.app.Activity;
    3. import android.content.Context;
    4. import android.os.Bundle;
    5. import android.util.Log;
    6. import android.widget.TextView;

    7. import java.io.File;
    8. import java.io.FileInputStream;
    9. import java.io.FileNotFoundException;
    10. import java.io.FileOutputStream;
    11. import java.io.IOException;
    12. import java.io.InputStream;
    13. import java.io.OutputStream;

    14. public class Tetris extends Activity {
    15.     private String TAG = "Tetris";

    16.     private TetrisView tetrisView;

    17.     private TextView highestScore;

    18.     private TextView info;

    19.     private TextView currentScore;

    20.     private TextView currentLevel;

    21.     String NAME = "score.txt";

    22.     /**
    23.      * 保存數(shù)據(jù)時(shí)用到的key
    24.      */
    25.     private static String ICICLE_KEY = "tetris-view";

    26.     /**
    27.      * 游戲的主要activity
    28.      */
    29.     public void onCreate(Bundle savedInstanceState) {
    30.         super.onCreate(savedInstanceState);
    31.         setContentView(R.layout.tetris_layout);
    32.         tetrisView = (TetrisView)findViewById(R.id.tetris);
    33.         highestScore = (TextView)findViewById(R.id.highest_score);
    34.         currentScore = (TextView)findViewById(R.id.current_score);
    35.         info = (TextView)findViewById(R.id.info);
    36.         currentLevel = (TextView)findViewById(R.id.current_level);
    37.         // 為view實(shí)例化這些文本框
    38.         tetrisView.setTextView(currentScore, highestScore, info, currentLevel);
    39.         if (savedInstanceState == null) {
    40.             // 開始一個(gè)新游戲,將游戲的狀態(tài)設(shè)為READY
    41.             tetrisView.setMode(TetrisView.READY);
    42.         } else {
    43.             // 如果存儲(chǔ)了一個(gè)游戲的狀態(tài),則將狀態(tài)讀出來,可以繼續(xù)游戲
    44.             Bundle map = savedInstanceState.getBundle(ICICLE_KEY);
    45.             if (map != null) {
    46.                 tetrisView.restoreState(map);
    47.             } else {
    48.                 tetrisView.setMode(TetrisView.PAUSE);
    49.             }
    50.         }
    51.         // 讀取歷史最高分
    52.         FileInputStream in;
    53.         byte[] by = new byte[10];
    54.         try {
    55.             in = openFileInput(NAME);
    56.             in.read(by);
    57.             StringBuffer buffer = new StringBuffer();
    58.             for (int i = 0; i < 10; i++) {
    59.                 if (by[i] != 0) {
    60.                     buffer.append(by[i] - 48);
    61.                 }
    62.             }
    63.             Log.d("dd", buffer.toString());
    64.             tetrisView.historyScore = Long.valueOf(buffer.toString());
    65.         } catch (FileNotFoundException e) {
    66.         } catch (IOException e) {
    67.             // TODO Auto-generated catch block
    68.             e.printStackTrace();
    69.         }

    70.     }

    71.     @Override
    72.     protected void onPause() {
    73.         //如果分?jǐn)?shù)超出了歷史最高分,則保存數(shù)據(jù)
    74.         if (tetrisView.overhistroy) {
    75.             FileOutputStream fos;
    76.             try {
    77.                 fos = openFileOutput(NAME, Context.MODE_PRIVATE);
    78.                 fos.write(String.valueOf(TetrisView.historyScore).getBytes());
    79.                 fos.close();

    80.             } catch (FileNotFoundException e) {
    81.                 // TODO Auto-generated catch block
    82.                 e.printStackTrace();
    83.             } catch (IOException e) {
    84.                 // TODO Auto-generated catch block
    85.                 e.printStackTrace();
    86.             }
    87.         }
    88.         super.onPause();
    89.         // 暫停游戲
    90.         tetrisView.setMode(TetrisView.PAUSE);
    91.     }

    92.     @Override
    93.     public void onSaveInstanceState(Bundle outState) {
    94.         // 保存游戲狀態(tài)
    95.         outState.putBundle(ICICLE_KEY, tetrisView.saveState());
    96.     }

    97. }


    1. package com.test;

    2. import android.content.Context;
    3. import android.content.res.Resources;
    4. import android.os.Bundle;
    5. import android.os.Handler;
    6. import android.os.Message;
    7. import android.util.AttributeSet;
    8. import android.util.Log;
    9. import android.view.KeyEvent;
    10. import android.view.View;
    11. import android.widget.TextView;

    12. import java.io.File;
    13. import java.io.FileNotFoundException;
    14. import java.io.FileOutputStream;
    15. import java.io.IOException;
    16. import java.util.ArrayList;
    17. import java.util.Random;

    18. public class TetrisView extends TileView {

    19.     private static final String TAG = "TetrisView";

    20.     /**
    21.      * 游戲的四種狀態(tài)
    22.      */
    23.     private int mMode = READY;

    24.     public static final int PAUSE = 0;

    25.     public static final int READY = 1;

    26.     public static final int RUNNING = 2;

    27.     public static final int LOSE = 3;

    28.     /**
    29.      * 三種背景圖片,由這些圖片拼裝成游戲的基本界面
    30.      */
    31.     private static final int RED_STAR = 1;

    32.     private static final int YELLOW_STAR = 2;

    33.     private static final int GREEN_STAR = 3;

    34.     /**
    35.      * 產(chǎn)生隨機(jī)數(shù),根據(jù)隨機(jī)數(shù)決定方塊的形狀
    36.      */
    37.     private static final Random RNG = new Random();

    38.     /**
    39.      * 當(dāng)前游戲的分?jǐn)?shù)
    40.      */
    41.     private long mScore = 0;

    42.     /**
    43.      * 歷史最高分
    44.      */
    45.     public static long historyScore = 0;
    46.     
    47.     /**
    48.      * 是否超出了最高分,如果超出了,則在退出時(shí)會(huì)保存數(shù)據(jù)
    49.      */
    50.     public static boolean overhistroy=false;
    51.     /**
    52.      * 方塊移動(dòng)的速度,數(shù)值越小則方塊的速度越高,難度也就越大
    53.      */
    54.     private long mMoveDelay;

    55.     /**
    56.      * 當(dāng)前方塊移動(dòng)的速度,和mMoveDelay配合使用,在游戲中更改游戲的速度都是更改此變量值
    57.      * 在每個(gè)方塊產(chǎn)生的時(shí)候,將此變量值賦給mMoveDelay。之所以采用兩個(gè)變量是因?yàn)楫?dāng)按下加速 方塊落下之后,下一個(gè)方塊的速度還要保持原來的速度。
    58.      */
    59.     private long currentDelay;

    60.     /**
    61.      * 預(yù)先顯示的方塊,在前一個(gè)方塊落下后,使其變?yōu)楫?dāng)前方塊
    62.      */
    63.     private ArrayList<Coordinate> preShape = new ArrayList<Coordinate>();

    64.     /**
    65.      * 當(dāng)前正在下落的方塊
    66.      */
    67.     private ArrayList<Coordinate> mShape = new ArrayList<Coordinate>();

    68.     private ArrayList<Coordinate> oldShape = new ArrayList<Coordinate>();

    69.     /**
    70.      * 顯示歷史最高分的文本框
    71.      */
    72.     private TextView highestScore;

    73.     /**
    74.      * 顯示當(dāng)前分?jǐn)?shù)的文本框
    75.      */
    76.     private TextView currentScore;

    77.     /**
    78.      * 顯示當(dāng)前游戲級(jí)別的文本框
    79.      */
    80.     private TextView currentLevel;

    81.     /**
    82.      * 記錄游戲的級(jí)別
    83.      */
    84.     private int gameLevel = 1;

    85.     /**
    86.      * 在屏幕中央顯示提示信息的文本框
    87.      */
    88.     private TextView info;

    89.     /**
    90.      * 記錄目前落下的方塊的最高層數(shù)
    91.      */
    92.     private int highLevel = 0;

    93.     /**
    94.      * 當(dāng)前方塊類型,主要用來標(biāo)示田形方塊,從而在旋轉(zhuǎn)方塊的時(shí)候可以讓田形方塊不旋轉(zhuǎn)
    95.      */
    96.     private int shapeType;

    97.     /**
    98.      * 預(yù)先顯示方塊的類型
    99.      */
    100.     private int preType;

    101.     /**
    102.      * 構(gòu)造方法
    103.      */
    104.     public TetrisView(Context context, AttributeSet attrs) {
    105.         super(context, attrs);
    106.         initGame();
    107.     }

    108.     public TetrisView(Context context, AttributeSet attrs, int defStyle) {
    109.         super(context, attrs, defStyle);
    110.         initGame();
    111.     }

    112.     /**
    113.      * 通過一個(gè)handler來更新界面的顯示,以及方塊下落的速度
    114.      */
    115.     private RefreshHandler mRedrawHandler = new RefreshHandler();

    116.     class RefreshHandler extends Handler {

    117.         @Override
    118.         public void handleMessage(Message msg) {
    119.             TetrisView.this.update();
    120.             TetrisView.this.invalidate();

    121.         }

    122.         public void sleep(long delayMillis) {
    123.             this.removeMessages(0);
    124.             sendMessageDelayed(obtainMessage(0), delayMillis);
    125.         }
    126.     };

    127.     /**
    128.      * 初始化游戲
    129.      */
    130.     private void initGame() {
    131.         setFocusable(true);
    132.         Resources r = this.getContext().getResources();
    133.         resetTiles(4);
    134.         loadTile(RED_STAR, r.getDrawable(R.drawable.redstar));
    135.         loadTile(YELLOW_STAR, r.getDrawable(R.drawable.yellowstar));
    136.         loadTile(GREEN_STAR, r.getDrawable(R.drawable.greenstar));

    137.     }

    138.     /**
    139.      * 開始一個(gè)新游戲,重置各種數(shù)據(jù)
    140.      */
    141.     private void startGame() {
    142.         clearTiles();
    143.         gameLevel = 1;
    144.         highLevel = 0;
    145.         currentDelay = 600;
    146.         mScore = 0;
    147.         currentScore.setText("當(dāng)前分?jǐn)?shù):\n" + mScore);
    148.         currentLevel.setText("當(dāng)前級(jí)別:\n" + gameLevel);
    149.         highestScore.setText("最高分?jǐn)?shù):\n"+historyScore);
    150.         setMode(RUNNING);
    151.     }


    152.     /**
    153.      * 將arraylist轉(zhuǎn)換為數(shù)組,從而可以將該部分?jǐn)?shù)據(jù)保存起來
    154.      */
    155.     private int[] coordArrayListToArray(ArrayList<Coordinate> cvec) {
    156.         int count = cvec.size();
    157.         int[] rawArray = new int[count * 2];
    158.         for (int index = 0; index < count; index++) {
    159.             Coordinate c = cvec.get(index);
    160.             rawArray[2 * index] = c.x;
    161.             rawArray[2 * index + 1] = c.y;
    162.         }
    163.         return rawArray;
    164.     }

    165.     /**
    166.      * 將已經(jīng)落下來的方塊的坐標(biāo)保存在一個(gè)ArrayList中
    167.      */
    168.     private ArrayList<Coordinate> tailsToList(int[][] tileGrid) {
    169.         ArrayList<Coordinate> tranList = new ArrayList<Coordinate>();
    170.         for (int i = 0; i < mXTileCount - 6; i++) {
    171.             for (int j = 1; j < mYTileCount - 1; j++) {
    172.                 if (tileGrid[i][j] == RED_STAR) {
    173.                     Coordinate cor = new Coordinate(i, j);
    174.                     tranList.add(cor);
    175.                 }
    176.             }
    177.         }
    178.         return tranList;
    179.     }

    180.     /**
    181.      * 保存游戲的狀態(tài),從而在切換游戲后還可以繼續(xù)游戲
    182.      *
    183.      * @return a Bundle with this view's state
    184.      */
    185.     public Bundle saveState() {
    186.         Bundle map = new Bundle();
    187.         map.putIntArray("preShapeList", coordArrayListToArray(preShape));
    188.         map.putIntArray("mShapeList", coordArrayListToArray(mShape));
    189.         map.putLong("mMoveDelay", Long.valueOf(mMoveDelay));
    190.         map.putLong("mScore", Long.valueOf(mScore));
    191.         map.putLong("hisScore", Long.valueOf(historyScore));
    192.         map.putInt("mLevel", highLevel);
    193.         map.putIntArray("tailList", coordArrayListToArray(tailsToList(mTileGrid)));

    194.         return map;
    195.     }

    196.     /**
    197.      * 將數(shù)組轉(zhuǎn)換為Arraylist,從而將保存的數(shù)據(jù)轉(zhuǎn)化為游戲的狀態(tài)
    198.      *
    199.      * @param rawArray : [x1,y1,x2,y2,...]
    200.      * @return a ArrayList of Coordinates
    201.      */
    202.     private ArrayList<Coordinate> coordArrayToArrayList(int[] rawArray) {
    203.         ArrayList<Coordinate> coordArrayList = new ArrayList<Coordinate>();
    204.         int coordCount = rawArray.length;
    205.         for (int index = 0; index < coordCount; index += 2) {
    206.             Coordinate c = new Coordinate(rawArray[index], rawArray[index + 1]);
    207.             coordArrayList.add(c);
    208.         }
    209.         return coordArrayList;
    210.     }

    211.     /**
    212.      * 從保存的數(shù)據(jù)中讀取已經(jīng)落下的方塊坐標(biāo),并重新在界面上畫出這些方塊
    213.      */
    214.     private void listToTail(ArrayList<Coordinate> cor) {
    215.         int count = cor.size();

    216.         for (int index = 0; index < count; index++) {
    217.             Coordinate c = cor.get(index);
    218.             mTileGrid[c.x][c.y] = RED_STAR;
    219.         }
    220.     }

    221.     /**
    222.      * 切換到游戲的時(shí)候,讀取所保存的數(shù)據(jù),重現(xiàn)游戲先前的狀態(tài)
    223.      *
    224.      * @param icicle a Bundle containing the game state
    225.      */
    226.     public void restoreState(Bundle icicle) {
    227.         setMode(PAUSE);
    228.         historyScore = icicle.getLong("hisScore");
    229.         highLevel = icicle.getInt("mLevel");
    230.         mMoveDelay = icicle.getLong("mMoveDelay");
    231.         mScore = icicle.getLong("mScore");
    232.         preShape = coordArrayToArrayList(icicle.getIntArray("preShapeList"));
    233.         mShape = coordArrayToArrayList(icicle.getIntArray("mShapeList"));
    234.         listToTail(coordArrayToArrayList(icicle.getIntArray("tailList")));
    235.     }

    236.     /**
    237.      * 對(duì)按鍵的響應(yīng)
    238.      */
    239.     public boolean onKeyDown(int keyCode, KeyEvent msg) {
    240.         // 按下了上鍵
    241.         if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
    242.             if (mMode == READY | mMode == LOSE) {

    243.                 startGame();
    244.                 setMode(RUNNING);
    245.                 return (true);
    246.             } else if (mMode == RUNNING) {
    247.                 transShape();
    248.                 update();
    249.                 return (true);
    250.             }
    251.             if (mMode == PAUSE) {
    252.                 setMode(RUNNING);
    253.                 update();
    254.                 return (true);
    255.             }
    256.         }
    257.         // 按下了下鍵
    258.         if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
    259.             moveDown();

    260.             return (true);
    261.         }
    262.         // 按下了左鍵
    263.         if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
    264.             moveLeft();
    265.             updateShape();
    266.             return (true);
    267.         }
    268.         // 按下了右鍵
    269.         if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
    270.             moveRight();
    271.             updateShape();
    272.             return (true);
    273.         }
    274.         return super.onKeyDown(keyCode, msg);
    275.     }

    276.     /**
    277.      * 加速方塊的下落
    278.      */
    279.     private void moveDown() {
    280.         mMoveDelay = 50;
    281.     }

    282.     /**
    283.      * 將方塊向右移動(dòng),在移動(dòng)前要判斷一下是否可以移動(dòng)
    284.      */
    285.     private void moveRight() {
    286.         newToOld(mShape, oldShape);
    287.         for (Coordinate c : mShape) {
    288.             c.x = c.x + 1;
    289.         }
    290.         // 如果不可以移動(dòng),則保持位置不變
    291.         if (!isMoveAble(mShape)) {
    292.             for (Coordinate c : mShape) {
    293.                 c.x = c.x - 1;
    294.             }
    295.         }
    296.     }

    297.     /**
    298.      * 將方塊向左移動(dòng)
    299.      */
    300.     private void moveLeft() {
    301.         newToOld(mShape, oldShape);
    302.         for (Coordinate c : mShape) {
    303.             c.x = c.x - 1;
    304.         }
    305.         if (!isMoveAble(mShape)) {
    306.             for (Coordinate c : mShape) {
    307.                 c.x = c.x + 1;
    308.             }
    309.         }
    310.     }

    311.     /**
    312.      * 旋轉(zhuǎn)方塊
    313.      */
    314.     private void transShape() {
    315.         Coordinate core = mShape.get(0);
    316.         if (shapeType == 3) {
    317.             // 田形,不用做任何事情
    318.         } else {
    319.             newToOld(mShape, oldShape);
    320.             for (Coordinate c : mShape) {
    321.                 int x = core.x + (core.y - c.y);
    322.                 int y = core.y + (c.x - core.x);
    323.                 c.x = x;
    324.                 c.y = y;
    325.             }
    326.             // 如果可以旋轉(zhuǎn),則旋轉(zhuǎn)90度并更新顯示
    327.             if (isMoveAble(mShape)) {
    328.                 updateShape();
    329.                 TetrisView.this.invalidate();
    330.             } else {
    331.                 for (Coordinate c : mShape) {
    332.                     int x = core.x + (c.y - core.y);
    333.                     int y = core.y + (core.x - c.x);
    334.                     c.x = x;
    335.                     c.y = y;
    336.                 }
    337.             }

    338.         }

    339.     }

    340.     /**
    341.      * 將一個(gè)方塊的形狀賦給另外一個(gè)
    342.      *
    343.      * @param mShape2
    344.      * @param oldShape2
    345.      */
    346.     private void newToOld(ArrayList<Coordinate> mShape2, ArrayList<Coordinate> oldShape2) {
    347.         oldShape2.clear();
    348.         for (int i = 0; i < 4; i++) {
    349.             Coordinate c1 = mShape2.get(i);
    350.             Coordinate c2 = new Coordinate(c1.x, c1.y);
    351.             oldShape2.add(c2);
    352.         }

    353.     }

    354.     /**
    355.      * 處理游戲的更新
    356.      */
    357.     public void update() {
    358.         if (mMode == RUNNING) {
    359.             // clearTiles();
    360.             updateBlackGround();
    361.             if (mXTileCount != 0) {
    362.                 // 如果是剛開始游戲,則初始化方塊形狀
    363.                 if (mShape.size() == 0) {
    364.                     shapeType = RNG.nextInt(7);
    365.                     mShape = getShape(shapeType);
    366.                     preType = RNG.nextInt(7);
    367.                     preShape = getShape(preType);
    368.                     mMoveDelay = currentDelay;
    369.                     // 設(shè)置方塊的初始位置
    370.                     for (Coordinate c : mShape) {
    371.                         c.x = c.x + mXTileCount / 3;
    372.                         c.y = c.y + 1;
    373.                     }
    374.                 }
    375.                 // 將方塊往下移動(dòng)一格
    376.                 newToOld(mShape, oldShape);
    377.                 for (Coordinate c : mShape) {
    378.                     c.y++;
    379.                 }
    380.                 // 如果方塊可以往下移動(dòng),則更新圖形
    381.                 if (canMoveDown(mShape)) {
    382.                     updateShape();
    383.                 } else {
    384.                     // 如果不可以往下移動(dòng)則將方塊的狀態(tài)改為已落下并開始落下新方塊
    385.                     updateBlew();
    386.                     mShape = preShape;
    387.                     shapeType = preType;
    388.                     for (Coordinate c : mShape) {
    389.                         c.x = c.x + mXTileCount / 3;
    390.                         c.y = c.y + 1;
    391.                     }
    392.                     preType = RNG.nextInt(7);
    393.                     preShape = getShape(preType);
    394.                     mMoveDelay = currentDelay;
    395.                 }
    396.                 updatePreShape();
    397.             }
    398.         }
    399.         // 設(shè)置方塊落下的速度
    400.         mRedrawHandler.sleep(mMoveDelay);

    401.     }

    402.     // 方塊落下過程中顏色為黃色
    403.     private void updateShape() {
    404.         for (Coordinate c : oldShape) {
    405.             setTile(0, c.x, c.y);
    406.             Log.d(TAG, "old" + c.x + c.y);
    407.         }
    408.         for (Coordinate c : mShape) {
    409.             Log.d(TAG, "new" + c.x + c.y);
    410.             if (mXTileCount != 0) {
    411.                 setTile(YELLOW_STAR, c.x, c.y);
    412.             }

    413.         }

    414.     }

    415.     // 方塊落下后顏色為紅色
    416.     private void updateBlew() {
    417.         for (Coordinate c : mShape) {
    418.             if (mXTileCount != 0) {
    419.                 setTile(RED_STAR, c.x, c.y - 1);
    420.                 if (mYTileCount - c.y > highLevel) {
    421.                     highLevel = mYTileCount - c.y;

    422.                 }
    423.             }

    424.         }
    425.         // GAME OVER
    426.         if (highLevel > mYTileCount - 3) {
    427.             setMode(LOSE);
    428.         }
    429.         // 已經(jīng)消去的行數(shù)
    430.         int deleRows = 0;
    431.         for (int i = 1; i <= highLevel + 1; i++) {
    432.             int redCount = 0;
    433.             for (int x = 1; x < mXTileCount - 7; x++) {
    434.                 if (mTileGrid[x][mYTileCount - i] == RED_STAR) {
    435.                     redCount++;
    436.                 }
    437.             }
    438.             // 如果某一行的紅色方格數(shù)等于列總數(shù),則該列需要消去
    439.             if (redCount == mXTileCount -8 ) {
    440.                 deleRows++;
    441.                 continue;
    442.             } else {
    443.                 // 將不需要消去的行向下移動(dòng),移動(dòng)的幅度取決于前面消去的行數(shù)
    444.                 if (deleRows != 0) {
    445.                     for (int x = 1; x < mXTileCount - 6; x++) {
    446.                         mTileGrid[x][mYTileCount - i + deleRows] = mTileGrid[x][mYTileCount - i];
    447.                         mTileGrid[x][mYTileCount - i] = 0;
    448.                     }
    449.                 }
    450.             }
    451.         }
    452.         // 更改分?jǐn)?shù),一次性消去的行數(shù)越多,得到的分?jǐn)?shù)就越多
    453.         switch (deleRows) {
    454.             case 1:
    455.                 mScore = mScore + 100;
    456.                 break;
    457.             case 2:
    458.                 mScore = mScore + 300;
    459.                 break;
    460.             case 3:
    461.                 mScore = mScore + 500;
    462.                 break;
    463.             case 4:
    464.                 mScore = mScore + 800;
    465.                 break;
    466.         }
    467.         // 更新最高分
    468.         if (mScore > historyScore) {
    469.             overhistroy=true;
    470.             historyScore = mScore;
    471.             highestScore.setText("最高分?jǐn)?shù): \n" + historyScore);
    472.         }
    473.         // 更新當(dāng)前分
    474.         currentScore.setText("當(dāng)前分?jǐn)?shù):\n" + mScore);
    475.         // 當(dāng)級(jí)別達(dá)到一定的程度后不再增加方塊下落的速度
    476.         if (mScore >= (500 * (gameLevel * 2 - 1))) {
    477.             gameLevel++;
    478.             currentDelay -= 50;
    479.             if (currentDelay < 50)
    480.                 currentDelay = 50;
    481.         }
    482.         // 更新當(dāng)前級(jí)別
    483.         currentLevel.setText("當(dāng)前級(jí)別:\n" + gameLevel);
    484.     }

    485.     /**
    486.      * 設(shè)置游戲的狀態(tài)
    487.      *
    488.      * @param newMode
    489.      */
    490.     public void setMode(int newMode) {
    491.         int oldMode = mMode;
    492.         mMode = newMode;
    493.         if (newMode == RUNNING & oldMode != RUNNING) {
    494.             info.setVisibility(View.INVISIBLE);
    495.             update();
    496.             return;
    497.         }

    498.         Resources res = getContext().getResources();
    499.         CharSequence str = "";
    500.         if (newMode == PAUSE) {
    501.             str = res.getText(R.string.mode_pause);
    502.         }
    503.         if (newMode == READY) {
    504.             str = res.getText(R.string.mode_ready);
    505.         }
    506.         if (newMode == LOSE) {
    507.             str = res.getString(R.string.mode_lose_prefix) + mScore
    508.                     + res.getString(R.string.mode_lose_suffix);
    509.         }
    510.         // 顯示提示信息
    511.         info.setText(str);
    512.         info.setVisibility(View.VISIBLE);
    513.     }

    514.     /**
    515.      * 更新預(yù)先顯示方塊
    516.      */
    517.     private void updatePreShape() {
    518.         for (int x = mXTileCount - 4; x < mXTileCount; x++) {
    519.             for (int y = 1; y < 6; y++) {
    520.                 setTile(0, x, y);

    521.             }
    522.         }
    523.         for (Coordinate c : preShape) {
    524.             if (mXTileCount != 0) {
    525.                 setTile(YELLOW_STAR, c.x + mXTileCount - 3, c.y + 2);
    526.             }
    527.         }
    528.     }

    529.     /**
    530.      * 判斷方塊是否可以移動(dòng)
    531.      *
    532.      * @param list
    533.      * @return
    534.      */
    535.     private boolean isMoveAble(ArrayList<Coordinate> list) {
    536.         boolean moveAble = true;
    537.         for (Coordinate c : list) {

    538.             if (mTileGrid[c.x][c.y] != GREEN_STAR && mTileGrid[c.x][c.y] != RED_STAR) {
    539.                 continue;
    540.             } else {
    541.                 moveAble = false;
    542.                 break;
    543.             }
    544.         }
    545.         return moveAble;

    546.     }

    547.     /**
    548.      * 判斷方塊是否可以往下移動(dòng)
    549.      *
    550.      * @param list
    551.      * @return
    552.      */
    553.     private boolean canMoveDown(ArrayList<Coordinate> list) {
    554.         boolean moveAble = true;
    555.         for (Coordinate c : list) {
    556.             if (c.y < mYTileCount - 1 && mTileGrid[c.x][c.y] != RED_STAR) {
    557.                 continue;
    558.             } else {
    559.                 moveAble = false;
    560.                 break;
    561.             }
    562.         }
    563.         return moveAble;

    564.     }

    565.     /**
    566.      * 畫出游戲的背景.即游戲的邊框
    567.      *
    568.      */
    569.     private void updateBlackGround() {
    570.         for (int x = 0; x < mXTileCount - 5; x++) {
    571.             setTile(GREEN_STAR, x, 0);
    572.             setTile(GREEN_STAR, x, mYTileCount - 1);
    573.         }
    574.         for (int y = 1; y < mYTileCount - 1; y++) {
    575.             setTile(GREEN_STAR, 0, y);
    576.             setTile(GREEN_STAR, mXTileCount - 6, y);
    577.         }
    578.     }

    579.     /**
    580.      * 根據(jù)隨機(jī)數(shù)產(chǎn)生各種形狀的方塊
    581.      *
    582.      * @param n
    583.      * @return
    584.      */
    585.     private ArrayList<Coordinate> getShape(int n) {
    586.         ArrayList<Coordinate> shape = new ArrayList<Coordinate>();
    587.         switch (n) {
    588.             case 1:
    589.                 // 反Z拐角
    590.                 shape.add(new Coordinate(0, 0));
    591.                 shape.add(new Coordinate(1, 0));
    592.                 shape.add(new Coordinate(0, 1));
    593.                 shape.add(new Coordinate(-1, 1));
    594.                 break;
    595.             case 2:
    596.                 // 正Z拐角
    597.                 shape.add(new Coordinate(0, 0));
    598.                 shape.add(new Coordinate(-1, 0));
    599.                 shape.add(new Coordinate(0, 1));
    600.                 shape.add(new Coordinate(1, 1));
    601.                 break;
    602.             case 3:
    603.                 // 田形
    604.                 shape.add(new Coordinate(0, 0));
    605.                 shape.add(new Coordinate(0, 1));
    606.                 shape.add(new Coordinate(1, 0));
    607.                 shape.add(new Coordinate(1, 1));
    608.                 break;
    609.             case 4:
    610.                 // 長條
    611.                 shape.add(new Coordinate(0, 0));
    612.                 shape.add(new Coordinate(-1, 0));
    613.                 shape.add(new Coordinate(1, 0));
    614.                 shape.add(new Coordinate(2, 0));
    615.                 break;
    616.             case 5:
    617.                 // 長左拐形
    618.                 shape.add(new Coordinate(0, 0));
    619.                 shape.add(new Coordinate(-1, 0));
    620.                 shape.add(new Coordinate(0, 1));
    621.                 shape.add(new Coordinate(0, 2));
    622.                 break;
    623.             case 6:
    624.                 // 長右拐形
    625.                 shape.add(new Coordinate(0, 0));
    626.                 shape.add(new Coordinate(1, 0));
    627.                 shape.add(new Coordinate(0, 1));
    628.                 shape.add(new Coordinate(0, 2));
    629.                 break;
    630.             case 0:
    631.                 // 凸形
    632.                 shape.add(new Coordinate(0, 0));
    633.                 shape.add(new Coordinate(-1, 0));
    634.                 shape.add(new Coordinate(1, 0));
    635.                 shape.add(new Coordinate(0, 1));
    636.                 break;
    637.         }
    638.         return shape;
    639.     }

    640.     public void setTextView(TextView curView, TextView higView, TextView infView, TextView levView) {
    641.         currentScore = curView;
    642.         highestScore = higView;
    643.         info = infView;
    644.         currentLevel = levView;
    645.     }

    646.     /**
    647.      * 用來標(biāo)示某一坐標(biāo)上的方塊
    648.      *
    649.      */
    650.     private class Coordinate {
    651.         public int x;

    652.         public int y;

    653.         public Coordinate(int newX, int newY) {
    654.             x = newX;
    655.             y = newY;
    656.         }

    657.         public boolean equals(Coordinate other) {
    658.             if (x == other.x && y == other.y) {
    659.                 return true;
    660.             }
    661.             return false;
    662.         }

    663.         public String toString() {
    664.             return "Coordinate: [" + x + "," + y + "]";
    665.         }
    666.     }
    667. }
   4.創(chuàng)建類TileView.java。該類是從貪吃蛇中復(fù)制過來的,沒做任何修改,可以直接拿來用?
以在sdk的smples/android 2.x.x/Snake目錄中找到。

   5.將貪吃蛇游戲res/drawable目錄下的三個(gè)圖片文件復(fù)制到自己工程的res/drawable目錄中,如果沒有這個(gè)目錄可以創(chuàng)建或者放在其他的drawable-xxx目錄中。

   6.創(chuàng)建布局文件tetris_layout.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <FrameLayout
  3.     xmlns:android="http://schemas.android.com/apk/res/android"
  4.     android:layout_width="match_parent"
  5.     android:layout_height="match_parent">
  6.     <com.test.TetrisView
  7.         android:id="@+id/tetris"
  8.         android:layout_width="match_parent"
  9.         android:layout_height="match_parent"
  10.         tileSize="24" />
  11.     <RelativeLayout
  12.         android:layout_width="match_parent"
  13.         android:layout_height="match_parent">
  14.         <TextView
  15.             android:id="@+id/info"
  16.             android:text="@string/mode_ready"
  17.             android:visibility="visible"
  18.             android:layout_width="wrap_content"
  19.             android:layout_height="wrap_content"
  20.             android:layout_centerInParent="true"
  21.             android:gravity="center_horizontal"
  22.             android:textColor="#ff8888ff"
  23.             android:textSize="20sp" />
  24.         <TextView
  25.             android:id="@+id/current_score"
  26.             android:text="當(dāng)前分?jǐn)?shù):\n 0"
  27.             android:visibility="visible"
  28.             android:layout_width="wrap_content"
  29.             android:layout_height="wrap_content"
  30.             android:layout_centerVertical="true"

  31.             android:layout_alignParentRight="true"
  32.             android:textColor="#ff8888ff"
  33.             android:textSize="16sp" />
  34.         <TextView
  35.             android:id="@+id/highest_score"
  36.             android:text="最高分?jǐn)?shù):\n 0"
  37.             android:visibility="visible"
  38.             android:layout_width="wrap_content"
  39.             android:layout_height="wrap_content"
  40.             android:layout_above="@id/current_score"
  41.             android:layout_alignParentRight="true"
  42.             android:textColor="#ff8888ff"
  43.             android:textSize="16sp" />

  44.         <TextView
  45.             android:id="@+id/current_level"
  46.             android:text="當(dāng)前級(jí)別:\n 1"
  47.             android:visibility="visible"
  48.             android:layout_width="wrap_content"
  49.             android:layout_height="wrap_content"
  50.             android:layout_below="@id/current_score"
  51.             android:layout_alignParentRight="true"
  52.             android:textColor="#ff8888ff"
  53.             android:textSize="16sp" />

  54.     </RelativeLayout>
  55. </FrameLayout>
  7.打開res/values/strings.xml,將其修改為以下內(nèi)容:

 
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>

  3.     <string
  4.         name="app_name">Tetris</string>
  5.     <string
  6.         name="mode_ready">\n按上開始游戲 </string>
  7.     <string
  8.         name="mode_pause"> 暫停\n按上繼續(xù)游戲 </string>
  9.     <string
  10.         name="mode_lose_prefix">Game Over\nScore: </string>
  11.     <string
  12.         name="mode_lose_suffix">\n按上重新開始游戲 </string>
  13. </resources>
    8.打開AndroidManifest.xml,修改其內(nèi)容如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest
  3.     xmlns:android="http://schemas.android.com/apk/res/android"
  4.     package="com.test"
  5.     android:versionCode="1"
  6.     android:versionName="1.0">
  7.     <application
  8.         android:icon="@drawable/icon"
  9.         android:label="@string/app_name">
  10.         <activity
  11.             android:name=".Tetris"
  12.             android:theme="@android:style/Theme.NoTitleBar"
  13.             android:screenOrientation="portrait"
  14.             android:configChanges="keyboardHidden|orientation">
  15.             <intent-filter>
  16.                 <action
  17.                     android:name="android.intent.action.MAIN" />
  18.                 <category
  19.                     android:name="android.intent.category.LAUNCHER" />
  20.             </intent-filter>
  21.         </activity>

  22.     </application>
  23. </manifest>
    至此,一個(gè)簡單的俄羅斯方塊游戲就完成了,游戲運(yùn)行時(shí)的圖片為:










    
   







您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號(hào)-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號(hào):11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國互聯(lián)網(wǎng)協(xié)會(huì)會(huì)員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請(qǐng)注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP