數據結構實驗迷宮問題_第1頁
數據結構實驗迷宮問題_第2頁
數據結構實驗迷宮問題_第3頁
數據結構實驗迷宮問題_第4頁
數據結構實驗迷宮問題_第5頁
已閱讀5頁,還剩11頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、實驗報告實驗課名稱:數據結構實驗實驗名稱:迷宮問題班級:20130613學號:16姓名:施洋時間:2015-5-18一、問題描述 這是心理學中的一個經典問題。心理學家把一只老鼠從一個無頂蓋的大盒子的入口處放入,讓老鼠自行找到出口出來。迷宮中設置很多障礙阻止老鼠前行,迷宮唯一的出口處放有一塊奶酪,吸引老鼠找到出口。簡而言之,迷宮問題是解決從布置了許多障礙的通道中尋找出路的問題。本題設置的迷宮如圖1所示。 圖1 迷宮示意圖 迷宮四周設為墻;無填充處,為可通處。設每個點有四個可通方向,分別為東、南、西、北。左上角為入口。右下角為出口。迷宮有一個入口,一個出口。設計程序求解迷宮的一條通路。二、數據結構

2、設計以一個m×n的數組mg表示迷宮,每個元素表示一個方塊狀態,數組元素0和1分別表示迷宮中的通路和障礙。迷宮四周為墻,對應的迷宮數組的邊界元素均為1。根據題目中的數據,設置一個數組mg如下int mgM+2N+2=1,1,1,1,1,1,1,1,1,0,0,1,0,0,0,1,1,1,0,0,0,1,1,1,1,0,0,1,0,0,0,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1;在算法中用到的棧采用順序存儲結構,將棧定義為Struct int i; /當前方塊的行號 int j; /當前方塊的列號 int di; /di是下一個相鄰的可走的方位號stMaxSi

3、ze;/ 定義棧int top=-1 /初始化棧三、算法設計要尋找一條通過迷宮的路徑,就必須進行試探性搜索,只要有路可走就前進一步,無路可進,換一個方向進行嘗試;當所有方向均不可走時,則沿原路退回一步(稱為回溯),重新選擇未走過可走的路,如此繼續,直至到達出口或返回入口(沒有通路)。在探索前進路徑時,需要將搜索的蹤跡記錄下來,以便走不通時,可沿原路返回到前一個點換一個方向再進行新的探索。后退的嘗試路徑與前進路徑正好相反,因此可以借用一個棧來記錄前進路徑。方向:每一個可通點有4個可嘗試的方向,向不同的方向前進時,目的地的坐標不同。預先把4個方向上的位移存在一個數組中。如把上、右、下、左(即順時針

4、方向)依次編號為0、1、2、3.其增量數組move4如圖3所示。move4xy0-1010121030-1圖2數組move4方位示意圖如下: 通路:通路上的每一個點有3個屬性:一個橫坐標屬性i、一個列坐標屬性j和一個方向屬性di,表示其下一點的位置。如果約定嘗試的順序為上、右、下、左(即順時針方向),則每嘗試一個方向不通時,di值增1,當d增至4時,表示此位置一定不是通路上的點,從棧中去除。在找到出口時,棧中保存的就是一條迷宮通路。(1)下面介紹求解迷宮(xi,yj)到終點(xe,ye)的路徑的函數:先將入口進棧(其初始位置設置為1),在棧不空時循環取棧頂方塊(不退棧)若該方塊為出口,輸出所有

5、的方塊即為路徑,其代碼和相應解釋如下:int mgpath(int xi,int yi,int xe,int ye)/求解路徑為:(xi,yi)->(xe,ye)struct int i;/當前方塊的行號int j;/當前方塊的列號int di;/di是下一可走方位的方位號 stMaxSize;/定義棧int top=-1;/初始化棧指針int i,j,k,di,find;top+; /初始方塊進棧sttop.i=xi;sttop.j=yi;sttop.di=-1;mg11=-1; while (top>-1)/棧不空時循環i=sttop.i;j=sttop.j;di=sttop.

6、di; /取棧頂方塊if (i=xe && j=ye)/找到了出口,輸出路徑 printf("迷宮路徑如下:n");for (k=0;k<=top;k+)printf("t(%d,%d)",stk.i,stk.j);if (k+1)%5=0)/每輸出每5個方塊后換一行printf("n"); printf("n");return(1);/找到一條路徑后返回1否則,找下一個可走的相鄰方塊若不存在這樣的路徑,說明當前的路徑不可能走通,也就是恢復當前方塊為0后退棧。若存在這樣的方塊,則其方位保存在棧

