C語言_迷宮的實現
阿新 • • 發佈:2018-11-04
#1、單條通路迷宮
實現思路:
程式碼如下:
標頭檔案maze.h
#ifndef __MAZE_H__ #define __MAZE_H__ #include <assert.h> #include <stdio.h> #include <stdlib.h> #define H 5 #define L 5 #define MAX_SIZE 100 typedef struct position { int x; int y; }position; typedef struct Maze { int _Map[H][L]; }Maze; typedef position DataType; typedef struct stack { DataType data[MAX_SIZE]; int top; }Stack; ///////////////////////////////////////////////////////// ////棧操作 void InitStack (Stack *p); //初始化棧 void PushStack (Stack *p, DataType d); //入棧 void PopStack (Stack *p); // 出棧 DataType TopNumAndTop (Stack *p); //返回棧頂元素然後出棧 int IsEmpty (Stack *p); // 判空 int StackSize (Stack* p); //返回棧的大小 ////////////////////////////////////////////////////////// //////迷宮操作 void InitMaze (Maze* maze, int arr[H][L]);//初始化迷宮地圖 void PrintMap (Maze maze);//列印迷宮 int IsEntry (Maze *maze, position *entry);//判斷迷宮是否合法,合法返回1,否則返回0 void RunInMaze (Maze *maze, position *entry);//走迷宮 int IsPositionOk (Maze* maze, position *pos);//判斷當前位置是否為通路 int IsExit(Maze* maze, position *entry, position *cur);//判斷是否為出口 #endif
主演函式main.c
#include "maze.h" /////////////////////////////////////////////////////////////// //棧操作 void InitStack (Stack *p) //初始化 { assert (p != NULL); p->top = 0; } void PushStack (Stack *p, DataType d) //入棧 { assert (p); if (p->top == MAX_SIZE) { printf ("棧滿,無法入棧!!!\n"); return; } p->data[p->top] = d; p->top++; } int IsEmpty (Stack *p) // 判空 { return (p->top == 0);//如果為空,返回1;如果不為空,返回0 } void PopStack (Stack *p)//出棧 { assert (p); if (p->top == 0) { printf ("棧空,操作失敗!!!\n"); return; } p->top --; } DataType TopNumAndTop (Stack *p) //返回棧頂元素(出棧) { if (p->top == 0) { printf ("棧為空!!\n"); return ; } return p->data[--(p->top)]; } int StackSize (Stack* p)//返回棧的大小 { return p->top; } //////////////////////////////////////////////////////////////// //單條通路迷宮操作 void InitMaze (Maze* maze,int arr[H][L]) //初始化迷宮 { int i = 0; int j = 0; for (i=0; i<H; i++) { for (j=0; j<L; j++) { maze->_Map[i][j] = arr[i][j]; } } } void PrintMap (Maze maze) //列印迷宮 { int i = 0; int j = 0; for (i=0; i<H; i++) { for (j=0; j<L; j++) { printf ("%d\t", maze._Map[i][j]); } printf ("\n\n\n"); } } int IsEntry (Maze *maze, position *entry) //判斷是否是迷宮入口 { if (entry->x == 0 || entry ->x == H-1 || entry->y == 0 || entry->y == L-1) { if (maze->_Map[entry->x][entry->y] == 1) { return 1; } } return 0; } int IsPositionOk (Maze* maze, position *pos) //判斷迷宮當前位置是否是通路 { assert (pos != NULL); if (pos->x >= 0 && pos->x < H && pos ->y >= 0 && pos ->y < L) { if (maze->_Map[pos->x][pos->y] == 1) { return 1; } } return 0; } int IsExit(Maze* maze, position *entry, position *cur)//判斷是否為出口 { assert (maze != NULL && entry != NULL && cur != NULL); if (cur->x == 0 || cur ->x == H-1 || cur->y == 0 || cur->y == L-1) { if (maze->_Map[cur->x][cur->y] == 2 && cur->x != entry->x && cur->y != entry->y) { return 1; } } return 0; } void RunInMaze (Maze *maze, position *entry)//走迷宮 { position *cur = NULL; position next ; Stack s; InitStack (&s); assert (maze != NULL && entry != NULL); if (IsEntry (maze, entry) == 0) { printf ("入口非法!!!\n"); return; } //入口合法 cur = entry; maze->_Map[cur->x][cur->y] = 2; next.x = cur->x; next.y = cur->y; PushStack (&s, next); while (!IsEmpty(&s) && !IsExit(maze, entry, &next)) { //上 next.x --; if(IsPositionOk (maze, &next) == 1)//位置合法 { maze->_Map[next.x][next.y] = 2; PushStack (&s, next); continue; } //左 next .x ++; next.y --; if(IsPositionOk (maze, &next) == 1)//位置合法 { maze->_Map[next.x][next.y] = 2; PushStack (&s, next); continue; } //右 next.y++; next.y ++; if(IsPositionOk (maze, &next) == 1)//位置合法 { maze->_Map[next.x][next.y] = 2; PushStack (&s, next); continue; } //下 next.y--; next.x ++; if(IsPositionOk (maze, &next) == 1)//位置合法 { maze->_Map[next.x][next.y] = 2; PushStack (&s, next); continue; } //四個方向都不合法,座標出棧,回退 next = TopNumAndTop (&s); } if (IsEmpty(&s) == 1) { printf ("迷宮無出口!!\n"); } else { printf ("迷宮已走完!!!\n"); } }
測試程式碼:
test.c
#include "maze.h" void test_1() { Maze maze; position entry ; int arr[H][L] = { {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 1, 1, 1, 1}, {0, 1, 0, 0, 0}, {0, 1, 0, 0, 0}, }; InitMaze (&maze, arr); PrintMap (maze); entry.x = H-1; entry.y = 1; RunInMaze (&maze, &entry); PrintMap (maze); } int main() { test_1(); system ("pause"); return 0; }
測試結果:
#2、多條通路的迷宮
對於多條通路的迷宮,和上面的一種相比,只是多了幾個出口,所以在遇到出口時,只需要將出口值賦為0,將出口堵死,知道棧為空時,迷宮走完所有通路
所以走迷宮的函式為(其餘函式和上一個的一樣):
void RunInMaze (Maze *maze, position *entry)//走迷宮
{
position* cur = NULL;
position next ;
Stack s;
InitStack (&s);
assert (maze != NULL && entry != NULL);
cur = entry;
if (0 == IsEntry (maze, entry))
{
printf ("非法入口!!!\n");
return ;
}
maze->_Map[cur->x][cur->y] = 2;
next.x = cur->x;
next.y = cur->y;
PushStack (&s, next);
while (!IsEmpty (&s))
{
//如果走到出口,將出口值賦為0,回退
if (1 == IsExit(maze, entry, &next))
{
maze->_Map[next.x][next.y] = 0;
next = TopNumAndTop (&s);
}
//上
next.x --;
if(IsPositionOk (maze, &next) == 1)//位置合法
{
/*cur = &next;*/
maze->_Map[next.x][next.y] = 2;
PushStack (&s, next);
continue;
}
next .x ++;
//左
next.y --;
if(IsPositionOk (maze, &next) == 1)//位置合法
{
/*cur = &next;*/
maze->_Map[next.x][next.y] = 2;
PushStack (&s, next);
continue;
}
next.y++;
//右
next.y ++;
if(IsPositionOk (maze, &next) == 1)//位置合法
{
/*cur = &next;*/
maze->_Map[next.x][next.y] = 2;
PushStack (&s, next);
continue;
}
next.y--;
//下
next.x ++;
if(IsPositionOk (maze, &next) == 1)//位置合法
{
/*cur = &next;*/
maze->_Map[next.x][next.y] = 2;
PushStack (&s, next);
continue;
}
//上下左右都不能走,出棧回退
next = TopNumAndTop (&s);
}
printf ("迷宮已經走完!!!\n");
}
測試結果:
#3、帶環的迷宮:
帶環迷宮和之前的也不一樣,標記方式改為每走一步就把值賦為前一步加一,判斷下一步的方式也有所改變,程式碼如下:
void InitMaze (Maze* maze,int arr[H][L])
{
int i = 0;
int j = 0;
for (i=0; i<H; i++)
{
for (j=0; j<L; j++)
{
maze->_Map[i][j] = arr[i][j];
}
}
}
void PrintMap (Maze maze)
{
int i = 0;
int j = 0;
for (i=0; i<H; i++)
{
for (j=0; j<L; j++)
{
printf ("%d\t", maze._Map[i][j]);
}
printf ("\n\n\n");
}
}
int IsEntry (Maze *maze, position *entry)
{
if (entry->x == 0 || entry ->x == H-1 || entry->y == 0 || entry->y == L-1)
{
if (maze->_Map[entry->x][entry->y] == 1)
{
return 1;
}
}
return 0;
}
int IsPositionOk (Maze* maze, position *pos, position *next)
{
assert (pos != NULL);
if (next->x >= 0 && next->x < H && next ->y >= 0 && next ->y < L)
{
if (maze->_Map[next->x][next->y] == 1 || maze->_Map[next->x][next->y] > maze->_Map[pos->x][pos->y])
{
return 1;
}
}
return 0;
}
int IsExit(Maze* maze, position *entry, position *cur)//判斷是否為出口
{
assert (maze != NULL && entry != NULL && cur != NULL);
if (cur->x == 0 || cur ->x == H-1 || cur->y == 0 || cur->y == L-1)
{
if (cur->x != entry->x && cur->y != entry->y)
{
return 1;
}
}
return 0;
}
Stack* GetShortPath(Stack* path, Stack* short_path)
{
if (StackSize (short_path) == 0 || StackSize (path) < StackSize (short_path))
{
int i = 0;
for ( ;i<StackSize (path); i++)
{
short_path->data[i] = path->data[i];
}
short_path->top = path->top;
}
return short_path;
}
void RunInMaze (Maze *maze, position cur, position* entry, Stack* path, Stack* short_path)//走迷宮---其中maze為迷宮,cur 為 當前所在位
//置,entry 為入口位置,path 為當前正在走的路徑,short_path為較短路徑
{
position up, down, left, right;
assert (maze != NULL && entry != NULL);
//不是出口,繼續往上左右下四個方向走
//上
up = cur;
up.x --;
if(IsPositionOk (maze, &cur, &up) == 1)//位置合法
{
PushStack (path, up); //入棧
//判斷當前是否為出口
if (IsExit (maze, entry, &up) == 1)//是出口
{
maze->_Map[up.x][up.y] = maze->_Map[cur.x][cur.y]+1; //標記
short_path = GetShortPath (path, short_path); //獲取最短路徑
cur = TopNumAndTop (path); //往回退,查詢其他路徑
return;
}
maze->_Map[up.x][up.y] = maze->_Map[cur.x][cur.y]+1; //標記
RunInMaze (maze, up, entry, path, short_path);
}
//左
left = cur;
left.y --;
if(IsPositionOk (maze, &cur, &left) == 1)//位置合法
{
PushStack (path, left); //入棧
//判斷當前是否為出口
if (IsExit (maze, entry, &left) == 1)//是出口
{
maze->_Map[left.x][left.y] = maze->_Map[cur.x][cur.y]+1; //標記
short_path = GetShortPath (path, short_path); //獲取最短路徑
cur = TopNumAndTop (path); //往回退,查詢其他路徑
return;
}
maze->_Map[left.x][left.y] = maze->_Map[cur.x][cur.y]+1; //標記
RunInMaze (maze, left, entry, path, short_path);
}
//右
right = cur;
right.y ++;
if(IsPositionOk (maze, &cur, &right) == 1)//位置合法
{
PushStack (path, right); //入棧
//判斷當前是否為出口
if (IsExit (maze, entry, &right) == 1)//是出口
{
maze->_Map[right.x][right.y] = maze->_Map[cur.x][cur.y]+1; //標記
short_path = GetShortPath (path, short_path); //獲取最短路徑
cur = TopNumAndTop (path); //往回退,查詢其他路徑
return;
}
maze->_Map[right.x][right.y] = maze->_Map[cur.x][cur.y]+1; //標記
RunInMaze (maze, right, entry, path, short_path);
}
//下
down = cur;
down.x ++;
if(IsPositionOk (maze, &cur, &down) == 1)//位置合法
{
PushStack (path, down); //入棧
//判斷當前是否為出口
if (IsExit (maze, entry, &down) == 1)//是出口
{
maze->_Map[down.x][down.y] = maze->_Map[cur.x][cur.y]+1; //標記
short_path = GetShortPath (path, short_path); //獲取最短路徑
cur = TopNumAndTop (path); //往回退,查詢其他路徑
return;
}
maze->_Map[down.x][down.y] = maze->_Map[cur.x][cur.y]+1; //標記
RunInMaze (maze, down, entry, path, short_path);
}
//四個方向都探測過,出棧回退
cur = TopNumAndTop (path);
}
測試結果: