文章目录
一、项目分析的一般步骤
分析一个项目时的步骤:
第一步:需求分析
第二步:问题分析
第三步:设计(流程图设计、代码设计)
第四步:代码测试
第五步:完成交付
二、迷宫问题的具体解决
1、需求分析
小机器人从入口开始试探,一直试探到出口位置,找到通路
2、问题分析
2.1、问题分析
小机器人从入口点开始试探,有四个方向,当某个方向为0继续往前走,为1则试探其他方向,若四个方向都试探完成后,若依然没有通路,我们就回退到上一个方向,那怎样才能体现这个回退呢?这是我们想到了数据结构中的栈,首先将小机器人的当前位置入栈,当某个方向满足条件可以继续向前走,则将下一位置入栈,若某个位置不满足继续走的条件,我们就出栈。每个方向都要进行试探,直到四个方向都不满足后,我们就进行出栈
2.2、数据结构设计的分析
3、设计(流程图设计、代码设计)
3.1流程图设计
主要内容流程图设计
3.2代码设计
#include<stdio.h>
#define UPMOVE 1
#define RIGHTMOVE 2
#define DOWNMOVE 3
#define LEFTMOVE 4
#define PASS 0 //地图上本身的通路
#define BAR 1 //墙
#define MARK 2 //标记,死路,如果路不通,我们标记2
#define PATH 8 //路径,从入口到出口是一条我们标记的通路
const int RowSize = 15;
const int ColSize = 15;
//迷宫二维数组表示
/*加2的目的是给迷宫设置一个外围的墙,
防止代码每次走到边缘的时候越界,
因此每次都要进行if判断是否越界
所以我们设置外围墙使代码更加简单
*/
typedef int MazeType[RowSize + 2][ColSize + 2];
//typedef 凡是合法的变量的定义都可以通过typedef转化为类型声名
//函数:如何设计一个函数
//1.首先函数名:一个好的函数名,做到见名知意
//2.凡是有printf的冲动,则设置为函数的返回值
//3.凡是有scanf的冲动,则设置为函数的参数
//位置信息的结构
typedef struct PosType
{
int row;
int col;
};
//小机器人的结构
typedef struct SElemType
{
int ord; //总的步数
PosType seat; //位置信息
int di; //方向
};
//栈的实现
#define SEQSTACK 100
typedef SElemType ElemType;
struct SeqStack
{
ElemType data[SEQSTACK];
int top;
int maxsize;
};
void InitSeqStack(SeqStack* sp)
{
sp->top = -1;
sp->maxsize = SEQSTACK;
}
int StackSize(SeqStack* sp) { return sp->top + 1; }
bool StackEmpty(SeqStack* sp) { return StackSize(sp) == 0; }
bool StackFull(SeqStack* sp) { return StackSize(sp) == sp->maxsize; }
void Push(SeqStack* sp, ElemType val)
{
if (StackFull(sp)) return;
sp->data[++sp->top] = val;
}
//
ElemType Top(SeqStack* sp)
{
return sp->data[sp->top];
}
void Pop(SeqStack* sp)
{
if (StackEmpty(sp)) return;
sp->top -= 1;
}
//判断是否为通路
bool Pass(MazeType maze, PosType curpos)
{
return maze[curpos.row][curpos.col] == PASS;
}
//在地图上打印脚印
void FootPrint(MazeType maze, PosType curpos)
{
maze[curpos.row][curpos.col] = PATH;
}
//记录下一个位置信息
PosType NextPos( PosType curpos,int di)
{
switch (di)
{
case UPMOVE: curpos.row -= 1; break;
case RIGHTMOVE:curpos.col += 1; break;
case DOWNMOVE: curpos.row += 1; break;
case LEFTMOVE: curpos.col -= 1; break;
}
return curpos;
}
//记录打印迷宫死路
void MakePrint(MazeType maze, PosType curpos)
{
maze[curpos.row][curpos.col] = MARK;
}
bool MazePath(MazeType maze, PosType start, PosType end)
{
PosType curpos = start; //当前位置
int curstep = 1; //当前步数
SeqStack st; //栈
InitSeqStack(&st);
SElemType e;
//判断当前路径是否为通路径
do
{
if (Pass(maze, curpos))
{
FootPrint(maze,curpos); //打印脚印函数
e.ord = curstep++; //当前步数加1
e.seat = curpos; //记录当前位置信息
e.di = 1; //记录当前方向
Push(&st,e); //机器人信息入栈
if (curpos.col == end.col && curpos.row == end.col) return true;
curpos = NextPos(curpos, 1); //下一个位置继续赋值给当前位置
}
else
{
if (!StackEmpty(&st)) //判断栈是否为空
{
e = Top(&st); Pop(&st); //获取栈顶元素、出栈
while (e.di == 4 && !StackEmpty(&st)) //当小机器人方向为4,并且栈不为空,回退
{
MakePrint(maze,e.seat); //标记打印死路
e = Top(&st); Pop(&st); //获取栈顶元素、出栈
}
if (e.di < 4) //如果小机器人方向小于4
{
e.di += 1; //方向加1
Push(&st,e); //入栈
curpos = NextPos(e.seat, e.di);
}
}
}
} while (!StackEmpty(&st));
return false;
}
//打印迷宫
void PrintMaze(MazeType maze)
{
// sizeof(maze);
for (int i = 0; i < RowSize + 2; ++i)
{
for (int j = 0; j < ColSize + 2; ++j)
{
printf("%2d", maze[i][j]);
}
printf("\n");
}
printf("\n");
}
int main()
{
// 地图信息
MazeType maze
{
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1},
{1,0,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1},
{1,0,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1},
{1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1},
{1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1},
{1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
};
PosType start = { 1,1 }, end = { 15,15 };
PrintMaze(maze);//打印地图信息
MazePath(maze,start,end); //迷宫路径搜索
PrintMaze(maze);
}
4、代码测试
8代表通路、2代表死路
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
1 0 1 1 0 1 1 1 0 1 1 1 1 1 1 1 1
1 0 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 8 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1
1 8 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1
1 8 1 1 2 2 2 2 2 1 1 1 1 1 1 1 1
1 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 8 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 8 8 8 8 8 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 8 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 8 8 8 8 8 8 8 8 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
D:\c基础数据结构\回溯问题—迷宫\Debug\回溯问题—迷宫.exe (进程 14940)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .