C语言迷宫求解

#pragma once
#include<stddef.h>
#define FOR_MAZE
//#ifdef FOR_MAZE
//typedef struct Point{
//	int row;
//	int col;
//}Point;
typedef Point SeqStackType;
//#else
//typedef char SeqStackType;
//#endif
#define SEQ_STACK_SIZE 100
typedef struct SeqStck
{
	SeqStackType data[SEQ_STACK_SIZE];
	size_t size;
}SeqStack;
void SeqStackInit(SeqStack *stack);
void SeqStackDestory(SeqStack* stack);
void SeqStackPush(SeqStack* stack, SeqStackType value);
void SeqStackPop(SeqStack *stack);
SeqStackType SeqStackTop(SeqStack* stack);
size_t SeqStackSize(SeqStack *stack);
void SeqStackAssign(SeqStack *from, SeqStack *to);

#define _CRT_SECURE_NO_WARNINGS 1

#include<Windows.h>
#include"maze.h"
#include<stdio.h>
//#include"seqstack.h"
#include<string.h>
#define MAZE_COL 6
#define  MAZE_ROM 6
#define SEQ_STACK_SIZE 100
#ifdef FOR_MAZE
typedef Point  SeqStackType;
#else
typedef char SeqStackType;
#endif
typedef struct Maze{
	int map[MAZE_COL][MAZE_ROM];
}Maze;
typedef struct Point{
	int row;
	int col;
}Point;


void SeqStackInit(SeqStack *stack)
{
	if (stack == NULL)
	{
		return;
	}
	stack->size = 0;
}
void SeqStackDestory(SeqStack* stack)
{
	if (stack == NULL)
	{
		return;
	}
	stack->size = 0;
}
void SeqStackPush(SeqStack* stack, SeqStackType value)
{
	if (stack == NULL)
	{
		stack->data[stack->size++] = value;
		return;
	}
	if (stack->size >= SEQ_STACK_SIZE)
	{
		return;
	}
	else
	{
		stack->data[stack->size++] = value;
	}
}
void SeqStackPop(SeqStack *stack)
{
	if (stack == NULL)
	{
		return;
	}
	if (stack->size == 0)
	{
		return;
	}
	else
	{
		stack->data[stack->size--] = 0;
	}
}
//SeqStackType  SeqStackTop(SeqStack* stack)
//{
//	if (stack == NULL)
//	{
//		return 0;
//	}
//	if (stack->size == 0)
//	{
//		return 0;
//	}
//	SeqStackType value = stack->data[stack->size];
//	return value;
//}
size_t SeqStackSize(SeqStack *stack)
{
	if (stack == NULL)
	{
		return 0;
	}
	return stack->size;
}
//赋值操作
void SeqStackAssign(SeqStack *from, SeqStack *to)
{
	if (from == NULL || to == NULL)
	{
		return;
	}
	/*size_t i = 0;
	to->size = from->size;
	for (; i < from->size; i++)
	{
	to->data[i] = from->data[i];
	}*/
	memcpy(to, from, sizeof(SeqStack));//malloc申请的空间不能使用该函数
}
void SeqStackPrintfChar(SeqStack *stack, const char* msg)
{
	size_t i = 0;
	printf("*++++++++*++++++++*++++++++*++++++++*++++++++*++++++++*");
	if (stack == NULL)
	{
		printf("stack is NULL");
		return;
	}
	printf("栈底[%s]:", msg);
	SeqStack*cur = stack;
	for (; i<cur->size; ++i)
	{
		printf("[%c]->", cur->data[i]);
	}
	printf("[栈顶]");
	printf("\n");


}


