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; @Override protected 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); //创建Game m_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; @Override protected 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); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.gamemenu, menu); return true; } @Override public 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() { @Override public 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); } @Override public 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