c語(yǔ)言實(shí)現(xiàn)迷宮問(wèn)題
《c語(yǔ)言實(shí)現(xiàn)迷宮問(wèn)題》由會(huì)員分享,可在線(xiàn)閱讀,更多相關(guān)《c語(yǔ)言實(shí)現(xiàn)迷宮問(wèn)題(19頁(yè)珍藏版)》請(qǐng)?jiān)谘b配圖網(wǎng)上搜索。
. 數(shù)據(jù)結(jié)構(gòu)試驗(yàn)——迷宮問(wèn)題 (一)基本問(wèn)題 1.問(wèn)題描述 這是心理學(xué)中的一個(gè)經(jīng)典問(wèn)題。心理學(xué)家把一只老鼠從一個(gè)無(wú)頂蓋的大盒子的入口處放入,讓老鼠自行找到出口出來(lái)。迷宮中設(shè)置很多障礙阻止老鼠前行,迷宮唯一的出口處放有一塊奶酪,吸引老鼠找到出口。 簡(jiǎn)而言之,迷宮問(wèn)題是解決從布置了許多障礙的通道中尋找出路的問(wèn)題。本題設(shè)置的迷宮如圖1所示。 圖1 迷宮示意圖 迷宮四周設(shè)為墻;無(wú)填充處,為可通處。設(shè)每個(gè)點(diǎn)有四個(gè)可通方向,分別為東、南、西、北(為了清晰,以下稱(chēng)“上下左右”)。左上角為入口。右下角為出口。迷宮有一個(gè)入口,一個(gè)出口。設(shè)計(jì)程序求解迷宮的一條通路。 2.數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì) 以一個(gè)mn的數(shù)組mg表示迷宮,每個(gè)元素表示一個(gè)方塊狀態(tài),數(shù)組元素0和1分別表示迷宮中的通路和障礙。迷宮四周為墻,對(duì)應(yīng)的迷宮數(shù)組的邊界元素均為1。根據(jù)題目中的數(shù)據(jù),設(shè)置一個(gè)數(shù)組mg如下 int mg[M+2][N+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} };在算法中用到的棧采用順序存儲(chǔ)結(jié)構(gòu),將棧定義為 Struct { int i; //當(dāng)前方塊的行號(hào) int j; //當(dāng)前方塊的列號(hào) int di; //di是下一個(gè)相鄰的可走的方位號(hào) }st[MaxSize];// 定義棧 int top=-1 //初始化棧 3設(shè)計(jì)運(yùn)算算法 要尋找一條通過(guò)迷宮的路徑,就必須進(jìn)行試探性搜索,只要有路可走就前進(jìn)一步,無(wú)路可進(jìn),換一個(gè)方向進(jìn)行嘗試;當(dāng)所有方向均不可走時(shí),則沿原路退回一步(稱(chēng)為回溯),重新選擇未走過(guò)可走的路,如此繼續(xù),直至到達(dá)出口或返回入口(沒(méi)有通路)。在探索前進(jìn)路徑時(shí),需要將搜索的蹤跡記錄下來(lái),以便走不通時(shí),可沿原路返回到前一個(gè)點(diǎn)換一個(gè)方向再進(jìn)行新的探索。后退的嘗試路徑與前進(jìn)路徑正好相反,因此可以借用一個(gè)棧來(lái)記錄前進(jìn)路徑。 方向:每一個(gè)可通點(diǎn)有4個(gè)可嘗試的方向,向不同的方向前進(jìn)時(shí),目的地的坐標(biāo)不同。預(yù)先把4個(gè)方向上的位移存在一個(gè)數(shù)組中。如把上、右、下、左(即順時(shí)針?lè)较颍┮来尉幪?hào)為0、1、2、3.其增量數(shù)組move[4]如圖3所示。 move[4] x y 0 -1 0 1 0 1 2 1 0 3 0 -1 圖2數(shù)組move[4] 方位示意圖如下: 通路:通路上的每一個(gè)點(diǎn)有3個(gè)屬性:一個(gè)橫坐標(biāo)屬性i、一個(gè)列坐標(biāo)屬性j和一個(gè)方向?qū)傩詃i,表示其下一點(diǎn)的位置。如果約定嘗試的順序?yàn)樯稀⒂?、下、左(即順時(shí)針?lè)较颍?,則每嘗試一個(gè)方向不通時(shí),di值增1,當(dāng)d增至4時(shí),表示此位置一定不是通路上的點(diǎn),從棧中去除。在找到出口時(shí),棧中保存的就是一條迷宮通路。 (1)下面介紹求解迷宮(xi,yj)到終點(diǎn)(xe,ye)的路徑的函數(shù):先將入口進(jìn)棧(其初始位置設(shè)置為—1),在棧不空時(shí)循環(huán)——取棧頂方塊(不退棧)①若該方塊為出口,輸出所有的方塊即為路徑,其代碼和相應(yīng)解釋如下: int mgpath(int xi,int yi,int xe,int ye) //求解路徑為:(xi,yi)->(xe,ye) { struct { int i; //當(dāng)前方塊的行號(hào) int j; //當(dāng)前方塊的列號(hào) int di; //di是下一可走方位的方位號(hào) } st[MaxSize]; //定義棧 int top=-1; //初始化棧指針 int i,j,k,di,find; top++; //初始方塊進(jìn)棧 st[top].i=xi;st[top].j=yi; st[top].di=-1;mg[1][1]=-1; while (top>-1) //棧不空時(shí)循環(huán) { i=st[top].i;j=st[top].j;di=st[top].di; //取棧頂方塊 if (i==xe && j==ye) //找到了出口,輸出路徑 { printf("迷宮路徑如下:\n"); for (k=0;k<=top;k++) { printf("\t(%d,%d)",st[k].i,st[k].j); if ((k+1)%5==0) //每輸出每5個(gè)方塊后換一行 printf("\n"); } printf("\n"); return(1); //找到一條路徑后返回1 } ②否則,找下一個(gè)可走的相鄰方塊若不存在這樣的路徑,說(shuō)明當(dāng)前的路徑不可能走通,也就是恢復(fù)當(dāng)前方塊為0后退棧。若存在這樣的方塊,則其方位保存在棧頂元素中,并將這個(gè)可走的相鄰方塊進(jìn)棧(其初始位置設(shè)置為-1) 求迷宮回溯過(guò)程如圖4所示 從前一個(gè)方塊找到相鄰可走方塊之后,再?gòu)漠?dāng)前方塊找在、相鄰可走方塊,若沒(méi)有這樣的方快,說(shuō)明當(dāng)前方塊不可能是從入口路徑到出口路徑的一個(gè)方塊,則從當(dāng)前方塊回溯到前一個(gè)方塊,繼續(xù)從前一個(gè)方塊找可走的方塊。 為了保證試探的可走的相鄰方塊不是已走路徑上的方塊,如(i,j)已經(jīng)進(jìn)棧,在試探(i+1,j)的下一方塊時(shí),又試探道(i,j),這樣會(huì)很悲劇的引起死循環(huán),為此,在一個(gè)方塊進(jìn)棧后,將對(duì)應(yīng)的mg數(shù)組元素的值改為-1(變?yōu)椴豢勺叩南噜彿綁K),當(dāng)退棧時(shí)(表示該方塊沒(méi)有相鄰的可走方塊),將其值恢復(fù)0,其算法代碼和相應(yīng)的解釋如下: find=0; while (di<4 && find==0) //找下一個(gè)可走方塊 { di++; switch(di) { case 0:i=st[top].i-1;j=st[top].j;break; case 1:i=st[top].i;j=st[top].j+1;break; case 2:i=st[top].i+1;j=st[top].j;break; case 3:i=st[top].i,j=st[top].j-1;break; } if (mg[i][j]==0) find=1;//找到下一個(gè)可走相鄰方塊 } if (find==1) //找到了下一個(gè)可走方塊 { st[top].di=di; //修改原棧頂元素的di值 top++; //下一個(gè)可走方塊進(jìn)棧 st[top].i=i;st[top].j=j;st[top].di=-1; mg[i][j]=-1; //避免重復(fù)走到該方塊 } else //沒(méi)有路徑可走,則退棧 { mg[st[top].i][st[top].j]=0;//讓該位置變?yōu)槠渌窂娇勺叻綁K top--; //將該方塊退棧 } } return(0); //表示沒(méi)有可走路徑,返回0 (2)求解主程序 建立主函數(shù)調(diào)用上面的算法,將mg和st棧指針定義為全局變量 void main() { mgpath(1,1,M,N); } 3界面設(shè)計(jì) 設(shè)計(jì)很簡(jiǎn)單的界面,輸出路徑 4運(yùn)行結(jié)果 圖5。基本運(yùn)行結(jié)果 (二)8個(gè)方向的問(wèn)題 1.設(shè)計(jì)思想 (1)設(shè)置一個(gè)迷宮節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)。 (2)建立迷宮圖形。 (3)對(duì)迷宮進(jìn)行處理找出一條從入口點(diǎn)到出口點(diǎn)的路徑。 (4)輸出該路徑。 (5)打印通路迷宮圖。 初始化迷宮 通過(guò)隨機(jī)方法設(shè)置迷宮布局 建立并輸出迷宮原圖 搜索迷宮通路 輸出迷宮通路及路線(xiàn)圖 結(jié)束 圖6功能結(jié)構(gòu)圖 當(dāng)迷宮采用二維數(shù)組表示時(shí),老鼠在迷宮任一時(shí)刻的位置可由數(shù)組的行列序號(hào)i,j來(lái)表示。而從 [i],[j]位置出發(fā)可能進(jìn)行的方向見(jiàn)下圖7.如果[i],[j]周?chē)奈恢镁鶠?值,則老鼠可以選擇這8個(gè)位置中的任一個(gè)作為它的下一位置。將這8個(gè)方向分別記作:E(東)、SE(東南)、S(南)SW(西南)W(西)、NW(西北)、N(北)和NE(東北)。但是并非每一個(gè)位置都有8個(gè)相鄰位置。如果[i],[j]位于邊界上,即i=1,或i=m,或j=1,或j=n,則相鄰位置可能是3個(gè)或5個(gè)為了避免檢查邊界條件,將數(shù)組四周?chē)弥禐?的邊框包圍起來(lái),這樣二維數(shù)組maze應(yīng)該聲明為maze[m+2],[n+2]在迷宮行進(jìn)時(shí),可能有多個(gè)行進(jìn)方向可選,我們可以規(guī)定方向搜索的次序是從東(E)沿順時(shí)針?lè)较蜻M(jìn)行。為了簡(jiǎn)化問(wèn)題,規(guī)定[i],[j]的下一步位置的坐標(biāo)是[x],[y],并將這8個(gè)方位傷的x和y坐標(biāo)的增量預(yù)先放在一個(gè)結(jié)構(gòu)數(shù)組move[8]中(見(jiàn)圖8)。該數(shù)組的每個(gè)分量有兩個(gè)域dx和dy。例如 要向東走,只要在j值上加上dy,就可以得到下一步位置的[x],[y]值為[i],[j+dy]。于是搜索方向的變化只要令方向值dir從0增至7,便可以從move數(shù)組中得到從[i],[j]點(diǎn)出發(fā)搜索到的每一個(gè)相鄰點(diǎn)[x],[y]。 x=i+move[dir].dx y=j+move[dir].dy dx dy 圖7 方向位移圖 圖8向量差圖 為了防止重走原路,我們規(guī)定對(duì)已經(jīng)走過(guò)的位置,將原值為0改為-1,這既可以區(qū)別該位置是否已經(jīng)走到過(guò),又可以與邊界值1相區(qū)別。當(dāng)整個(gè)搜索過(guò)程結(jié)束后可以將所有的-1改回到0,從而恢復(fù)迷宮原樣。 這樣計(jì)算機(jī)走迷宮的方法是:采取一步一步試探的方法。每一步都從(E)開(kāi)始,按順時(shí)針對(duì)8個(gè)方向進(jìn)行探測(cè),若某個(gè)方位上的maze[x],[y]=0,表示可以通行,則走一步;若maze[x],[y]=1,表示此方向不可通行須換方向再試。直至8個(gè)方向都試過(guò),maze[x],[y]均為1,說(shuō)明此步已無(wú)路可走,需退回一步,在上一步的下一個(gè)方向重新開(kāi)始探測(cè)。為此需要設(shè)置一個(gè)棧,用來(lái)記錄所走過(guò)的位置和方向(i,j,dir)。 當(dāng)退回一步時(shí),就從棧中退出一個(gè)元素,以便在上一個(gè)位置的下一個(gè)方向上探測(cè),如又找到一個(gè)行進(jìn)方向,則把當(dāng)前位置和新的方向重新進(jìn)棧,并走到新的位置。如果探測(cè)到x=m,y=n,則已經(jīng)到達(dá)迷宮的出口,可以停止檢測(cè),輸出存在棧中的路徑;若在某一位置的8個(gè)方向上都堵塞,則退回一步,繼續(xù)探測(cè),如果已經(jīng)退到迷宮的入口(棧中無(wú)元素),則表示此迷宮無(wú)路徑可通行。 2系統(tǒng)算法(偽代碼描述): (1)建立迷宮節(jié)點(diǎn)的結(jié)構(gòu)類(lèi)型stack[]。 (2)入迷宮圖形 0表示可以通 1表示不可以通。 用二維數(shù)組maze[m+2][n+2]進(jìn)行存儲(chǔ)。 數(shù)組四周用1表示墻壁,其中入口點(diǎn)(1,1)與出口點(diǎn)(m,n)固定。 (3)函數(shù)path()對(duì)迷宮進(jìn)行處理,從入口開(kāi)始: While(!((s->top==-1)&&(dir>=7)||(x==M)&&(y==N)&&(maze[x][y]==-1))) { For(掃描八個(gè)可以走的方向) { If(找到一個(gè)可以走的方向) { 進(jìn)入棧 標(biāo)志在當(dāng)前點(diǎn)可以找到一個(gè)可以走的方向 避免重復(fù)選擇maze[x][y]=-1 不再對(duì)當(dāng)前節(jié)點(diǎn)掃描 } If(八個(gè)方向已經(jīng)被全部掃描過(guò),無(wú)可以通的路) { 標(biāo)志當(dāng)前節(jié)點(diǎn)沒(méi)有往前的路 后退一個(gè)節(jié)點(diǎn)搜索 } } If(找到了目的地) { 輸出路徑退出循環(huán) } } 未找到路徑 (4)輸出從入口點(diǎn)到出口點(diǎn)的一條路徑。 (5)輸出標(biāo)有通路的迷宮圖。 3.算法流程圖: 開(kāi)始 初始化迷宮,顯示迷宮 初始化方向位移數(shù)組 尋找迷宮中的一條出路 If maze[x][y]==0 設(shè)1,1為出口 該點(diǎn)數(shù)據(jù)入棧 T F While 棧不空且dir<7 do elseIf dir<7 dir++ T F 回退一步 出口或入口 dir>=7 或??? 顯示通路 結(jié)束 圖9 算法流程圖 4.程序代碼: #define M2 12 /*M2*N2為實(shí)際使用迷宮數(shù)組的大小*/ #define N2 11 #define maxlen M2 // 棧長(zhǎng)度 #include- 1.請(qǐng)仔細(xì)閱讀文檔,確保文檔完整性,對(duì)于不預(yù)覽、不比對(duì)內(nèi)容而直接下載帶來(lái)的問(wèn)題本站不予受理。
- 2.下載的文檔,不會(huì)出現(xiàn)我們的網(wǎng)址水印。
- 3、該文檔所得收入(下載+內(nèi)容+預(yù)覽)歸上傳者、原創(chuàng)作者;如果您是本文檔原作者,請(qǐng)點(diǎn)此認(rèn)領(lǐng)!既往收益都?xì)w您。
下載文檔到電腦,查找使用更方便
10 積分
下載 |
- 配套講稿:
如PPT文件的首頁(yè)顯示word圖標(biāo),表示該P(yáng)PT已包含配套word講稿。雙擊word圖標(biāo)可打開(kāi)word文檔。
- 特殊限制:
部分文檔作品中含有的國(guó)旗、國(guó)徽等圖片,僅作為作品整體效果示例展示,禁止商用。設(shè)計(jì)者僅對(duì)作品中獨(dú)創(chuàng)性部分享有著作權(quán)。
- 關(guān) 鍵 詞:
- c語(yǔ)言實(shí)現(xiàn) 迷宮問(wèn)題 語(yǔ)言 實(shí)現(xiàn) 迷宮 問(wèn)題
鏈接地址:http://m.appdesigncorp.com/p-12826867.html