mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "MAZE.h"
#include <QMainWindow>
#include <QWidget>
#include <iostream>
#include <QTime>
#include <QLineEdit>
#include <QPushButton>
#include <QPainter>
#include <QLabel>
#include <QMessageBox>
#include <QDebug>
#include <QKeyEvent>
#include <QPixmap>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void paintEvent(QPaintEvent *);//键盘监听
void keyPressEvent(QKeyEvent *e);//绘图重写
private:
MAZE *m; ///<迷宫地图
///< 当前人物在迷宫的位置(X,Y)
int X = 1;
int Y = 0;
bool bfs_fg = false; ///< 最短路径绘制标志
private slots:
void on_queding_clicked();//创建迷宫
void on_zhaolu_clicked();//寻找路径
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
maze.h
#ifndef MAZE_H
#define MAZE_H
static const int N = 650;
class MAZE
{
public:
///< 值为0:绘制迷宫过道
///< 值为1:绘制迷宫围墙
///< 值为2:绘制你当前的位置
///< 值为3:绘制迷宫终点
///< 值为4:绘制你当前的位置
///< 值为6:绘制最短路径提示
int maze[N][N];
struct point//定义结构体point
{
int x, y, pre;
}q[N*N], path[N*N];//结构体数组
MAZE();
void set_n(int tn);
int get_n();
//int get_len_path(){return len_path;}
//void set_len_path(int tn){len_path = tn;}
void printPath()//打印通路
{
bfs();
for(int i = len_path-1; i >= 0; i--)
if(maze[path[i].x][path[i].y]==0)
maze[path[i].x][path[i].y] = 6;
}
void recoverPath()
{
for(int i = len_path-1; i >= 0; i--)
if(maze[path[i].x][path[i].y]==6)
maze[path[i].x][path[i].y] = 0;
}
void mazeInit();//迷宫信息
int searchPath(int x, int y);//搜索路径
void print();
~MAZE();
private:
int n, len_path, nn;
void bfs();
void getPath(int pos);
};
#endif // MAZE_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
maze.cpp
#include "MAZE.h"
#include <iostream>
#include <windows.h>
#include <cstdio>
#include <cmath>
#include <time.h>
#include <cstring>
using namespace std;
int fa[N*N];
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
MAZE::MAZE(){}
void MAZE::set_n(int tn)
{
n = tn;
nn = n/2;
}
int MAZE::get_n()
{
return n;
}
void MAZE::print()
{
bfs();
}
void MAZE::mazeInit()
{
//迷宫围墙,nn*2+2是规划的迷宫地图大小
for(int i=0; i<=nn*2+2; ++i)
for(int j=0; j<=nn*2+2; ++j)
maze[i][j] = 1;
//在迷宫之外的的轮廓默认为过道
for(int i=0, j=2*nn+2; i<=2*nn+2; ++i)
{
maze[i][0] = 0;
maze[i][j] = 0;
}
for(int i=0, j=2*nn+2; i<=2*nn+2; ++i)
{
maze[0][i] = 0;
maze[j][i] = 0;
}
//默认迷宫坐标第三行第一例为起点
maze[2][1] = 2;
//默认2*nn 行 和 2*nn+1列为终点
maze[2*nn][2*nn+1] = 3;
//生成无符号随机数
srand((unsigned)time(NULL));
//生成的随机数在 [0, nn+1]之间,生成路径
searchPath(rand()%nn+1, rand()%nn+1);
//将地图整体向左上方平移一个单位
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
maze[i][j] = maze[i+1][j+1];
}
}
len_path = 0;
}
int MAZE::searchPath(int x, int y)
{
//往四个方向
static int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
int zx = x*2;
int zy = y*2;
int next, turn, i;
maze[zx][zy] = 0;
//设置turn为[0, 4]之间的任意一个奇数
turn = rand()%2 ? 1 : 3;
//next=rand()%4 取值范围[0, 4),
//next=(next+turn)%4 每个循环在奇数和偶数之间切换,[0, 4)遍历一遍
//在迷宫地图里,随机选一个地方,开始挖路,4次循环,往4个方向挖
for(i=0, next=rand()%4; i<4; ++i, next=(next+turn)%4)
//搜索当前位置的第二步,如果是围墙,这将当前位置的沿着指定方向的下一步设置为路
if(maze[zx+2*dir[next][0]][zy+2*dir[next][1]] == 1)
{
maze[zx+dir[next][0]][zy+dir[next][1]] = 0;
searchPath(x+dir[next][0], y+dir[next][1]);//等于searthPath(zx+2*dir[next][0]][zy+2*dir[next][1])当前位置的下一步为节点开始搜索
}
return 0;
}
void MAZE::getPath(int pos)
{
while(pos != -1)
{
path[len_path].x = q[pos].x;
path[len_path].y = q[pos].y;
len_path++;
pos = q[pos].pre;
}
}
void MAZE::bfs()//寻路
{
int front, tail, sx, sy;
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
if(maze[i][j] == 2)
{
sx = i; sy = j;
}
front = tail = 0;
q[tail].x = sx;
q[tail].y = sy;
q[tail].pre = -1;
tail++;
int x, y, nx, ny;
bool fg = false;
while(front < tail)
{
x = q[front].x;
y = q[front].y;
for(int i = 0; i < 4; i++)
{
nx = x+dx[i];
ny = y+dy[i];
if(nx>=0&&nx<n&&ny>=0&&ny<n&&maze[nx][ny]==0)//确保头结点在路上
{
maze[nx][ny] = 5;//把此节点设为通路
q[tail].x = nx;
q[tail].y = ny;
q[tail].pre = front;//加入到数组q中
tail++;
}
if(maze[nx][ny] == 3){//起点和终点重合
q[tail].x = nx;
q[tail].y = ny;
q[tail].pre = front;
tail++;
fg = true;//结束标志
len_path = 0;
path[len_path].x = nx;
path[len_path].y = ny;
len_path++;
getPath(front);
}
}
if(fg)break;//如果找到终点结束循环
front++;//否则头结点到上一个节点
}
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
if(maze[i][j] == 5)
maze[i][j] = 0;
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "MAZE.h"
#include <iostream>
//绘制迷宫最小单元的(矩形)的长和宽20,即正方形
#define size 20
using namespace std;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//调整窗口中其它控件的大小
int n = 31;
/*新建迷宫*/
m = new MAZE();
m->set_n(n);
//迷宫初始化
m->mazeInit();
//迷宫绘制
m->print();
//设置窗口标题
this->setWindowTitle("迷宫");
//设置窗口固定大小
this->setFixedSize(620,650);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::paintEvent(QPaintEvent *)
{
QPainter painter(this);
int n = m->get_n();
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
//绘制迷宫围墙
if(m->maze[i][j] ==1){
painter.setPen(Qt::black);
painter.setBrush(QBrush(Qt::black,Qt::SolidPattern));
painter.drawRect(QRect(j*size,i*size,size,size));
}
//绘制你当前的位置
else if(m->maze[i][j] == 2){
painter.setPen(Qt::yellow);
painter.setBrush(Qt::yellow);
painter.drawRect(j*20,i*20,20,20);
}
//绘制迷宫终点
else if(m->maze[i][j] == 3){
painter.setPen(Qt::red);
painter.setBrush(Qt::red);
painter.drawRect(j*20,i*20,20,20);
}
//绘制迷宫过道
else if(m->maze[i][j] == 0){
painter.setPen(Qt::white);
painter.setBrush(QBrush(Qt::white,Qt::SolidPattern));
painter.drawRect(QRect(j*size,i*size,size,size));
}
//绘制最短路径提示
else if(m->maze[i][j] == 6){
painter.setPen(Qt::white);
painter.setBrush(Qt::blue);
painter.drawRect(j*20+5,i*20+5,10,10);
}
}
}
}
void MainWindow::keyPressEvent(QKeyEvent *e)//键盘监听
{
if(bfs_fg){
m->recoverPath();
bfs_fg = false;
update();
}
int tx = X, ty = Y;
int n = m->get_n();
if(e->key()==Qt::Key_W)//上
{
if(X>0 && m->maze[X-1][Y] != 1)
{
X=X-1;
}
}
else if(e->key()==Qt::Key_S)//下
{
if(X<n-1 && m->maze[X+1][Y] != 1)
{
X=X+1;
}
}
else if(e->key()==Qt::Key_A)//左
{
if(Y>0 && m->maze[X][Y-1] != 1)
{
Y=Y-1;
}
}
else if(e->key()==Qt::Key_D)//右
{
if(Y<n-1 && m->maze[X][Y+1] != 1)
{
Y=Y+1;
}
}
int tmp = m->maze[X][Y];
if(tmp == 3){
QMessageBox::information(this,"提示","到达终点",QMessageBox::Yes);
}else{
m->maze[X][Y] = m->maze[tx][ty];
m->maze[tx][ty] = tmp;
}
update();
}
void MainWindow::on_queding_clicked()//重建迷宫
{
m->mazeInit();
//初始化人物当前位置
X = 1, Y = 0;
//重绘地图,会调用void MainWindow::paintEvent(QPaintEvent *)
update();
}
void MainWindow::on_zhaolu_clicked()//自动寻路
{
m->printPath();
bfs_fg = true;
update();
}