0

我正在构建简单的比赛 3 游戏来学习建议,现在我在简单游戏中有部分当宝石移动到某个方向(X 或 Y)时,需要找出周围的宝石是否
相同并且连续超过 1 个我编程不是那么聪明的解决方案,我正在寻找使其更通用的想法。这是我的注释代码:

/

* 
 detect and store the gems that are alike the selected gem
*/

bool GameController::matchDetector(Gem* pSelected)
{
    // get the gem that are near the selected gem based on the selected gem movement type 
    // for example if moved right the movement type is (RightMovment) so the next gem is row,col+1
    Gem* pNextSprite = getNextGem(pSelected,pSelected->getGemState());
    // array that will store the Gems that are found for each direction array of its own
    CCArray * rightGemsToRemove = CCArray::create();
    CCArray * leftGemsToRemove = CCArray::create();
    CCArray * upperGemsToRemove = CCArray::create();
    CCArray * downGemsToRemove = CCArray::create();

    if(pNextSprite == NULL)
    {
        return false;
    }
    //copy the selected NEXT gem to the selected gem
    //so the calculation to find the next gems will be right 
    pSelected->swap(pNextSprite);
    int col = pSelected->getColNum();
    int row = pSelected->getRowNum();
    /*

        its long switch case that on its option doing the same so only the first one commented 

    */
    switch(pSelected->getGemState())
    {
        case kMoveRight:
        {
            // if its right direction i need to run on all the right gems until its NOT the same and stor it 
            for(int i=pSelected->getColNum()+1;i < maxGemsInCol;i++)
            {
                std::string nextInnerSpriteId = pUT->setGemId(i,row);
                // get the next gem from the container 
                Gem* pNextInnerSprite = (Gem*)GameSingleTone::getInstance()->getGemsDictionary()->objectForKey(nextInnerSpriteId);

                if(pNextInnerSprite == NULL)
                {
                    return false;
                }
                else
                {
                    // add it to the container 
                    rightGemsToRemove->addObject(pNextInnerSprite);
                }
            }
            break;
        }
        case kMoveLeft:
        {

            for(int i=pSelected->getColNum()-1;i < maxGemsInCol;i++)
            {
                std::string nextInnerSpriteId = pUT->setGemId(i,row);
                Gem* pNextInnerSprite = (Gem*)GameSingleTone::getInstance()->getGemsDictionary()->objectForKey(nextInnerSpriteId);

                if(pNextInnerSprite == NULL)
                {
                    return false;
                }
                else
                {
                    leftGemsToRemove->addObject(pNextInnerSprite);
                }
            }
            break;
        }
        case kMoveUp:
        {
            for(int i=pSelected->getRowNum()+1;i < maxGemsInRow ;i++)
            {
                std::string nextInnerSpriteId = pUT->setGemId(col,i);
                Gem* pNextInnerSprite = (Gem*)GameSingleTone::getInstance()->getGemsDictionary()->objectForKey(nextInnerSpriteId);

                if(pNextInnerSprite == NULL)
                {
                    return false;
                }
                else
                {
                    upperGemsToRemove->addObject(pNextInnerSprite);
                }
            }
            break;
        }
        case kMoveDown:
        {
            for(int i=pSelected->getRowNum()-1;i < maxGemsInRow ;i++)
            {
                std::string nextInnerSpriteId = pUT->setGemId(col,i);
                Gem* pNextInnerSprite = (Gem*)GameSingleTone::getInstance()->getGemsDictionary()->objectForKey(nextInnerSpriteId);

                if(pNextInnerSprite == NULL)
                {
                    return false;
                }
                else
                {
                    downGemsToRemove->addObject(pNextInnerSprite);
                }
            }
            break;
        }
    }

    /*
    this function will run on all the arrays and will check which gems needs to be removed from the GRID and all the rest ( fill the grid with new gems and so on .. ) 
    */
    handleGems(downGemsToRemove,upperGemsToRemove,leftGemsToRemove,rightGemsToRemove)

}
4

1 回答 1

1

我认为您当前使用的算法绝对没有问题(“在给定方向上循环遍历宝石,直到遇到不同的宝石”)。除非游戏板有数百万行或列,否则这最多需要几微秒,而且它是迄今为止您可以使用的最简单的算法。

我不明白的一件事是为什么您要累积四个单独的列表rightGemsToRemove等。每种leftGemsToRemovehandleGems()做不同的事情吗?如果没有,只需使用一个gemsToRemove列表。

另一个建议:您有四个案例,每个案例都包含基本相同的代码。这种重复是滋生错误的沃土:如果您需要对逻辑进行一些更改,很容易忘记在所有四个副本中进行相同的更改,或者不小心进行了错误的更改(例如使用复制和粘贴) )。我建议将您的switch陈述缩减为:

int dx, dy;
switch (switch(pSelected->getGemState())) {
case kMoveRight: dx = 1;  dy = 0;  break;
case kMoveLeft:  dx = -1; dy = 0;  break;
case kMoveUp:    dx = 0;  dy = -1; break;
case kMoveDown:  dx = 0;  dy = 1;  break;
}

之后,您可以只编写一个添加dxtoxdyto的循环y

int x = pSelected->getColNum() + dx;
int y = pSelected->getRowNum() + dy;
while (x >= 0 && x < maxGemsInRow && y >= 0 && x < maxGemsInCol) {
    std::string nextInnerSpriteId = pUT->setGemId(x, y);
    Gem* pNextInnerSprite = (Gem*)GameSingleTone::getInstance()->getGemsDictionary()->objectForKey(nextInnerSpriteId);

    if(pNextInnerSprite == NULL) {
        return false;
    } else {
        gemsToRemove->addObject(pNextInnerSprite);
    }

    x += dx;
    y += dy;
}

可以说更好:如果kMoveRightetc. 都是小整数值,您可以直接从静态数组中查找它们:

static int dxFromMovement[] = { 1, -1, 0, 0 };
static int dyFromMovement[] = { 0, 0, -1, 1 };

dx = dxFromMovement[pSelected->getGemState()];
dy = dyFromMovement[pSelected->getGemState()];

这可能会稍微快一些,尽管在我看来它不太清楚,而且速度差异远远低于明显,在我看来不值得。

于 2013-08-31T18:24:52.477 回答