其實這個議題對於每次遇到要寫類似迷宮程式的時候都是一個頭痛需要思考的問題。

在此我就提供其中一個方法,也許方法很多我的不代表就是最佳但是一個參考方向。

當你要寫迷宮程式的時候也許你會有以下的作法:

1.亂數隨意產生牆壁的作法,長度不要過長的方式來達到,但有會走不到終點的情況,因為有死路產生。

2.乾脆將地圖寫死,多做幾個在程式中亂數選擇之一,還算可以的作法好處是不會有死路產生但變化不多。

3.取一的作法加入更多的限制條件,但是還是會有死路產生的狀況無法解決。

條件:在下點的情況下需檢查周圍狀況之類.....

我這提供的作法其實很簡單,就是把路先長出來然後填牆......說來簡單就幾句話而已,難道我當大家是白癡喔!!

大家都知道阿....問題就在作法上的處理了。

我以31x31的地圖大小來做說明,記住地圖一定要是積數絕不要用偶數,如果使用我的方法的話。

範例使用C語言設計,請不要問我其他語言請自行修改設計。

1.清空地圖
數位高手(NBP)
 
for(i=0;i<31;i++)
for(j=0;j<31;j++)
mz[i][j]=0;
2.建圍牆
數位高手(NBP)
 
for(i=0;i<31;i++)
{
mz[0][i] = 1;
mz[30][i] = 1;
mz[i][0] = 1;
mz[i][30]=1;
}

3.取偶數點,這就是訣竅點了......

為什麼要取偶數點呢?經過前面兩個動作之後如果我們只取偶數點的話圖形會如下所示:





橘色就是我們取點決定牆起點的位置。

數位高手(NBP)
 
xx = (random(14)+1)*2;
yy = (random(14)+1)*2;
 

4.決定牆延展的方向和限制牆的長度。

5.將牆依據檢查路線實際填上就完成。

6.列印迷宮。

經過以上的過程我們就可以完成一個不死迷宮,我必須強調不是永不死是機率上降低許多。

因為也許有人會說你可能會連續挑到同一直線或者橫線的點而且又相同的一個方向,沒錯這個機率是存在的但

他可能跟中樂透是一樣的,機率不高而且你可以在實際希望劃上的線(牆壁)不要這麼密集又可以將變成死迷宮的機率降低更多。

原始程式碼:

數位高手(NBP)

#include
#include
#include
 
int random(int n) {return rand() % n; }
void randomize() { srand(time(NULL)); }
 
using namespace std;
 
int main(void)
{
int mz[31][31];
int i,j;
//initial
for(i=0;i<31;i++)
for(j=0;j<31;j++)
mz[i][j]=0;
//make border
for(i=0;i<31;i++)
{
mz[0][i] = 1;
mz[30][i] = 1;
mz[i][0] = 1;
mz[i][30]=1;
}
int xx,yy; //random position
int x_tmp,y_tmp; //backup position
int dir; //directory way
int count;
randomize();
for(i=0;i<100;i++)
{
xx = (random(14)+1)*2;
yy = (random(14)+1)*2;
x_tmp = xx;
y_tmp = yy;
if(mz[xx][yy] == 0){
do{
count = 0;
xx = x_tmp;
yy = y_tmp;
dir = random(4);
cout << "dir:" << dir << endl;
do{
count = count + 1;
switch (dir)
{
case 0: xx = xx-1;
break;
case 1: xx = xx+1;
break;
case 2: yy = yy+1;
break;
case 3: yy = yy-1;
break;
}
}while(mz[xx][yy]!=1);
cout << "count:" << count << endl;
}while(count > 10);
xx = x_tmp;
yy = y_tmp;
do{
mz[xx][yy] = 1;
switch (dir)
{
case 0: xx = xx-1;
break;
case 1: xx = xx+1;
break;
case 2: yy = yy+1;
break;
case 3: yy = yy-1;
break;
}
}while(mz[xx][yy] != 1);
}//if end
}
for(i=0;i<31;i++){
for(j=0;j<31;j++){
if(mz[i][j]==1)
cout << "■";
else
cout << "□";
}
cout << endl;
}
cin.get();
}
 

piratechu 發表在 痞客邦 PIXNET 留言(0) 人氣()