【数据结构与算法(C语言)】栈的实际应用之二:迷宫求解(具有动画效果)

1. 前言

本文使用栈结构实现迷宫求解。
迷宫求解是一个非常经典的算法。算法刚开始看觉得复杂,将栈的结构熟悉以后,单独看迷宫的算法,就不会感觉到复杂了。如果学会了该算法,就可以编写一些简单的小游戏。
先看一下动画效果版的运行结果:
在这里插入图片描述

2. 结构变量和函数

栈结构的基本操作可以看上一篇博文《栈的基本操作函数(动图演示)》,这里不做赘述。

2.1 方格坐标结构类型 PosType

自定义一个迷宫中的方格坐标类型

typedef struct {
	int x;
	int y;
}PosType ;               //迷宫上每个方块(通道)的坐标

2.2 方格元素结构类型 SElemType

迷宫方格的信息封装,程序中 栈结构就是保存此元素类型。

typedef struct {
	int ord;	//通道块在路径上的序号
	PosType seat;	//通道块在迷宫的坐标
	int di;		//下个通道块的方向
}SElemType; 	//元素类型

2.3 定义变量

定义迷宫信息的变量,并初始化。这些变量可以集中到一个结构体中。此程序因为是测试程序,就没有在定义一个结构体,增加复杂度了。
maze数组,就是迷宫的结构。数组为10*10的二维数组,其中数值中的元素组成 一个正方形,正方形的外围都为0,代表着迷宫的墙,墙是走不通的。

int x=10,y=10; //迷宫的行列数
int curStep = 2; //足迹路线,开始在入口处,每走一步递增1;之所以从2开始,因为在迷宫中,数字为1时有其他作用:代表着是通道可通行
PosType direc[4]={{0,1},{1,0},{0,-1},{-1,0}};//移动方向依次为东(右)、南(下)、西(左)、北(上)
//定义一个迷宫10*10的二维数组,
int maze[10][10]={  {0,0,0,0,0,0,0,0,0,0},					// 0 行  
					{0,1,1,0,1,1,1,0,1,0},					// 1 行
					{0,1,1,0,1,1,1,0,1,0},					// 2 行
					{0,1,1,1,1,0,0,1,1,0},					// 3 行
					{0,1,0,0,0,1,1,1,1,0},					// 4 行
					{0,1,1,1,0,1,1,1,1,0},					// 5 行
					{0,1,0,1,1,1,0,1,1,0},					// 6 行
					{0,1,0,0,0,1,0,0,1,0},					// 7 行
					{0,0,1,1,1,1,1,1,1,0},					// 8 行
					{0,0,0,0,0,0,0,0,0,0}};					// 9 行		; //迷宫数组 
PosType begin={1,1} ; //迷宫入口坐标
PosType end={8,8};    //迷宫出口坐标 

2.4 打印迷宫结构 PrintMaze

功能: 打印迷宫结构,即输出maze数组的元素。

//打印迷宫结构
void PrintMaze()
{
  int i, j;
  for(i=0;i<x;i++)
  {
	for (j=0; j< y; j++)
		 printf("%3d",maze[i][j]);
	puts("");
  }
}

2.5 标记方格(位置)不可走 MarkPrint

//标记坐标pos所在的方格为不可走
void MarkPrint(PosType pos)
{
	maze[pos.x][pos.y] = -1;	
}

2.6 判断方格是否能通行

功能:判断坐标为pos的方格是否可以通行

/* 判断是否可以通行,只要是数字1,就可以通行 */
Status Pass(PosType pos)
{
	if(maze[pos.x][pos.y] == 1)
		return TRUE;
	return FALSE;
}

2.7 标记路径

功能:标记路径,将通道块的数字设置为步数,路径从数字2开始。

//标记路径,将通道块的数字设置为步数;
void FootPrint(PosType pos){
	maze[pos.x][pos.y]=curStep;
}

2.8 获取路径的下一步

功能:坐标pos所在方格的四周找到路径上的下一个方格

//路径的下一步
PosType NextPos(PosType pos,int di)
{
	pos.x +=direc[di].x;
	pos.y +=direc[di].y;
	return pos;
}

2.9 路径求解(算法的核心)

功能:获取迷宫的一条路径

Status MazePath(PosType start,PosType end)
{

  SqStack stack;
  PosType curpos;
  SElemType e;
  InitStack(&stack);
  curpos=start;  //入口位置
  do{
	 if(Pass(curpos))	//当前位置可以通过,即是未曾走到过的通道快
	 {
		FootPrint(curpos); //标记足迹
		e.ord=curStep;     //保存步数
		e.seat=curpos;     //位置 
		e.di=0;            //direc[0]是南,默认先向南(即向下)
		Push(&stack,e);    //将当前的通道块信息入栈

		if( curpos.x==end.x && curpos.y==end.y ) 
			return TRUE;	// 到达终点
		curpos=NextPos(curpos, e.di); //下一个位置是当前元素的东邻
		curStep++; //探索下一步 


	 }else				//当前位置不能通过
	 {

		if(!StackEmpty(stack))
		{
			Pop(&stack,&e); //退栈
			curStep--;
			while(e.di == 3 && !StackEmpty(stack)) // e.di==3,表示三个方向都走过了;这个循环就是在栈里找
			{
				MarkPrint(e.seat); //留下不能通过的标记
				Pop(&stack,&e);	   //退回一步,
				curStep--; 	       //足迹减1
			}
			if(e.di < 3)
			{
			   e.di++; //换一个方向探索
			   Push(&stack,e); //入栈
			   curStep++;
			   curpos=NextPos(e.seat,e.di);
			}
		 }
	 }
  }while (!StackEmpty(stack));
  return FALSE;
}

除了栈的基本操作,迷宫求解就只需要上面的 2个结构体类型 ,7个重要的变量和8个函数

3. 简易版完整代码

3.1 完整源码



#include <stdio.h>
#include <stdlib.h>

#define STACK_INIT_SIZE 100  //初始内存空间
#define STACKINCREMENT  10   // 内存空间增量

#define TRUE 1
#define FALSE 0

typedef struct {
	int x;
	int y;
}PosType ;               //迷宫上每个方块(通道)的坐标

typedef struct {
	int ord;	//通道块在路径上的序号
	PosType seat;	//通道块在迷宫的坐标
	int di;		//下个通道块的方向
}SElemType; 	//元素类型


typedef struct Stack{
	SElemType * base; //栈底指针
	SElemType * top; //栈顶指针
	int stacksize;   //当前已分配的存储空间
} SqStack;

typedef int Status;



//下面的10个函数是栈的基本操作函数(通用的)声明
Status InitStack(SqStack * stack);
Status DestroyStack(SqStack * stack);
Status ClearStack(SqStack * stack);
Status StackEmpty(SqStack stack);
int StackLength(SqStack stack);
Status GetTop(SqStack stack, SElemType * e);
Status Push(SqStack * stack,SElemType e);
Status Pop(SqStack * stack, SElemType *e);
void Visit(SElemType e);
Status StackTraverse(SqStack stack,void (*visit)(SElemType));



//下面是迷宫问题(专用的)变量和函数声明
int x=10,y=10; //迷宫的行列数
int curStep = 2; //足迹路线,开始在入口处,每走一步递增1;之所以从2开始,因为在迷宫中,数字为1时有其他作用:代表着是通道可通行

PosType direc[4]={{0,1},{1,0},{0,-1},{-1,0}};//移动方向依次为东(右)、南(下)、西(左)、北(上)

//定义一个迷宫10*10的二维数组,
int maze[10][10]={  {0,0,0,0,0,0,0,0,0,0},					// 0 行  
					{0,1,1,0,1,1,1,0,1,0},					// 1 行
					{0,1,1,0,1,1,1,0,1,0},					// 2 行
					{0,1,1,1,1,0,0,1,1,0},					// 3 行
					{0,1,0,0,0,1,1,1,1,0},					// 4 行
					{0,1,1,1,0,1,1,1,1,0},					// 5 行
					{0,1,0,1,1,1,0,1,1,0},					// 6 行
					{0,1,0,0,0,1,0,0,1,0},					// 7 行
					{0,0,1,1,1,1,1,1,1,0},					// 8 行
					{0,0,0,0,0,0,0,0,0,0}};					// 9 行		; //迷宫数组 