7、頂元素中,并將這個可走的相鄰方塊進棧(其初始位置設置為-1) 求迷宮回溯過程如圖4所示從前一個方塊找到相鄰可走方塊之后,再從當前方塊找在、相鄰可走方塊,若沒有這樣的方快,說明當前方塊不可能是從入口路徑到出口路徑的一個方塊,則從當前方塊回溯到前一個方塊,繼續從前一個方塊找可走的方塊。 為了保證試探的可走的相鄰方塊不是已走路徑上的方塊,如(i,j)已經進棧,在試探(i+1,j)的下一方塊時,又試探道(i,j),這樣會很悲劇的引起死循環,為此,在一個方塊進棧后,將對應的mg數組元素的值改為-1(變為不可走的相鄰方塊),當退棧時(表示該方塊沒有相鄰的可走方塊),將其值恢復0,其算法代碼和相應的解釋如下

8、:find=0;while (di<4 && find=0)/找下一個可走方塊di+;switch(di)case 0:i=sttop.i-1;j=sttop.j;break;case 1:i=sttop.i;j=sttop.j+1;break;case 2:i=sttop.i+1;j=sttop.j;break;case 3:i=sttop.i,j=sttop.j-1;break;if (mgij=0) find=1;/找到下一個可走相鄰方塊if (find=1)/找到了下一個可走方塊sttop.di=di;/修改原棧頂元素的di值top+;/下一個可走方塊進棧stto

9、p.i=i;sttop.j=j;sttop.di=-1;mgij=-1;/避免重復走到該方塊else/沒有路徑可走,則退棧mgsttop.isttop.j=0;/讓該位置變為其他路徑可走方塊top-;/將該方塊退棧return(0);/表示沒有可走路徑,返回0(2)求解主程序 建立主函數調用上面的算法,將mg和st棧指針定義為全局變量void main()mgpath(1,1,M,N);四、界面設計設計很簡單的界面,輸出路徑。五、運行測試與分析圖5.基本運行結果六、實驗收獲與思考思考:8個方向的問題1.設計思想(1)設置一個迷宮節點的數據結構。(2)建立迷宮圖形。(3)對迷宮進行處理找出一條從

10、入口點到出口點的路徑。(4)輸出該路徑。(5)打印通路迷宮圖。初始化迷宮通過隨機方法設置迷宮布局建立并輸出迷宮原圖搜索迷宮通路輸出迷宮通路及路線圖結束圖6功能結構圖當迷宮采用二維數組表示時,老鼠在迷宮任一時刻的位置可由數組的行列序號i,j來表示。而從 i,j位置出發可能進行的方向見下圖7.如果i,j周圍的位置均為0值,則老鼠可以選擇這8個位置中的任一個作為它的下一位置。將這8個方向分別記作:E(東)、SE(東南)、S(南)SW(西南)W(西)、NW(西北)、N(北)和NE(東北)。但是并非每一個位置都有8個相鄰位置。如果i,j位于邊界上,即i=1,或i=m,或j=1,或j=n,則相鄰位置可能是

11、3個或5個為了避免檢查邊界條件,將數組四周圍用值為1的邊框包圍起來,這樣二維數組maze應該聲明為mazem+2,n+2在迷宮行進時,可能有多個行進方向可選,我們可以規定方向搜索的次序是從東(E)沿順時針方向進行。為了簡化問題,規定i,j的下一步位置的坐標是x,y,并將這8個方位傷的x和y坐標的增量預先放在一個結構數組move8中(見圖8)。該數組的每個分量有兩個域dx和dy。例如 要向東走,只要在j值上加上dy,就可以得到下一步位置的x,y值為i,j+dy。于是搜索方向的變化只要令方向值dir從0增至7,便可以從move數組中得到從i,j點出發搜索到的每一個相鄰點x,y。x=i+movedi

12、r.dxy=j+movedir.dy 圖7 方向位移圖 圖8向量差圖為了防止重走原路,我們規定對已經走過的位置,將原值為0改為-1,這既可以區別該位置是否已經走到過,又可以與邊界值1相區別。當整個搜索過程結束后可以將所有的-1改回到0,從而恢復迷宮原樣。這樣計算機走迷宮的方法是:采取一步一步試探的方法。每一步都從(E)開始,按順時針對8個方向進行探測,若某個方位上的mazex,y=0,表示可以通行,則走一步;若mazex,y=1,表示此方向不可通行須換方向再試。直至8個方向都試過,mazex,y均為1,說明此步已無路可走,需退回一步,在上一步的下一個方向重新開始探測。為此需要設置一個棧,用來記

13、錄所走過的位置和方向(i,j,dir)。當退回一步時,就從棧中退出一個元素,以便在上一個位置的下一個方向上探測,如又找到一個行進方向,則把當前位置和新的方向重新進棧,并走到新的位置。如果探測到x=m,y=n,則已經到達迷宮的出口,可以停止檢測,輸出存在棧中的路徑;若在某一位置的8個方向上都堵塞,則退回一步,繼續探測,如果已經退到迷宮的入口(棧中無元素),則表示此迷宮無路徑可通行。2系統算法(偽代碼描述):(1)建立迷宮節點的結構類型stack。(2)入迷宮圖形 0表示可以通 1表示不可以通。 用二維數組mazem+2n+2進行存儲。數組四周用1表示墻壁,其中入口點(1,1)與出口點(m,n)固

