项目三 迷宫

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QWidget>
#include <QPushButton>
#include "mazewidget.h"

class MainWindow : public QWidget
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);

signals:

public slots:
    void changeWin();

private:
    QPushButton b;
    MazeWidget sub;

protected:
    void paintEvent(QPaintEvent*);
};

#endif // MAINWINDOW_H

mazewidget.h

#ifndef MAZEWIDGET_H
#define MAZEWIDGET_H

#include <QWidget>
#include <iostream>
#include <vector>
#include <queue>
#include <QTime>
#include <QLineEdit>
#include <QPushButton>
#include <QPainter>
#include <QLabel>
#include <QMessageBox>
#include <QDebug>
#include <QKeyEvent>
#include <QPixmap>
#include <QPen>
#include <QStack>

using namespace std;

namespace Ui
{
    class MazeWidget;
}
class Maze    //存放迷宫节点
{
    public:
    int i,j;    //迷宫节点的坐标
    int state;    //迷宫节点的状态,其中:0:墙;1:路:2:自动寻路路径
};
class Box1    //存放自动寻路时路径的信息
{
public:
    int i,j;
    int pre;    //前驱节点编号
    int num;    //当前节点编号
};

class MazeWidget : public QWidget
{
    Q_OBJECT

public:
    explicit MazeWidget(QWidget *parent = 0);
    ~MazeWidget();

    void paintEvent(QPaintEvent *);    //绘图事件
    void CreatMaze();    //创建迷宫
    void keyPressEvent(QKeyEvent*);    //键盘事件
    void FindShortWay();    //自动寻路
    void timerEvent(QTimerEvent*);    //定时器事件
    int score=0;

private:
    Ui::MazeWidget *ui;
    Maze **map;    //二维数组,存放迷宫地图
    vector<Maze> FinalPath;    //存放自动寻路的路径
    QStack<Maze> MazeStack;    //存放迷宫节点
    QStack<Box1> Box1Stack;    //存放自动寻路中处理后的节点
    queue<Box1> Box1Queue;    //存放自动寻路中未处理的节点
    int M,N;    //迷宫的行列数
    bool paint_flag;    //判断是否需要绘制画面
    QLineEdit *Xline;    //行编辑控件
    QLineEdit *Yline;    //列编辑控件
    QLabel *tips;    //显示提示的标签
    QLabel *recounts;    //显示“倒计时”图片的标签
    QPushButton *creatmazebtn;    //创建迷宫的按钮
    QPushButton *findshortwaybtn;    //自动寻路的按钮
    QLabel *time;    //显示时间的标签
    QLabel *toScore;    //显示得分的标签
    int X,Y;    //玩家的坐标
    int timerId;    //定时器ID
    bool find=false;    //判断自动寻路是否到达终点
    bool flag=false;    //判断有没有通路
    bool useFindRoad=false;    //判断游戏中是否使用了自动寻路功能

 private slots:
    void creatmazebtnSlot();
    void findshortwaybtnSlot();
    void counttimeSlot();
};

#endif // MAZEWIDGET_H

main.cpp

#include "mazewidget.h"
#include"mainwindow.h"
#include <QApplication>
#include<QtMultimedia/QMediaPlayer>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

mainwindow.cpp

#include "mainwindow.h"
#include <QPainter>
#include <QSound>

MainWindow::MainWindow(QWidget *parent) : QWidget(parent)
{
    this->setWindowTitle("开始界面");

    b.setParent(this);
    b.setGeometry(250,200,400,150);
    b.setStyleSheet("QPushButton{border-image:url(:/maze/image/start.png);border-radius:5px;}");

    QSound *sound=new QSound(":/maze/image/bgm.wav",this);
    sound->setLoops(-1);
    sound->play();

    this->setFixedSize(900,600);
    connect(&b,&QPushButton::released,this,&MainWindow::changeWin);
}

void MainWindow::changeWin()    //改变窗口
{
    sub.show();
    this->hide();
}

void MainWindow::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    p.drawPixmap(0,0,width(),height(),QPixmap(":/maze/image/background.png"));
}

mazewidget.cpp

#include "mazewidget.h"
#include "ui_mazewidget.h"
#include <QSound>

MazeWidget::MazeWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MazeWidget)
{
    ui->setupUi(this);
    paint_flag=false;
    M=35;
    N=35;
    X=3;
    Y=3;

    this->setWindowTitle("迷宫");
    this->setFixedSize((N+10)*20,(M+1)*20);
    this->setFocus(Qt::MouseFocusReason);

    Xline=new QLineEdit(this);
    Yline=new QLineEdit(this);
    Xline->setText("35");
    Yline->setText("35");
    Xline->setGeometry((N+2)*20+10,245,40,20);
    Yline->setGeometry((N+2)*20+70,245,40,20);

    creatmazebtn=new QPushButton(this);
    creatmazebtn->setText("开始游戏");
    creatmazebtn->setGeometry((N+2)*20,280,120,30);
    creatmazebtn->setStyleSheet("QPushButton{background-color:yellow;}");

    findshortwaybtn=new QPushButton(this);
    findshortwaybtn->setText("自动寻路");
    findshortwaybtn->setStyleSheet("QPushButton{background-color:rgb(250,128,114);}");
    findshortwaybtn->setGeometry((N+2)*20,20,120,30);
    findshortwaybtn->setEnabled(false);

    tips=new QLabel(this);
    tips->setText(" 地图边长范围:15~50");
    tips->setGeometry((N+2)*20,200,120,30);
    tips->setStyleSheet("QLabel{background-color:rgb(122,154,255)};font-weight:bold;");

    recounts=new QLabel(this);
    QPixmap pixmap;
    pixmap.load(":maze/image/counttime.jpg");
    recounts->setPixmap(pixmap);
    recounts->setScaledContents(true);
    recounts->setGeometry((N+2)*20,70,120,50);

    time=new QLabel(this);
    time->setGeometry((N+2)*20,100,120,20);

    toScore=new QLabel(this);
    toScore->setGeometry((N+2)*20,130,120,20);
    toScore->setStyleSheet("QLabel{background-color:rgb(250,128,114);font-size:22px;color:white;border-radius:5px;}");
    toScore->setText(QString("得分:%1").arg(score));

    map=new Maze*[M];    //初始化迷宫,节点全部设为墙壁
    for(int i=0;i<M;i++)
    {
        map[i]=new Maze[N];
    }
    for(int i=0;i<M;i++)
    {
        for(int j=0;j<N;j++)
        {
            map[i][j].state=0;
            map[i][j].i=i;
            map[i][j].j=j;
        }
    }

    connect(creatmazebtn,&QPushButton::clicked,this,&MazeWidget::creatmazebtnSlot);
    connect(findshortwaybtn,&QPushButton::clicked,this,&MazeWidget::findshortwaybtnSlot);
}

void MazeWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    QPen pen;
    pen.setColor(QColor(Qt::yellow));
    pen.setStyle(Qt::CustomDashLine);
    painter.setPen(pen);

    for(int i=FinalPath.size()-1;i>=0;i--)
    {
        map[FinalPath.at(i).i][FinalPath.at(i).j].state=2;
        if(FinalPath.at(i).i==X&&FinalPath.at(i).j==Y)    //清除走过的路的寻路痕迹
        {
            map[FinalPath.at(i).i][FinalPath.at(i).j].state=1;
            FinalPath.pop_back();
        }
    }

    if(paint_flag)
    {
        for(int i=0;i<M;i++)
        {
            for(int j=0;j<N;j++)
            {
                if(i==X&&j==Y)    //画角色
                {
                    painter.drawPixmap(j*20,i*20,20,20,QPixmap(":maze/image/character.png"));
                }
                else if(i==M-2&&j==N-2)    //画金币
                {
                    painter.drawPixmap(j*20,i*20,20,20,QPixmap(":maze/image/gold.png"));
                }
                else
                {
                    switch(map[i][j].state)
                    {
                    case 0:    //画墙壁
                        painter.drawPixmap(j*20,i*20,20,20,QPixmap(":maze/image/wall.jpg"));
                        break;
                    case 1:    //画道路
                        painter.drawPixmap(j*20,i*20,20,20,QPixmap(":maze/image/road.png"));
                        break;
                    case 2:    //画自动寻路路径
                        painter.setBrush(QBrush(QColor(250,128,114),Qt::SolidPattern));
                        painter.drawRect(QRect(j*20,i*20,20,20));
                        break;
                    }
                }
            }
        }
    }
}

MazeWidget::~MazeWidget()
{
    delete ui;
}