PosType begin={1,1} ; //迷宫入口坐标
PosType end={8,8};    //迷宫出口坐标


void PrintMaze();							//打印迷宫结构
void MarkPrint(PosType e);					//标志当前位置走不通
Status Pass(PosType b);						//判断当前位置是否能通行
void FootPrint(PosType b);					//路径打印
PosType NextPos(PosType ,int di);			//获取当前位置的下一步坐标
Status MazePath(PosType start,PosType end); //寻找迷宫路径



/*下面是栈的基本操作函数定义*/ 

/*初始化栈*/
Status InitStack(SqStack * stack)
{
	stack->base =(SElemType * )malloc(STACK_INIT_SIZE* sizeof(SElemType));
	if(!stack->base)
		exit(EXIT_FAILURE);
	stack->top=stack->base;	// 栈顶指针初始 指向栈底;
	stack->stacksize=STACK_INIT_SIZE;
	return TRUE;
}

/*销毁栈 */
Status DestroyStack(SqStack * stack)
{
	free(stack->base);
	stack->top=stack->base=NULL;
	stack->stacksize=0;
	return TRUE;
}
/* 清理stack,只需要将top指针指向base*/
Status ClearStack(SqStack * stack)
{
	stack->top=stack->base;
	return TRUE;
}

/* 判断栈是否为空 */
Status StackEmpty(SqStack stack)
{
	if(stack.base == stack.top)
		return TRUE;
	else 
		return FALSE;
}

/* 获取stack的长度 */
int StackLength(SqStack stack)
{
	
	return stack.top - stack.base;
}

/* 获取栈顶元素,并将值传递给 e*/
Status GetTop(SqStack stack, SElemType * e)
{
	if(StackEmpty(stack))
		return FALSE;
	*e = *--stack.top;
}



/*入栈, 将元素e压入栈中 */
Status Push(SqStack * stack,SElemType e)
{
	if(stack->top - stack->base >= stack->stacksize)//如果空间不够的话,扩容
	{
		stack->base =(SElemType *) realloc(stack->base,(stack->stacksize+STACKINCREMENT)* sizeof(SElemType));
		if(!stack->base)
			exit(EXIT_FAILURE);
		stack->stacksize += STACKINCREMENT;
	}
	*stack->top++ = e;
	return TRUE;
}
/*出栈, 从栈顶弹出元素,并将元素值传递给e*/
Status Pop(SqStack * stack ,SElemType * e)  
{
	if(!stack->base)
		return FALSE;
	if(stack->base == stack->top) //空栈
		return FALSE;
	*e = *(--stack->top);
	return TRUE;
}


/* 访问元素 */
void Visit(SElemType e)
{
    //	printf("%d\t", e);
}

/* 遍历stack,对stack的每一个元素调用visit函数 */
Status StackTraverse(SqStack stack,void (*visit)(SElemType e))
{

	SElemType * curElem=stack.base;
	if(StackEmpty(stack))
		return FALSE;
	while(curElem!=stack.top)
		visit(*curElem++);
	return TRUE;

}

//打印迷宫结构
void PrintMaze()
{
  int i, j;
  for(i=0;i<x;i++)
  {
	for (j=0; j< y; j++)
		 printf("%3d",maze[i][j]);
	puts("");
  }
}

//标记为不可走
void MarkPrint(PosType pos)
{
	maze[pos.x][pos.y] = -1;	
}

/* 判断是否可以通行,只要是数字1,就可以通行 */
Status Pass(PosType pos)
{
	if(maze[pos.x][pos.y] == 1)
		return TRUE;
	return FALSE;
}

//标记路径,将通道块的数字设置为步数;
void FootPrint(PosType pos)
{
	maze[pos.x][pos.y]=curStep;
}

//路径的下一步
PosType NextPos(PosType pos,int di)
{
	pos.x +=direc[di].x;
	pos.y +=direc[di].y;
	return pos;
}



