2013-08-31 42 views
0

IM構建簡單的匹配3遊戲學習建議,現在我在簡單的遊戲 當寶石移動到某個方向(X或Y)部分和需要的,如果找出寶石周圍是
相同的,更多的則1一排我編程,沒有這麼聰明的解決方案和IM尋找創意,使之更加普遍。 這是我的代碼註釋:尋找更好的算法爲比賽3寶石碰撞檢測

/

* 
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) 

} 

回答

1

我覺得有絕對沒有錯,你當前正在使用的算法(「環通在給定方向上的寶石,直到你打一個很不同「)。除非遊戲板擁有數百萬行或列,否則這個過程最多需要幾微秒,這是迄今爲止最直接的算法。

我不明白的一件事就是爲什麼你累積四個單獨的列表rightGemsToRemove,leftGemsToRemove等。handleGems()會做各種不同的事情嗎?如果沒有,只需使用一個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; 
} 

在此之後,你可以寫只是一個單一的循環,增加了dxxdyy

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; 
} 

可以說甚至更好:如果kMoveRight等。都是小整數值,你可以直接從靜態數組中查找:

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

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

這可能更快稍微,但在我看來,這是稍微不太清楚,而且速度差異是遠遠低於顯着的,它是不值得在我看來。

+0

感謝您百忙之中抽出時間來回答! – user63898

+0

不客氣@ user63898 :) –