void MazeWidget::CreatMaze()    //创建迷宫节点矩阵
{
    int i=3,j=3;
    map[i][j].state=1;

    int randDir=0;

    Maze temp;
    temp.i=i;
    temp.j=j;
    temp.state=1;

    bool Up=true;    //判断各个方向能否到达
    bool Down=true;
    bool Right=true;
    bool Left=true;

    while(1)    //不断生成迷宫节点,直至栈为空
    {
        temp.i=i;
        temp.j=j;
        randDir=qrand()%4;    //获取随机方向:0:上;1:右;2:下;3:左

        switch(randDir)
        {
        case 0:
            if(Up&&i>2&&map[i-2][j].state==0)
            {
                MazeStack.push(temp);
                map[i-2][j].state=1;
                map[i-1][j].state=1;
                i=i-2;

                int rand;
                rand=qrand()%10;
                if(rand>3)
                {
                    Up=true;
                    Right=true;
                    Down=true;
                    Left=true;
                }
                else
                {
                    Up=false;
                    Right=false;
                    Down=false;
                    Left=false;
                }
            }
            else
            {
                Up=false;
            }
            break;
          case 1:
            if(Right&&j<N-3&&map[i][j+2].state==0)
            {
                MazeStack.push(temp);
                map[i][j+2].state=1;
                map[i][j+1].state=1;
                j=j+2;

                int rand;
                rand=qrand()%10;
                if(rand>3)
                {
                    Up=true;
                    Right=true;
                    Down=true;
                    Left=true;
                }
                else
                {
                    Up=false;
                    Right=true;
                    Down=false;
                    Left=true;
                }
            }
            else
            {
                Right=false;
            }
            break;
          case 2:
            if(Down&&i<M-3&&map[i+2][j].state==0)
            {
                MazeStack.push(temp);
                map[i+2][j].state=1;
                map[i+1][j].state=1;
                i=i+2;

                int rand;
                rand=qrand()%10;
                if(rand>3)
                {
                    Up=true;
                    Right=true;
                    Down=true;
                    Left=true;
                }
                else
                {
                    Up=false;
                    Right=false;
                    Down=false;
                    Left=false;
                }
            }
            else
            {
                Down=false;
            }
            break;
        case 3:
            if(Left&&j>2&&map[i][j-2].state==0)
            {
                MazeStack.push(temp);
                map[i][j-2].state=1;
                map[i][j-1].state=1;
                j=j-2;

                Up=true;
                Right=true;
                Down=true;
                Left=true;
            }
            else
            {
                Left=false;
            }
            break;
        }

        if(!Up&&!Down&&!Right&&!Left)    //四个方向都不能创建新节点
        {
            if(!MazeStack.empty())    //回溯
            {
                i=MazeStack.top().i;
                j=MazeStack.top().j;
                MazeStack.pop();
                Up=true;
                Down=true;
                Right=true;
                Left=true;
            }
            else return;
        }
    }
}

void MazeWidget::creatmazebtnSlot()    //创建迷宫的槽函数
{
    if(Xline->text().toInt()>=15&&Yline->text().toInt()>=15&&Xline->text().toInt()<=50&&Yline->text().toInt()<=50)
    {
        M=Xline->text().toInt();    //重新配置画面元素
        N=Yline->text().toInt();
        if(M%2==0) M--;
        if(N%2==0) N--;
        this->setFixedSize((N+10)*20,(M+1)*20);
        Xline->setGeometry((N+2)*20+10,245,40,20);
        Yline->setGeometry((N+2)*20+70,245,40,20);
        creatmazebtn->setGeometry((N+2)*20,280,120,30);
        findshortwaybtn->setGeometry((N+2)*20,20,120,30);
        findshortwaybtn->setEnabled(true);
        tips->setGeometry((N+2)*20,200,120,30);
        recounts->setGeometry((N+2)*20,70,120,50);
        time->setGeometry((N+2)*20,130,120,20);
        time->setStyleSheet("QLabel{background-color:rgb(200,101,202);font-size:25px;color:white;}");
        toScore->setGeometry((N+2)*20,160,120,20);
        toScore->setText(QString("得分:%1").arg(score));
        FinalPath.clear();
        this->setFocus(Qt::MouseFocusReason);

        X=1;    //初始化
        Y=1;
        map=new Maze*[M];
        for(int i=0;i<M;i++)
        {
            map[i]=new Maze[N];
        }
        for(int i=0;i<M;i++)
        {
            for(int j=0;j<N;j++)
            {
                map[i][j].state=0;
                map[i][j].i=i;
                map[i][j].j=j;
            }
        }

        this->CreatMaze();
        paint_flag=true;
        update();
    }
    else
    {
       QMessageBox::information(this,"错误","输入的边长不在限制范围内!",QMessageBox::Yes);
       Xline->clear();
       Yline->clear();
    }

    this->killTimer(timerId);
    timerId=this->startTimer(1000);

    this->findshortwaybtnSlot();    //保证通路
    useFindRoad=false;
    FinalPath.clear();
    while(!Box1Queue.empty())
    {
         Box1Queue.pop();
    }
    if(flag==false) creatmazebtnSlot();

    disconnect(creatmazebtn,&QPushButton::clicked,this,&MazeWidget::creatmazebtnSlot);
}

