GitHub地址: https://github.com/weijifen/AndroidTetris

移动方向

移动方向包括左移,右移和下移。
移动方块实际是对position向量做改变,改变之后使用handler进行渲染:

/* 将正在下落的方块与停止下落的方块区别对待 */
for ( int i = 0; i < ySize; i++ )
{if ( allBlock[i] == 0 ){for ( int j = 0; j < xSize; j++ ){blockList.set( i * xSize + j, 0 );}} else {for ( int j = 0; j < xSize; j++ ){blockList.set( i * xSize + j, blockColor[i][j] );}}
}
for ( int i = 3; i >= 0; i-- )
{int line = i + position[0];if ( line >= 0 && StateFang.shape[rand][i] != 0 ){for ( int j = 0; j < xSize; j++ ){if ( ( (1 << j) & (leftMath( StateFang.shape[rand][i], position[1] ) ) ) != 0 ){blockList.set( line * xSize + j, randColor );}}}
}

这里将能否进行这些动作的判断放在改变posiotion之前判断。

左移

在判断该位置符合左移的条件就改变position数组,然后通过handler.sendEmptyMessage(1)进行渲染。
如何判断是否可以左移?

  1. 判断是否越界
  2. 判断是否重复
判断是否越界

本游戏方块的左移实际是二进制的右移,我们可以根据二进制右移的特性来做判断。
右移的时候低位移出,高位补0,左移的时候高位移出,低位补0.
所以我们可以通过先右移再左移,如果结果和原数字相同,则说明可以右移,如果和原数字不相同,则说明不可以右移。
如(1010)2(1010)_2(1010)2​右移一位为(101)2(101)_2(101)2​,再左移一位为(1010)2(1010)_2(1010)2​.
(1011)2(1011)_2(1011)2​右移一位为(101)2(101)_2(101)2​,再左移一位为(1010)2(1010)_2(1010)2​.

判断是否与其他方块重复

如果没有越界,则通过将可以运动的方块与已经固定的方块进行按位与操作,如果结果为0,则说明没有重复,如果结果不为0,则说明有重复。

leftMove.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//左移实际是数字的右移//左移需要判断是否能够左移for (int i=3;i>=0;i--) {if ((((leftMath(StateFang.shape[rand][i] ,position[1])) >> 1) << 1)!= (leftMath(StateFang.shape[rand][i] ,position[1]))) {//                        如果越界了return;}}for (int i=3;i>=0;i--) {int line = i + position[0];if (line >= 0 && StateFang.shape[rand][i]!=0) {if ((allBlock[line] & (leftMath(StateFang.shape[rand][i], position[1]) >> 1)) != 0) {return;}}}position[1]--;handler.sendEmptyMessage(1);}});
右移
判断是否越界

通过判断右移之后的二进制数组是否大于10位二进制可以表示的最大数字,如果大于,则说明右移之后越界,不可以右移,如果不大于,说明可以右移。

判断是否与其他方块重复

与左移一样。

