QT小游戏开发(马走日)示例_qt小游戏编程100例_McQueen_LT的博客-程序员秘密

技术标签: QT开发  信号槽使用  最短路径  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. 路径寻找完毕

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/McQueen_LT/article/details/97276178

智能推荐

2013-C++第11周项目参考解答链接集_迂者-贺利坚的博客-程序员秘密

课程首页在:http://blog.csdn.net/sxhelijian/article/details/11890759完整题目见:http://blog.csdn.net/sxhelijian/article/details/14109337【项目1-调用函数输出星号图】参考解答见:http://blog.csdn.net/sxhelijian/article/details/1454841

【异常处理】Tomcat启动时乱码、IDEA控制台乱码的解决方案_农民真快落的博客-程序员秘密

本文的参考文章对于Tomcat启动时乱码:如下图所示,Intellij IDEA显示中文为乱码。首先使用chcp查看控制台编码,如果显示936说明是GBK,65001则是UTF-8,再到tomcat-conf中的logging.properties文件中将编码更改为和控制台一致,我这里控制台是936,因此将文件的UTF-8全部改为GBK。对于IDEA控制台乱码String a="我...

Linux系统中源文件到软件的过程_笨鸟晚飞的博客-程序员秘密

一、通过tartall归档文件安装(一)、基本步骤取得源文件:将tartall文件在/usr/local/src目录下解压缩;取得步骤流程:进入新建的目录下,区查阅INSTALL和README等相关文件;相关属性软件安装:根据INSTALL、README的内容说明安装好一些相关的软件(非必须);建立makefile:以自动检测程序(configure或autoconfig)检测环境变量...

2019学习python有前景吗_2019年学Python发展前景怎么样?零基础如何学习Python?_weixin_39851977的博客-程序员秘密

Python之所以近些年在国内也被发掘与追捧,主要也与互联网发展到此阶段有着重要关系。Python的开放、简洁、黏合正符合了现发展阶段对大数据分析、可视化、各种平台程序协作产生了快速的促进作用。自Python3的发布到现在已有五六年的时间,从刚发布的反对声音到慢慢被接受与喜欢经过了太漫长的时间,然而可能也与国情与发展需求有着相当的关系。总之,越来越多人开始使用Python。创一个小群,供大家学习交...

mqtt协议qos,retain,dup,cleanSession,will的简单理解和应用_mqtt dup_pipixx的博客-程序员秘密

mqtt协议qos,retain,dup,cleanSession,will的简单理解和应用前言qosretaindupcleanSessionwill前言搞过物联网开发的同学们肯定都知道mqtt协议,对于简单的应用大家很快就能上手做出来一些东西,稍微深入一点去了解的时候就会发现根本没有想象的那么简单,能查到的资料基本都晦涩难懂,下面简单讨论一下协议中的qos,retain,dup,cleanSession,will的基本概念和应用.以下代码部分全都是js实现的.参考文章:规范部分:协议规范qo

python与金融工程的区别_科研进阶 | 纽约大学 | 金融工程、量化金融、商业分析:Python金融工程分析..._weixin_39969060的博客-程序员秘密

科研进阶 | 纽约大学 | 金融工程、量化金融、商业分析:Python金融工程分析(2021.2.6开课)​mp.weixin.qq.com课题名称= Python金融工程分析 =项目配景大数据时代的金融行业,涌动着以量化生意业务、风险控制和治理、智能投顾为代表的金融创新,而创新结果的取得又离不开实用编程软件的生长。在众多编程语言中,Matlab、C++、Python的使用规模最为广泛。近几年, ...

随便推点

mpp使用注意事项(分布键)_键盘上的五花肉的博客-程序员秘密

各位读者好! 我之前写的内容是都是自己学习python写的一些笔记及自己编写的小脚本。其实我本人是一位数据库开发人员。15年开始工作,熟悉oracle数据库、擅长mpp数据库,mpp数据库熟悉Teradata,国产列式数据库Gbase 8a。Greenplum有简单使用过(当时公司挑选时候性能不好而pass了,简单语法了解过。用客户的话说,都是出来混的,谁能比谁差哪去,所以当时GP性能...

ArcEngine添加指北针、比例尺、图例(注意UID值)_arcengine添加指北针,比例尺_kone666的博客-程序员秘密

指北针C#代码  public void AddNorthArrow(IPageLayout pageLayout)         {              IGraphicsContainer container = pageLayout as IGraphicsContainer;               IActiveView activeV

牛客小白月赛2 E 是是非非 【尼姆博弈】_aoxuan7259的博客-程序员秘密

链接:https://www.nowcoder.com/acm/contest/86/E来源:牛客网题目描述 坎为水,险阳失道,渊深不测;离为火,依附团结,光明绚丽。 坎卦:水洊至,习坎;君子以常德行,习教事。一轮明月照水中,只见影儿不见踪,愚夫当财下去取,摸来摸去一场空。 离卦:明两作,离,大人以继明照四方。官人来占主高升,庄农人家产业增,生意买卖利息厚,...

oracle的导入dmp 文件 报sp2-0734_vanillamba的博客-程序员秘密

imp 命令是在dos提示符下执行的。 直接cmd后执行而不是在sql下执行的  oracle 查询路径的语句:select * from all_directories where directory_name = 'ADMIN_TBS'; 导入eg:create directory DMPDIR as 'D:\Oracleapp\ADMIN_TBS';impdp...

SQL Server使用笔记(联合mysql必知必会书一起看)_study_&的博客-程序员秘密

SQL Server使用笔记(一)第三章:使用mysql一、连接到数据库有两类DBMS(数据库管理系统),一类是共享文件系统(Microsoft Access);另一类是客户机-服务器DBMS系统(mysql\oracle等),如果是客户机-服务器DBMS则需要在执行命令之前登录到服务器DBMS,我只简单实验一下,所以使用SQL Server默认的localhost二、选择数据库在刚使用SQL Server时,没有任何打开的数据库可供使用,所以需要自己用USE关键字选择一个数据库。必须先打开数据库

cesium3dtiles自定义shader的实现之一_不羁之路的博客-程序员秘密

cesium自定义的shader实现改变3dtiles显示,感觉还行吧。但纯粹是误打误撞的,瞎调的参数,shader真是个神奇的东东啊。

推荐文章

热门文章

相关标签