Status MazePath(PosType start,PosType end)
{

  SqStack stack;
  PosType curpos;
  SElemType e;
  InitStack(&stack);
  curpos=start;  //入口位置
  do{
	 if(Pass(curpos))	//当前位置可以通过,即是未曾走到过的通道快
	 {

		FootPrint(curpos); //标记足迹

		e.ord=curStep;     //保存步数
		e.seat=curpos;     //位置 
		e.di=0;            //direc[0]是南,默认先向南(即向下)
		Push(&stack,e);    //将当前的通道块信息入栈

		if( curpos.x==end.x && curpos.y==end.y ) 
			return TRUE;	// 到达终点
		curpos=NextPos(curpos, e.di); //下一个位置是当前元素的东邻
		curStep++; //探索下一步 


	 }else				//当前位置不能通过
	 {

		if(!StackEmpty(stack))
		{
			Pop(&stack,&e); //退栈
			curStep--;
			while(e.di == 3 && !StackEmpty(stack)) // e.di==3,表示三个方向都走过了;这个循环就是在栈里找
			{
				MarkPrint(e.seat); //留下不能通过的标记
				Pop(&stack,&e);	   //退回一步,
				curStep--; 	       //足迹减1
			}
			if(e.di < 3)
			{
			   e.di++; //换一个方向探索
			   Push(&stack,e); //入栈
			   curStep++;
			   curpos=NextPos(e.seat,e.di);
			}
		 }
	 }
  }while (!StackEmpty(stack));
  return FALSE;
}

int main()
{
	printf("迷宫结构如图:\n");
    PrintMaze(); 
	if(MazePath(begin,end))
	{
	 	printf("\n此迷宫的一条路径如下:\n");
		PrintMaze();
	}else
	{
		printf("迷宫走不通\n");
	}
	getchar();
	return 0;
}

3.2 运行结果

在这里插入图片描述

4 . 动画效果版本代码

动态效果,可以看 Windows控制台的API函数文章详细介绍了表格的绘制。


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <Windows.h>
#include <conio.h>


#define STACK_INIT_SIZE 100  //初始内存空间
#define STACKINCREMENT  10   // 内存空间增量

#define TRUE 1
#define FALSE 0

typedef struct {
	int x;
	int y;
}PosType ;               //迷宫上每个方块(通道)的坐标

typedef struct {
	int ord;	//通道块在路径上的序号
	PosType seat;	//通道块在迷宫的坐标
	int di;		//下个通道块的方向
}SElemType; 	//元素类型


typedef struct Stack{
	SElemType * base; //栈底指针
	SElemType * top; //栈顶指针
	int stacksize;   //当前已分配的存储空间
} SqStack;

typedef int Status;



//下面的10个函数是栈的基本操作函数(通用的)声明
Status InitStack(SqStack * stack);
Status DestroyStack(SqStack * stack);
Status ClearStack(SqStack * stack);
Status StackEmpty(SqStack stack);
int StackLength(SqStack stack);
Status GetTop(SqStack stack, SElemType * e);
Status Push(SqStack * stack,SElemType e);
Status Pop(SqStack * stack, SElemType *e);
void Visit(SElemType e);
Status StackTraverse(SqStack stack,void (*visit)(SElemType));


//下面是迷宫问题(专用的)变量和函数声明
int x=10,y=10; //迷宫的行列数
int curStep = 2; //足迹路线,开始在入口处,每走一步递增1;之所以从2开始,因为在迷宫中,数字为1时有其他作用:代表着是通道可通行

PosType direc[4]={{0,1},{1,0},{0,-1},{-1,0}};//移动方向依次为东(右)、南(下)、西(左)、北(上)

//迷宫数组 原始结构, 
//之所以要多定义只读数值,是因为当MarkPrint标记中,
//将方格的颜色恢复到原来样子,maze数组中的值已经改变,无法判断原来位置的数据
const int maze_orign[10][10]={  {0,0,0,0,0,0,0,0,0,0},					// 0 行  
					{0,1,1,0,1,1,1,0,1,0},					// 1 行
					{0,1,1,0,1,1,1,0,1,0},					// 2 行
					{0,1,1,1,1,0,0,1,1,0},					// 3 行
					{0,1,0,0,0,1,1,1,1,0},					// 4 行
					{0,1,1,1,0,1,1,1,1,0},					// 5 行
					{0,1,0,1,1,1,0,1,1,0},					// 6 行
					{0,1,0,0,0,1,0,0,1,0},					// 7 行
					{0,0,1,1,1,1,1,1,1,0},					// 8 行
					{0,0,0,0,0,0,0,0,0,0}};					// 9 行		; 
