项目三源代码

该代码实现了一个基于Qt的GUI应用,包括menu.h和maze_widget.h两个核心组件。menu类负责界面展示,如背景图片和按钮响应;maze_widget类处理游戏逻辑,如玩家移动、地图生成、寻路算法等。应用中使用了QPropertyAnimation进行动画效果,QPainter进行图形绘制,以及QTimer控制游戏流程。
摘要由CSDN通过智能技术生成

1.menu.h

#ifndef MENU_H
#define MENU_H

#include <QWidget>
#include <maze_widget.h>
#include <QPropertyAnimation>
#include <mylabel.h>
#include <QDebug>

namespace Ui {
class menu;
}

class menu : public QWidget
{
    Q_OBJECT

public:
    explicit menu(QWidget *parent = nullptr);
    ~menu();
    Ui::menu *ui;

private slots:
    void on_quit_button_clicked();

    void on_ts_model_clicked();





private:
    void mousePressEvent(QMouseEvent* event);

};

#endif // MENU_H

2.maze_widget.h

#ifndef MAZE_WIDGET_H
#define MAZE_WIDGET_H

#include <QWidget>
#include <QPainter>
#include <QPointF>
#include <QTimer>
#include <cstring>
#include <algorithm>
#include <QPixmap>
#include <QDebug>
#include <QKeyEvent>
#include <queue>
#include <QMessageBox>
#include <menu.h>
#include <QThread>

#define mapWidth 80
#define mapHeigh 80
struct squ
{
    QRectF coo;
    std::pair<int,int> rel_coo;
    int if_wall;  //0为路 1为墙 2为边界
    int if_find_way;  //是否为答案路径  1是抵达终点的路径 3是马里奥追到玩家的路径
};

QT_BEGIN_NAMESPACE
namespace Ui { class maze_Widget; }
QT_END_NAMESPACE

class maze_Widget : public QWidget
{
    Q_OBJECT

public:
    maze_Widget(QWidget *parent = nullptr);
    ~maze_Widget();
    int RANK;
    std::pair<int,int> player_coo;//玩家坐标
    void map_generate(std::pair<int,int>,int);

protected:
    void keyPressEvent(QKeyEvent *event);
    void paintEvent(QPaintEvent *event);

    void map_dfs(std::pair<int,int>,int);
    bool find_bfs(std::pair<int,int>,std::pair<int,int>);  //判断是否可以抵达终点
    std::pair<int,int> find_way(std::pair<int,int>,std::pair<int,int>);

//    std::pair<int,int> find(std::pair<int,int>);  //寻找某点所在路径编号

private slots:
    void player_move(); //玩家移动动画
    void cop_catch();
    void rule();
    void g_time();
    void map_dynamic();

private:
    Ui::maze_Widget *ui;
    QTimer * ai_move,* cop_move,*game_rule,*game_time,*map_d;
    bool game_start;
    int nodeWidth = 80;  //单位尺寸
    int nodeHeight = 80;
    squ beg,fin;   //起点与终点
    squ **map = new squ *[mapWidth];
//    std::pair<int,int> **p = new std::pair<int,int> *[mapWidth];

    std::pair<int,int> cop_coo; //警察
    std::pair<int,int> lj[mapWidth][mapHeigh];   //lj[i][j]表示抵达(i,j)的上一个点

    int player_dir=0;  //玩家朝向0为左 1为右
    bool if_showay=false;
    bool if_findway = false;
    bool if_k = false,if_p = true,if_j = false,if_l = false;
    int game_model;
    int gametime;
    bool if_cheat = false,if_dynamic = false; //判断作弊
};
#endif // MAZE_WIDGET_H

3.menu.cpp

#include "menu.h"

#include "ui_menu.h"


menu::menu(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::menu)
{
    ui->setupUi(this);
    setFixedSize(800,800);
    ui->menu_label->setPixmap(QPixmap(":/new/prefix1/picture/player_right_1.png"));
    ui->menu_label->setScaledContents(true);
    QWidget::setMouseTracking(true);

    //生成背景图片
    QImage background = QImage(":/new/prefix1/picture/bj2.jpg");
    QBrush *brush = new QBrush(background.scaled(this->size()));
    QPalette pa(this->palette());
    pa.setBrush(QPalette::Window,*brush);
    this->setPalette(pa);
}


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


void menu::on_quit_button_clicked()
{
    this->close();
}

void menu::on_ts_model_clicked()
{
    maze_Widget * game = new maze_Widget(0);
    this->close();
    game->show();
}



void menu::mousePressEvent(QMouseEvent *event)
{

    if(ui->menu_frame->pos().x()==800)
    {
        QPropertyAnimation * ani = new QPropertyAnimation(ui->menu_frame,"pos");
        ani->setDuration(200);
        ani->setStartValue(QPoint(ui->menu_frame->pos().x(),390));
        ani->setEndValue(QPoint(600,390));
        ani->start();
    }
    else
    {
        QPropertyAnimation * ani = new QPropertyAnimation(ui->menu_frame,"pos");
        ani->setDuration(200);
        ani->setStartValue(QPoint(ui->menu_frame->pos().x(),390));
        ani->setEndValue(QPoint(800,390));
        ani->start();
    }
}

4.maze_widget.cpp

#include "maze_widget.h"
#include "ui_maze_widget.h"
#include "md_thread.h"

maze_Widget::maze_Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::maze_Widget)
{
    ui->setupUi(this);
    setFixedSize(11*nodeWidth,11*nodeHeight);//固定尺寸


    //生成背景图片
    QImage background = QImage(":/new/prefix1/picture/bj4.jpg");
    QBrush *brush = new QBrush(background.scaled(this->size()));
    QPalette pa(this->palette());
    pa.setBrush(QPalette::Window,*brush);
    this->setPalette(pa);

    //初始化地图和难度
    for(int i=0;i<mapWidth;i++)
    {
        map[i] = new squ[mapHeigh];
//        p[i] = new std::pair<int,int> [mapHeigh];
    }
    RANK = 4;
    beg = {map[2][mapHeigh-1].coo,{2,mapHeigh-1},0,1}; //生成起点位置
    map[beg.rel_coo.first][beg.rel_coo.second] = beg;
    map_generate(beg.rel_coo,RANK);

    //初始化难度
//    game_model = model;

    //初始化人物
    player_coo = beg.rel_coo;
    cop_coo = {-1,-1};
    ai_move = new QTimer;
    cop_move = new QTimer;
    game_rule = new QTimer;
    game_time = new QTimer;
    map_d = new QTimer;
    connect(ai_move,SIGNAL(timeout()),this,SLOT(player_move()));
    connect(cop_move,SIGNAL(timeout()),this,SLOT(cop_catch()));
    connect(game_rule,SIGNAL(timeout()),this,SLOT(rule()));
    connect(game_time,SIGNAL(timeout()),this,SLOT(g_time()));
    connect(map_d,SIGNAL(timeout()),this,SLOT(map_dynamic()));

    //判断终点
    if(find_bfs(fin.rel_coo,beg.rel_coo))if_findway = true,qDebug()<<if_findway;
    else if_findway = false,qDebug()<<if_findway;
    for(int i = 0;i<mapWidth;i++)
        for(int j = 0;j<mapHeigh;j++)
            map[i][j].if_find_way = 0;

    //设置游戏开始
    game_start = true;
    game_rule->start(20);
    game_time->start(1000);

    //设置秒表
    ui->time_num->setDigitCount(3);
    ui->time_num->setDecMode();
    ui->time_num->setStyleSheet("border: none");
    ui->time_num->setSegmentStyle(QLCDNumber::Flat);
    gametime = 0;
}

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

