cocos2d 簡單消除遊戲演算法 (一),cocos2d演算法
1. 遊戲視頻示範
2.三消遊戲我的理解
上面視頻中的遊戲,我做了2個星期時間,只能算個簡單Demo,還有bug,特效也幾乎沒有。感覺三消遊戲主要靠磨,越磨越精品。市場上三消遊戲已經超級多了。主流的是地圖型的,幾乎是無盡模式,各種消除特效,各種各樣的過關方式,玩起來還是不錯的,就是遇到比較難的關卡,要多試幾次,運氣非常好的時候就過了,不然卡死。這個遊戲真正擴充的地方就是過關模式,還需要整個特殊的地圖編輯器,配合策劃,不斷升級遊戲。
3.消除涉及到的簡單演算法
3.1 產生隨機地圖演算法
有各種各樣的地圖,這裡拿最簡單的矩形來說。需求:1.這個演算法要產生一個隨機的地圖,不能有3個橫著相同或者3個豎著相同。2.這個地圖使用者移動一步能進行消除(不能是個死地圖)
初看到這個需求感覺還是蠻難的,後來想了下第2個需求應該先別管,如果是死地圖,再重建一張地圖就可以了。測試了下,產生死地圖的機率非常低。
演算法實現的描述:假設地圖的(0,0)在左上方。非常簡單x從上面的最左邊開始往右產生,y從最上面直到底部。每次先判斷下它的左邊兩個是否已經同色,還有上面兩個是否已經同色,如果同色了,要去掉這個顏色。假設已經產生的地圖是:2, 3, 3, 4, 1, 3, 21, 2, 3, 4, 4, 3, 31, 2, 4, 2, 2, X因為X的左邊兩個都是2,所以X不能再是2了,它的上面兩個都是3,所以X不能再是3了。所以X的結果只能是0,1,4中隨機取一個了。
下面是虛擬碼(是不能啟動並執行真代碼):
enum MatchItemType{ kRedItem = 0, //0 kGreenItem, //1 kBlueItem, //2 kWhiteItem, //3 kOrangeItem //4};MatchItemType getOneRandomTypeExceptParameter(const MatchItemType& type){ MatchItemType allType[5] = {kRedItem, kGreenItem, kBlueItem, kWhiteItem, kOrangeItem}; std::vector restType; for(int i = 0; i < 5; ++i){ if(allType[i] != type){ restType.push_back(allType[i]); } } int restSize = restType.size(); int randomIndex = rand() % restSize; return restType[randomIndex];}Array2D<MatchItemType> getOneRandomMapArray(){ Array2D<MatchItemType> map = Array2D<MatchItemType>(7, 7); bool findThreeSameInX = false; bool findThreeSameInY = false; for(int y = 0; y < 7; ++y){ for(int x = 0; x < 7; ++x){ MatchItemType randomType = (MatchItemType)(rand() % 5); if(x >= 2){ //左邊兩個是同色 if( map.Get(x - 1, y) == map.Get(x - 2, y)){ //need find a new type findThreeSameInX = true; }else{ findThreeSameInX = false; } }else{ findThreeSameInX = false; } if(y >= 2){ //上面兩個是同色 if(map.Get(x, y - 1) == map.Get(x, y -2)){ //need find a new type; findThreeSameInY = true; }else{ findThreeSameInY = false; } }else{ findThreeSameInY = false; } if(findThreeSameInX == false && findThreeSameInY == false){ //do nothing }else if(findThreeSameInX == true && findThreeSameInY == false){ randomType = getOneRandomTypeExceptParameter(map.Get(x - 1, y)); }else if(findThreeSameInX == false && findThreeSameInY == true){ randomType = getOneRandomTypeExceptParameter(map.Get(x, y - 1)); }else{ randomType = getOneRandomTypeExceptParameter(map.Get(x - 1, y), map.Get(x, y - 1)); } map.Set(x, y, randomType); } } return map;}
3.2 判斷地圖是否是死地圖
如果整個地圖,使用者移動任何一步也不能有消除,就是死地圖了,要重建地圖了。
//case 1/////[x]//////[x]//////////[x][o][x][x][o][x]//////////[x]//////[x]///////////////////////////////////case 2////////[x]///////////////////[x][o][x]///////////////////[x]//////////////////////[x]///////////////////[x][o][x]///////////////////[x]//////////////
這裡用注釋畫了簡單的兩種情況,注意x的位置。case1 是橫著有兩個同色的情況,移動一步能消除只有6種可能,左邊3種,右邊3種。下面是豎著有兩個同色的情況,移動一步能消除也是6種情況。上面3種,下面3種。知道了這個,代碼就容易了。記得找到一個就直接return。
vector<MatchItem*> getThreeMatchItemCanRemoveByOneStep(const Array2D<MatchItem*> & map){ vector<MatchItem*> result; int maxX = 7; int maxY = 7; for(int y = 0; y < maxY; ++y){ for(int x = 0; x < maxX; ++x){ if(x + 1 < maxX){ //case 1 if(map.Get(x, y)->getType() == map.Get(x + 1, y)->getType()){ MatchItemType currentType = map.Get(x, y)->getType(); //check 6 item, one move one step can combine three same item if(x - 2 >= 0){ if(map.Get(x - 2, y)->getType() == currentType){ //find one result.push_back(map.Get(x, y)); result.push_back(map.Get(x + 1, y)); result.push_back(map.Get(x - 2, y)); return result; } } if(x - 1 >= 0 && y - 1 >= 0){ if(map.Get(x - 1, y - 1)->getType() == currentType){ //find one result.push_back(map.Get(x, y)); result.push_back(map.Get(x + 1, y)); result.push_back(map.Get(x - 1, y - 1)); return result; } } if(x + 2 < maxX && y - 1 >= 0){ if(map.Get(x + 2, y - 1)->getType() == currentType){ //find one result.push_back(map.Get(x, y)); result.push_back(map.Get(x + 1, y)); result.push_back(map.Get(x + 2, y - 1)); return result; } } if(x + 3 < maxX){ if(map.Get(x + 3, y)->getType() == currentType){ //find one result.push_back(map.Get(x, y)); result.push_back(map.Get(x + 1, y)); result.push_back(map.Get(x + 3, y)); return result; } } if(x + 2 < maxX && y + 1 < maxY){ if(map.Get(x + 2, y + 1)->getType() == currentType){ //find one result.push_back(map.Get(x, y)); result.push_back(map.Get(x + 1, y)); result.push_back(map.Get(x + 2, y + 1)); return result; } } if(x - 1 >= 0 && y + 1 < maxY){ if(map.Get(x - 1, y + 1)->getType() == currentType){ //find one result.push_back(map.Get(x, y)); result.push_back(map.Get(x + 1, y)); result.push_back(map.Get(x - 1, y + 1)); return result; } } } } if(y + 1 < maxY){ MatchItemType currentType = map.Get(x, y)->getType(); //case 2 if(map.Get(x, y)->getType() == map.Get(x, y + 1)->getType()){ if(y - 2 >= 0){ if(map.Get(x, y - 2)->getType() == currentType){ //find one result.push_back(map.Get(x, y)); result.push_back(map.Get(x, y + 1)); result.push_back(map.Get(x, y - 2)); return result; } } if(x + 1 < maxX && y - 1 >= 0){ if(map.Get(x + 1, y - 1)->getType() == currentType){ //find one result.push_back(map.Get(x, y)); result.push_back(map.Get(x, y + 1)); result.push_back(map.Get(x + 1, y - 1)); return result; } } if(x + 1 < maxX && y + 2 < maxY){ if(map.Get(x + 1, y + 2)->getType() == currentType){ //find one result.push_back(map.Get(x, y)); result.push_back(map.Get(x, y + 1)); result.push_back(map.Get(x + 1, y + 2)); return result; } } if(y + 3 < GameGlobal::xMapCount){ if(map.Get(x, y + 3)->getType() == currentType){ //find one result.push_back(map.Get(x, y)); result.push_back(map.Get(x, y + 1)); result.push_back(map.Get(x, y + 3)); return result; } } if(x - 1 >= 0 && y + 2 < maxY){ if(map.Get(x - 1, y + 2)->getType() == currentType){ //find one result.push_back(map.Get(x, y)); result.push_back(map.Get(x, y + 1)); result.push_back(map.Get(x - 1, y + 2)); return result; } } if(x - 1 >= 0 && y - 1 >= 0){ if(map.Get(x - 1, y + 1)->getType() == currentType){ //find one result.push_back(map.Get(x, y)); result.push_back(map.Get(x, y + 1)); result.push_back(map.Get(x - 1, y - 1)); return result; } } } } } } return result;}
看起來是有點複雜,窮舉了12種情況,這個演算法應該速度很快的。還有個地方要用到這個演算法,就是在消除遊戲中,使用者很久時間沒有進行消除了,要給提示。就用這個演算法找到哪3個可以移動一步進行消除。
演算法先到這裡... 後續有時間再更新...
http://www.waitingfy.com/archives/1335
一個簡單的演算法問題,解答
由內向外層層剝離
for i←1 to n
@x←x+1
end
1+1+1+...+1=n次
for j←1 to n
for i←1 to j
@x←x+1
end
end
A(n)=n
SA(n)=n*(n+1)/2
for i←1 to n
for j←1 to i
for k←1 to j
@x←x+1
end
end
end
B(n)=SA(n)
SB(n)=B(1)+B(2)+...+B(n)
......
方法就是這樣
===================================
1)n*n*(n+1)/2
2)請變成求解
3)請變成求解
===================================
2),3)的結果我不能給出,因為,很顯然,我不是電腦
想用cocos2d-x寫一個帶關卡的遊戲,助思路
一個關卡就是一個情境,可以寫成不同的類,也可以寫同樣的類,看個人編程習慣和關卡的具體差異,暫停按鈕每個情境都是要重新addchild的,可以把這些語句自己寫成一個函數,調用就方便了。