目录
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;
}