void maze_Widget::paintEvent(QPaintEvent *)
{
    QPixmap pix_q_sm,pix_db_sm,pix_player_l,pix_player_r,pix_q_sl_1,pix_q_sl_2,pix_db_sl,pix_cop;
    pix_q_sm.load(":/new/prefix1/picture/sm_q.jpg");   //沙漠墙
    pix_q_sl_1.load(":/new/prefix1/picture/sl_q_1.jpg");   //森林墙1
    pix_q_sl_2.load(":/new/prefix1/picture/sl_q_2.jpg");   //森林墙2
    pix_db_sm.load(":/new/prefix1/picture/sm_d.jpg");   //沙漠地板
    pix_db_sl.load(":/new/prefix1/picture/sl_d.jpg");   //森林地板
    pix_player_l.load(":/new/prefix1/picture/player_left_1.png");
    pix_player_r.load(":/new/prefix1/picture/player_right_1.png");
    pix_cop.load(":/new/prefix1/picture/cop_1.png");
    QPainter painter(this);  //设置画笔
    painter.setRenderHint(QPainter::Antialiasing,true);   //抗锯齿
    for(int i=0;i<11;i++)
    {
        for(int j=0;j<11;j++)
        {
            if(player_coo.first-5+i>=0&&player_coo.second-5+j>=0&&player_coo.first-5+i<=mapWidth-1&&player_coo.second-5+j<=mapHeigh-1)
            {
                switch(map[player_coo.first+i-5][player_coo.second+j-5].if_wall){
                case 0:
                    painter.drawPixmap(i*nodeWidth,j*nodeHeight,nodeWidth,nodeHeight,pix_db_sl);
                    break;
                case 1:
                    painter.drawPixmap(i*nodeWidth,j*nodeHeight,nodeWidth,nodeHeight,pix_q_sl_1);
                    break;
                case 2:
                    painter.drawPixmap(i*nodeWidth,j*nodeHeight,nodeWidth,nodeHeight,pix_q_sl_2);
                    break;
                }
                if(if_showay&&map[player_coo.first+i-5][player_coo.second+j-5].if_find_way==1)
                    painter.drawPixmap(i*nodeWidth,j*nodeHeight,nodeWidth,nodeHeight,pix_db_sm);
                if(map[player_coo.first+i-5][player_coo.second+j-5].if_find_way==3)
                    painter.drawPixmap(i*nodeWidth,j*nodeHeight,nodeWidth,nodeHeight,pix_db_sm);
            }
        }
    }
    switch (player_dir) {
    case 0:
        painter.drawPixmap(5*nodeWidth,5*nodeHeight,nodeWidth,nodeHeight,pix_player_l);//画人物
        break;
    case 1:
        painter.drawPixmap(5*nodeWidth,5*nodeHeight,nodeWidth,nodeHeight,pix_player_r);//画人物
        break;
    }
    if(cop_coo.first!=-1)
    {
        painter.drawPixmap((cop_coo.first-player_coo.first+5)*nodeWidth,(cop_coo.second-player_coo.second+5)*nodeHeight,nodeWidth,nodeHeight,pix_cop);//画警察
    }
//    qDebug()<<"左上角坐标"<<player_coo.first-5<<" "<<player_coo.second-5;
}


void maze_Widget::keyPressEvent(QKeyEvent *event)
{

    switch(event->key())
    {
        case Qt::Key_W:  //W键
        if(player_coo.second>0&&!map[player_coo.first][player_coo.second-1].if_wall)
            player_coo.second-=1;
            break;
        case Qt::Key_A:  //A键
        player_dir = 0;
        if(player_coo.first>0&&!map[player_coo.first-1][player_coo.second].if_wall)
            player_coo.first-=1;
            break;
        case Qt::Key_S:  //S键
        if(player_coo.second<mapHeigh-1&&!map[player_coo.first][player_coo.second+1].if_wall)
            player_coo.second+=1;
            break;
        case Qt::Key_D:  //D键
        player_dir = 1;
        if(player_coo.first<mapWidth-1&&!map[player_coo.first+1][player_coo.second].if_wall)
            player_coo.first+=1;
            break;
        case Qt::Key_J:  //动态地图
        if_dynamic = true;
        if(!if_j)
        {
            if_j = true;
//            QEventLoop eventloop;
//            QTimer::singleShot(2000, &eventloop, SLOT(quit())); //wait 2s
//            eventloop.exec();
            map_d->start(10000);
        }
        else map_d->stop(),if_j = false;
            break;
        case Qt::Key_P: //自动寻路或暂停
        if_cheat = true;
        if(!if_p)ai_move->stop(),if_p = true;
        else if(if_findway)
        {
            for (int i=0;i<mapWidth;i++)
            {
                for (int j=0;j<mapHeigh;j++)
                {
                    map[i][j].if_find_way = 0;
                }
            }
            if_p = false,find_bfs(fin.rel_coo,player_coo),ai_move->start(100);
        }
            break;
        case Qt::Key_K: //显示路径
        if_cheat = true;
        if(!if_k&&if_findway)
        {
            for (int i=0;i<mapWidth;i++)
            {
                for (int j=0;j<mapHeigh;j++)
                {
                    map[i][j].if_find_way = 0;
                }
            }
            find_bfs(fin.rel_coo,player_coo),if_k = true,if_showay = true;
        }
        else if_showay = false,if_k = false;
            break;
        case Qt::Key_L: //启动追逐
        if(!if_l)
        {
            if_l = true;
            QEventLoop eventloop;
            QTimer::singleShot(2000, &eventloop, SLOT(quit())); //wait 2s
            eventloop.exec();
            cop_coo = beg.rel_coo;
            cop_move->start(200);
        }
            break;
    }
    update();
}

void maze_Widget::map_dfs(std::pair<int, int> t,int RANK)
{
//    map[t.first][t.second].if_wall = 0;
//    if(t.first==mapWidth-1)return ;
    int direction[4][2] = { { 1,0 },{ -1,0 },{ 0,1 },{ 0,-1 } };

    for (int i = 0; i < 4; i++) {
        int r = rand() % 4;
        std::swap(direction[0][0],direction[r][0]);
        std::swap(direction[0][1],direction[r][1]);
    }
    //向四个方向开挖
    for (int i = 0; i < 4; i++) {
        int dx = t.first;
        int dy = t.second;
qDebug()<<"209"<<i<<t;
        //控制挖的距离,由Rank来调整大小
        int range = 1 + (RANK == 0 ? 0 : rand() % RANK);
qDebug()<<"212"<<range<<t;
        while (range>0) {
            dx += direction[i][0];
            dy += direction[i][1];
qDebug()<<"216"<<dx<<dy<<t;
            //排除掉回头路和围墙
            if (map[dx][dy].if_wall!=1) {
                break;
            }
qDebug()<<"221"<<i<<range<<t;
            //判断是否挖穿路径
            int count = 0;
            for (int j = dx - 1; j <= dx + 1; j++) {
                for (int k = dy - 1; k <= dy + 1; k++) {
                    //abs(j - dx) + abs(k - dy) == 1 确保只判断九宫格的四个特定位置
                    if (std::abs(j - dx) + std::abs(k - dy) == 1 && !map[j][k].if_wall) {
                        count++;
                    }
                }
            }

            if (count > 1) {
                break;
            }

            //确保不会挖穿时,前进
            range--;
            map[dx][dy].if_wall=0;
//            qDebug()<<" 挖到"<<map[dx][dy].rel_coo;
        }
        //没有挖穿危险,以此为节点递归
        if (range <= 0) {

//            srand(time(NULL));
            map_dfs({dx,dy},RANK);
qDebug()<<"244"<<t;
        }
    }

}



void maze_Widget::map_generate(std::pair<int,int> b,int rank)
{
    //初始化地图(边界内全为墙)

    for(int i=0;i<mapWidth;i++)
    {
        for(int j=0;j<mapHeigh;j++)
        {
            map[i][j].rel_coo = {i,j};
            QPointF lefttop = QPointF(i*nodeWidth,j*nodeHeight);
            QPointF rightbotom = QPointF(i*nodeWidth+nodeWidth,j*nodeHeight+nodeHeight);
            map[i][j].coo = QRectF(lefttop,rightbotom);
            map[i][j].if_wall = 1;
            map[i][j].if_find_way = 0;
        }
    }

    for(int i=0;i<mapWidth;i++)
    {
        map[i][0].if_wall = 2;
        map[i][mapHeigh-1].if_wall = 2;
    }

    for(int i=0;i<mapHeigh;i++)
    {
        map[0][i].if_wall = 2;
        map[mapWidth-1][i].if_wall = 2;
    }
    map[b.first][b.second].if_wall = 0;
    map[b.first][b.second].if_find_way = 1;
    //dfs生成地图

    map_dfs(b,rank);

    //寻找终点位置
    for (int i = 0; i <mapHeigh; i++) {
        if (map[mapWidth-2][i].if_wall==0) {
            map[mapWidth-1][i].if_wall=0;
            fin = map[mapWidth-1][i];
            break;
        }
    }


//    map[beg.rel_coo.first][beg.rel_coo.second-1].if_wall = 0;
//    map[fin.rel_coo.first-1][fin.rel_coo.second].if_wall = 0;
//    for(int i=0;i<mapWidth;i++)
//        for(int j=0;j<mapHeigh;j++)
//            if(!map[i][j].if_wall)
//                p[i][j] = {i,j};
//    p[beg.rel_coo.first][beg.rel_coo.second] = {2,mapHeigh-2};
//    p[fin.rel_coo.first][fin.rel_coo.second] = {mapWidth-2,2};
//    srand(time(NULL));
//    qDebug()<<"115";


//    while (find({beg.rel_coo.first,beg.rel_coo.second})!=find({fin.rel_coo.first,fin.rel_coo.second}))
//    {

//        int x = rand()%mapWidth;
//        int y = rand()%mapHeigh;
//        int dx[4] = {-1,0,1,0};
//        int dy[4] = {0,1,0,-1};
//        //拆墙
//        if(map[x][y].if_wall==1)
//        {
//            qDebug()<<"拆墙"<<x<<"^"<<y;
//            bool if_comb = false;
//            map[x][y].if_wall = 0;
//            for(int i=0;i<4;i++)
//                if(x+dx[i]>=0&&x+dx[i]<mapWidth&&y+dy[i]>=0&&y+dy[i]<mapHeigh&&map[x+dx[i]][y+dy[i]].if_wall==0)
//                {
//                    p[find({x,y}).first][find({x,y}).second] = find({x+dx[i],y+dy[i]});
//                    if_comb = true;
//                    break;
//                }
//            if(!if_comb)p[x][y] = {x,y};
//        }
//    }


}

std::pair<int,int> maze_Widget::find_way(std::pair<int,int> t,std::pair<int,int> q)
{
    if(q==player_coo)map[t.first][t.second].if_find_way = 1;
    else map[t.first][t.second].if_find_way = 3;
    if(t==q)return t;
    if(t.first>=mapWidth||t.first<0||t.second>=mapHeigh||t.second<0||map[t.first][t.second].if_wall)return {-1,-1};
    return find_way(lj[t.first][t.second],q);
}

bool maze_Widget::find_bfs(std::pair<int,int> sub_fin,std::pair<int,int> p)
{
    int d[mapWidth][mapHeigh];  //定义某个点第几次被搜到(即到起点距离为几)
    std::queue<std::pair<int,int>> qu;

    qu.push(p);      //队头从玩家位置开始
    memset(d,-1,sizeof d);   //初始化所有点,表示都没被搜索到
    d[p.first][p.second]=0;
    int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};  //上下左右
    while(!qu.empty())      //当队列不空
    {
        auto t=qu.front();
        qu.pop();
        for(int i=0;i<4;i++)
        {
            int x=t.first+dx[i],y=t.second+dy[i];  //遍历上下左右四个操作
            if(x>=0&&x<mapWidth&&y>=0&&y<mapHeigh&&map[x][y].if_wall==0&&d[x][y]==-1)  //如果不出界且可以走且没走到过
            {
                d[x][y]=d[t.first][t.second]+1; //就让这个点到起点的距离比队头到起点的距离多1
                lj[x][y] = t;
                qu.push({x,y});  //将这个点入队
            }
        }
    }
    if(find_way(sub_fin,p).first==-1)return false;
    else return true;

}

void maze_Widget::player_move()
{

    int dx[4] = {0,1,0,-1};
    int dy[4] = {1,0,-1,0};
    for(int i=0;i<4;i++)
    {
        if(player_coo.first+dx[i]>=0&&player_coo.first+dx[i]<=mapWidth-1&&player_coo.second+dy[i]>=0&&player_coo.second+dy[i]<=mapHeigh-1)
        {
             if(map[player_coo.first+dx[i]][player_coo.second+dy[i]].if_find_way==1)
             {
                 map[player_coo.first][player_coo.second].if_find_way = 2;
                 player_coo = {player_coo.first+dx[i],player_coo.second+dy[i]};
             }


        }
    }

    update();
}
void maze_Widget::cop_catch()
{
    map[cop_coo.first][cop_coo.second].if_find_way=3;
    int dx[4] = {0,1,0,-1};
    int dy[4] = {1,0,-1,0};
    for(int i=0;i<4;i++)
    {
        if(cop_coo.first+dx[i]>=0&&cop_coo.first+dx[i]<=mapWidth-1&&cop_coo.second+dy[i]>=0&&cop_coo.second+dy[i]<=mapHeigh-1)
        {
             if(map[cop_coo.first+dx[i]][cop_coo.second+dy[i]].if_find_way==3)
             {
                 map[cop_coo.first][cop_coo.second].if_find_way = 4;
                 cop_coo = {cop_coo.first+dx[i],cop_coo.second+dy[i]};
             }


             if(map[cop_coo.first+dx[i]][cop_coo.second+dy[i]].rel_coo==player_coo)
                 cop_coo = {cop_coo.first+dx[i],cop_coo.second+dy[i]};
        }
    }


    update();
}
void maze_Widget::rule()
{
    if(cop_coo.first!=-1)
    {
        game_time->stop();
        gametime = 0;
        ui->time_num->display(gametime);
        find_bfs(player_coo,cop_coo);
    }

    if(cop_coo==player_coo)
    {
        game_rule->stop();
        game_time->stop();
        map_d->stop();
        game_start = false,cop_move->stop(),qDebug()<<"game over";
        QMessageBox::information(this,"游戏结束!","你被恶魔制服了!");
    }
    if(fin.rel_coo==player_coo)
    {
        game_start = false,cop_move->stop(),qDebug()<<"game win";
        game_rule->stop();
        game_time->stop();
        map_d->stop();
        if(cop_coo.first!=-1)
            QMessageBox::information(this,"游戏结束!","冒险者,你成功逃脱了恶魔的追捕!");
        else if(!if_cheat)
        {
            if(gametime<999)
            {
                QString m = "本次用时"+QString::number(gametime)+"秒";
                QMessageBox::information(this,"游戏结束!",m);
            }
            else
                QMessageBox::information(this,"游戏结束!","冒险者,你绕迷糊了!");

        }
        else
        {
            QMessageBox::information(this,"游戏结束!","冒险者,请动用自己的智慧完成迷宫!");
        }

    }
    if(!game_start)
    {  
        menu *m = new menu();
        this->close();
        m->show();
    }
}

void maze_Widget::g_time()
{
    ui->time_num->display(gametime++);
    if(gametime==999)game_time->stop();
}


void maze_Widget::map_dynamic()
{
    map_generate(player_coo,RANK);
    update();
    QEventLoop eventloop;
    QTimer::singleShot(500, &eventloop, SLOT(quit())); //wait 0.5s
    eventloop.exec();
    if(!if_p)find_bfs(fin.rel_coo,player_coo);

}

main.cpp和.qrc和.ui文件略

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值