【C语言】迷宫

一,涉及知识点
结构体,栈,递归
二,实现逻辑
1.定义一个结构体保存当前位置坐标
2.用数组初始化一个迷宫,1表示可以走,0表示墙,迷宫最后一列都是出口
3.打印迷宫
4.走迷宫方法一:使用栈,通过压栈出栈回溯;方法二:在栈的基础上,用递归做回溯
5.记录最短路径,把路径压入栈中,打印最短路径
三,源码
#pragma once
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>

#define ROWS (6)       //行数
#define COLS (6)        //列数
#define MAX_SIZE (100)

//结构体存放坐标
typedef struct Position
{
	int x;
	int y;
}Position;
typedef Position StackDataType;
//栈
typedef struct Stack
{
	StackDataType array[MAX_SIZE];
	int top;        //表示当前个数
}Stack;
void StackInit(Stack *pStack)
{
	pStack->top = 0;
}
void StackDestroy(Stack *pStack)
{
	pStack->top = 0;
}
void StackPush(Stack *pStack, StackDataType data)
{
	assert(pStack->top < MAX_SIZE);
	//pStack->top 永远指向的栈顶后的一个空间
	pStack->array[pStack->top++] = data;
}
void StackPop(Stack *pStack)
{
	assert(pStack->top>0);
	pStack->top--;
}
Position StackTop(Stack *pStack)
{
	assert(pStack->top > 0);
	return pStack->array[pStack->top-1];
}
int StackSize(const Stack *pStack)
{
	return pStack->top;
}
int StackFull(const Stack *pStack)
{
	return pStack->top >= MAX_SIZE;
}
int StackEmpty(const Stack *pStack)
{
	return pStack->top <= 0;
}
void StackCopy(Stack *pDest,Stack *pSrc)
{
	memcpy(pDest->array, pSrc->array, sizeof(StackDataType)*pSrc->top);
	pDest->top = pSrc->top;
}

Stack path;     //当前路径
Stack min;      //之前的最小路径

//简单迷宫
int gMaze[ROWS][COLS] = {
            { 0, 0, 0, 0, 0, 0 },
            { 0, 0, 1, 0, 0, 0 },
            { 0, 0, 1, 0, 0, 0 },
            { 0, 0, 1, 1, 1, 0 },
            { 0, 0, 1, 0, 1, 1 },
            { 0, 0, 1, 0, 0, 0 }
};
//入口
Position gEntry = { 5, 2 };
//判断是否走到出口,最后一列都是出口
int IsExit(Position pos)
{
	if (pos.y == COLS - 1){
		return 1;
	}
	else {
		return 0;
	}
}
//判断是否可以走,没有越界&&值是1
int CanPass(Position pos)
{
	if (pos.x >= ROWS){
		return 0;
	}
	if (pos.y >= COLS){
		return 0;
	}
	return gMaze[pos.x][pos.y] == 1;
}
//打印路径
void PrintPath(Stack *pStack)
{
	Position at;
	for (int i = 0; i < pStack->top; i++){
		at = pStack->array[i];
		printf("x=%d y=%d\n", at.x, at.y);
	}
}
//打印迷宫
void PrintMaze()
{
	for (int i = 0; i < ROWS;i++){
		for (int j = 0; j < COLS;j++){
			if (gMaze[i][j] == 0)
			{
				printf("■", gMaze[i][j]);
			}
			else if (gMaze[i][j] == 1)
			{
				printf("  ", gMaze[i][j]);
			}
			else if (gMaze[i][j] == 2){
				printf("☆", gMaze[i][j]);
			}
		}
		printf("\n");
	}
	printf("\n\n");
}
//方法二
//调用栈做回溯,递归
void RunMazeRec(Position at)
{
	Position next;
	StackPush(&path,at);

	//一进来标记我走过了
	gMaze[at.x][at.y] = 2;
	PrintMaze();

	if (IsExit(at)){
		//如果当前路径(path)小于之前的最小路径(min),最小路径是path
		if (StackEmpty(&min) || StackSize(&path) < StackSize(&min)){
			StackCopy(&min, &path);
            //打印出最短路径
			PrintPath(&path);
		}
	}
	//根据左->上->右->下来尝试
	//左
	next.x = at.x;
	next.y = at.y - 1;
	if (CanPass(next)){
		RunMazeRec(next);//递归
		//PrintMaze();
	}
	//上
	next.x = at.x - 1;
	next.y = at.y;
	if (CanPass(next)){
		RunMazeRec(next);
		//PrintMaze();
	}
	//右
	next.x = at.x;
	next.y = at.y + 1;
	if (CanPass(next)){
		RunMazeRec(next);
		//PrintMaze();
	}
	//下
	next.x = at.x + 1;
	next.y = at.y;
	if (CanPass(next)){
		RunMazeRec(next);
		//PrintMaze();
	}
	//如果at的四周都没法儿走,at重新置为1
	gMaze[at.x][at.y] = 1;
	StackPop(&path);
	return;   //回溯
}

//方法一
//需要一个栈回溯,压栈出栈
void RunMaze()
{
	Stack stack;
	StackInit(&stack);
	Position next;
	Position at;
	at.x = gEntry.x;
	at.y = gEntry.y;
	
	while (1){
		//一进来标记我走过了
		gMaze[at.x][at.y] = 2;
		PrintMaze();
		//把当前位置压入栈中,方便做回溯
		StackPush(&stack, at);

		if (IsExit(at)){
			//如果到了出口,退出
			PrintPath(&stack);
			return;
		}
		//根据左->上->右->下来尝试
		//左
		next.x = at.x;
		next.y = at.y - 1;
		if (CanPass(next)){
			at.x = next.x;
			at.y = next.y;
			continue;
		}
		//上
		next.x = at.x - 1;
		next.y = at.y;
		if (CanPass(next)){
			at.x = next.x;
			at.y = next.y;
			continue;
		}
		//右
		next.x = at.x;
		next.y = at.y + 1;
		if (CanPass(next)){
			at.x = next.x;
			at.y = next.y;
			continue;
		}
		//下
		next.x = at.x + 1;
		next.y = at.y;
		if (CanPass(next)){
			at.x = next.x;
			at.y = next.y;
			continue;
		}
		//如果四周都没法儿走,出栈
		StackPop(&stack);
		if (StackEmpty(&stack)){
			printf("没有出口\n");
			return;
		}
		at = StackTop(&stack);   //回溯
		StackPop(&stack);
	}
}
void testRunMazeRec()
{
	StackInit(&path);
	StackInit(&min);
	PrintMaze();
	RunMazeRec(gEntry);
}
int main()
{
	PrintMaze();
	//RunMaze();  
	testRunMazeRec();
	system("pause");
	return 0;
}


猜你喜欢

转载自blog.csdn.net/ch15029286692/article/details/83029549
今日推荐