QT小游戏开发(马走日)示例

一、概述

        本次博客是为了记录大三时期做的一个实训,用QT开发的,感觉这个小软件用到了不少QT里面的东西,现在记录一下,以后需要用的时候看一下就很快能上手了。这里尤其是对信号槽,绘制更新等用得比较多。


二、功能和算法分析

本次小程序实现的功能有:

1. 输入行数和列数,自动生成网格棋盘;

2. 通过交互来设置起点和终点;

3. 寻找到最短的路径并一步一步动态的显示路径;

4. 可以读取棋盘文件来自动生成棋盘。

算法:

要找最短路径,很简单的就是使用广度优先搜索算法,利用队列来寻找最短路径,使用数组来存储棋盘,同时标记是否已经遍历过。

三、工程结构和目录

       使用的基本框架为dialog,基本所有的代码都是在dialog.cpp文件里编写。dialog.h里要声明很多函数和变量,还有很重要的槽函数,这些函数都要在dialog.cpp文件里实现出来。dialog.ui就是通过QT的界面绘制方式自动生成的文件,下面的Resources文件里存储的都是在界面中用到的图片文件。

四、代码

这里就直接上代码吧,最主要的目的还是为了找个地方存一下这些代码,为了以后用到相似的功能时可以更加快速的上手。

1.  .pro文件(QT)

#-------------------------------------------------
#
# Project created by QtCreator 2018-01-08T09:39:37
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = AlgorithmAnalisys
TEMPLATE = app


SOURCES += main.cpp\
        dialog.cpp

HEADERS  += dialog.h

FORMS    += dialog.ui

RESOURCES += \
    icon_1.qrc \
    start.qrc \
    final.qrc \
    jump.qrc \
    file.qrc \
    finish.qrc

这里注意到,要在.pro文件中添加RESOURCES的路径。

2. dialog.h文件

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QMouseEvent>
#include <QPaintEvent>
#include <QQueue>
#include <QStack>
#include <QTime>
#include <QVector>

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();
    int rows=0;
    int cols=0;
    int N;
    int flag=-1;
    int rect_num1=-1;
    int rect_num2=-1;
    QQueue<int> queue;
    QStack<int> stack;
    int rect_jumpNo=-1;
    int l=0;
    QTimer *timer;
    int flag1=0;
private:
    Ui::Dialog *ui;
    QRect rect[1000];
    int a[1000];
    int b[500];
    void mousePressEvent(QMouseEvent *);
    void paintEvent(QPaintEvent *);
private slots:
    void finish();
    void final();
    void start();
    void jump();
    void update_jumpNo();
    void selectFile();

};

#endif // DIALOG_H

3. dialog.cpp文件

#include "dialog.h"
#include "ui_dialog.h"
#include <QRect>
#include <QPainter>
#include <iostream>
#include <QMouseEvent>
#include <QTimer>
#include <QString>
#include <QFileDialog>
#include <QMessageBox>
#include <QFile>
#include <QTextStream>
#include <QChar>
#include <QDebug>
using namespace std;

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(finish()));
    connect(ui->start,SIGNAL(clicked()),this,SLOT(start()));
    connect(ui->final_2,SIGNAL(clicked()),this,SLOT(final()));
    connect(ui->btn_jump,SIGNAL(clicked()),this,SLOT(jump()));
    connect(ui->btn_inputfile,SIGNAL(clicked()),this,SLOT(selectFile()));
}

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

void Dialog::mousePressEvent(QMouseEvent *e)
{
    if(e->button()==Qt::LeftButton)
    {
        for(int i=0;i<N;i++)
        {
            if(rect[i].contains(e->pos()))
            {

                if(flag==0)
                {

                    rect_num1=i;
                    a[(rect_num1/cols+2)*(cols+4)+rect_num1%cols+2]=-2;
                }

                if(flag==1)
                {
                    rect_num2=i;
                    a[(rect_num2/cols+2)*(cols+4)+rect_num2%cols+2]=-3;
                }

                break;
            }
        }
    }
    update();

}

void Dialog::paintEvent(QPaintEvent *)
{
    QPainter paint(this);
    if(flag==-1)
    {
        paint.setBrush(Qt::white);
        paint.drawRects(rect,N);
    }
    if(flag==0)
    {
        paint.setBrush(Qt::white);
        paint.drawRects(rect,N);
        paint.setBrush(Qt::blue);
        paint.drawRect(rect[rect_num1]);
    }
    if(flag==1)
    {
        paint.setBrush(Qt::white);
        paint.drawRects(rect,N);
        paint.setBrush(Qt::blue);
        paint.drawRect(rect[rect_num1]);
        paint.setBrush(Qt::white);

        paint.setBrush(Qt::red);
        paint.drawRect(rect[rect_num2]);
    }

    if(flag==4)
    {
        paint.setBrush(Qt::black);
        paint.drawRect(rect[rect_jumpNo]);
    }
    //cout<<"Hello"<<endl;
}

