讲讲消灭星星的算法实现思路吧

这个游戏的关键算法是选取同色区域。

我的方法是每个方块是一个对象,包含几项属性:自身所在的行,自身所在的列,自身的颜色。

还加了一个id作备用,暂时没用到。

 

基本思路是递归,显而易见。

首先准备两个列表。

一个用来装被检查过了的方块,因为左边方块的右边就等于右边方块的左边,如果不检查的话就无限递归到溢出了。

另一个用来装与传入方块颜色相同的方块,留待递归完成后作为返回值。

 

然后传入第一个方块,分别检查它四个方向上的方块,如果颜色和它相同的话就用对应方向上的方块来进行下一次递归。

上方检测举例,其他方向同理:

private static void checkUp(Block block) {
    // 越界(上方不存在方块)则跳出。
    if ((block.getRow()-1) < 0) {
        return;
    }
    
    // 获取上方方块。
    Block blockUpside = GameSurfaceView.blockList[block.getRow()-1][block.getColumn()];
    
    // 如果方块不存在或者颜色不同就跳出。
    if (blockUpside == null || blockUpside.getColor() != block.getColor()) {
        return;
    }
    
    // 下一次递归。
    checkFourSides(blockUpside);
}

 

跳出递归的唯一条件是当前方块有没有被检查过,因为考虑到单一职责原则,我把方块对比的代码都放到了单个方向检测的方法里了,包括是否越界和颜色是否相同还有对应方向上的方块存不存在。

这些是找到了对应方向上的方块才有讨论的必要的。

比如我看到的那个C++的条件判断是这样的……

//递归求解
void MyRecursion(LinkList _head1, LinkList _head2, int _x, int _y, int number) {
    if ((_x >= 10) || (_x < 0) || (_y >= 10) || (_y < 0)
            || (MyTraverseLinkList(_head2, _x, _y)) || (0 == MyArray[_x][_y])) {
        return;
    } else {
        MyInsertLinkList(_head2, _x, _y);
        if ((MyArray[_x][_y] == number)) {
            MyInsertLinkList(_head1, _x, _y);
            if ((_x - 1) >= 0)    //递归 - 上
                    {
                MyRecursion(_head1, _head2, _x - 1, _y, number);
            }
            if ((_y - 1) >= 0)    //递归 - 左
                    {
                MyRecursion(_head1, _head2, _x, _y - 1, number);
            }
            if ((_x + 1) < 10)    //递归 - 下
                    {
                MyRecursion(_head1, _head2, _x + 1, _y, number);
            }
            if ((_y + 1) < 10)    //递归 - 右
                    {
                MyRecursion(_head1, _head2, _x, _y + 1, number);
            }
        }
    }
}
姐夫你不要这样你是有对象的啊

里面还有重复的边界判断。

而且这哥们的起名姿势很有特点。

 

如果一个方法只做一件事的话,思路就清晰多了,像这样。

/** 递归,不停检查四面。*/
private void checkFourSides(Block block) {
    // 如果当前方块已被检查过,则跳出当前递归。
    if (isChecked(block)) {
        return;
    }
    
    // 标记当前方块为已被检查过。
    checkedBlocks.add(block);
    // 将当前方块加入同色列表。
    blocksInSameColor.add(block);
    
    // 检查上下左右的方块。
    checkUp(block);
    checkDown(block);
    checkLeft(block);
    checkRight(block);
}

 

于是像这样,当检查方法碰到边界,或者碰到了不存在的方块,或者周围已经没有颜色相同的方块了的时候,递归停止。

最后同色列表里保存的就是首尾相连的一片同色方块了。

然后把整个算法封装起来,再对外暴露一个接口就搞定了。

/** 获取存有与当前方块颜色相同首尾相连的一片方块的列表。*/
public static ArrayList<Block> getBlocksInSameColor(Block selectedBlock) {
    // 初始化两个缓存列表。
    checkedBlocks = new ArrayList<Block>();
    blocksInSameColor = new ArrayList<Block>();
    
    // 执行递归。
    checkFourSides(selectedBlock);
    
    return blocksInSameColor;
}

 

posted @ 2014-06-12 10:14  Chihane  阅读(3105)  评论(3编辑  收藏  举报