void MazeInit(Maze* maze)
{
	if (maze == NULL)
	{
		return;
	}
	int map[MAZE_COL][MAZE_ROM] = { 
	{ 0, 1, 0, 0, 0, 0 },
	{ 0, 1, 1, 1, 0, 0 }, 
	{ 0, 1, 0, 1, 1, 0 },
	{ 0, 1, 1, 0, 0, 0 },
	{ 0, 0, 1, 1, 0, 0 }, 
	{ 0, 0, 0, 1, 0, 0 } };
	size_t i = 0;
	for (; i < MAZE_COL; i++)
	{
		size_t j = 0;
		for (; j < MAZE_ROM; j++)
		{
			maze->map[i][j] = map[i][j];
		}
	}
}
void MazePrint(Maze*maze)
{
	if (maze == NULL)
	{
		return;
	}
	size_t i = 0;
	for (; i < MAZE_COL; i++)
	{
		size_t j = 0;
		for (; j < MAZE_ROM; j++)
		{
			printf("%2d", maze->map[i][j]);//左右对齐问题
		}
		printf("\n");//每一行的所有列完成
	}
	printf("\n");
}
int PointInMap(Point cur)
{
	if (cur.col < 0 || cur.col >= MAZE_COL || cur.row < 0 || cur.row >= MAZE_ROM)
		return 0;
	else
		return 1;
}
int CanStay(Maze*maze, Point cur)
{
	//1.点在地图上
	if (!PointInMap(cur))
	{
		return 0;
	}
	//2.当前点对应的值为1
	if (maze->map[cur.row][cur.col] == 1)
	{
		return 1;
	}
	return 0;
}
void Mark(Maze* maze, Point cur)//标记走过的点
{
	//if (maze == NULL)//如果在其他场景下调用需要判断
	//{
	//	return;
	//}
	maze->map[cur.row][cur.col] = 2;
}
int IsExit(Point cur, Point entry)//判定是否是出口
{
	//点在地图边缘。不是入口
	
	
	if (cur.col == 0 || cur.col == MAZE_COL - 1 || cur.row == 0 || cur.row == MAZE_ROM - 1)//在边缘
	{


		if (cur.row == entry.row&&cur.col == entry.col)//是入口
		{
			return 0;
		}
		return 1;
	}
	return 0;
}
void _HasPath(Maze* maze, Point cur, Point entry)
{
	//1.判定当前点能否落脚(点在地图上,位置为一)
	if (!CanStay(maze, cur))
	{
	return;
	}
	//2.标记走过的点
	Mark(maze, cur);
	//3.判断当前点是否是出口(落在边缘且不为入口)
	if (IsExit(cur,entry))
	{
	printf("找到路了\n");
	return;
	}
	//4.按照顺时针方向探测周围的临界点(递归调用haspath)
	Point up = cur;
	up.row -= 1;//根据地图来上下移动
	_HasPath(maze, up,entry);
	Point right = cur;
	right.col += 1;
	_HasPath(maze, right,entry);
	Point down = cur;
	down.row += 1;
	_HasPath(maze, down,entry);
	Point left = cur;
	up.col -= 1;
	_HasPath(maze, left,entry);
	//5.如果是个方向都探测过了,就直接返回
	return;
}
//使用递归方式查找迷宫是否有路径
void HasPath(Maze* maze, Point entry)//*maze用到地址是为了提高效率,还要修改地址
{
	if (maze == NULL)
	{
		return;
	}
	_HasPath(maze,entry,entry);
	return;
}
//非递归的解决简单迷宫
void HasPathByLoop(Maze* maze, Point entry)
{
	if (maze == NULL)
	{
		return;
	}
	//1.判断入口点是否能落脚
	if (!CanStay(maze, entry))
	{
		return;
	}
	//2.标记走过的入口点,并且将入口点入栈
	Mark(maze, entry);
	SeqStack stack;
	SeqStackInit(&stack);
	SeqStackPush(&stack,entry);


	//3.进入循环,取栈顶元素为入口点
	Point cur;
	while (SeqStackTop(&stack, &cur))
	{
		//4.判定是不是出口
		if (IsExit(cur, entry))
		{
			printf("找到路了\n");
			return;
		}


		//5.按照一定的顺序判断当前点的临界点是否能落脚
		Point up = cur;
		up.row -= 1;
		//6.如果某一个临界点能够落脚,标记此点并入栈,直接进入下一次循环
		if (!CanStay(maze, up))
		{
			Mark(maze, up);
			SeqStackPush(&stack, up);
			continue;
		}
		Point right = cur;
		right.col += 1;
		if (!CanStay(maze, right))
		{
			Mark(maze, right);
			SeqStackPush(&stack, right);
			continue;


		}
		Point down = cur;
		down.row += 1;
		if (!CanStay(maze, down))
		{
			Mark(maze, down);
			SeqStackPush(&stack, down);
			continue;
		}
		Point left = cur;
		up.col -= 1;
		if (!CanStay(maze, left))
		{
			Mark(maze, left);
			SeqStackPush(&stack, left);
			continue;
		}
		//7.四个方向探测完毕,当前点入栈
		SeqStackPop(&stack);
	}
	return;
}
void _GetShortPath(Maze* maze, Point cur, Point entry, SeqStack* short_path, SeqStack* cur_path)
{
	//1.判断当前点能否落脚
	if (!CanStay(maze, entry))
	{
		return;
	}
	//2.标记当前点,把当前点push到cur_path
	Mark(maze, cur);
	SeqStackPush(cur_path, cur);
	//3.判断当前点是不是出口,如果是出口
	if (IsExit(cur, entry))
	{
		//a)比较当前cur_path与short_path的长短
		if (SeqStackSize(cur_path) < SeqStackSize(short_path) || SeqStackSize(short_path) == 0)
		{//b)如果cur_path比较小或者short_path为空,用cur_path替换short_path
			SeqStackAssign(cur_path, short_path);
		}
		//c)让cur_path出栈,同时返回到上一层栈帧
		SeqStackPop(cur_path);
		return;
	}
	//4.按照一定的顺序,递归的调用该函数完成临界点的判定
	Point up = cur;
	up.row -= 1;
	_GetShortPath(maze, up, entry, &cur_path, &short_path);
	Point right = cur;
	right.col += 1;
	_GetShortPath(maze, right, entry, &cur_path, &short_path);
	Point down = cur;
	down.row += 1;
	_GetShortPath(maze, down, entry, &cur_path, &short_path);
	Point left = cur;
	left.col -= 1;
	_GetShortPath(maze, left, entry, &cur_path, &short_path);
	//5.回溯到上一个位置,先将cur_path出栈,再return
	SeqStackPop(cur_path);
	return;
}
int CanStayWithCycle(Maze*maze, Point cur, Point pre)
{
	if (pre.row < 0)
	{//初始情况,只判断cur
		if (!PointInMap(cur))
		{
			return 0;
		}
		//2.当前点对应的值为1
		int cur_value = maze->map[cur.row][cur.col];
		if (cur_value == 1)
		{
			return 1;
		}
		return 0;
	}
	//1.点在地图上
	if (!PointInMap(cur))
	{
		return 0;
	}
	//2.当前点对应的值为1
	int cur_value = maze->map[cur.row][cur.col];
	if (cur_value == 1)
	{
		return 1;
	}
	//3.判定当前点的值和前一个点的值的大小,满足cur_value-1>pre_value时才能落脚
	int pre_value = maze->map[cur.row][cur.col];
	if (cur_value - 1 > pre_value)
	{
		return 1;
	}
	return 0;
}
void MarkWithCycle(Maze* maze, Point cur, Point pre)
{
	if (PointInMap(cur))
	{
		//pre非法
		Mark(maze,cur);
		return;
	}
	int pre_value = maze->map[cur.row][cur.col];
	maze->map[cur.row][cur.col]=pre_value+1;
}
void _GetShortPathWithPath(Maze* maze, Point cur, Point pre, Point entry, SeqStack* short_path, SeqStack* cur_path)
{
	//1.判断当前点能否落脚
	if (!CanStayWithCycle(maze, cur,pre))
	{
		return;
	}
	//2.标记当前点,把当前点push到cur_path
	MarkWithCycle(maze, cur,pre,entry);
	SeqStackPush(cur_path, cur);
	
	//3.判断当前点是不是出口,如果是出口
	if (IsExit(cur, entry))
	{
		//a)比较当前cur_path与short_path的长短
		SeqStackPrintfChar(&short_path, "最短路径是:");
		if (SeqStackSize(cur_path) < SeqStackSize(short_path) || SeqStackSize(short_path) == 0)
		{//b)如果cur_path比较小或者short_path为空,用cur_path替换short_path
			SeqStackAssign(cur_path, short_path);
		}
		//c)让cur_path出栈,同时返回到上一层栈帧
		SeqStackPop(cur_path);
		return;
	}
	//4.按照一定的顺序,递归的调用该函数完成临界点的判定
	Point up = cur;
	up.row -= 1;
	_GetShortPathWithPath(maze, up,cur, entry, &cur_path, &short_path);
	Point right = cur;
	right.col += 1;
	_GetShortPathWithPath(maze, right, cur, entry, &cur_path, &short_path);
	Point down = cur;
	down.row += 1;
	_GetShortPathWithPath(maze, down, cur, entry, &cur_path, &short_path);
	Point left = cur;
	left.col -= 1;
	_GetShortPathWithPath(maze, left, cur, entry, &cur_path, &short_path);
	//5.回溯到上一个位置,先将cur_path出栈,再return
	SeqStackPop(cur_path);
	return;
}
void GetShortPath(Maze* maze, Point entry)
{
	SeqStack short_path;
	SeqStack cur_path;
	SeqStackInit(&short_path);
	SeqStackInit(&cur_path);
	_GetShortPath(maze, entry, entry, &cur_path, &short_path);
	
}


void test()
{
	Maze maze;
	Point entry= { 0, 1 };//常用表示方法
	Point pre = { -1, -1 };//非法值
	MazeInit(&maze);
	MazePrint(&maze);
	//HasPath(&maze, entry);
	//MazePrint(&maze);
}
int main()
{
	test();
	system("pause");
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值