void Dialog::finish()
{
    stack.clear();
    disconnect(timer,SIGNAL(timeout()),this,SLOT(update_jumpNo()));

    if(flag1==0)
    {
        rows=ui->lineEdit->text().toInt();
        cols=ui->lineEdit_2->text().toInt();
    }
    else
        flag1=0;
    N=rows*cols;
    int width=ui->widget->width()/cols;
    int height=ui->widget->height()/rows;
    int x=ui->widget->x();
    int y=ui->widget->y();

    for(int i=0;i<2;i++)
    {
        for(int j=0;j<cols+4;j++)
            a[i*(cols+4)+j]=-1;
    }
    for(int i=rows+2;i<rows+4;i++)
    {
        for(int j=0;j<cols+4;j++)
            a[i*(cols+4)+j]=-1;
    }
    for(int i=2;i<rows+2;i++)
    {
        for(int j=0;j<2;j++)
            a[i*(cols+4)+j]=-1;
        for(int j=cols+2;j<cols+4;j++)
            a[i*(cols+4)+j]=-1;
    }

    for(int i=0;i<rows;i++)
    {
        for(int j=0;j<cols;j++)
        {
            rect[i*cols+j]=QRect(x,y,width,height);
            a[(i+2)*(cols+4)+j+2]=0;
            x+=width;
        }
        x=ui->widget->x();
        y+=height;
    }

    flag=-1;
    update();

}

void Dialog::start()
{
    flag=0;
}

void Dialog::final()
{
    flag=1;
}

void Dialog::jump()
{
    queue.clear();
    stack.clear();
    disconnect(timer,SIGNAL(timeout()),this,SLOT(update_jumpNo()));
    bool finish=false;
    int start=-2;
    int final=-3;
    int current_pos;
    for(int i=0;i<(rows+4)*(cols+4);i++)
    {
        if(a[i]==-2)
        {
            start=i;
            queue.push_back(i);
            break;
        }
    }
    for(int i=0;i<(rows+4)*(cols+4);i++)
    {
        if(a[i]==-3)
        {
            final=i;
            break;
        }
    }
     ui->label_3->setText("正在搜寻路径...");

    while(!queue.isEmpty())
    {
        int pos=queue.dequeue();
        // queue.pop_front();
        current_pos=pos;
        cout<<pos<<" ";
        if(pos==final)
        {
            stack.push(final);
            int lastStep=final;
            while(true)
            {
                lastStep=a[lastStep];
                if(lastStep==start)
                {
                    finish=true;
                    break;
                }
                else
                {
                    stack.push(lastStep);
                }
            }
            break;
        }
        int next_pos1=(current_pos/(cols+4)-2)*(cols+4)+(current_pos%(cols+4)+1);
        if(a[next_pos1]==0||a[next_pos1]==-3)
        {
            queue.enqueue(next_pos1);
            a[next_pos1]=current_pos;
        }

        int next_pos2=(current_pos/(cols+4)-1)*(cols+4)+(current_pos%(cols+4)+2);
        if(a[next_pos2]==0||a[next_pos2]==-3)
        {
            queue.enqueue(next_pos2);
            // queue.push_back(next_pos2);
            a[next_pos2]=current_pos;
        }

        int next_pos3=(current_pos/(cols+4)+1)*(cols+4)+(current_pos%(cols+4)+2);
        if(a[next_pos3]==0||a[next_pos3]==-3)
        {
            queue.enqueue(next_pos3);
            a[next_pos3]=current_pos;
        }

        int next_pos4=(current_pos/(cols+4)+2)*(cols+4)+(current_pos%(cols+4)+1);
        if(a[next_pos4]==0||a[next_pos4]==-3)
        {
            queue.enqueue(next_pos4);
            a[next_pos4]=current_pos;
        }

        int next_pos5=(current_pos/(cols+4)+2)*(cols+4)+(current_pos%(cols+4)-1);
        if(a[next_pos5]==0||a[next_pos5]==-3)
        {
            queue.enqueue(next_pos5);
            a[next_pos5]=current_pos;
        }

        int next_pos6=(current_pos/(cols+4)+1)*(cols+4)+(current_pos%(cols+4)-2);
        if(a[next_pos6]==0||a[next_pos6]==-3)
        {
            queue.enqueue(next_pos6);
            a[next_pos6]=current_pos;
        }

        int next_pos7=(current_pos/(cols+4)-1)*(cols+4)+(current_pos%(cols+4)-2);
        if(a[next_pos7]==0||a[next_pos7]==-3)
        {
            queue.enqueue(next_pos7);
            a[next_pos7]=current_pos;
        }

        int next_pos8=(current_pos/(cols+4)-2)*(cols+4)+(current_pos%(cols+4)-1);
        if(a[next_pos8]==0||a[next_pos8]==-3)
        {
            queue.enqueue(next_pos8);
            a[next_pos8]=current_pos;
        }
    }

    if(finish)
    {
        timer=new QTimer(this);
        connect(timer,SIGNAL(timeout()),this,SLOT(update_jumpNo()));
        timer->start(1000);
        flag=4;
        //        int i=0;
        //        flag==4;
        //        while(!stack.isEmpty())
        //        {
        //            b[i]=stack.top();
        //            stack.pop();

        //           // rect_jumpNo=(b[i]/(cols+4)-2)*cols+b[i]%(cols+4)-2;
        //            cout<<b[i]<<" ";
        //        }
        //        cout<<endl;
    }
    else
        ui->label_3->setText("无法顺利到达终点");
}

