Android版俄罗斯方块的实现
學習Android的基本開發也有一段時間了,可是由于沒有常常使用Android漸漸的也就忘記了。
Android編程學的不深,不過為了對付逆向,可是有時還是會感到力不從心的。畢竟不是一個計算機專業畢業的Coder,相對來說編程的基礎對于以后非常多方面的學習都是非常重要的,特別是想在軟件安全或軟件的企業開發的過程中有所進步,必需要計算機專業知識扎實。
?
不多說了,發個Android版的俄羅斯方塊,當然基本框架是參照之前的學的C語言版的俄羅斯方塊的。俄羅斯方塊程序的開發方法比較多,感覺使用數組的方法去實現還是非常方便的。以下看代碼的詳細實現。
俄羅斯方塊界面顯示代碼的實現:
//俄羅斯方塊界面的顯示package com.example.mytetris;import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.View; import android.view.WindowManager;public class GameUI extends View {public Game m_Game = null;private byte[][] m_Groundback = null;private Paint m_Paint = new Paint(); //畫刷private final int PADDING = 2; private int m_TetrisWidth = 0;@Overrideprotected void onDraw(Canvas canvas) { //設置背景顏色setBackgroundColor(Color.BLACK);//畫背景drawGoundback(canvas);//畫方塊int nX = m_Game.m_nX;int nY = m_Game.m_nY;if (m_Game.m_CurrBlock == null)return;byte[][] data = m_Game.m_CurrBlock;for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){if (data[i][j] == Game.ISWALL) {int nLeft = nX * m_TetrisWidth + j * m_TetrisWidth;int nTop = nY * m_TetrisWidth + i * m_TetrisWidth;//外框m_Paint.setColor(Color.WHITE);canvas.drawRect(nLeft, nTop, nLeft + m_TetrisWidth, nTop + m_TetrisWidth, m_Paint);//內框m_Paint.setColor(Color.GREEN);canvas.drawRect(nLeft + PADDING, nTop + PADDING, nLeft + m_TetrisWidth - PADDING, nTop +m_TetrisWidth - PADDING, m_Paint);}}}}private void drawGoundback(Canvas canvas){//獲取背景m_Groundback = m_Game.getGroundback();for (int i = 0; i < Game.NROWS; i++) {for (int j = 0; j < Game.NCOLS; j++) {if (m_Groundback[i][j] == Game.ISWALL){//畫白色的方塊--外框m_Paint.setColor(Color.WHITE);canvas.drawRect(j*m_TetrisWidth, i*m_TetrisWidth, (j+1)*m_TetrisWidth, (i+1)*m_TetrisWidth, m_Paint);//畫綠色的方塊--內框m_Paint.setColor(Color.GREEN);canvas.drawRect(j*m_TetrisWidth + PADDING, i*m_TetrisWidth + PADDING,(j+1)*m_TetrisWidth - PADDING, (i+1)*m_TetrisWidth - PADDING, m_Paint);}}}}public GameUI(Context context, AttributeSet attrs, int defStyleAttr){super(context, attrs, defStyleAttr);}//自己定義view組件。構造調用該函數public GameUI(Context context, AttributeSet attrs){super(context, attrs);//創建Gamem_Game = new Game();//獲取手機分辨率WindowManager wmgr = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);DisplayMetrics outMetrics = new DisplayMetrics();wmgr.getDefaultDisplay().getMetrics(outMetrics);//手機屏幕寬度int nTetrisWidth = outMetrics.widthPixels;//依據手機分辨率。設置方塊寬度m_TetrisWidth = nTetrisWidth/Game.NCOLS*3/4;}public GameUI(Context context){super(context);}}
package com.example.mytetris;import java.util.Arrays; import java.util.Random;import android.R.integer;public class Game {public static final byte ISWALL = 1; //墻public static final int NROWS = 20; //18行public static final int NCOLS = 12; //12列public byte[][] m_Groundback = null;public int m_nX = 0; //方塊x坐標public int m_nY = 0; //方塊y坐標private Random m_Random = new Random(); //產生隨機對象private byte[][][] m_Tetris = null; //方塊的各種變化public byte[][] m_CurrBlock = new byte[4][4]; //當前方塊private byte[][] m_NextBlock = new byte[4][4]; //下一個方塊public Game(){m_Groundback = new byte[NROWS][NCOLS]; initGroundback();initTetris();}//初始化背景public void initGroundback(){for (int i = 0; i < NROWS; i++){for (int j = 0; j < NCOLS; j++){if (i == NROWS - 1 || j == 0 || j == NCOLS - 1){//設置墻m_Groundback[i][j] = ISWALL;}}}}//初始化變換方塊的類型public void initTetris(){//這樣的初始化不能給維數m_Tetris = new byte [][][]{/*1*/{{1, 1, 1, 1},{0, 0, 0, 0}, {0, 0, 0, 0},{0, 0, 0, 0}},/*2*/{{1, 0, 0, 0},{1, 0, 0, 0}, {1, 0, 0, 0},{1, 0, 0, 0}},/*3*/{{1, 0, 0, 0},{1, 1, 0, 0}, {0, 1, 0, 0},{0, 0, 0, 0}},/*4*/{{0, 1, 0, 0},{1, 1, 0, 0}, {1, 0, 0, 0},{0, 0, 0, 0}},/*5*/{{1, 1, 0, 0},{0, 1, 1, 0}, {0, 0, 0, 0},{0, 0, 0, 0}},/*6*/{{0, 1, 1, 0},{1, 1, 0, 0}, {0, 0, 0, 0},{0, 0, 0, 0}},/*7*/{{0, 1, 0, 0},{1, 1, 1, 0}, {0, 0, 0, 0},{0, 0, 0, 0}},/*8*/{{1, 1, 1, 0},{0, 1, 0, 0}, {0, 0, 0, 0},{0, 0, 0, 0}},/*9*/{{1, 0, 0, 0},{1, 1, 0, 0}, {1, 0, 0, 0},{0, 0, 0, 0}},/*10*/{{0, 1, 0, 0},{1, 1, 0, 0}, {0, 1, 0, 0},{0, 0, 0, 0}},/*11*/{{1, 1, 0, 0},{0, 1, 0, 0}, {0, 1, 0, 0},{0, 0, 0, 0}},/*12*/{{1, 1, 0, 0},{1, 0, 0, 0}, {1, 0, 0, 0},{0, 0, 0, 0}},/*13*/{{1, 0, 0, 0},{1, 1, 1, 0}, {0, 0, 0, 0},{0, 0, 0, 0}},/*14*/{{1, 1, 1, 0},{0, 0, 1, 0}, {0, 0, 0, 0},{0, 0, 0, 0}},/*15*/{{1, 1, 0, 0},{1, 1, 0, 0}, {0, 0, 0, 0},{0, 0, 0, 0}},};}//獲取背景public byte[][] getGroundback(){return m_Groundback;}//開始游戲public void startGame(){m_nX = NCOLS / 2 - 2;m_nY = 0;// 產生方塊m_CurrBlock = RandomBlock();m_NextBlock = RandomBlock();}//結束游戲public void stopGame(){}//左移public void moveLeft(){if (IsCanMove(m_nX - 1, m_nY)){m_nX--;}}//右移public void moveRight(){if (IsCanMove(m_nX + 1, m_nY)){m_nX++;}}//方塊變換時,變換方塊--這個產生的問題還沒解決?
public byte[][] getNextBlock() { //產生一個隨機數 int nLen = m_Tetris.length; //右移高位補0--去掉符號位 int nIndex = (m_Random.nextInt() >>> 1) % nLen; return m_Tetris[(nIndex+2)%15]; } //變換 public void moveChange() { byte[][] oldBlock = m_CurrBlock; m_CurrBlock = getNextBlock(); if (!IsCanMove(m_nX, m_nY)) { m_CurrBlock = oldBlock; } } //下移 public void moveDown() { if (IsCanMove(m_nX, m_nY + 1)) { m_nY++; } else { Fixbircks(); } } //隨機產生方塊 public byte[][] RandomBlock() { //產生一個隨機數 int nLen = m_Tetris.length; //右移高位補0--去掉符號位 int nIndex = (m_Random.nextInt() >>> 1) % nLen; return m_Tetris[nIndex]; } //產生方塊 private void CreateBircks() { m_nX = NCOLS / 2 - 2; m_nY = 0; // 產生方塊 m_CurrBlock = m_NextBlock; m_NextBlock = RandomBlock(); } //下移究竟 public void MoveFix() { while (IsCanMove(m_nX, m_nY + 1)) { m_nY++; } Fixbircks(); } //推斷方塊是否能移動 private boolean IsCanMove(int x, int y) { byte[][] data = m_CurrBlock; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (data[i][j] == ISWALL && m_Groundback[y + i][x + j] == ISWALL) { return false; } } } return true; } //固定方塊 private void Fixbircks() { byte[][] data = m_CurrBlock; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { //填充背景 if (data[i][j] == ISWALL) { m_Groundback[m_nY + i][m_nX + j] = ISWALL; } } } int nRows = ReleaseRows(); //產生新方塊 CreateBircks(); //新方塊不能移動,結束游戲 } //消除方塊 private int ReleaseRows() { int nReleaseRows = 0; for (int nRow = NROWS - 2; nRow > 0; nRow--) { if (IsCanRelease(nRow)) { //消除方塊 nReleaseRows++; //調整方塊--下移 MoveRows(nRow); //又一次推斷本行是否能夠消行 nRow++; } } return nReleaseRows; } //是否能消除方塊 private boolean IsCanRelease(int nRow) { for (int nCol = 1; nCol < NCOLS - 1; nCol++) { if (m_Groundback[nRow][nCol] == 0) { return false; } } return true; } //消除方塊以后,下移方塊 private void MoveRows(int nRow) { for (int i = nRow; i > 0; i--) { for (int j = 1; j < NCOLS - 1; j++) { m_Groundback[i][j] = m_Groundback[i - 1][j]; } } } }
package com.example.mytetris;import java.util.Timer; import java.util.TimerTask;import android.media.MediaPlayer; import android.os.Bundle; import android.app.Activity; import android.util.DisplayMetrics; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.view.WindowManager; import android.widget.Button;public class MainActivity extends Activity implements OnClickListener {private GameUI m_GameUi = null;private Game m_Game = null;private Button btnLeft = null;private Button btnRight = null;private Button btnDown = null;private Button btnChange = null;private MediaPlayer mp2 = null;@Overrideprotected void onCreate(Bundle savedInstanceState){//設置全屏無標題顯示this.requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);super.onCreate(savedInstanceState);setContentView(R.layout.linearlayout);//獲取組件m_GameUi = (GameUI)findViewById(R.id.GameUI);m_Game = m_GameUi.m_Game;btnLeft = (Button)findViewById(R.id.button1_left);btnRight = (Button)findViewById(R.id.button2_right);btnDown = (Button)findViewById(R.id.button3_down);btnChange = (Button)findViewById(R.id.button4_change);//設置監聽btnLeft.setOnClickListener(this);btnRight.setOnClickListener(this);btnDown.setOnClickListener(this);btnChange.setOnClickListener(this);//mp2 = MediaPlayer.create(this, R.raw.action);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {getMenuInflater().inflate(R.menu.gamemenu, menu);return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item){int nIndex = item.getItemId();switch (nIndex) {case R.id.item1_startgame:{//開始游戲m_Game.startGame();m_GameUi.invalidate();//播放音效MediaPlayer mp = MediaPlayer.create(this, R.raw.ready_go);mp.start();//mp.release();//定時器new Timer().schedule(new TimerTask(){@Overridepublic void run() {m_GameUi.m_Game.moveDown();m_GameUi.invalidate();mp2.start();}}, 0, 2000);//線程 // new Thread(new Runnable() // { // @Override // public void run() // { // try // { // Thread.sleep(1000); // } // catch (InterruptedException e) // { // e.printStackTrace(); // } // // m_GameUi.m_Game.moveDown(); // m_GameUi.invalidate(); // // } // }).start();}break;case R.id.item2_restartgame:{}break;case R.id.item3_stopgame:{}break;default:break;}return super.onOptionsItemSelected(item);}@Overridepublic void onClick(View v) {int nId = v.getId();switch (nId){case R.id.button1_left:{m_Game.moveLeft();}break;case R.id.button2_right:{m_Game.moveRight();}break;case R.id.button3_down:{m_Game.MoveFix();}break;case R.id.button4_change:{m_Game.moveChange();}break;default:break;}//重繪m_GameUi.invalidate();}}
執行效果圖,界面做的比較挫:
Android俄羅斯方塊的代碼實現還不全,有興趣的Coder能夠完好一下。網上Android版俄羅斯方塊代碼到處都是,可是我認為這份代碼給出了俄羅斯方塊編寫的基本框架,依照這個框架。能夠寫出非常多語言版本號的俄羅斯方塊。
代碼下載地址:http://download.csdn.net/detail/qq1084283172/9037683
總結
以上是生活随笔為你收集整理的Android版俄罗斯方块的实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我的Android进阶之旅------g
- 下一篇: 1.二叉树的中序遍历