Android使用GridView实现俄罗斯方块(附源码)(四)

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

行满判定与处理

如果方块的移动是下移,则handler.sendEmptyMessage(0),
这是先判断可否下移.
如何判断可否向下移动一位?
先向下移动一位,如果没有出界或者与已经固定的方块重复,则渲染移动之后的结果,如果出界或者重复,则移回原来的位置,停止移动,将移动方块加入固定的方块的数组,进行行满判定,如果行满则消除,重新产生新的方块,并下落。

/*
 * 如果处于等时间间隔下落状态
 * 检测是否可以按要求移动
 */
position[0]++;
for ( int i = 3; i >= 0; i-- )
{
	int line = i + position[0];
	if ( line >= 0 && StateFang.shape[rand][i] != 0 )
	{
		/* 如果到底了,或者下面有方块 */
		if ( line >= ySize ||
		     ( (allBlock[line] & (leftMath( StateFang.shape[rand][i], position[1] ) ) ) != 0)
		     )
		{
			canMove = false;
			break;
		}
	}
}
if ( !canMove )
{
	position[0]--;
	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 );
				}
			}
		}
	}
	stopDown();
} else {
	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 );
				}
			}
		}
	}
}

如何判断一行是否已经满了?
因为已经固定的方块是用二进制表示的,所以只要10个二进制位全部为1则说明该行已经满了,即:

if (allBlock[i] == 0x3ff) {
    // 该行已经满了
}

因为行满消除之后上面的方块会往下掉,所以我们从最后一行往上遍历,如果有行满,则按照从下往上的顺序,一行一行往下掉,这一次掉落完成之后,最上面的行赋值0,然后进一步检测该行是否已满,如果没有满,则继续检测下一行,如果满了,继续掉落。

for ( int i = ySize - 1; i >= 0; )
{
	if ( allBlock[i] == 0x3ff )
	{
		score++;
		scoreTextView.setText( "分数:" + score );
		for ( int j = i - 1; j >= 0; j-- )
		{
			allBlock[j + 1] = allBlock[j];
			for ( int k = 0; k < xSize; k++ )
			{
				blockColor[j + 1][k] = blockColor[j][k];
			}
		}
		allBlock[0] = 0;
		for ( int j = 0; j < xSize; j++ )
		{
			blockColor[0][j] = 0;
		}
	} else {
		i--;
	}
}

检测到不能继续往下移动之后:

void stopDown()
{
	/* 写入、消除、重置 */
	for ( int i = 3; i >= 0; i-- )
	{
		int line = i + position[0];
		if ( line >= 0 && StateFang.shape[rand][i] != 0 )
		{
			allBlock[line] += (leftMath( StateFang.shape[rand][i], position[1] ) );
			for ( int j = 0; j < xSize; j++ )
			{
				if ( ( (1 << j) & (leftMath( StateFang.shape[rand][i], position[1] ) ) ) != 0 )
				{
					blockColor[line][j] = randColor;
				}
			}
		}
	}
	for ( int i = ySize - 1; i >= 0; )
	{
		if ( allBlock[i] == 0x3ff )
		{
			score++;
			scoreTextView.setText( "分数:" + score );
			for ( int j = i - 1; j >= 0; j-- )
			{
				allBlock[j + 1] = allBlock[j];
				for ( int k = 0; k < xSize; k++ )
				{
					blockColor[j + 1][k] = blockColor[j][k];
				}
			}
			allBlock[0] = 0;
			for ( int j = 0; j < xSize; j++ )
			{
				blockColor[0][j] = 0;
			}
		} else {
			i--;
		}
	}
	if ( allBlock[0] != 0 )
	{
		if ( score > highestScore )
		{
			cacheUtils.getValue( "highestScore" + grade, score + "" );
			highestScore = score;
			maxScoreTextView.setText( "最高分:" + highestScore );
			scoreTextView.setText( "分数:" + score );
		}

		gameOver();
	}
	rand		= nextRand;
	position[0]	= StateFang.initPosition[rand][1];
	position[1]	= StateFang.initPosition[rand][0];
	randColor	= nextRandColor;

	nextRand	= random.nextInt( 19 );
	nextRandColor	= random.nextInt( 5 ) + 1;
	nextTetrisShow();
	Log.i( TAG, rand + "" );
}

