兩點串連尋徑演算法

來源:互聯網
上載者:User
這個算是用我上次發布的連連看中的一個兩點串連演算法,上次發布了源碼以後,很多朋友發郵件或能過MSN尋問源碼中問題,演算法佔了一大部分,我當時答應會發一篇文章,詳細講解一下這個演算法,但由於最近忙於工作,所以一拖再拖,在這裡先說聲Sorry.
希望各位看了這個演算法後,能給點評價,謝謝。還有,上次把我連連看最終發布版拿到我在的C#開發群裡,沒想到一下子就發現了BUG,比較鬱悶的,主要平時也沒做測試,給女朋友玩的時候,都已經明確告訴她,這個不用點的,沒用的,這邊有用的。看來還是要好好測試一下,所以我決定過一兩天把那個最終版發布出來,希望大家幫忙測試一下(就當是工作之餘玩點小遊戲輕鬆一下)。 下面就來講演算法基本演算法如下:首先是知道它的要求:
1:兩個目標是相同的
2:兩個目標之間連接線的折點不超過兩個。(連接線由x軸和y軸的平行線組成) 那麼分析一下串連的情況可以看到,一般分三種情況
1:直線相連 2:一個折點 3:兩個折點。可以發現,如果有折點,每個折點必定有且至少有一個座標(x或者y)是和其中一個目標點是相同的,也就是說,折點必定在兩個目標點所在的x方向或y方向的直線上。
所以設計思路如下:
假設目標點 p1 , p2 ,如果有兩個折點分別為z1 , z2 那麼,所要進行的是
1:如果驗證p1 , p2 直線連線,則串連成立
2:搜尋以p1,p2的x,y方向四條直線即下文所講的十字路徑(可能某兩條直線會重合)上的有限點,每次取兩點作為z1,z2 ,驗證p1到z1/z1到z2/z2到p2 是否都能直線相連 ,是則串連成立。(如果z1=z2也就是只有一個折點,對判斷沒影響) 看下面的一個矩陣0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 9 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 9 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 希望串連的是兩個點(9)分別取出點1(3,2)和點2(12,5)的十字路徑(點1的路徑線以數字1表示,點2的路徑以數字2表示,交叉點任取一數),得結果也下,0 0 0 1 0 0 0 0 0 0 0 0 2 0 0 00 0 0 1 0 0 0 0 0 0 0 0 2 0 0 01 1 1 9 1 1 1 1 1 1 1 1 1 1 1 10 0 0 1 0 0 0 0 0 0 0 0 2 0 0 00 0 0 1 0 0 0 0 0 0 0 0 2 0 0 02 2 2 1 2 2 2 2 2 2 2 2 9 2 2 20 0 0 1 0 0 0 0 0 0 0 0 2 0 0 00 0 0 1 0 0 0 0 0 0 0 0 2 0 0 0  以上是具體思路,下面從代碼來具體講解思路,要判斷兩點是否可串連,首先要分別獲得這兩點的十字路徑,  /// <summary>/// 獲點指定點的水平可達路徑/// </summary> private int[,] GetTempPointX(Common.Position p, int[,] buffer){// 橫向檢測,基點為1以左int nBufX = 1;buffer[0,0] = p.x;buffer[0,1] = p.y;for (int TmpX = p.x - 1; TmpX >= 0; --TmpX){       if (map[p.y,TmpX] == 0)       {              buffer[nBufX,0] = TmpX;              buffer[nBufX,1] = p.y;              ++nBufX;       }       else              {                     break;              }       }        // 橫向檢測,基點為1以右       for (short TmpX = (short)(p.x + 1); TmpX < Common.MAP_WIDTH; ++TmpX)       {              if (map[p.y,TmpX] == 0)              {                     buffer[nBufX,0] = TmpX;                     buffer[nBufX,1] = p.y;                     ++nBufX;              }              else              {                     break;              }       }       buffer[nBufX,0] = -1;       buffer[nBufX,1] = -1;       return buffer;}   /// <summary>/// 獲點指定點的垂直可達路徑/// </summary> private int[,] GetTempPointY(Common.Position p, int[,] buffer){       int nBufY = 1;       buffer[0,0] = p.x;       buffer[0,1] = p.y;       // 縱向檢測,基點1以上       for (int TmpY = p.y - 1; TmpY >= 0; --TmpY)       {              if (map[TmpY,p.x] == 0)              {                     buffer[nBufY,0] = p.x;                     buffer[nBufY,1] = TmpY;                     ++nBufY;              }              else              {                     break;              }       }        // 縱向檢測,基點1以下       for (int TmpY = p.y + 1; TmpY < Common.MAP_HEIGHT; ++TmpY)       {              if (map[TmpY,p.x] == 0)              {                     buffer[nBufY,0] = p.x;                     buffer[nBufY,1] = TmpY;                     ++nBufY;              }              else              {                     break;              }       }       buffer[nBufY,0] = -1;       buffer[nBufY,1] = -1;       return buffer;} 獲得水平與垂直可達路徑的方法都已經有了,現在就可以進行判斷了 private bool CheckInLineX(int[,] buffer1, int[,] buffer2, bool isInternal){//判斷是否在同一條直線上,可加速檢測       if(CheckInLine(buffer1,buffer2))       {//該檢查方法CheckInLine略              return false;       }       // 橫向檢測:縱向通路檢測       // 連通標誌       bool isInLine = false;       for (int nChkLink1 = 0; !(buffer1[nChkLink1,0] < 0 && buffer1[nChkLink1,1] < 0); ++nChkLink1)       {              // 設定同軸加速檢查標誌              bool bShortPass = false;               for (int nChkLink2 = 0; !(buffer2[nChkLink2,0] < 0 && buffer2[nChkLink2,1] < 0); ++nChkLink2)              {                     // 檢查是否在同一縱軸                     if (buffer1[nChkLink1,0] == buffer2[nChkLink2,0])                     {                            // 因為已經檢查到同軸點,所以設定同軸對比加速度檢查標誌為true                            bShortPass = true;                             // 計算對比點距離                            int nStep = buffer1[nChkLink1,1] - buffer2[nChkLink2,1];                            // 位移量                            int OpNum;                            if (nStep > 0)                            {                                   OpNum = -1;                                   --nStep;                            }                            else                            {                                   OpNum = 1;                                   ++nStep;                            }                             isInLine = true;                            int tmpvx = buffer1[nChkLink1,0];                            for (int mStep = nStep; mStep != 0; mStep += OpNum)//Math.Abs(mStep-0) < 1                            {                                   if (map[buffer1[nChkLink1,1] - mStep,tmpvx] == 0)                                   {                                          // 繼續檢查下一點                                          continue;                                   }                                   else                                   {                                          // 通路有阻礙,無法連通                                          isInLine = false;                                          break;                                   }                            }                            // 如果連通                            if (isInLine == true)                            {#if DEBUG       System.Windows.Forms.MessageBox.Show("Linked\n");#endif                                   return true;                            }                     }                     else                     {                            // 判斷同軸加速檢查標誌,以確定檢查加速                            if (bShortPass == true)                            {                                   break;                            }                     }              }}return false;}判斷的思路基本如下:從得到的兩個十字路徑中,先拿出橫軸(兩點的橫向線上的點),然後拿點1橫縱上的第一個連,找到點2橫縱上與其相對在同一直線上的點,然後判斷這兩個點是否可連能,如果可加通,則表示點1和點2是可連通的,如果不能連通,則拿點1橫軸上的下一個點,再去與點2橫軸上相應的點進行判斷,直到找到相連通的點或點1上的點全部判斷完。如果兩點的橫軸不能連通,然後比較兩點的縱軸。同軸加速檢查標誌是用來提早結束迴圈的,當兩個橫軸進行比較是否有點相連通時,其中一點如果比到與其同縱軸時,不管是否可連通,都不需要再比較下面的點。其實在這個地方可以加以修改,使其直接定位到對比軸內的相應位置(呵,由於比較忙,也沒空去搞這個東西,做完到現在已經好幾個月沒碰了) 這個演算法在連點上的擴充性不好,如果它的要求變成可以四折,五折,那樣的話,就很難擴充,相比之下,普通的那種尋路演算法,就要好多了,但我發現這個演算法在維度上的擴充比較好,如果將來有個3D的連連看,需要在3維空間中串連,也許這個演算法的擴充性可能會相對好一些。不知道各位有沒明白,其實我當時就覺得這個演算法好理解,才用它的,在效率上,我也不知道是這個演算法怎麼樣,或許還是大部分人用的尋路算好,希望各位評價一下這個演算法,給點意見,謝謝 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.