• 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



  • 相关阅读:
    配置secureCRT
    LINUX的网口绑定(bond)
    背包形动态规划 fjutoj2375 金明的预算方案
    背包形动态规划 fjutoj1380 Piggy-Bank
    背包形动态规划 fjutoj2347 采药
    树形动态规划 fjutoj-2392 聚会的快乐
    树形动态规划 fjutoj-2131 第四集,聚集城市
    andriod开发--使用Http的Get和Post方式与网络交互通信
    线段树复合标记
    图论之拓扑排序 poj 2367 Genealogical tree
  • 原文地址:https://www.cnblogs.com/csnd/p/11800691.html
Copyright © 2020-2023  润新知