最近2048这个小游戏比较火,自己也喜欢玩,就想着自己去利用安卓实现一个,先上图
大概实现流程有下面几步:
转载请注明出处:http://blog.csdn.net/u014695956/article/details/23620863
1.使用GridLayout作为装载方块的容器
<GridLayout
android:id="@+id/gridContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:alignmentMode="alignMargins"
android:background="@anim/submit_item_selected"
android:columnCount="4"
android:rowCount="4" >
GridLayout是Android 4.0之后出现的布局,相关使用说明和优点可以去网上搜一下。指定4行4列,装方块的容器就准备好了。
2.定义方块的Bean
public class ItemInfo {
/**
* 当前Item的数值
*/
private int number;
/**
* 当前Item的位置
*/
private Point point;
/**
* 当前Item上面的item
*/
private ItemInfo aboveItem;
/**
* 当前Item下面的item
*/
private ItemInfo belowItem;
/**
* 当前Item左边的item
*/
private ItemInfo leftItem;
/**
* 当前Item右边的item
*/
private ItemInfo rightItem;
/**
* 当前Item的View
*/
private ImageView view;
//下面写相关get与set方法
}
方块本身保留有自己上下左右的方块对象。
3.定义两个List集合,一个集合用于存储所有方块,一个集合用于存储没有显示数字的方块,初始化如下:
/**
* 定义存储显示空项的Item的集合
*/
private List<Integer> spaceItem;
/**
* 定义存储所有Item的集合
*/
private List<ItemInfo> itemInfos;
...
for (int i = 0; i < 16; i++) {
spaceItem.add(i);
}
...
// 向gridConteainer里面添加spaceItem
for (int i = 0; i < 16; i++) {
// 定义一个ItemInfo的集合
ItemInfo info = new ItemInfo();
// 设定初始值
info.setNumber(0);
// 设定Point对象
Point point = EngineUtils.getPoint(i);
info.setPoint(point);
// 得到填充item的View
View view = View.inflate(this, R.layout.item_home, null);
ImageView imageView = (ImageView) view.findViewById(R.id.iv);
// 设置默认的背景
imageView.setBackgroundResource(icons[0]);
// 设置info对象里面的ImageView引用
info.setView(imageView);
gridContainer.addView(view);
// 向Item集合中添加Item对象
itemInfos.add(info);
}
4.遍历设定每个方块自身上下左右的方块对象
// 遍历gridContainer,设置各个Item的属性
for (int i = 0; i < itemInfos.size(); i++) {
ItemInfo info = itemInfos.get(i);
// 判断是否在容器的左边缘
if (i % 4 != 0) {// 不在容器的左边缘,说明左边有Item
ItemInfo leftItem = itemInfos.get(i - 1);
info.setLeftItem(leftItem);
}
// 判断是否在容器的右边缘
if ((i + 1) % 4 != 0) {// 不在容器的右边缘,说明右边有Item
ItemInfo rightItem = itemInfos.get(i + 1);
info.setRightItem(rightItem);
}
// 判断是否在窗口的上边缘
if (i / 4 != 0) {// 不在容器的上边缘,说明上边有Item
ItemInfo aboveItem = itemInfos.get(i - 4);
info.setAboveItem(aboveItem);
}
// 判断是否在容器的下边缘
if (i < 12) {// 不在容器的下边缘,说明上边有Item
ItemInfo belowItem = itemInfos.get(i + 4);
info.setBelowItem(belowItem);
}
}
5.向左移动逻辑
/**
* 向左移动
*/
private void moveToLeft() {
List<Integer> temp = new ArrayList<Integer>();
// 外层控制列数
for (int i = 1; i < 4; i++) {
// 内层控件行数据
for (int j = 0; j < 4; j++) {
// 计算索引
int index = i + j * 4;
// 通过索引得到集合中的item对象
ItemInfo info = itemInfos.get(index);
// 得到自身的Number
int selfNumber = info.getNumber();
// 如果当前的Number为0,则不做任何操作
if (selfNumber == 0) {
continue;
}
int d = 0;
for (int k = 1; k < i + 1; k++) {
int tempIngex = index - k;
ItemInfo tempInfo = itemInfos.get(tempIngex);
int tempNumber = tempInfo.getNumber();
if (tempNumber != 0) {
break;
} else {
d++;
}
}
if (d != 0) {
isLeftMove = true;
repalceSpaceItem(index - d, index);
replaceItem(index, index - d, selfNumber, false);
}
index = index - d;
info = itemInfos.get(index);
selfNumber = info.getNumber();
// 通过item对象得到其左边的item,并判断左边的item的数值是否为0
ItemInfo leftItem = info.getLeftItem();
if (leftItem != null) {
// 得到左边item的数值
int leftNumber = leftItem.getNumber();
if (leftNumber == selfNumber && !temp.contains(index - 1)) {// 合并
isLeftMove = true;
int tempNumber = leftNumber + selfNumber;
replaceItem(index, index - 1, tempNumber, true);
nowScore += tempNumber;
// 更新分数
Message msg = handler.obtainMessage();
msg.obj = nowScore;
handler.sendMessage(msg);
spaceItem.add(index);
temp.add(index - 1);
}
}
}
}
}
实现思路:
a.两个for循环,分别控制循环行数与列数。遍历当前方块的时候如果当前方块的数值为0,则不做任何操作(第5步第17行代码)。
b.在遍历的过程中,遍历当前方块的时候判断当前方块最左边有几个空位,并将当前数值替换到到最左边的空位(第5步第35行代码)。
c.在b的基础上,继续向下执行,再判断当前方块左边的方块是否与自身方块数字相同,如果相同,则合并(第5步第47行代码)。
d.合并之后调用handler更新分数
收尾:设置手势监听,其他方向移动逻辑类似。
本代码实现基于Android 4.0以上,想在低版本上使用GridLayout需用 Android support-v7下的GridLayout,在此就不详述。
只实现了移动逻辑,方块移动动画等有空再续。
代码下载地址:http://download.csdn.net/detail/u014695956/7188665