第一章 任务概述
1.1背景
1.2总体任务要求
第二章 需求分析
2.1总体需求概述
2.2功能需求
2.3非功能需求
第三章 概要设计
3.1总体架构设计
3.2关键流程设计
第四章 详细设计
4.1界面详细设计
4.2数据结构详细设计
一、任务概述
1.1背景
以一个m*n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。设计一个程序,对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。
1.2总体任务要求
(1)实现一个以链表作存储结构的栈类型,然后编写一个求解迷宫的非递归程序。求得的通路一三元组(i,j,d)的形式输出,其中:(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向。
(2)编写递归形式的算法,求得迷宫中所有可能的通路;
(3)以方阵形式输出迷宫及其通路
二、需求分析
2.1总体需求概述
该程序可随机生成指定大小的迷宫,该迷宫有三种可能:1.无通路2.有一条通路3.有多条通路。通过可视化界面清晰地展示出通路。
2.2功能需求
(1)生成迷宫:通过指定长和宽随机生成对应大小的迷宫。
(2)有无通路:在生成迷宫的同时若无通路则弹出提示。
(3)若有通路:动态地指示出从起点到终点的一条通路、所有通路、最短通路。 2.3非功能需求 该程序界面应简洁清晰,操作简便,快速操作。
三、概要设计
3.1总体架构设计 使用程序时可完成以下操作:
四、详细设计
4.1界面详细设计
起始界面/功能界面
该界面为程序的界面及主界面,在控制区的迷宫高度、宽度中输入数字点击生成迷宫按钮,若不输入数值点击生成迷宫按钮则默认生成11*11的迷宫。
此时提示当前生成的迷宫没有通路,需再次点击生成迷宫,直到不提示“没有通路”即迷宫存在通路方可执行下面生成通路的操作。
此时没有提示“没有通路”,解锁生成通路的三个按钮,可点击操作。
4.2数据结构详细设计
各功能的实现思路:
(1)生成迷宫
迷宫分为三种情况:1)无通路 2)有一条通路 3)有多条通路1.将迷宫全置为障碍,将起点置为通路。2.递归地随机选取四个方向中的一个方向进行探路,若没有超出迷宫且该点为障碍则将该邻接点(与上一点之间间隔一个点)置为通路,并将邻接点与上一点的中间点置为通路。若当前点的四个方向都无法继续前进则退回上一个点,递归结束后则得到有唯一通路的迷宫。3.为实现无通路或多通路,生成迷宫范围内的随机数将若干点置为0或1。
(2)非递归求出一条通路或无通路
非递归的深度优先搜索算法:从起点出发,按照某一方向优先顺序向四周探路,走过的点设置为已访问过,压入栈中,若当前点为死路,则退回上一点,当前点出栈。直到当前点为终点。若为空,则没有通路。
(3)递归输出所有通路
深度优先搜索算法:从起点出发,按照某一方向优先顺序向四周递归地探路,将当前点设置为已访问过,将该点压入栈中,当某一方向的递归结束时,该点出栈,设置该点为未访问过,当到达终点时输出栈中的点,并将终点设置为未访问过。
(4)求迷宫最短通路
广度优先搜索算法:设置迷宫大小的二维数组用于存放每一个点的前驱。从起点出发,将起点放入队列中,按照某一方向优先顺序向四周探路,将邻接点放入队列中,记录邻接点的前驱。从终点递归输出前驱得到最短通路。
具体代码实现:
QT creator
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "mythread.cpp"
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_pushButton_3_clicked();
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_pushButton_4_clicked();
void on_pushButton_6_clicked();
private:
Ui::Widget *ui;
QVector<QVector<mybutton *> > btnsofwidget;
mythread * t;
ListStack<location> fp;
ListStack<location> *BFS;
ListStack<location> *DFS;
maze m;
};
#endif // WIDGET_H
liststack.cpp
#include<iostream>
#include <QDebug>
using namespace std;
template <class T>
class ListStack{
//内部节点类
public: class Node{
public:
T data;
Node *next;
Node(T t,Node *next)
{
this->data=t;
this->next=next;
}
};
Node *top;
//构造方法
ListStack<T>()
{
top=0;
}
//压栈
void push(T t)
{
Node *node=new Node(t,top);
top=node;
}
//出栈
T* pop() {
if(top==0){
throw "栈为空,元素不可出栈";//c++中直接throw
return 0;
}
Node *node=top;
top=top->next;
return &node->data;
}
//打印栈
void printStack()
{
Node *node=top;
while(node!=0)
{
cout<<node->data;
node=node->next;
}
}
//判断栈是否为空
bool isEmpty()
{
if(top==0)
return true;
else
return false;
}
//倒置栈
void revert()
{
ListStack<T> *l=new ListStack<T>();
while(!this->isEmpty())
{
l->push(*this->pop());
}
this->top=l->top;
}
};
//int main()
//{
// ListStack<int> list;
// list.push(1);
// list.push(2);
// list.pop();
// list.pop();
// list.printStack();
// cout<<list.isEmpty();
//}
main.cpp
#include "widget.h"
#include <QApplication>
#include <QDebug>
#include<musicthread.cpp>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.setWindowTitle("迷宫游戏 by xdl");
w.show();
return a.exec();
}
maze.cpp
#include"liststack.cpp"
#include<iostream>
#include<string>
#include <ctime>
#include<stdlib.h>
#include<time.h>
#include<queue>
#include<QMessageBox>
using namespace std;
#define random(x) (rand()%x)
template<class T>
class ArrayList
{
public:
int count;
T * shuzu[100];
ArrayList()
{
for(int i=0;i<100;i++)
shuzu[i]=0;
count=0;
}
T get(int i)
{
return *shuzu[i];
}
int size()
{
return count;
}
void add(T &t)//传地址的要传引用,否则地址会消失,变成空指针!
{
shuzu[count]=&t;
count++;
}
void print()
{
for(int i=0;i<100;i++)
{
if(shuzu[i]!=0)
{
cout<<*shuzu[i]<<endl;
}
else
break;
}
}
};
class location {
public:
int x;//横纵坐标
int y;
//空白构造方法
location()
{
}
location(int x,int y)
{
this->x=x;
this->y=y;
}
//重写输出运算符
friend ostream& operator<<(ostream& out,const location& obj)
{
std::string a = std::to_string(obj.x);
std::string b = std::to_string(obj.y);
out<<"location[x="+a+"y="+b+"]"<<endl;
return out;
}
//重写不等于运算符
friend bool operator==(const location& obj1,const location& obj2)
{
if(obj1.x==obj2.x&&obj1.y==obj2.y)
return true;
else
return false;
}
friend bool operator!=(const locat