void Dialog::update_jumpNo()
{
    if(!stack.isEmpty())
    {
        b[l]=stack.top();
        stack.pop();
        rect_jumpNo=(b[l]/(cols+4)-2)*cols+b[l]%(cols+4)-2;
        update(QRegion(rect[rect_jumpNo]));
        l++;
    }
    else
    {
        QString str=QString::number(l);
        ui->label_3->setText(("顺利到达终点,最短需要\n跳"+str+"步"));
        disconnect(timer,SIGNAL(timeout()),this,SLOT(update_jumpNo()));
        ui->lineEdit->setText("");
        ui->lineEdit_2->setText("");
        l=0;

    }

}

void Dialog::selectFile()
{
    flag1=1;
    QString fileName = QFileDialog :: getOpenFileName(this, NULL, NULL, "*.h *.cpp *.txt");
    //---打开文件并读取文件内容
    QFile file(fileName);

    //--打开文件成功
    if (file.open(QIODevice ::ReadOnly | QIODevice ::Text))
    {
        QTextStream textStream(&file);

        QString str;

        rows=0;
        cols=0;
        str=textStream.readLine();
        rows++;
        for( int i=0;i<str.length();i++)
        {
            if(str.at(i)==' ')
            {
                cols++;
            }
        }
        while(!textStream.atEnd())
        {
            str=textStream.readLine();
            rows++;
        }
        ui->label_3->setText("已读入文件");


    }
    else    //---打开文件失败
    {
        QMessageBox ::information(NULL, NULL, "open file error");
    }


}

4. main.cpp文件

#include "dialog.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog w;
    w.show();

    return a.exec();
}

5. UI界面

五、效果演示

1. 设置行数和列数,绘制棋盘;设置起点和终点,起点为蓝色,终点为红色。

先输入行数和列数,然后点击绘制棋盘按钮。然后点击设置起点按钮,并在右侧棋盘中选择一个方格作为起点,同样再选择一个终点。

2. 点击开始跳按钮

3. 路径寻找完毕

已标记关键词 清除标记
相关推荐
<p> 1.带领你学习QT5/C++,<span style="color:#FF0000;"><strong>从开发环境(QTCreator和VS2015两种)</strong></span>搭建到项目实战,从入门到精通。 </p> <p> 2.所有章节均有理论知识介绍、接口讲解、实例代码讲解,讲解过程中不断穿插老师在开发过程中遇到的问题及解决方法(<span style="color:#FF0000;"><strong>可以下载所有的电子课件与源码</strong></span>)。 </p> <p> 3.本阶段主要完成Qt开发环境搭建、<span style="color:#00B050;"><strong>基于Widget的图形控件、布局管理、容器类、QT事件处理、QSS、QML</strong></span>等几个方面知识的学习 </p> <p> 4.项目实战部分包括:<span style="color:#E36C09;"><strong>计算器、CRM、视频播放器、视频加密器</strong></span>、等。 </p> <p> 5.通过学习qt框架,进一步加深了对<span style="color:#FF0000;"><strong>C++设计模式</strong></span>的理解。可以<span style="color:#00B050;"><strong>真正投入到实战中</strong></span>,能做基于QT跨平台功能强大的界面程序。 </p> <p> ---------------------------------------- </p> <p> 第1章 Qt开发环境搭建及使用(VS2015及Qt Creator)<br /> 第2章 Qt的HelloWorld(GUI)及剖析<br /> 第3章 Qt信号槽使用及其原理<br /> 第4章 Qt容器类<br /> 第5章 Qt窗口基类QWidget<br /> 第6章 Qt应用程序主窗口<br /> 第7章 Qt基于Widget的控件<br /> 第8章 Qt布局管理<br /> 第9章 Qt事件<br /> 第10章 QSS快速入门<br /> 第11章 Qml快速入门<br /> 第12章 Qt项目实战之计算器<br /> 第13章 Qt项目实战之信息管理系统<br /> 第14章 Qt项目实战之视频播放器<br /> 第15章 Qt项目实战之视频加密器<br /> 第16章 Qt项目实战之视频转码器<br /> 第17章 Qt面试题分析与讲解<br /> 第18章 Qt小白是怎么炼成大牛的之中级篇概览<br /></p><div> <br /></div> <p> <br /></p> <p> <br /></p> <p> <br /></p> <p> <br /></p> <p> <br /></p> <p> <br /></p> <p> <br /></p> <p> <br /></p> <p> <br /></p> <p> <br /></p> <p> <br /></p> <p> <br /></p> <p> <br /></p> <p> <br /></p> <p> <br /></p> <p> <br /></p> <p> <br /></p> <p> <br /></p> <p> <br /></p>
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页