[爆卦]走迷宮演算法是什麼?優點缺點精華區懶人包

為什麼這篇走迷宮演算法鄉民發文收入到精華區:因為在走迷宮演算法這個討論話題中,有許多相關的文章在討論,這篇最有參考價值!作者yantchen (球童Yanting)看板NTUE-CS99標題[課業] 走迷宮程式參考時間W...


抱歉,今天早上臨時寫出來的有一些bug,已經修正

http://stu.ntue.edu.tw/~s9516009/maze.rar

裡面有 6 個檔案

mapmaker.exe 會亂數產生25x25地圖檔 map.txt
(起點終點一定是0;其他格亂數產生0或1,不一定有路可以走)

map.txt 這個rar附贈的地圖檔 經過測試有路可以走

map_method1.cpp 順時鐘走法迷宮程式檔
(下面會詳細講解這個程式)

map_method1.exe 順時鐘走法迷宮執行檔

map_method2.cpp 填數字走法迷宮程式檔
(我自己的解法,另外一種演算法,僅供參考)

map_method2.exe 填數字走法迷宮執行檔


=============================================================================

map_method1.cpp

順時鐘走法的演算法:

1.順時針檢查八個方向 有路就走(不管是不是死路) 沒路(牆壁或走過)就轉下一個方向

把走到的那一個 x、y、方向 三個東西放到堆疊

2.如果某一格八個方向都試過沒有路可以走 從堆疊彈出上一步的 x、y、方向

並回到步驟1嘗試下一個方向

3.重複步驟1、2,如果 x、y = 終點 就跳出迴圈 輸出路徑

如果堆疊沒有東西可以彈出了 就是無解

( 一開始記得把起點放到堆疊裡面 如果起點被彈出來後還是死路

還要再談出堆疊找上一步 就知道是無解 )




宣告堆疊:

step是用陣列作成的堆疊 有1000個空間(其實25x25就夠了)

每個空間可以放3樣資訊 x、y、方向

s是記錄堆疊頂端的變數

push是把x、y、方向放入堆疊的函數

pop是把x、y、方向取出堆疊的函數

show是把堆疊從0到top輸出(show出路徑)的函數


class stack{

int step[1000][3];
int s;

public:

stack(){

s=0;
}

void push(int x,int y,int d){

step[s][0]=x;
step[s][1]=y;
step[s][2]=d;
s++;
}

int pop(int &x,int &y,int &d){

s--;
if(s==0) return -1;
x=step[s-1][0];
y=step[s-1][1];
d=step[s-1][2];
}

void show(){

for(int i=0;i<s;i++)
cout<<"第"<<i+1<<"步"<<"("<<step[i][0]<<","<<step[i][1]<<")\n";

}
};

主程式部份

int main(){

宣告二維陣列map存放地圖

為了避免判斷有沒有超出地圖範圍的麻煩 把陣列設成27x27 並把多的四邊設成牆壁

所以地圖實際存放在陣列的區域是(1,1)~(25,25)


int map[27][27];

讀檔,請參考精華區一下程設投影片

for(int j=0;j<27;j++)
for(int i=0;i<27;i++)
map[i][j]=1;

FILE* f=fopen("map.txt","r");

char buf[25];

for(int j=1;j<=25;j++){

fgets(buf,30,f);

for(int i=0;i<25;i++)

map[i+1][j]=buf[i]-'0';


}

fclose(f);

宣告變數:

stk存放路徑堆疊;x,y目前所在位置;d目前嘗試方向;xt,yt下一步預計要往那裡走

stack stk;

int x=1,y=1,d=0,xt,yt;

起點設定:

把起點放進堆疊(方便之後判斷是否無解)

地圖上0是路;1是牆壁;2是走過的路;3是死路

stk.push(x,y,d);

map[x][y]=2;

do{

方向設定:

d=0~7 分別代表一個方向 用switch算出這個方向的下一步 存在xt、yt裡面

switch(d){

case 0: xt=x+1; yt=y-1; break; // 右上

case 1: xt=x+1; yt=y; break; // 右

case 2: xt=x+1; yt=y+1; break; // 右下

case 3: xt=x; yt=y+1; break; // 下

case 4: xt=x-1; yt=y+1; break; // 左下

case 5: xt=x-1; yt=y; break; // 左

case 6: xt=x-1; yt=y-1; break; // 左上

case 7: xt=x; yt=y-1; break; // 上

}

如果可以走 (地圖=0) x,y,d丟入堆疊 地圖設2 走到下一格d歸零

if(map[xt][yt]==0){

x=xt;
y=yt;

stk.push(x,y,d);
map[x][y]=2;

d=0;

} else {

不能走就轉下一個方向(d++)

d++;

}

若d加到超過8 想必是遇到了轉了一圈都找不到路的死路 彈出上一步

轉下一個方向 並把死路這格設成3

k用來存pop的傳回值 上面的pop函數設定沒有東西可以彈出得時候傳回-1

判斷k=-1的時候 輸出無解 並結束程式

if(d>=8){

map[x][y]=3;

int k=stk.pop(x,y,d);

if(k==-1){
cout<<"沒有路可以走喔\n";
system("pause");
return 0;
}


d++;

}

走到終點才跳出迴圈

走完後先用座標顯示走過路徑

再用地圖顯示走過路徑

}while(x!=25||y!=25);

stk.show();

for(int j=1;j<=25;j++){
for(int i=1;i<=25;i++){
if(map[i][j]==1) cout<<"█";
else if(map[i][j]==2) cout<<"‧";
else cout<<" ";
}
cout<<endl;
}


system("pause");
}

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 203.68.15.99
jyc180: 豔婷你好正~!>\\\\\\< 11/01 00:48
jyc180:抱歉抱歉><按錯...推一個回來 11/01 00:51
miyuika: 謝謝彥廷~>口</ (歡呼) 11/01 08:05
hjh0803: 謝謝彥廷~>口</ (歡呼) 11/01 13:57
jill1116: 謝謝彥廷~>口</ (歡呼) 11/01 17:34
gn02254995: 謝謝彥廷~>口</ (歡呼) 11/01 23:16

你可能也想看看

搜尋相關網站