您现在的位置是:首页 >技术教程 >用零知识证明实现地图的三染色问题(qt),简单实验网站首页技术教程
用零知识证明实现地图的三染色问题(qt),简单实验
以前随便弄应付的,上传一下看看能否帮助别人。
一、实验要求
用零知识证明实现地图的三染色问题(用三种颜色染色一个地图,保证任意两个相邻的地区都是不同的颜色)。设地图的三染色问题答案在Alice手上,Alice要向Bob证明自己有答案,但又不想把答案给Bob知道。地图有六个顶点和6条边,编写程序,并验证至少20次结果。
二、设计
从题目中,可以设计如下数据结构:
·节点类,其中要有颜色信息,要有绘图的位置坐标。
·边类,边类的设定很灵活,这里我采用的是有对应两个点的序号。
·Alice类,包含有6个节点和6条边,并且提供可以打乱节点颜色的函数。
·Bob类,Bob类只有一个函数,用于选择看哪条边。
三、效果
初始界面,依托答辩,谁有事没事愿意搞这hapi东西。混,然后又混又没有人脉拿到别人搞的东西,所以无奈只能自己写,什么操作系统、c++课程设计还好超一点,而这种又好混一点。但别的什么跟java有关的什么web,小程序,数据库后台啥的痛苦无比。
主界面:
然后选择看,当然每次看颜色都会改变。
作弊:
四、实验步骤
还是经典的qt哈。创建一个mainwindow项目,然后新建一个graph.h
然后写节点和边,其中节点保存默认颜色(程序初始化是随机的颜色,也就是tm Alice知道的答案),颜色(每次Bob看到的颜色)和画图的位置。
边则需要保存两个node即可,而且保存的是node数组的下标。
#ifndef GRAPH_H
#define GRAPH_H
#include<QColor>
#include<QVector>
#include<QTime>
#include<QtGlobal>
using namespace std;
//节点,但没必要用邻接表,不需要搞那么复杂,不需要写指针了(仅仅需要保存颜色)
struct Node
{
QColor defaultColor;//默认颜色,也就是答案
QColor color;//随时都可能更改的颜色
QVector<float> position;//画图的位置
//构
Node()
{
color = QColor();
position = QVector<float>(2);
position[0] = 0;
position[1] = 0;
}
//构
Node(QColor c, float x, float y)
{
defaultColor = c;
color = c;
position = QVector<float>{x, y};
}
};
//边类
struct Edge
{
//保存节点的序号,其实用指针应该更省内存,但暂不需要
int node_1, node_2;
Edge(){node_1=0;node_2=0;}
Edge(int n1, int n2)
{
node_1 = n1;
node_2 = n2;
}
};
然后我们再写一个类,也就是Alice,里面要有node[6],要有edge[6],然后写构造函数,初始化,并且为每条边绑定一下对应的节点下标就完事了。
最后再写一个类,Bob,里面空空的,只需要提供一个看节点的函数就完事了。
//
class Alice
{
public:
Node nodes[6];//6个节点
Edge edges[6];//6条边
//初始化所有信息
Alice()
{
nodes[0] = Node(QColor(255, 0, 0), 100, 100);nodes[1] = Node(QColor(255, 255, 0), 300, 100);
nodes[2] = Node(QColor(0, 255, 0), 300, 300);nodes[3] = Node(QColor(255, 255, 0), 100, 300);
nodes[4] = Node(QColor(0, 255, 0), 500, 100);nodes[5] = Node(QColor(255, 0, 0), 500, 300);
edges[0] = Edge(0, 1);edges[1] = Edge(0, 2);edges[2] = Edge(0, 3);
edges[3] = Edge(1, 4);edges[4] = Edge(2, 5);edges[5] = Edge(4, 5);
}
//打乱整数
void Transform()
{
nodes[0].color = QColor(0, qrand()%256, qrand()%256);
nodes[5].color = QColor(0, qrand()%256, qrand()%256);
nodes[1].color = QColor(qrand()%256, qrand()%256, 0);
nodes[3].color = QColor(qrand()%256, qrand()%256, 0);
nodes[2].color = QColor(qrand()%256, 0, qrand()%256);
nodes[4].color = QColor(qrand()%256, 0, qrand()%256);
}
};
class Bob
{
public:
Bob(){}
//Bob有个猜测函数,随机找一条边进行猜测,
int Gauss()
{
return (rand() % 6);
}
};
#endif // GRAPH_H
/以上就是graph.h的全部了
然后,拖拖拽拽一些按钮和输入框,至于输入框对应的名字,我下面给你们标注好了,我就不需要传源程序了。至于那些label,自己想拖进去就拖进去,不要也没事,就是可视化起来看不到哪是哪。建议自己搞一下。
接着,让我们来把mainwindow.h搞进去,请注意,按理说这里面应该绑定信号了,如果把全部代码copy进去后,点击按钮无法运行的话,请注意按钮的命名(上图已经给标记了),还有实在不行你需要在ui那里点击按钮->右键->转到槽,其实就是需要绑定一下函数给个信号。
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include"graph.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
public:
virtual void timerEvent(QTimerEvent *);
int time;
int number = 0;
Alice alice;
Bob bob;
void Init();
bool isCheat;
void paintEvent(QPaintEvent *event);
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
void on_pushButton_4_clicked();
void on_pushButton_5_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
最后一段代码,也就是mainwindow.cpp,我上机检查时候,没问过啥,基本放心用,而且可以看,不复杂。
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QPainter>
#include<QRect>
#include<QColor>
#include<QTime>
#include<QtGlobal>
#include<QMessageBox>
MainWindow::MainWindow(QWidget *parent):
QMainWindow(parent),
ui(new Ui::MainWindow)
{
Init();
//timer = new QTimer(this);
isCheat = false;
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::Init()
{
for(int i = 0; i < 6; i++)
{
//把颜色搞掉
alice.nodes[i].color = QColor(0,0,0);
}
}
//绘图事件
void MainWindow::paintEvent(QPaintEvent *event)
{
QPainter painter;
QBrush qb = QBrush(QColor(0,0,0));;
painter.begin(this);//设置窗口画布
//画线
for(int i = 0; i < 6; i++)
{
painter.drawLine(alice.nodes[alice.edges[i].node_1].position[0] + 20, alice.nodes[alice.edges[i].node_1].position[1] + 20, alice.nodes[alice.edges[i].node_2].position[0] + 20, alice.nodes[alice.edges[i].node_2].position[1] + 20);
}
//画节点
for(int i = 0; i < 6; i++)
{
qb = QBrush(alice.nodes[i].color);
QRectF rectangle(alice.nodes[i].position[0], alice.nodes[i].position[1], 40, 40);
painter.setBrush(qb);
painter.drawEllipse(rectangle);
}
//是否看答案,如果看答案的画就画出来
if(isCheat)
{
for(int i = 0; i < 6; i++)
{
painter.drawLine(alice.nodes[alice.edges[i].node_1].position[0] + 20, alice.nodes[alice.edges[i].node_1].position[1] + 310, alice.nodes[alice.edges[i].node_2].position[0] + 20, alice.nodes[alice.edges[i].node_2].position[1] + 310);
}
for(int i = 0; i < 6; i++)
{
qb = QBrush(alice.nodes[i].defaultColor);
QRectF rectangle(alice.nodes[i].position[0], alice.nodes[i].position[1] + 290, 40, 40);
painter.setBrush(qb);
painter.drawEllipse(rectangle);
}
}
painter.end();
}
void MainWindow::timerEvent(QTimerEvent *ev)
{
if(ev->timerId() == time)
{
//猜一猜
int num = bob.Gauss();
ui->textBrowser_3->clear();
ui->textBrowser_3->append("这次猜" + QString::number(num+1) + "号边!");
//打乱颜色
alice.Transform();
//然后,输出
//再设置
for(int i = 0; i < 6; i++)
{
if(i == alice.edges[num].node_1 || i == alice.edges[num].node_2)
{
continue;
}
//把颜色搞掉
alice.nodes[i].color = QColor(0,0,0);
}
ui->textBrowser_3->append("其中一点的颜色值为: R:" + QString::number(alice.nodes[alice.edges[num].node_1].color.red()) + " G:" + QString::number(alice.nodes[alice.edges[num].node_1].color.green()) + " B:" + QString::number(alice.nodes[alice.edges[num].node_1].color.blue()));
ui->textBrowser_3->append("另一点的颜色值为: R:" + QString::number(alice.nodes[alice.edges[num].node_2].color.red()) + " G:" + QString::number(alice.nodes[alice.edges[num].node_2].color.green()) + " B:" + QString::number(alice.nodes[alice.edges[num].node_2].color.blue()));
ui->textBrowser_3->append("颜色不相同");
ui->textBrowser_3->append("第"+QString::number(++number)+"次,Bob输了");
repaint();
}
}
void MainWindow::on_pushButton_clicked()
{
int num = ui->lineEdit->text().toInt() - 1;
if(num < 0 || num > 6)
{
QMessageBox::information(nullptr, "提示", "非法输入,边的序号只能1 - 6", QMessageBox::Yes);
return;
}
ui->textBrowser->clear();
ui->textBrowser->append("这次猜" + QString::number(num+1) + "号边!");
//打乱颜色
alice.Transform();
//然后,输出
//再设置
for(int i = 0; i < 6; i++)
{
if(i == alice.edges[num].node_1 || i == alice.edges[num].node_2)
{
continue;
}
//把颜色搞掉
alice.nodes[i].color = QColor(0,0,0);
}
//QString::number(alice.nodes[alice.edges[num].node_1].color.red())
ui->textBrowser->append("一点的颜色值为: R:" + QString::number(alice.nodes[alice.edges[num].node_1].color.red()) + " G:" + QString::number(alice.nodes[alice.edges[num].node_1].color.green()) + " B:" + QString::number(alice.nodes[alice.edges[num].node_1].color.blue()));
ui->textBrowser->append("一点的颜色值为: R:" + QString::number(alice.nodes[alice.edges[num].node_2].color.red()) + " G:" + QString::number(alice.nodes[alice.edges[num].node_2].color.green()) + " B:" + QString::number(alice.nodes[alice.edges[num].node_2].color.blue()));
ui->textBrowser->append("颜色不相同");
repaint();
}
void MainWindow::on_pushButton_2_clicked()
{
isCheat = true;
for(int i = 0; i < 6; i++)
{
ui->textBrowser_2->append("点" + QString::number(i+1)+"的颜色值为: R:" + QString::number(alice.nodes[i].defaultColor.red()) + " G:" + QString::number(alice.nodes[i].defaultColor.green()) + " B:" + QString::number(alice.nodes[i].defaultColor.blue()));
}
repaint();
}
void MainWindow::on_pushButton_3_clicked()
{
isCheat = false;
ui->textBrowser_2->clear();
repaint();
}
void MainWindow::on_pushButton_4_clicked()
{
time = startTimer(3000);
}
void MainWindow::on_pushButton_5_clicked()
{
killTimer(time);
}
五、结尾
最开始我是用unity,一样的效果只需要10分钟搞完...,差不多就这样,效果很差但胜在10分钟,主打的就是一个拖拽方块、鼠标检测并随机赋予颜色。
上学期极度混,好像没上过几节课,都是翘完完,这学期的视觉和智能优化也全部翘完完。现在想想挺后悔的,以前太混了,感觉啥也不会,现在被这个什么系统能力综合培养搞的要生要死,超人家的什么微信小程序,一行代码看不懂。从微信前端到web前端到后台java再到数据库,全部看不懂,笑嘻了。
如果看的你也在混,没有考虑好将来,至少得学点东西,什么java,js。迷茫不知道走什么方向的话,也别浪费时间去玩去睡,多看某B占上的教程,至少别等到搞什么综合培养还是什么毕业设计的时候,连选什么题目都不懂,结果和我一样随便选个什么微信小程序配java后台与web端的管理啥的折磨自己。
还有个gcd的,那个不传了。