Android SurfaceView实现游戏2048[二]

二、实现算法

说实在话,算法这东西,我真不适合讨论,只因太菜(默默流泪ing...)。但是既然选择写这么一篇文章,是螺是马都得放出来溜溜。

1.每个滑块是一个Block对象,重写equals和hashCode方法,并在内部处理滑块颜色。总共16个滑块,数字相同的滑块代表的是同一个对象。用SparseArray<Block>保存0-2048对应的Block对象,这样可方便处理操作。以下是Block类代码:

package com.walk.game2048.model;

/**
 * 滑块实体类
 * @author walk
 *
 */
public class Block {
	
	public static final int MAX = 2048;
	
	private int number;
	
	private int color;
	
	public Block(int number) {
		super();
		this.number = number;
		setColor();
	}

	public int getNumber() {
		return number;
	}
	
	public int getColor() {
		return color;
	}

	private void setColor () {
		switch (number) {
		case 0:
			color = 0xFFCDC0B5;
			break;
		case 2:
			color = 0xFFEEE4DB;
			break;
		case 4:
			color = 0xFFEDE0C9;
			break;
		case 8:
			color = 0xFFF0B17D;
			break;
		case 16:
			color = 0xFFF39568;
			break;
		case 32:
			color = 0xFFF47C63;
			break;
		case 64:
			color = 0xFFF35F43;
			break;
		case 128:
			color = 0xFFECCB69;
			break;
		case 256:
			color = 0xFFECC75A;
			break;
		case 512:
			color = 0xFFFFAA00;
			break;
		case 1024:
			color = 0xFFFFEE00;
			break;
		case 2048:
			color = 0xFF1100FF;
			break;
		}
	}


	@Override
	public String toString() {
		return "Block [number=" + number + ", color=" + color + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + color;
		result = prime * result + number;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Block other = (Block) obj;
		if (color != other.color)
			return false;
		if (number != other.number)
			return false;
		return true;
	}

	
}

2.玩法操作

首先,这游戏有四个操作,上、下、左、右,四个操作需要处理的方式是一样的。这里只讨论向左滑动。

复杂的算法真心不会,小菜就只能用最普通的了。向左滑动后,同一行的情况下,从左边第一个滑块算起(除掉空的),如果两相邻滑块是相同数字的,就合在一起,并且左边的滑块数字在原来的基础上乘以2,并且这一行的所有滑块会向左填充空块,当然前提是左边有空块。(唉~表达能力实在是不行呀,还是按图说话吧可怜



操作分两部分完成:

1)、图一,滑块1和滑块2相同(2),可合并成(4)并填充在滑块1的位置,滑块2置为空块。同样的,滑块3、4合并填充在滑块3的位置上,也就是图二;

2)、原滑块2与滑块1合并后,成为空块,所以滑块3要向左填充过来,并把原来的位置置为空块。所以操作的最终效果如图三。

其他三个方向操作也是这样的,只是具体实现的代码有些差异。下面附上小菜实现的代码(求拍砖,求指导~):

//1.合并步骤
		//行列,mBlocks是4X4数组,保存的是滑块Block对象
		for (int row = 0; row < mBlocks.length; row++) {
			for (int column = 0; column < mBlocks[row].length; column++) {
				//已经是最后一个元素,结束循环
				if (column == mBlocks[row].length - 1) {
					break;
				}
				//mBlockObjArray保存0-2048对应滑块Block对象,其中0代表空块
				if (mBlocks[row][column] == mBlockObjArray.get(0)) { 
					//元素为空块,跳出当前循环
					continue;
				}
				for (int k = column + 1; k < mBlocks[row].length; k++) {
					//元素为空块,跳出当前循环
					if (mBlocks[row][k] == mBlockObjArray.get(0)) {
						continue;
					}
					if (mBlocks[row][column] == mBlocks[row][k]) {
						//相邻有效元素相同,合并,并把后无素置为空块,结束循环
						mBlocks[row][column] = mBlockObjArray.get(mBlocks[row][column].getNumber() * 2);
						mScore += mBlocks[row][column].getNumber();
						mBlocks[row][k] = mBlockObjArray.get(0);
						break;
					} else {
						//元素不为空块,并且不相等,结束循环
						break;
					}
				}
			}
		}
		
		//2.移动步骤
		for (int row = 0; row < mBlocks.length; row++) {
			for (int column = 0; column < mBlocks[row].length; column++) {
				//如果当前元素为空块,则拿同行最近且不为空块的滑块来填充
				if (mBlocks[row][column] == mBlockObjArray.get(0)) {
					for (int k = column + 1; k < mBlocks[row].length; k++) {
						if (mBlocks[row][k] != mBlockObjArray.get(0)) {
							mBlocks[row][column] = mBlocks[row][k];
							mBlocks[row][k] = mBlockObjArray.get(0);
							break;
						}
					}
				}
			}
		}

(砖头+1...+1...+1024...)


其他三个方向的也是类似的,就不上代码了。这里要特别说明一点的时,完成一个操作后,会随机生成一个新的滑块,并把该滑块填充到可放置的位置(也就是空块位置),在这里就不讨论这个功能的实现了。


3.GameOver or Win

玩是可以玩了,但是告知玩家游戏状态还是很有必要的。

1)、游戏结束:当四个方向都不可操作的时候,可判断游戏结束。直接附上我的实现代码:

private boolean isGameOver () {
		for (int row = 0; row < mBlocks.length - 1; row++) {
			for (int column = 0; column < mBlocks[row].length; column++) {
				if (mBlocks[row][column].equals(mBlocks[row + 1][column])) {
					//游戏未结束
					return false;
				}
			}
		}
		for (int column = 0; column < mBlocks[0].length - 1; column++) {
			for (int row = 0; row < mBlocks.length; row++) {
				if (mBlocks[row][column].equals(mBlocks[row][column + 1])) {
					//游戏未结束
					return false;
				}
			}
		}
		//游戏结束
		return true;
	}
有点搓,使用地毯式匹配,求优化~

2)、游戏胜利:当16个滑块中有一个达到了2048,即为胜利。方法:遍历元素,或者在合并的时候判断即可。


算法部分就到这吧。

PS:文中如有不对之处,敬请指出!谢谢~大笑

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值