项目三 基于A*算法的随机迷宫的实现源代码

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QPainter>
#include <QDebug>
#include <QStack>
#include <QMessagebox>
#include <QKeyEvent>
#include <QEvent>
#include <QTime>
#include <QProcess>

//方块大小
#define xsize 20
#define ysize 20
//行列
#define H 29
#define W 29

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void paintEvent(QPaintEvent *event);

    void keyPressEvent(QKeyEvent *event);

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

private:
    Ui::Widget *ui;
    //起点位置
    int x=xsize*2,y=ysize*2;
    //当前坐标
    int row=1,col=1;


public:

    QPainter painter;
    QPen pen;

    void initmaze();
    void Astart(int r,int c);
};
#endif // WIDGET_H

main.cpp

#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <iostream>
#include <QHash>
#include <QList>
#include <QQueue>
using namespace std;


Widget::Widget(QWidget *parent):QWidget(parent),ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setFixedSize(this->size());
    qDebug()<<this->size();
}
Widget::~Widget()
{
    delete ui;
}


//1,2代表墙,0代表类似树的节点。破墙赋4,访问过赋4
int MAP[H][W];
int isFind[H+2][W+2];

struct Point {
    int row;
    int col;
};

QStack<Point> load;


void Widget::initmaze()
{
    Point curP = { 2,2 };//辅组地图上的起始点
    QStack<Point> ms;
    ms.push(curP);//压入栈顶

    int direction = 0;
    srand(QTime::currentTime().msec());//设置随机数生成器的种子。使用当前时间的毫秒部分作为随机数生成器的种子,使得每次运行程序时生成的随机数序列都不同。

    while (1) {
        //结束循环条件:遍历完了
        int n = 0;
        for (int i = 0; i < H+2; i++) {
            for (int j = 0; j < W+2; j++) {
          if (isFind[i][j] == 0)n++;//如果等于,有格子是空的
            }
        }
        if (n == 0)break;//所有格子都已经被访问过了

        direction = rand()%4;//随机生成方向2

        //退栈条件是走到死胡同
        //死胡同是上下左右都走过了
        if (isFind[curP.row - 2][curP.col] == 1 && isFind[curP.row][curP.col - 2] == 1 &&
            isFind[curP.row + 2][curP.col] == 1 && isFind[curP.row][curP.col + 2] == 1)
        {
            if(!ms.empty())ms.pop();
            if(ms.empty()){
                qDebug()<<"生成失败";

            }
            curP = ms.top();
        }

//如果方向为0,向上,并且当前位置的前两个位置为0,将上一个位置打破
        if (direction == 0 && isFind[curP.row - 2][curP.col] == 0) {
            MAP[curP.row - 1 - 1][curP.col - 1] = 0;//打破墙,原地图比isfind地图小1
            isFind[curP.row - 2][curP.col] = 1;//当前已经被访问过
            curP.row -= 2;//移动两个位置
            ms.push(curP);//添加到ms数组中,跟踪当前位置
        }
        else if (direction == 1 && isFind[curP.row][curP.col - 2] == 0) {
            MAP[curP.row - 1][curP.col - 1 - 1] = 0;
            isFind[curP.row][curP.col - 2] = 1;
            curP.col -= 2;
            ms.push(curP);
        }
        else if (direction == 2 && isFind[curP.row + 2][curP.col] == 0) {
            MAP[curP.row + 1 - 1][curP.col - 1] = 0;
            isFind[curP.row + 2][curP.col] = 1;
            curP.row += 2;
            ms.push(curP);
        }
        else if (direction == 3 && isFind[curP.row][curP.col + 2] == 0) {
            MAP[curP.row - 1][curP.col + 1 - 1] = 0;
            isFind[curP.row][curP.col + 2] = 1;
            curP.col += 2;
            ms.push(curP);
        }


    }

}


void Widget::paintEvent(QPaintEvent *event)
{
    painter.begin(this);
    //设置间距
    pen.setWidth(xsize);

    for(int i=0;i<H;i++)
    {
        for(int j=0;j<W;j++)
        {
            if(MAP[i][j]==1)
            {
                pen.setColor(Qt::black);
                painter.setPen(pen);
                painter.drawPoint((j+1)*xsize,(i+1)*ysize);
            }
            //类似节点
            if(MAP[i][j]==0)
            {
                pen.setColor(Qt::white);
                painter.setPen(pen);
                painter.drawPoint((j+1)*xsize,(i+1)*ysize);
            }
        }
    }

    pen.setColor(Qt::blue);
    painter.setPen(pen);
    painter.drawPoint((col+1)*xsize,(row+1)*ysize);
    pen.setColor(Qt::red);
    painter.setPen(pen);
    painter.drawPoint((H-1)*xsize,(W-1)*ysize);
    //画自动走的路径
    while(!load.empty())//当优先队列不为空时
    {
        Point temp = load.top();
        qDebug() << "row = " << temp.row << " col = " << temp.col;//qDebug来打印这个对象的行和列
        pen.setColor(Qt::green);
        painter.setPen(pen);
        painter.drawPoint((temp.col+1)*xsize,(temp.row+1)*ysize);//在图像上绘制一个点
        load.pop();
    }



    painter.end();


}

