您现在的位置是:首页 >技术教程 >用零知识证明实现地图的三染色问题(qt),简单实验网站首页技术教程

用零知识证明实现地图的三染色问题(qt),简单实验

天空即为极限tk 2023-06-17 08:00:02
简介用零知识证明实现地图的三染色问题(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的,那个不传了。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。