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();
} }
执行效果图,界面做的比較挫:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
Android俄罗斯方块的代码实现还不全,有兴趣的Coder能够完好一下。网上Android版俄罗斯方块代码到处都是,可是我认为这份代码给出了俄罗斯方块编写的基本框架,依照这个框架。能够写出非常多语言版本号的俄罗斯方块。
Android版俄罗斯方块的实现的更多相关文章
- 还是俄罗斯方块之android版
前面的,口水话 请直接跳过. 虽然现在不比以前了 也没多少人气了,放到首页 都不到几百的点击量.也许博客园整体水平也是在往水的方向发展.不谈那些了,哥也曾经辉煌过 有过一天上千的点击量 ,哥也曾经有过 ...
- 【项目记录】-液化气配送app android版
15年底参与过甲方呼叫中心平台开发.液化气配送app android版要求1个月开发完成.开发此项目以前我只有过一周android的开发经验.(与甲方签署过保密协议,遵循职业道德有些敏感信息不能写.) ...
- android版高仿淘宝客户端源码V2.3
android版高仿淘宝客户端源码V2.3,这个版本我已经更新到2.3了,源码也上传到源码天堂那里了,大家可以看一下吧,该应用实现了我们常用的购物功能了,也就是在手机上进行网购的流程的,如查看产品(浏 ...
- Android版的菜谱客户端应用源码完整版
Android版的菜谱客户端应用源码完整版,这个文章是从安卓教程网转载过来的,不是本人的原创,希望能够帮到大家的学习吧. <ignore_js_op> 152936qc7jdnv6vo0c ...
- Android版2048
虽然说2048是好久前比较火的小游戏,但直到最近才有机会去研究下2048实现的源码,这里就简单写一下我(bie)的(ren)思路: 首先2048需要有十六个卡片,这个卡片可以用FrameLayout的 ...
- H5版俄罗斯方块(2)---游戏的基本框架和实现
前言: 上文中谈到了H5版俄罗斯方块的需求和目标, 这次要实现一个可玩的版本. 但饭要一口一口吃, 很多东西并非一蹴而就. 本文将简单实现一个可玩的俄罗斯方块版本. 下一步会引入AI, 最终采用coc ...
- H5版俄罗斯方块(4)---火拼对战的雏形
前言: 勿忘初心, 本系列的目标是实现一款类似QQ"火拼系列"的人机对战版俄罗斯方块. 在完成了基本游戏框架和AI的算法探索后, 让我们来尝试一下人机大战雏形编写. 本系列的文章链 ...
- Android版-支付宝APP支付
此项目已开源 赶快来围观 Start支持下吧 [客户端开源地址-JPay][服务端端开源地址-在com.javen.alipay 包名下] 上一篇详细介绍了微信APP支付 点击这里 此篇文章来详细介绍 ...
- Android版Ftp服务端软件
分享一款开发的Android版Ftp服务端软件,支持Android4.0及以上版本,可以实现局域网无线传输文件到手机,或者把手机上的多媒体文件分享到iPad等设备来扩展这些设备的存储空间,详情请见软件 ...
随机推荐
- qwb与学姐 (带秩并查集)
qwb与学姐 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 149 Solved: 54[Submit][Status][Web Board] Des ...
- ES5 方法学习
Object 1. Object.getPrototypeOf(o)获取对象的prototype对象.等价于以前的o.__proto__ var o = {}; Object.getPrototype ...
- JZYZOJ 1388 旅游 状压dp
http://172.20.6.3/Problem_Show.asp?id=1388 求拓扑排序方案数 状压dp,最开始以为是拓扑排序加数论或者搜索,没想到是状压dp,突然气死.jpg: 完全没有 ...
- BZOJ 1109 [POI2007]堆积木Klo(树状数组)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1109 [题目大意] Mary在她的生日礼物中有一些积木.那些积木都是相同大小的立方体. ...
- 【高精度】POJ1001-Exponentiation
整个题库的第二题,原本都没有屑于去做,突发奇想抱着秒杀的心态去写了代码,却硬生生地吃了4个WA.. [思路]先去除掉小数点,进行最基本的高精度乘法运算,再在运算得到的结果中添加小数点输出. [前铺]让 ...
- 【判断解是否可行-二分】POJ1064-Cable master
http://poj.org/problem?id=1064 [题目大意] 给出几条绳子的长度,问如果要切出k条长度相等的绳子,这k条绳子最常多长? [思路] 二分.把下界设为0,上界设为所有绳子长度 ...
- Manthan, Codefest 16 E. Startup Funding ST表 二分 数学
E. Startup Funding 题目连接: http://codeforces.com/contest/633/problem/E Description An e-commerce start ...
- Linux下KVM的图形界面管理工具(virt-manager)(桌面版)
背景: virt-manager是用于管理KVM虚拟环境的主要工具,virt-manager默认设置下需要使用root用户才能够使用该工具.当你想在KVM hypervisor服务器上托管虚拟机,由最 ...
- Ubuntu下查看APT安装的软件安装路径和版本
1.查询安装路径 dpkg -L 软件名 例如:dpkg -L gedit dpkg -L gedit /. /usr /usr/bin /usr/bin/gedit /usr/share /usr/ ...
- 在WPF中使用FontAwesome之类的字体图标
我之前在博客中介绍过几个矢量图库网站,在WPF程序中,一般接触到的矢量图标资源有XAML.SVG.字体这三种格式.XAML是标准格式就不说了,SVG并不是直接支持的,不过微软提供了Expression ...