void MazeWidget::keyPressEvent(QKeyEvent *e)
{
    int temp;
    if(e->key()==Qt::Key_W)
    {
        temp=X-1;
        if(temp && map[temp][Y].state) X=temp;
    }
    else if(e->key()==Qt::Key_S)
    {
        temp=X+1;
        if(temp<M-1 && map[temp][Y].state) X=temp;
    }
    else if(e->key()==Qt::Key_A)
    {
        temp=Y-1;
        if(temp && map[X][temp].state) Y=temp;
    }
    else if(e->key()==Qt::Key_D)
    {
        temp=Y+1;
        if(temp<N-1 && map[X][temp].state) Y=temp;
    }

    if(X==M-2 && Y==N-2)    //到达终点
    {
        QSound *sound=new QSound(":/maze/image/getgold.wav",this);
        sound->setLoops(1);
        sound->play();

        if(!useFindRoad)
        {
            QMessageBox::information(this,"恭喜","您获得了一枚金币!",QMessageBox::Yes);
            toScore->setText(QString("得分:%1").arg(++score));
        }
        else
        {
            QMessageBox::information(this,"提示","您使用了自动寻路功能\n因此分数不增加!",QMessageBox::Yes);
            useFindRoad=false;
        }

        for(int i=0;i<M;i++)
        {
            for(int j=0;j<N;j++)
            {
                map[i][j].state=0;
            }
        }

        FinalPath.clear();
        this->creatmazebtnSlot();
        this->counttimeSlot();
    }
    update();
}

void MazeWidget::FindShortWay()    //自动寻路
{
    FinalPath.clear();    //删除已有自动寻路结果
    while(!Box1Queue.empty())
    {
         Box1Queue.pop();
    }

    Maze maze[M][N];
    int i,j;
    for(i=0;i<M;i++)
    {
        for(j=0;j<N;j++)
        {
            maze[i][j].i=i;
            maze[i][j].j=j;
            maze[i][j].state=map[i][j].state;
        }
    }

    int t=0,pos=0;
    Box1 box;
    box.i=X;
    box.j=Y;
    box.pre=-1;
    box.num=t;
    Box1Queue.push(box);
    maze[X][Y].state=-1;    //-1:已走过该节点;1:未走过该节点
    Maze temp;
    find=false;
    flag=false;

    while(!Box1Queue.empty()&&!find)
    {
        i=Box1Queue.front().i;    //把队首的节点入栈
        j=Box1Queue.front().j;
        box.i=i;
        box.j=j;
        box.num=Box1Queue.front().num;
        box.pre=Box1Queue.front().pre;
        Box1Stack.push(box);

        if(i==M-2&&j==N-2)    //到达终点
        {
            find=true;
            flag=true;

            while(!Box1Stack.empty())    //按栈原路返回
            {
                temp.i=Box1Stack.top().i;
                temp.j=Box1Stack.top().j;
                temp.state=1;
                FinalPath.push_back(temp);
                pos=Box1Stack.top().pre;
                while(!Box1Stack.empty()&&pos!=Box1Stack.top().num)
                {
                    Box1Stack.pop();
                }
            }

        }

        int dire=0;
        for(dire=0;dire<4;dire++)    //0:上;1:右;2:下;3:左
        {
            switch(dire)
            {
            case 0:
                i=Box1Queue.front().i-1;
                j=Box1Queue.front().j;
                break;
            case 1:
                i=Box1Queue.front().i;
                j=Box1Queue.front().j+1;
                break;
            case 2:
                i=Box1Queue.front().i+1;
                j=Box1Queue.front().j;
                break;
            case 3:
                i=Box1Queue.front().i;
                j=Box1Queue.front().j-1;
                break;
            }
            if(maze[i][j].state==1)    //还未走过
            {
                t++;
                box.i=i;
                box.j=j;
                box.num=t;
                box.pre=Box1Queue.front().num;
                Box1Queue.push(box);
                maze[i][j].state=-1;
            }
        }
        Box1Queue.pop();
    }
}

void MazeWidget::findshortwaybtnSlot()    //自动寻路的槽函数
{
    useFindRoad=true;
    for(int i=0;i<M;i++)
    {
        for(int j=0;j<N;j++)
        {
            if(map[i][j].state==2)
            {
                map[i][j].state=1;
            }
        }
    }
    FindShortWay();
    update();
}

void MazeWidget::timerEvent(QTimerEvent *)
{
    counttimeSlot();
}

void MazeWidget::counttimeSlot()
{
    static int sec=180;
    time->setText(QString("%1").arg(sec--));
    if(time->text().toInt()==0)
    {
        this->killTimer(timerId);
        int ret=QMessageBox::information(this,"游戏结束!","您本轮游戏获得的金币数为:"+QString::number(score)+"。\n点击确认键开始新一轮的游戏!",QMessageBox::Yes);
        if(ret==QMessageBox::Yes)
        {
            this->creatmazebtnSlot();
            connect(creatmazebtn,&QPushButton::clicked,this,&MazeWidget::creatmazebtnSlot);
        }
        sec=180;
        score=0;
        toScore->setText(QString("得分:%1").arg(score));
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值