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



评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值