本次博客是为了记录大三时期做的一个实训,用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. 路径寻找完毕
课程首页在: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启动时乱码:如下图所示,Intellij IDEA显示中文为乱码。首先使用chcp查看控制台编码,如果显示936说明是GBK,65001则是UTF-8,再到tomcat-conf中的logging.properties文件中将编码更改为和控制台一致,我这里控制台是936,因此将文件的UTF-8全部改为GBK。对于IDEA控制台乱码String a="我...
一、通过tartall归档文件安装(一)、基本步骤取得源文件:将tartall文件在/usr/local/src目录下解压缩;取得步骤流程:进入新建的目录下,区查阅INSTALL和README等相关文件;相关属性软件安装:根据INSTALL、README的内容说明安装好一些相关的软件(非必须);建立makefile:以自动检测程序(configure或autoconfig)检测环境变量...
Python之所以近些年在国内也被发掘与追捧,主要也与互联网发展到此阶段有着重要关系。Python的开放、简洁、黏合正符合了现发展阶段对大数据分析、可视化、各种平台程序协作产生了快速的促进作用。自Python3的发布到现在已有五六年的时间,从刚发布的反对声音到慢慢被接受与喜欢经过了太漫长的时间,然而可能也与国情与发展需求有着相当的关系。总之,越来越多人开始使用Python。创一个小群,供大家学习交...
mqtt协议qos,retain,dup,cleanSession,will的简单理解和应用前言qosretaindupcleanSessionwill前言搞过物联网开发的同学们肯定都知道mqtt协议,对于简单的应用大家很快就能上手做出来一些东西,稍微深入一点去了解的时候就会发现根本没有想象的那么简单,能查到的资料基本都晦涩难懂,下面简单讨论一下协议中的qos,retain,dup,cleanSession,will的基本概念和应用.以下代码部分全都是js实现的.参考文章:规范部分:协议规范qo
科研进阶 | 纽约大学 | 金融工程、量化金融、商业分析:Python金融工程分析(2021.2.6开课)mp.weixin.qq.com课题名称= Python金融工程分析 =项目配景大数据时代的金融行业,涌动着以量化生意业务、风险控制和治理、智能投顾为代表的金融创新,而创新结果的取得又离不开实用编程软件的生长。在众多编程语言中,Matlab、C++、Python的使用规模最为广泛。近几年, ...
各位读者好! 我之前写的内容是都是自己学习python写的一些笔记及自己编写的小脚本。其实我本人是一位数据库开发人员。15年开始工作,熟悉oracle数据库、擅长mpp数据库,mpp数据库熟悉Teradata,国产列式数据库Gbase 8a。Greenplum有简单使用过(当时公司挑选时候性能不好而pass了,简单语法了解过。用客户的话说,都是出来混的,谁能比谁差哪去,所以当时GP性能...
指北针C#代码 public void AddNorthArrow(IPageLayout pageLayout) { IGraphicsContainer container = pageLayout as IGraphicsContainer; IActiveView activeV
链接:https://www.nowcoder.com/acm/contest/86/E来源:牛客网题目描述 坎为水,险阳失道,渊深不测;离为火,依附团结,光明绚丽。 坎卦:水洊至,习坎;君子以常德行,习教事。一轮明月照水中,只见影儿不见踪,愚夫当财下去取,摸来摸去一场空。 离卦:明两作,离,大人以继明照四方。官人来占主高升,庄农人家产业增,生意买卖利息厚,...
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一、连接到数据库有两类DBMS(数据库管理系统),一类是共享文件系统(Microsoft Access);另一类是客户机-服务器DBMS系统(mysql\oracle等),如果是客户机-服务器DBMS则需要在执行命令之前登录到服务器DBMS,我只简单实验一下,所以使用SQL Server默认的localhost二、选择数据库在刚使用SQL Server时,没有任何打开的数据库可供使用,所以需要自己用USE关键字选择一个数据库。必须先打开数据库
cesium自定义的shader实现改变3dtiles显示,感觉还行吧。但纯粹是误打误撞的,瞎调的参数,shader真是个神奇的东东啊。