先上一張圖給大家看看
當大家看到這張圖片的時候會看到周圍一圈對號,這個是我做標記用的,當然 真正的開發遊戲過程中 這些對號是不存在的。我這裡想給大家說明的是 假如我們的 地圖是14*8的
那麼其實真正的地圖佈局應該是16*10 為什麼要這麼做呢 那是因為我們要讓我們所有的路線都從我們規定的方格內經過,不能越界。如果你是14*8 的那麼當四邊上有可以連通的時候 就要做大量的判斷來處理。那麼為什麼我們不避免這些問題呢。這樣我們在規劃路線的時候 就不存在了特殊的情況。
不知道大家是否明白我說的什麼意思。如果不懂的話可以給我留言我會給大家回覆 解答。
關於圖片的生成我這裡說一下 如何保證所有的圖片 都是成對出現呢 這裡有個前提條件就是我們的地圖佈局一定要成偶數。那麼我們在生出圖片的 我們每一次取出一張圖片生成兩個一模一樣的 這樣就保證地圖裡面所有的圖片肯定是成對出現的。
主要程式碼是這樣的
-
int totalcout=this->row*this->cloum;
-
CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("point.plist","point.png");
-
CCArray* temparry=CCArray::create();
-
-
for (int i=0;i<totalcout/2;i++){
-
int num=CCRANDOM_0_1()*35;
-
CustomSprite* phit1= CustomSprite::createWithSpritePicIndex(num,CCSize(picWidth,picHeight));
-
CustomSprite* phit2= CustomSprite::createWithSpritePicIndex(num,CCSize(picWidth,picHeight));
-
temparry->addObject(phit1);
-
temparry->addObject(phit2);
-
}
是不是很簡單啊
至於如何把生成的東西給打亂。這個cocos2d-x 提供了很好用的方法那就是從陣列中取出的時候 可以隨機去取出。
下面把整個地圖佈局的方法給貼出來
-
bool LLKmapLayer::setUpdateView(){
-
bool isRet=false;
-
do {
-
-
int totalcout=this->row*this->cloum;
-
CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("point.plist","point.png");
-
CCArray* temparry=CCArray::create();
-
-
for (int i=0;i<totalcout/2;i++){
-
int num=CCRANDOM_0_1()*35;
-
CustomSprite* phit1= CustomSprite::createWithSpritePicIndex(num,CCSize(picWidth,picHeight));
-
CustomSprite* phit2= CustomSprite::createWithSpritePicIndex(num,CCSize(picWidth,picHeight));
-
temparry->addObject(phit1);
-
temparry->addObject(phit2);
-
}
-
-
for(int i=0;i<row+2;i++){
-
for(int j=0;j<this->cloum+2;j++){
-
-
if ((i==0)||(j==0)||(j==cloum+1)||(i==row+1)){
-
CustomSprite* temp= CustomSprite::createWithSpritePicIndex(0,CCSize(picWidth,picHeight));
-
temp->displayCustome();
-
temp->setX(j);
-
temp->setY(i);
-
-
temp->setAnchorPoint(ccp(0,0));
-
temp->setPosition(ccp(45*(j-1),51*(i-1)));
-
this->addChild(temp);
-
this->totalArray->addObject(temp);
-
-
}else {
-
CustomSprite* phit=(CustomSprite*)temparry->randomObject();
-
temparry->removeObject(phit,false);
-
phit->setAnchorPoint(ccp(0,0));
-
phit->setPosition(ccp(45*(j-1),51*(i-1)));
-
this->addChild(phit);
-
llkArray->addObject(phit);
-
phit->setX(j);
-
phit->setY(i);
-
this->totalArray->addObject(phit);
-
}
-
}
-
}
-
isRet=true;
-
} while (0);
-
return isRet;
-
}
是不是很少的程式碼就實現了這個功能了。
下面就開始我們今天的重頭戲 那就是連連看的主要演算法
首先先說明最簡單 那就是一線貫通。
大家看到我畫的紅線 是連連看中最簡單的 兩種連線方式
只要兩張圖片 處於同一水平線或者同一垂直線 如果兩張圖片中沒有別的圖片間隔就代表可以連通消除了
主要程式碼
-
-
CCArray* LLKAlgorithm::horizon(cocos2d::CCArray* llkArray,cocos2d::CCArray* hitArray){
-
CustomSprite* hit1=(CustomSprite*)hitArray->objectAtIndex(0);
-
CustomSprite* hit2=(CustomSprite*)hitArray->objectAtIndex(1);
-
int x1=hit1->getX();
-
int x2=hit2->getX();
-
bool isda=x1>x2?true:false;
-
int temp=isda?x1-x2:x2-x1;
-
CCArray* temparray=CCArray::create();
-
-
if (temp==1){
-
temparray->addObject(hit1);
-
temparray->addObject(hit2);
-
}else {
-
-
if (isda){
-
temparray->addObject(hit1);
-
temparray->addObject(hit2);
-
for(int i=1;i<temp;i++){
-
CustomSprite* hitteim=LLKAlgorithm::getCustByXandY(llkArray,x1-i,hit2->getY());
-
-
if (!hitteim->getIsEliminate()){
-
LLKAlgorithm::removeAllArray(temparray,false);
-
break;
-
}else {
-
temparray->addObject(hitteim);
-
}
-
}
-
-
}else {
-
temparray->addObject(hit2);
-
temparray->addObject(hit1);
-
for(int i=1;i<temp;i++){
-
CustomSprite* hitteim=LLKAlgorithm::getCustByXandY(llkArray,x2-i,hit2->getY());
-
-
if (!hitteim->getIsEliminate()){
-
LLKAlgorithm::removeAllArray(temparray,false);
-
break;
-
}else {
-
temparray->addObject(hitteim);
-
}
-
}
-
}
-
-
}
-
-
-
return temparray;
-
-
}
-
-
CCArray* LLKAlgorithm::vertical(cocos2d::CCArray* llkArray,cocos2d::CCArray* hitArray){
-
CustomSprite* hit1=(CustomSprite*)hitArray->objectAtIndex(0);
-
CustomSprite* hit2=(CustomSprite*)hitArray->objectAtIndex(1);
-
int y1=hit1->getY();
-
int y2=hit2->getY();
-
bool isda=y1>y2?true:false;
-
int temp=isda?y1-y2:y2-y1;
-
CCArray* temparray=CCArray::create();
-
-
if (temp==1){
-
temparray->addObject(hit1);
-
temparray->addObject(hit2);
-
}else {
-
-
if (isda){
-
temparray->addObject(hit1);
-
temparray->addObject(hit2);
-
for(int i=1;i<temp;i++){
-
CustomSprite* hitteim=LLKAlgorithm::getCustByXandY(llkArray,hit2->getX(),y1-i);
-
-
if (!hitteim->getIsEliminate()){
-
LLKAlgorithm::removeAllArray(temparray,false);
-
break;
-
}else {
-
temparray->addObject(hitteim);
-
}
-
}
-
-
}else {
-
temparray->addObject(hit2);
-
temparray->addObject(hit1);
-
for(int i=1;i<temp;i++){
-
CustomSprite* hitteim=LLKAlgorithm::getCustByXandY(llkArray,hit2->getX(),y2-i);
-
-
if (!hitteim->getIsEliminate()){
-
LLKAlgorithm::removeAllArray(temparray,false);
-
break;
-
}else {
-
temparray->addObject(hitteim);
-
}
-
}
-
}
-
-
}
-
-
-
-
return temparray;
-
}
其中返回的 array 就是兩個圖片的之間的路徑 包含兩張圖片在內。
對於兩張圖片是否可以垂直相連或者橫向相連這個我不用多講大家都應該明白怎麼去做。
下面講解一個拐角相連的情況
首先我先上張圖
看到這張圖片的時候大家先看藍色矩形框裡面 是兩張可以經過一個拐角消除的圖片 但是怎麼確定兩張圖片可以經過一個拐角就可以連線呢
大家有沒有發現 這兩個張圖片剛好是矩形的兩個對角頂點 。也就是說圍繞著兩張圖片我們可以畫出一個最小的矩形,而矩形的其中兩個頂點就是這兩張圖片。
好大家如果理解了這裡 我們就說下面的,如果不理解好好的想一下。既然已知矩形的 其中兩個頂點,那麼另外兩個頂點的座標也就輕鬆的計算出來。就是我們看到的兩個綠色的框。
我們先拿出最上面的那個綠色的矩形框,我們發現他不是一個空白或者說已經消除的一個圖片 。那麼這個頂點是不符合規則的。我們看下面的那個綠色矩形框。 我們驚奇的發現 他竟然和我們選擇的那兩張(藍色框)圖片能直接連通 也就是通過這個綠色的矩形框(已經消除掉的) 我們可以把他轉化成 一個橫向可以連通和一個縱向可以連通的。
看到這裡有的人或許已經恍然大悟了。其實我們要向知道兩個點是否可以經過一個拐角相連,我們首先要確定兩個圖片的座標點是可以畫出一個矩形的並且這個矩形的兩個對角頂點就是你選中的兩張圖片。(必須是對角)然後我們找出這兩個矩形另外兩個頂點的座標,找到時候首先要確定找到這個頂點必須是已經消除的掉的一個空白在哪裡,或者說沒有阻礙物。如果找到一個這樣的頂點,那麼只要這個頂點能和我們剛開始選擇的那兩張圖片 形成一個縱向的連通和一個橫向的連通 那麼就說明這兩個點可以經過一個拐角進行相連。
簡單一點說就是 兩個拐角的==想辦法轉成===》一個縱向連通+一個橫向連通。
說到這裡不知道大家是否已經明白我所表達的意思。
主要程式碼實現
-
CCArray* LLKAlgorithm::oneCorner(cocos2d::CCArray* llkArray,cocos2d::CCArray* hitArray){
-
CustomSprite* hit1=(CustomSprite*)hitArray->objectAtIndex(0);
-
CustomSprite* hit2=(CustomSprite*)hitArray->objectAtIndex(1);
-
int x1=hit1->getX();
-
int x2=hit2->getX();
-
int y1=hit1->getY();
-
int y2=hit2->getY();
-
bool isXg=x1>x2?true:false;
-
bool isYg=y1>y2?true:false;
-
-
-
int temx=0;
-
int temy=0;
-
-
-
-
if(isYg){
-
temy=hit1->getY();
-
temx=hit2->getX();
-
}else {
-
temy=hit2->getY();
-
temx=hit1->getX();
-
}
-
CCArray* temparray=CCArray::create();
-
-
CustomSprite* hity=LLKAlgorithm::getCustByXandY(llkArray,temx,temy);
-
CCArray* tempHit=CCArray::create();
-
-
if (hity->getIsEliminate()){
-
tempHit->addObject(hity);
-
tempHit->addObject(isYg?hit1:hit2);
-
CCArray* temx=LLKAlgorithm::horizon(llkArray,tempHit);
-
if(temx->count()>0){
-
temparray->addObjectsFromArray(temx);
-
LLKAlgorithm::removeAllArray(tempHit,false);
-
tempHit->addObject(hity);
-
tempHit->addObject(isYg?hit2:hit1);
-
CCArray* temy=LLKAlgorithm::vertical(llkArray,tempHit);
-
if (temy->count()>0){
-
temparray->removeObject(hity,false);
-
temparray->addObjectsFromArray(temy);
-
}else {
-
LLKAlgorithm::removeAllArray(temparray,false);
-
}
-
}else {
-
LLKAlgorithm::removeAllArray(tempHit,false);
-
}
-
}
-
-
if (temparray->count()==0){
-
-
-
-
-
if (isYg){
-
temy=hit2->getY();
-
temx=hit1->getX();
-
}else {
-
temy=hit1->getY();
-
temx=hit2->getX();
-
}
-
-
CustomSprite* hitx=LLKAlgorithm::getCustByXandY(llkArray,temx,temy);
-
if (hitx->getIsEliminate()){
-
tempHit->addObject(hitx);
-
tempHit->addObject(isYg?hit2:hit1);
-
CCArray* temx=LLKAlgorithm::horizon(llkArray,tempHit);
-
if(temx->count()>0){
-
temparray->addObjectsFromArray(temx);
-
LLKAlgorithm::removeAllArray(tempHit,false);
-
tempHit->addObject(hitx);
-
tempHit->addObject(isYg?hit1:hit2);
-
CCArray* temy=LLKAlgorithm::vertical(llkArray,tempHit);
-
if (temy->count()>0){
-
temparray->removeObject(hitx,false);
-
temparray->addObjectsFromArray(temy);
-
}else {
-
LLKAlgorithm::removeAllArray(temparray,false);
-
}
-
}else {
-
LLKAlgorithm::removeAllArray(tempHit,false);
-
}
-
}
-
-
}
-
-
return temparray;
-
-
}
下面我們說下拐兩角 可以相連的。
大家看看藍色區域內的是我選擇的兩張圖片。從圖中我們看出這兩張圖片是可以經過兩個拐角相連的。
那麼如何知道可以經過兩個拐角可以 可以相連的 我相信通過上面那一個拐角的演算法 大家或許就可以猜出來了。這裡我詳細說明一下 首先我們拿出一個點 那麼就像這個點的上下左右去找,找到一個 可以經過一個拐角和另外一個點相連的。經過一個拐角的演算法請看上面那個講解。首先找到的這個點可以和我們拿出的這個點縱向相連或者橫向相連 。(但是必須保證這個點已經沒有別的圖片佔位置或者說是一個空白)。如果能找到這樣的一個點那麼就可以說明我們開始選擇的兩個圖片是可以經過兩個拐角進行相連的。
總體來說 可以這樣理解 兩個拐角==轉化成===》(一個橫向相連/縱向相連)+ 一個拐角可以相連的
一個拐角的看上面的解釋。
主要實現程式碼
-
CCArray* LLKAlgorithm::twoCorner(cocos2d::CCArray* llkArray,cocos2d::CCArray* hitArray){
-
-
bool isjiance=false;
-
-
CustomSprite* lastCutom=(CustomSprite*)llkArray->lastObject();
-
int max=lastCutom->getX();
-
int may=lastCutom->getY();
-
CustomSprite* hit1=(CustomSprite*)hitArray->objectAtIndex(0);
-
CustomSprite* hit2=(CustomSprite*)hitArray->objectAtIndex(1);
-
-
-
-
-
CCArray* temparray=CCArray::create();
-
int x1=hit1->getX();
-
int y1=hit1->getY();
-
-
CCArray* temphit=CCArray::create();
-
temphit->addObject(hit2);
-
for(int i=(x1-1);i>=0;i--){
-
CustomSprite* tepcou =LLKAlgorithm::getCustByXandY(llkArray, i, y1);
-
if (tepcou->getIsEliminate()){
-
-
temparray->addObject(tepcou);
-
if(tepcou->getX()==hit2->getX()||hit2->getY()==tepcou->getY()){
-
-
continue;
-
}
-
isjiance=true;
-
temphit->addObject(tepcou);
-
CCArray* temparr=LLKAlgorithm::oneCorner(llkArray,temphit);
-
if (temparr->count()>0){
-
temparray->addObjectsFromArray(temparr);
-
break;
-
}else {
-
if(i==0){
-
LLKAlgorithm::removeAllArray(temparray,false);
-
}
-
-
temphit->removeLastObject(false);
-
}
-
}else{
-
LLKAlgorithm::removeAllArray(temparray,false);
-
-
break;
-
}
-
-
}
-
-
if (isjiance==false){
-
LLKAlgorithm::removeAllArray(temparray,false);
-
}
-
-
if(temparray->count()==0){
-
bool isjiance=false;
-
-
for(int i=(x1+1);i<=max;i++){
-
CustomSprite* tepcou =LLKAlgorithm::getCustByXandY(llkArray, i, y1);
-
if (tepcou->getIsEliminate()){
-
-
temparray->addObject(tepcou);
-
if(tepcou->getX()==hit2->getX()||hit2->getY()==tepcou->getY()){
-
continue;
-
}
-
isjiance=true;
-
temphit->addObject(tepcou);
-
CCArray* temparr=LLKAlgorithm::oneCorner(llkArray,temphit);
-
if (temparr->count()>0){
-
temparray->addObjectsFromArray(temparr);
-
break;
-
}else {
-
if(i==max){
-
LLKAlgorithm::removeAllArray(temparray,false);
-
}
-
temphit->removeLastObject(false);
-
}
-
}else{
-
LLKAlgorithm::removeAllArray(temparray,false);
-
break;
-
}
-
}
-
-
if (isjiance==false){
-
LLKAlgorithm::removeAllArray(temparray,false);
-
}
-
}
-
-
if(temparray->count()==0){
-
bool isjiance=false;
-
-
for(int i=(y1-1);i>=0;i--){
-
CustomSprite* tepcou =LLKAlgorithm::getCustByXandY(llkArray, x1, i);
-
if (tepcou->getIsEliminate()){
-
temparray->addObject(tepcou);
-
-
if(tepcou->getX()==hit2->getX()||hit2->getY()==tepcou->getY()){
-
continue;
-
}
-
isjiance=true;
-
temphit->addObject(tepcou);
-
CCArray* temparr=LLKAlgorithm::oneCorner(llkArray,temphit);
-
if (temparr->count()>0){
-
temparray->addObjectsFromArray(temparr);
-
break;
-
}else {
-
if (i==0){
-
LLKAlgorithm::removeAllArray(temparray,false);
-
}
-
temphit->removeLastObject(false);
-
}
-
}else{
-
LLKAlgorithm::removeAllArray(temparray,false);
-
break;
-
}
-
}
-
if (isjiance==false){
-
LLKAlgorithm::removeAllArray(temparray,false);
-
}
-
}
-
-
-
if(temparray->count()==0){
-
bool isjiance=false;
-
-
for(int i=(y1+1);i<=may;i++){
-
CustomSprite* tepcou =LLKAlgorithm::getCustByXandY(llkArray, x1, i);
-
if (tepcou->getIsEliminate()){
-
temparray->addObject(tepcou);
-
-
if(tepcou->getX()==hit2->getX()||hit2->getY()==tepcou->getY()){
-
continue;
-
}
-
isjiance=true;
-
temphit->addObject(tepcou);
-
CCArray* temparr=LLKAlgorithm::oneCorner(llkArray,temphit);
-
if (temparr->count()>0){
-
temparray->addObjectsFromArray(temparr);
-
break;
-
}else {
-
if(i==may){
-
LLKAlgorithm::removeAllArray(temparray,false);
-
}
-
-
temphit->removeLastObject(false);
-
}
-
}else{
-
LLKAlgorithm::removeAllArray(temparray,false);
-
-
break;
-
}
-
}
-
if (isjiance==false){
-
LLKAlgorithm::removeAllArray(temparray,false);
-
}
-
}
-
-
if (temparray->count()>0){
-
temparray->addObject(hit1);
-
}
-
-
return temparray;
寫到這裡連連看的演算法基本算是已經完成了
我在網上看了很多方法感覺不太容易理解,這個是我自己想出來的。感覺很通俗易懂,其實就是化繁為簡。我最麻煩的變成最簡單。不過連連看的演算法有很多種。不如著名的A*
尋路演算法就可以。不過我感覺那個給大家講解其實會很麻煩,有希望瞭解瞭解的同學可以在百度上上搜尋一下A* 尋路演算法。
其實我子所以寫這個練練看看的演算法是交大家以後學習中的一種思路,有些同學一開始把問題弄得很複雜導致一時半會想不通,我建議剛開始考慮情況的時候從最簡單的開始考慮。到繁瑣的階段的時候看看能不能轉化成
簡單的方式。中國人其實都喜歡大事化小 小事化了 哈哈。 本章講解結束。 至於重新佈局+自動查詢 等演算法我會慢慢加進去 希望大家耐心等待。
另外給大家說下以後我所有的部落格首發地址將會是天地會的論壇,由於我是他們哪裡的原創管理。所以我以後在釋出部落格首發地址將會天地會感興趣的同學可以關注一下
http://bbs.9ria.com/forum.php?mod=forumdisplay&fid=318
我給本演算法起名字交錯化繁為簡 演算法。
如果沒有看懂的同學可給我留言,我給給大家仔細講解一下
原始碼下載