void Widget::keyPressEvent(QKeyEvent *event)
{
    //点击按键会给direction赋值,但如果是向上走就不能往下  上下左右0123
    switch (event->key())
    {
    case Qt::Key_W:
        if(row*ysize>0&&MAP[row-1][col]==0)
        {
            row--;
        }
        break;
    case Qt::Key_S:
        if((row+2)*ysize<=ysize*H&&MAP[row+1][col]==0)
        {
            row++;
        }
        break;
    case Qt::Key_A:
        if(col*xsize>0&&MAP[row][col-1]==0)
        {
            col--;
        }
        break;
    case Qt::Key_D://x=(col+1)*xsize
        if((col+2)*xsize<=ysize*W&&MAP[row][col+1]==0)
        {
            col++;
        }
        break;
    default:
        break;
    }
    update();

    //走到终点
    if(row==H-2&&col==W-2)
    {
        //创建 QMessageBox 类对象
        QMessageBox MyBox(QMessageBox::Question,"提示","你已走出迷宫,是否重新开始?",QMessageBox::Yes|QMessageBox::No);
        //使 MyBox 对话框显示
        int rec=MyBox.exec();
        if (rec==QMessageBox::Yes) {
                QProcess::startDetached(qApp->applicationFilePath(), QStringList());
        }
        else if (rec==QMessageBox::No) {
                this->close();
        }
    }
}

void Widget::on_pushButton_clicked()
{
    row=1;
    col=1;
    //初始化MAP迷宫
    for (int i=0;i<H;i++)
        {
            for(int j=0;j<W;j++)
            {
//如果i和j都是奇数的元素设为0
                if(i%2==1&&j%2==1)
                {
                    MAP[i][j]=0;
                    continue;
                }
                MAP[i][j]=1;
            }
        }

    //设计边界
    for (int i=0;i<H+2;i++)
    {
        for(int j=0;j<W+2;j++)
        {
            isFind[i][j]=1;
        }
    }
    for (int i=0;i<H;i++)
    {
        for(int j=0;j<W;j++)
        {
            isFind[i+1][j+1]=MAP[i][j];
        }
    }

    initmaze();
    update();
}



void Widget::Astart(int r,int c)
{
   while(!load.empty())load.pop();
    //初始化数组
    int arr[H][W];
    for (int i=0;i<H;i++)
    {
        for(int j=0;j<W;j++)
        {
            arr[i][j]=0;
        }
    }

    Point beginPoint = { r,c };//自定义起点
    Point endPoint = { H-2,W-2 };//自定义终点
    load.push(beginPoint);


    Point currentPoint = beginPoint;//当前走到的位置
    arr[currentPoint.row][currentPoint.col] = 1;//arr记录已经走过的路径,arr标记数组

    while (1)//while循环一直走下去,一直走到终点栈来存储路径上的点,从起点开始尝试
        //基于栈的深度优先算法,代码中的while循环会一直执行,直到找到终点,如果有可行的方向,就更新当前位置并将其压入栈中,否则就弹出栈顶元素回退到上一个位置
    {
        //下
        if (MAP[currentPoint.row + 1][currentPoint.col] == 0 &&
            arr[currentPoint.row + 1][currentPoint.col] == 0)//可以向下走的条件
        {
            arr[currentPoint.row + 1][currentPoint.col] = 1;
            currentPoint.row = currentPoint.row + 1;
            load.push(currentPoint);
        }
        //右
        else if (MAP[currentPoint.row][currentPoint.col+1] == 0 &&
            arr[currentPoint.row][currentPoint.col+1] == 0)//可以向右走的条件
        {
            arr[currentPoint.row][currentPoint.col + 1] = 1;
            currentPoint.col = currentPoint.col + 1;
            load.push(currentPoint);
        }
        //上
        else if (MAP[currentPoint.row - 1][currentPoint.col] == 0 &&
            arr[currentPoint.row - 1][currentPoint.col] == 0)//可以向上走的条件
        {
            arr[currentPoint.row - 1][currentPoint.col] = 1;
            currentPoint.row = currentPoint.row - 1;
            load.push(currentPoint);
        }
        //左
        else if (MAP[currentPoint.row][currentPoint.col-1] == 0 &&
            arr[currentPoint.row][currentPoint.col-1] == 0)//可以向左走的条件
        {
            arr[currentPoint.row][currentPoint.col - 1] = 1;
            currentPoint.col = currentPoint.col - 1;
            load.push(currentPoint);
        }
        else//死胡同,即上下左右都无法走
        {
            load.pop();
            currentPoint = load.top();
        }

        if (currentPoint.row == endPoint.row && currentPoint.col == endPoint.col)
        {
            qDebug() << "找到终点!路径回退:" ;
            break;
        }
        if (load.empty())
        {
            qDebug() << "找不到路!";
            break;
        }
    }
}


void Widget::on_pushButton_2_clicked()
{
    Astart(row,col);
    update();
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值