//定义一个迷宫10*10的二维数组,
int maze[10][10]={  {0,0,0,0,0,0,0,0,0,0},					// 0 行  
					{0,1,1,0,1,1,1,0,1,0},					// 1 行
					{0,1,1,0,1,1,1,0,1,0},					// 2 行
					{0,1,1,1,1,0,0,1,1,0},					// 3 行
					{0,1,0,0,0,1,1,1,1,0},					// 4 行
					{0,1,1,1,0,1,1,1,1,0},					// 5 行
					{0,1,0,1,1,1,0,1,1,0},					// 6 行
					{0,1,0,0,0,1,0,0,1,0},					// 7 行
					{0,0,1,1,1,1,1,1,1,0},					// 8 行
					{0,0,0,0,0,0,0,0,0,0}};					// 9 行		; //迷宫数组 可以修改

PosType begin={1,1} ; //迷宫入口坐标
PosType end={8,8};    //迷宫出口坐标

//定义一个表格
typedef struct grid_s{
	COORD startPos; //左上角坐标
	COORD size;	   // 表格的长度和宽度
} Grid_t;



void PrintMaze();							//打印迷宫结构
void MarkPrint(PosType pos,HANDLE handle_output,Grid_t grid);					//标志当前位置走不通
Status Pass(PosType b);						//判断当前位置是否能通行
void FootPrint(PosType b,HANDLE handle_output,Grid_t grid);					//路径打印
PosType NextPos(PosType ,int di);			//获取当前位置的下一步坐标
Status MazePath(PosType start,PosType end,HANDLE handle_output,Grid_t grid); //寻找迷宫路径
void sleep(float time);
void DrawGrid(HANDLE handle_out,Grid_t grid);
void LocateGridPos(HANDLE handle_out,Grid_t grid,int x,int y);//定位表格的位置

/*下面是栈的基本操作函数定义*/ 

/*初始化栈*/
Status InitStack(SqStack * stack)
{
	stack->base =(SElemType * )malloc(STACK_INIT_SIZE* sizeof(SElemType));
	if(!stack->base)
		exit(EXIT_FAILURE);
	stack->top=stack->base;	// 栈顶指针初始 指向栈底;
	stack->stacksize=STACK_INIT_SIZE;
	return TRUE;
}

/*销毁栈 */
Status DestroyStack(SqStack * stack)
{
	free(stack->base);
	stack->top=stack->base=NULL;
	stack->stacksize=0;
	return TRUE;
}
/* 清理stack,只需要将top指针指向base*/
Status ClearStack(SqStack * stack)
{
	stack->top=stack->base;
	return TRUE;
}

/* 判断栈是否为空 */
Status StackEmpty(SqStack stack)
{
	if(stack.base == stack.top)
		return TRUE;
	else 
		return FALSE;
}

/* 获取stack的长度 */
int StackLength(SqStack stack)
{
	
	return stack.top - stack.base;
}

/* 获取栈顶元素,并将值传递给 e*/
Status GetTop(SqStack stack, SElemType * e)
{
	if(StackEmpty(stack))
		return FALSE;
	*e = *--stack.top;
}



/*入栈, 将元素e压入栈中 */
Status Push(SqStack * stack,SElemType e)
{
	if(stack->top - stack->base >= stack->stacksize)//如果空间不够的话,扩容
	{
		stack->base =(SElemType *) realloc(stack->base,(stack->stacksize+STACKINCREMENT)* sizeof(SElemType));
		if(!stack->base)
			exit(EXIT_FAILURE);
		stack->stacksize += STACKINCREMENT;
	}
	*stack->top++ = e;
	return TRUE;
}
/*出栈, 从栈顶弹出元素,并将元素值传递给e*/
Status Pop(SqStack * stack ,SElemType * e)  
{
	if(!stack->base)
		return FALSE;
	if(stack->base == stack->top) //空栈
		return FALSE;
	*e = *(--stack->top);
	return TRUE;
}


/* 访问元素 */
void Visit(SElemType e)
{
    //	printf("%d\t", e);
}

