講講消滅星星的算法實現思路吧


這個游戲的關鍵算法是選取同色區域。

我的方法是每個方塊是一個對象,包含幾項屬性:自身所在的行,自身所在的列,自身的顏色。

還加了一個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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM