cocos2d-x3.6 連連看自動消除,cocos2d-x3.6連連看
我的部落格:http://blog.csdn.net/dawn_moon
前面已經寫完了連連看的主要邏輯,這一節來講如何自動消除,並且,如果棋盤成了死局以後怎麼辦。
前面章節講解連連看消除演算法的時候講過,後續自動消除演算法也是基於串連演算法的。
原理很簡單,兩層for迴圈,掃描棋盤,判斷是否有串連,如果有,添加串連路徑,如果整個棋盤都沒有可以相連的兩個點,那麼就是死局。
死局如何來解,我這裡的做法是,再隨機打亂現有棋盤,重新布局。
先看死局演算法:
bool GameScene::die(){ for (int y = 1; y < yCount; y++) { for (int x = 1; x < xCount; x++) { if (mMap[x][y] != 0) { for (int j = y; j < yCount - 1; j++) { if (j == y) { for (int i = x + 1; i < xCount - 1; i++) { if (mMap[i][j] == mMap[x][y] && link(Vec2(x, y), Vec2(i, j))) { return false; } } }else{ for (int i = 1; i < xCount - 1; i++) { if (mMap[i][j] == mMap[x][y] && link(Vec2(x, y), Vec2(i, j))) { return false; } } } } } } } return true;}
其實就是幾個遍曆,棋盤上每一個點,和其餘的做連通判斷,漸進式掃描。
因為link函數會將連通的點加入到路徑容器,所以一旦die函數返回false,那麼在路徑容器裡面就已經存了連通路徑的點了。
如果die,那麼就要隨機變化棋盤
if (die()) { changeMap(); }
來看changeMap():
void GameScene::changeMap(){ // 隨機種子 srand((unsigned int)time(NULL)); // 臨時變數,用來交換兩個位置的資料 int tempX, tempY, tempM; // 遍曆地圖數組,隨機交換位置 for (int x = 1; x < xCount - 1 ; x++) for (int y = 1; y < yCount - 1; y++) { tempX = 1 + (int)(CCRANDOM_0_1() * (xCount - 2)); tempY = 1 + (int)(CCRANDOM_0_1() * (yCount - 2)); tempM = mMap[x][y]; mMap[x][y] = mMap[tempX][tempY]; mMap[tempX][tempY] = tempM; // 交換精靈位置,交換tag值 int tag1 = (yCount - 2) * ( x - 1 ) + y; int tag2 = (yCount - 2) * ( tempX - 1 ) + tempY; auto pos1 = indextoScreen(x, y); auto pos2 = indextoScreen(tempX, tempY); auto pic1 = getChildByTag(tag1); auto pic2 = getChildByTag(tag2); if (pic1) { pic1->setPosition(pos2); pic1->setTag(tag2); }else{ // 如果為空白,地圖數組對應值要置0 mMap[tempX][tempY] = 0; } if (pic2) { pic2->setPosition(pos1); pic2->setTag(tag1); }else{ mMap[x][y] = 0; } }}
我在UI上放一個按鈕,點擊按鈕,就會調用autoClear()函數,就是自動清除機制.
auto tip = Sprite::createWithTexture(textureCache->getTextureForKey(s_game_leisure)); auto menuItemSprite = MenuItemSprite::create(tip, tip, CC_CALLBACK_1(GameScene::autoClear, this)); auto menu = Menu::create(menuItemSprite, nullptr); menu->setAnchorPoint(Vec2(1, 1)); menu->setPosition(wSize.width - 100, wSize.height - 100); addChild(menu);
這裡很簡單,沒有什麼好說的,來看autoClear函數:
void GameScene::autoClear(Ref *spender){ // 左右抖動的動畫 auto rote = RotateBy::create(0.05, 20); auto seq = Sequence::create(rote, rote->reverse(), rote->reverse(), rote->clone(), nullptr); ((Sprite*)spender)->runAction(seq); if (die()) { CCLOG("die-----"); changeMap(); }else{ drawLine(); }}
好了,就這麼簡單,如果die,那麼變換棋盤,如果沒有die,那麼畫線。
再說一下這個die(),if(die())執行的時候,如果die是true,沒什麼說的,changeMap,如果die返回false,那麼這時候其實已經遍曆了棋盤,講能連通的路徑放到了成員變數mPath裡面,所以就可以直接drawLine()了。
好了,到這裡,連連看基本完成。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。