rightMove.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {for (int i=3;i>=0;i--) {if (((leftMath(StateFang.shape[rand][i], position[1])) << 1) > 0x3ff) {//                        如果越界了return;}}for (int i=3;i>=0;i--) {int line = i + position[0];if (line >= 0 && StateFang.shape[rand][i]!=0) {if ((allBlock[line] & (leftMath(StateFang.shape[rand][i], position[1]) << 1)) != 0) {return;}}}position[1]++;handler.sendEmptyMessage(1);}});

旋转设计

反L形方块表示方法如下:

{0x8, 0x8, 0xc, 0x0}

表示为二进制为:

1 0 0 0
1 0 0 0
1 1 0 0
0 0 0 0

但是方格以左边为低位更方便,所以变为:

0 0 0 1
0 0 0 1
0 0 1 1
0 0 0 0

所以这是一个形状为反L的方块。
那么方块的旋转应该如何表示?
例如反L形的逆时针旋转之后为shape[1]({0xe, 0x8, 0, 0}):

0 1 1 1
0 0 0 1
0 0 0 0
0 0 0 0

这样我们就可以定义一个数组nextShape,其下标i表示第i个方块形状,值表示旋转之后是第几个方块形状。

public static int[] nextShape = new int[] {1, 2, 3, 0, 5, 6, 7, 4, 9, 8, 11, 10, 13, 14, 15, 12, 17, 16, 18
};

这样需要旋转的时候我们就可以根据数组的下标的下标(shape[nextShape[i]])找到旋转之后的形状。

另外需要判断旋转之后是否越界或者与已经固定的方块重复,如果出现这些情况,那就不能旋转。
方法是先旋转,再检查。

rotateMove.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {int nextRotate = StateFang.nextShape[rand];for (int i=3;i>=0;i--) {int line = i + position[0];
//                检查是否越界if (leftMath(StateFang.shape[nextRotate][i] ,position[1]) > 0x3ff){//右边界return;}else if(StateFang.shape[nextRotate][i]>0 && line>=ySize){//下边界return;} else if (leftMath(leftMath(StateFang.shape[nextRotate][i], position[1]),-position[1]) != StateFang.shape[nextRotate][i]) {return;}//检查是否与其他方块重合else if (line>0 && line<ySize &&(leftMath(StateFang.shape[nextRotate][i], position[1]) & allBlock[line]) != 0) {return;}}rand = nextRotate;handler.sendEmptyMessage(1);}
});

值得一提的是,检查是否超越左边界的方法和检查左移的方法类似,先将方块移到指定位置,再反向移动,检查是否和原来数字相同。

下移

目标:一次下移到不能再下移的为位置。
计算运动的方块的每一行可以下移的最大距离,再找出这些最大距离里面的最小值。
如何找出运动的方块的某一行可以下移的最大距离
这一行的每一列检测是否有方块,如果有方块,则检测该列下方最近的方块(检查下一行是否有方块,再下一行是否有方块,直到边界处)。记录最大的移动量。
通过该移动量改变position数组,使用handler.sendEmptyMessage(0)渲染游戏界面。

downMove.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {int down=1<<10;for(int i=3;i>=0;i--) {int line = i + position[0];if (line >= 0 && StateFang.shape[rand][i] != 0) {down = Math.min(down, ySize - line - 1);for (int j=0;j<xSize;j++) {if (((1 << j)& (leftMath(StateFang.shape[rand][i] ,position[1])))!=0) {for(int k=0;k+line<ySize;k++) {if (blockColor[k + line][j] > 0) {down = Math.min(down, k-1);break;}}}}}}if (down <= 0 || down==(1<<10)) {return;} else {position[0] += down;handler.sendEmptyMessage(0);}}});

下落速度设计

该游戏可以选择下落速度。
在selectActivity中:

    @Overridepublic void onClick(View v) {Intent intent = new Intent(SelectActivity.this, MainActivity.class);switch (v.getId()) {case R.id.grade1:intent.putExtra("grade", 1);break;case R.id.grade2:intent.putExtra("grade", 2);break;case R.id.grade3:intent.putExtra("grade", 3);break;case R.id.grade4:intent.putExtra("grade", 4);break;case R.id.grade5:intent.putExtra("grade", 5);break;default:break;}startActivity(intent);}

使用intent传输:

Intent intent = getIntent();
grade = intent.getIntExtra( "grade", 3 );switch ( grade )
{case 1:timeInterval = 1200;break;
case 2:timeInterval = 1000;break;
case 3:timeInterval = 800;break;
case 4:timeInterval = 600;break;
case 5:timeInterval = 400;break;
default:break;
}

该游戏使用定时器,每过一个 timeInterval 时间,自动下落一格,所以通过改变timeInterval控制下落速度。
感兴趣的朋友请继续阅读 Android使用GridView实现俄罗斯方块(附源码)(四)

Android使用GridView实现俄罗斯方块(附源码)(三)相关推荐

  1. 基于嵌入式linux五子棋游戏,Android 实战项目之五子棋 附源码

    Android五子棋游戏五子连珠算法实现 1.游戏规则 五子棋是两个人之间进行的竞技活动,黑方白方规则规则相同,黑棋必须先行,五连子的方向为横.竖.斜,如黑白色任一方先五子连一线则算胜出. 2.五子连 ...

  2. 项目实战:简易俄罗斯方块(附源码)

    前言 学了java,一直想找一个项目实战,俄罗斯方块就是一个不错的实战项目,它原理实现比较简单.话虽如此,我一开始还是毫无头绪,直到去油管上看一个俄罗斯方块的视频和在GitHub上看他实现的源码,才有 ...

  3. Android高仿QQ通讯录(附源码)

    先看看效果图吧 通讯录的基本实现功能 1,从android手机中读取联系人,通话记录,短信息数据 2,打电话,发送短信,接受短信(安装此应用后要先把手机重启下才能接受到短信息,不然会被其他第三方应用屏 ...

  4. JS/Jquery版本的俄罗斯方块(附源码分析)

    转载于 http://blog.csdn.net/unionline/article/details/63250597 且后续更新于此 1.前言 写这个jQuery版本的小游戏的缘由在于我想通过从零到 ...

  5. Android 统一打包框架(附源码下载)

    唠叨: 把手给我,我带你去吃云浮吃石磨肠粉.云吞面,木瓜渣. 那里的肠粉和广州的不一样,皮很薄很滑,肉馅没广州的那么花里胡哨,只有肉碎和香葱.但吃起来就很香滑,再配上它的甜辣酱.那味道好极了. 云吞面 ...

  6. Android中SQLiteDatabase操作【附源码】

    像我们做的很多应用程序及网站一样,基本都是对数据库进行增删改查来实现相应的功能.那么Android开发也一样,不过由于在移动客户端应用,所以不会像sql server.mysql那么复杂,Androi ...

  7. Android卡通人脸转换APP(附源码)

    Android卡通人脸转换APP 写在前面~ 效果~ 拍照或者从相册中选图片 前景融合 背景融合 个性签名 如何运行~ 注意的bug 写在后面~ 写在前面~ APP界面参考了微信小程序AI卡通秀,项目 ...

  8. Android植物大战僵尸附源码

    本文介绍cocos2d-android实现的Android植物大战僵尸,最后附源码 内容介绍: 一.游戏最原始的开发框架. 主要会介绍 a)  SurfaceView+SurfaceHolder.Ca ...

  9. Android 小项目之--数据存储【Files】(附源码)

    继上篇数据存储,现在我们来讲讲另外一种数据存储,Files.本篇讲述步骤如下: 1.温故而知新,复习四种数据存储的区别. 2.什么是 Files 数据存储. 3.什么是 Properties ? 4. ...

最新文章

  1. 计算机网络-OSPF协议
  2. 设置更改root密码 连接mysql mysql常用命令
  3. 25.计算机和计算器的区别
  4. Android 网络交互之MD5为什么要加盐
  5. spring和ejb2.x集成共享applicationContext.xml的问题
  6. jquery --- 使用when方法等待2个异步事件结束后执行某一个函数.
  7. 05 | 前馈网络与反向传播:模型的自我学习(下)
  8. 假如你心中有个莎乐美
  9. FPGA UART总线协议简介
  10. android.view.WindowManager$BadTokenException
  11. 1.组合数据类型练习: 分别定义字符串,列表,元组,字典,集合,并进行遍历。 总结列表,元组,字典,集合的联系与区别。...
  12. 洛谷 P1631 序列合并
  13. for循环里面嵌套if_信不信两层python嵌套for循环就能把你搞懵了
  14. 职场 PUA 你知多少?
  15. 最直白的编译原理-词法分析(清华-王书3版)
  16. 路飞学城python电子书闲鱼_路飞学城-python开发集训-第一章之用户登录作业
  17. python打气球小游戏(一)
  18. 笑谈游览器-有图有真相
  19. 几个实用的生活服务网站和APP
  20. 对IBL的specular部分的思考

热门文章

  1. config语言和config.in文件
  2. ESP8266开发之旅 阿里云物联网平台篇⑤ LED智能灯控制系统(使用HTTPS认证再连接)
  3. Vue过滤器-filter
  4. 某信息安全攻防大赛周周练考核(一) Writeup By 2ha0yuk7on
  5. Linux中的pushd和popd
  6. klayout 源码分析系列续 执行脚本
  7. win怎么在计算机里按日期搜索文件,小编教你在Win10系统电脑中设置搜索内容日期范围的小技巧...
  8. 泉州计算机公司排名2015,福建企业100强榜单出炉!分布在这些地方
  9. 传感器检测技术——传感器的动态特性
  10. JAVA通用分页代码