1. 程式人生 > >C語言_迷宮的實現

C語言_迷宮的實現

#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);

}

測試結果:

這裡寫圖片描述