14、定。 (3)函數path()對迷宮進行處理,從入口開始:While(!(s->top=-1)&&(dir>=7)|(x=M)&&(y=N)&&(mazexy=-1) For(掃描八個可以走的方向) If(找到一個可以走的方向)進入棧標志在當前點可以找到一個可以走的方向避免重復選擇mazexy=-1不再對當前節點掃描 If(八個方向已經被全部掃描過,無可以通的路) 標志當前節點沒有往前的路 后退一個節點搜索If(找到了目的地) 輸出路徑退出循環 未找到路徑 (4)輸出從入口點到出口點的一條路徑。 (5)輸出標有通路的迷宮圖。3.算法流程

15、圖:開始初始化迷宮,顯示迷宮初始化方向位移數組尋找迷宮中的一條出路If mazexy=0設1,1為出口該點數據入棧TFWhile 棧不空且dir<7doelseIf dir<7dir+TF回退一步出口或入口dir>=7 或棧空顯示通路結束圖9 算法流程圖4.程序代碼:#define M2 12 /*M2*N2為實際使用迷宮數組的大小*/#define N2 11#define maxlen M2 / 棧長度#include <stdio.h>#include<iostream.h>#include <malloc.h>int M=M2-2,

16、N=N2-2;/M*N迷宮的大小typedef struct /定義棧元素的類型int x,y,dir;elemtype;typedef struct / 定義順序棧elemtype stack maxlen;int top;sqstktp; struct moved /定義方向位移數組的元素類型對于存儲坐標增量的方向位移數組move int dx,dy;/ void inimaze(int mazeN2)/初始化迷宮 int i,j,num; for(i=0,j=0;i<=M+1;i+)/設置迷宮邊界mazeij=1; for(i=0,j=0;j<=N+1;j+) mazeij=

17、1; for(i=M+1,j=0;j<=N+1;j+) mazeij=1; cout<<"原始迷宮為:"<<endl; for(i=1;i<=M;i+) for (j=1;j<=N;j+) num=(800*(i+j)+1500) % 327;/根據MN的值產生迷宮 if (num<150)&&(i!=M|j!=N) mazeij=1; else mazeij=0; cout<<mazeij<<" "/顯示迷宮 cout<<endl; cout<&l

18、t;endl; /inimaze/void inimove(struct moved move)/初始化方向位移數組/依次為East,Southeast,south,southwest,west,northwest,north,northeastmove0.dx=0;move0.dy=1;move1.dx=1;move1.dy=1;move2.dx=1;move2.dy=0;move3.dx=1;move3.dy=-1;move4.dx=0;move4.dy=-1;move5.dx=-1;move5.dy-=1;move6.dx=-1;move6.dy=0;move7.dx=-1;move7.

19、dy=1;/void inistack(sqstktp *s) /*初始化棧*/s->top=-1; /*inistack*/int push(sqstktp*s,elemtype x)if(s->top=maxlen-1)return(false);elses->stack+s->top=x;/*棧不滿,執行入棧操作*/return(true);/*push*/elemtype pop(sqstktp *s)/*棧頂元素出棧*/elemtype elem;if(s->top<0) /如果棧空,返回空值elem.x=NULL;elem.y=NULL;elem

20、.dir=NULL;return(elem);elses->top-;return(s->stacks->top+1); /棧不空,返回棧頂元素 /pop/void path(int mazeN2,struct moved move,sqstktp *s) /尋找迷宮中的一條通路int i,j,dir,x,y,f;elemtype elem;i=1;j=1;dir=0;maze11=-1; /設11為入口處do x=i+movedir.dx;/球下一步可行的到達點的坐標y=j+movedir.dy;if(mazexy=0)elem.x=i;elem.y=j;elem.dir=

21、dir;f=push(s,elem);/如果可行將數據入棧if(f=false)/如果返回假,說明棧容量不足cout<<"棧長不足"i=x;j=y;dir=0;mazexy=-1;elseif (dir < 7)dir+;elseelem=pop(s); /8個方向都不行,回退if(elem.x!=NULL)i=elem.x;j=elem.y;dir=elem.dir+1;while(!(s->top=-1)&&(dir>=7)|(x=M)&&(y=N)&&(mazexy=-1); /循環if(s

22、->top=-1)/若是入口,則無通路cout<<"此迷宮不通"elseelem.x=x; elem.y=y; elem.dir=dir;/將出口坐標入棧f=push(s,elem);cout<<"迷宮通路是:"<<endl;i=0;while (i <= s->top)cout<<"("<<s->stacki.x<<","<<s->stacki.y<<")"/顯示迷宮通路if(i!=s->top)cout<<"->"if(i+1)%4=0)cout<<

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論