/* 遍历stack,对stack的每一个元素调用visit函数 */
Status StackTraverse(SqStack stack,void (*visit)(SElemType e))
{

	SElemType * curElem=stack.base;
	if(StackEmpty(stack))
		return FALSE;
	while(curElem!=stack.top)
		visit(*curElem++);
	return TRUE;

}

//打印迷宫结构
void PrintMaze()
{
  int i, j;
  for(i=0;i<x;i++)
  {
	for (j=0; j< y; j++)
		 printf("%3d",maze[i][j]);
	puts("");
  }
}

//标记为不可走
void MarkPrint(PosType pos,HANDLE handle_output,Grid_t grid)
{
	maze[pos.x][pos.y] = -1;
	sleep(0.45); //做一个延迟,可以形成动态的程序
	LocateGridPos(handle_output,grid,pos.y,pos.x);
	if(maze_orign[pos.x][pos.y] ==0)
	{
		SetConsoleTextAttribute(handle_output, FOREGROUND_RED);	  //将输出修改成红色
	    printf("%s","■");

	}else{
		SetConsoleTextAttribute(handle_output, 0x0f);	  //将输出修改成红色
		printf("%2s"," ");
	}

}

/* 判断是否可以通行,只要是数字1,就可以通行 */
Status Pass(PosType pos)
{
	if(maze[pos.x][pos.y] == 1)
		return TRUE;
	return FALSE;
}

//标记路径,将通道块的数字设置为步数;
void FootPrint(PosType pos,HANDLE handle_output,Grid_t grid)
{
	   
	maze[pos.x][pos.y]=curStep;
	sleep(0.45);//做一个延迟,可以形成动态的程序
	//SetConsoleTextAttribute(handle_output, FOREGROUND_GREEN);	  //将输出修改成红色
	SetConsoleTextAttribute(handle_output, 0xaf);	  //将输出修改成绿底白字
	LocateGridPos(handle_output,grid,pos.y,pos.x);
	printf("%2d",curStep-1);
}




//路径的下一步
PosType NextPos(PosType pos,int di)
{
	pos.x +=direc[di].x;
	pos.y +=direc[di].y;
	return pos;
}



Status MazePath(PosType start,PosType end,HANDLE handle_output,Grid_t grid)
{

  SqStack stack;
  PosType curpos;
  SElemType e;
  InitStack(&stack);
  curpos=start;  //入口位置
  do{
	 if(Pass(curpos))	//当前位置可以通过,即是未曾走到过的通道快
	 {

		FootPrint(curpos, handle_output,grid); //标记足迹
		e.ord=curStep;     //保存步数
		e.seat=curpos;     //位置 
		e.di=0;            //direc[0]是南,默认先向南(即向下)
		Push(&stack,e);    //将当前的通道块信息入栈

		if( curpos.x==end.x && curpos.y==end.y ) 
			return TRUE;	// 到达终点
		curpos=NextPos(curpos, e.di); //下一个位置是当前元素的东邻
		curStep++; //探索下一步 

	 }else				//当前位置不能通过
	 {

		if(!StackEmpty(stack))
		{
			Pop(&stack,&e); //退栈
			curStep--;
			while(e.di == 3 && !StackEmpty(stack)) // e.di==3,表示三个方向都走过了;这个循环就是在栈里找
			{
				MarkPrint(e.seat,handle_output,grid); //留下不能通过的标记
				Pop(&stack,&e);	   //退回一步,
				curStep--; 	       //足迹减1
			}
			if(e.di < 3)
			{
			   e.di++; //换一个方向探索
			   Push(&stack,e); //入栈
			   curStep++;
			   curpos=NextPos(e.seat,e.di);
			}
		 }
	 }
  }while (!StackEmpty(stack));
  return FALSE;

}