分数、等级显示与存储

每一个等级的最高分都需要存储并显示。
我们使用SharedPreferences实现分数的存储和显示,将它封装成为CacheUtils:

public class CacheUtils {
    String fileName;
    SharedPreferences preferences;
    SharedPreferences.Editor editor;

    public CacheUtils(Context context, String fileName)//fileName是缓存的唯一标识
    {
        this.fileName=fileName;
//        数据只能被本应用程序读写
        preferences=context.getSharedPreferences(this.fileName,Context.MODE_PRIVATE);
        editor=preferences.edit();
    }

    /**
     * 向Cache存入指定key对应的数据
     * 其中value可以是String、boolean、float、int、long等各种基本类型的值
     * @param key
     * @param value
     */
    public void putValue(String key,String value)
    {
        editor.putString(key,value);
//        提交所做的修改
        editor.commit();
    }
    public void putValue(String key,int value)
    {
        editor.putInt(key,value);
//        提交所做的修改
        editor.commit();
    }
    public void putValue(String key,List<String> value)
    {
        editor.putStringSet(key,(Set<String>) value);
//        提交所做的修改
        editor.commit();
    }
    /**
     * 向Cache存入指定key对应的数据
     * 其中value可以是String、boolean、float、int、long等各种基本类型的值
     * @param key
     * @param value
     */
    public void putValue(String key,boolean value)
    {
        editor.putBoolean(key,value);
//        提交所做的修改
        editor.commit();
    }

    /**
     * 获取Cache数据里指定key对应的value。如果key不存在,则返回默认值def。
     * @param key
     * @param def
     * @return
     */
    public String getValue(String key,String def)
    {
        return preferences.getString(key,def);
    }

    /**
     * 清空Cache里所有数据
     */
    public void clearCache()
    {
        editor.clear();
//        保存修改
        editor.commit();
    }
}

在Activity的onCreate方法里面取出并显示:

cacheUtils = new CacheUtils( MainActivity.this, "UserInfo" );
String maxString = "";
try {
	maxString = cacheUtils.getValue( "highestScore" + grade, String.valueOf( 0 ) );
} catch ( Exception e ) {
	Log.e( TAG, e.toString() );
}


try {
	highestScore = Integer.parseInt( maxString.toString() );
} catch ( NumberFormatException e ) {
	highestScore = 0;
}
maxScoreTextView.setText("最高分:" + highestScore);

本局的分数累加并且显示:
每行满消除一行便累加1,在本局游戏结束的时候,判断当前分数和历史最高分比较,如果大于历史最高分,就写入到SharedPreferences中。

if ( score > highestScore )
{
	cacheUtils.getValue( "highestScore" + grade, score + "" );
	highestScore = score;
	maxScoreTextView.setText( "最高分:" + highestScore );
	scoreTextView.setText( "分数:" + score );
}

暂停

暂停的时候“左移”,“右移”,“旋转”按钮都不能使用,而且还要能够点击继续。
我们在点击暂停的时候取消定时器,设置动作按钮不可用,点击“继续”时候重置定时器,设置动作按钮可用。

private void pause()
{
	isPause = !isPause;
	if ( isPause )
	{
		stopTimer();
		pausebtn.setText( "继续" );
		leftMove.setEnabled( false );
		rightMove.setEnabled( false );
		rotateMove.setEnabled( false );
		downMove.setEnabled( false );
	} else {
		startTimer();
		pausebtn.setText( "暂停" );
		leftMove.setEnabled( true );
		rightMove.setEnabled( true );
		rotateMove.setEnabled( true );
		downMove.setEnabled( true );
	}
}
// 停止定时器
    private void stopTimer(){
        if(timer != null){
            timer.cancel();
            // 一定设置为null,否则定时器不会被回收
            timer = null;
        }
    }
    private void startTimer() {
        if (timer == null) {
            timer = new Timer();
        }
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                handler.sendEmptyMessage(0);
            }
        },0,timeInterval);
    }

附:
感兴趣的朋友可以回顾:
Android使用GridView实现俄罗斯方块(附源码)(一)
Android使用GridView实现俄罗斯方块(附源码)(二)
Android使用GridView实现俄罗斯方块(附源码)(三)
Android使用GridView实现俄罗斯方块(附源码)(四)

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值