//定位表格的位置
void LocateGridPos(HANDLE handle_out,Grid_t grid,int x,int y)
{	

	 COORD pos={4*x+2, 2*y+1};
	 pos.X += grid.startPos.X;
	 pos.Y += grid.startPos.Y;
     SetConsoleCursorPosition(handle_out,pos);        /* 设置控制台光标坐标(设备句柄, 光标坐标) */

}
//绘制表格
void DrawGrid(HANDLE handle_out,Grid_t grid)
{

	int i,j,k;
	int realRowLen;		//实际画表格的行数; 第0行 - 第realRowLen行
	int realColLen;		//实际画表格的列数; 第0列 - 第realColLen列
	char * top[4] = { "┌", "───", "┬", "┐" };		//顶部的4个绘表符号
    char * center_data[2] = { "│", "   " };			//表格中间的行(输出数据的行)
    char * center[4] = { "├", "───", "┼", "┤" };	//表格中间的行 (数据行分隔的行);
    char * bottom[4] = { "└", "───", "┴", "┘" };	//底部的4个绘表符号
    
	realRowLen = 2 * grid.size.Y + 1;
	realColLen = 2 * grid.size.X + 1;
	
	SetConsoleCursorPosition(handle_out,grid.startPos);        /* 设置控制台光标坐标(设备句柄, 光标坐标) */

	//输出顶部字符
    printf(top[0]);								//最左边的边框 "┌"
    for (i = 1; i < realColLen-1; i++)
    {
		if (i % 2 == 1)
			printf(top[1]);						//奇数列,输出 "─"
		else
		    printf(top[2]);						//偶数列,输出 "┬"

    }
    printf("%s\n",top[3] );						//最右边的边框 "┐"


	//输出表格中间的部分
	for(i = 1;	i < realRowLen-1; i++)
	{
		for(k =0 ;k < grid.startPos.X ; k++)
		{
			printf(" ");
		}
		if( i % 2 == 1)							//相当于if(i=1,3,5,7...2*row-3)单数行,即带有数据的行
		{
			for(j = 0;j < realColLen ; j++)	
			{
				if( j % 2 == 0)
					printf(center_data[0]);		//双数列,  输出 "|"
				else
					printf(center_data[1]);		//单数列为空 ,输出 " "	
			}
			printf("\n");
		}
		else									//相当于  if(i=0,i=2...) 双数行 即分隔行
		{
			printf(center[0]);					//最左边的边框 "├"
			for(j = 1;j < realColLen-1 ; j++)	
			{
				if( j % 2 == 1)
					printf(center[1]);			//奇数列,输出 "─" 
				else
					printf(center[2]);			//偶数列,输出 "┼"
			}
			 printf("%s\n",center[3] );			//最右边的边框 "┐"
		}
	}


	 //输出底部字符
	for(k =0 ;k < grid.startPos.X ; k++)
	{
			printf(" ");
	}

	printf(bottom[0]);							//最左边框 "└"
    for (i = 1; i <realColLen-1; i++)
    {
            if (i % 2 == 1)					
				printf("%s",bottom[1]);			//奇数列 "─"
            else							
                printf("%s",bottom[2]);			//偶数列 "┴"
    }
    printf("%s\n",bottom[3] );					//最右边框 "┘"

}


//休眠函数
void sleep(float time)
{
   clock_t   now   =   clock(); 
   while( clock() - now < time*1000); 
}



int main()
{
	
	int i,j;
	Grid_t grid={ {1,1}, {10,10}};			//定义一个表格起始位置为{3,3},长度为,宽度为5;
	 COORD pos={20, 30};
	
	HANDLE handle_output = GetStdHandle(STD_OUTPUT_HANDLE);   //获取标准输出句柄
	SetConsoleTextAttribute(handle_output, FOREGROUND_GREEN); //将输出修改成绿色,这样表格就画出绿色的了

	DrawGrid(handle_output,grid);		


	SetConsoleTextAttribute(handle_output, FOREGROUND_RED);	  //将输出修改成红色
	
	for(i = 0; i < 10; i++)									  //在表格的指定位置赋值
	{
		for(j = 0;j < 10; j++)
			if(maze[j][i]==0){
				LocateGridPos(handle_output,grid,i,j);
				printf("%s","■");
			}
	}

	SetConsoleTextAttribute(handle_output, FOREGROUND_GREEN); //将输出修改成绿色,这样表格就画出绿色的了
	printf("\n\n\n");
   /* PrintMaze();*/

	if(!MazePath(begin,end,handle_output,grid))
	{
	  SetConsoleCursorPosition(handle_output,pos);        /* 设置控制台光标坐标(设备句柄, 光标坐标) */
	   printf("迷宫走不通\n");
	}
	 CloseHandle(handle_output);		
	getchar();
	return 0;
}

  • 24
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值