给四条线段,判断是否是矩形

今天又做了一个题目,这个感觉比昨天的复杂一些,代码量都多了一些。

题目是这样的,要求输入一系列点坐标,一共输入16个整型,两个两个一对,就是8个坐标,再两个两个一对,就是4条线段,判断这4条线段,是否围成一个矩形。

想了下,大概分为如下几个步骤来做:
1. 获取输入,组织数据结构,怎么存储这些点,这些线段。
2. 然后就是怎么判断矩形。

怎么判断矩形?我又分为下面几个步骤来考虑:
1. 先判断四条线段是否首尾相连在一起。可以判定图形是否是封闭图形。
2. 四条线段中对于任意一条线段与其非相邻线段是否平行。做两次平行判断,可以判定为平行四边形。
3. 在平行四边形的基础上,判断任意两条相邻的线段是否垂直。有垂直就是直角了,也就是矩形。
4. 判断每一条线段的长度都不为0。

首先我是自定了一些数据结构来存储输入的数据,Point, Line, Rectangle, RectangleSet。

然后通过输入获取了点的信息后,需要做一个首尾相连的判断。我的基本思路是,首先将第一条线段作为起始线段,任意选一个端点作为last端点。然后遍历剩下的线段,判断每一条线段中的两个端点是否与last端点相同,如果相同,就把这条线段的另一个端点赋值给last端点,这样两条线段就连接上了,最后循环结束后,判断下第一条线段的另一个端点与最后不断赋值得到的last端点是否是同一个点,就完事了。

在这个遍历的过程中,我添加了一个order的属性,第一条起始线段order为1,其他的order为-1,当发现一条与第一条相连的线段是,将其order值改为2,依序进行,就按顺序将首尾相连的线段标记为1,2,3,4的order值了。

有了order值后,如果图形是个首尾相连的封闭图形,那么就判断平行了,有了order值就很方便,只需要判断1与3是否平行,2与4是否平行即可。

平行如果也达成了,那么就随便判断1与2是否是垂直关系就好了。

最后再判断下每条线段是否为0长度,这样就可以判断是否是矩形了。

因为是用C++写的,各种坑啊……VS调试起来也不熟练。

代码如下:

/*
输入四个点,判断是否是矩形
*/

#include
using namespace std;

class Point {
public:
    int x, y = -1;  //默认值负一
    Point() {}

    ~Point() {}

    bool equals (Point p) {
        if (p.x == x && p.y == y) {
            return true;
        } else {
            return false;
        }
    }
};

class Line {
public:
    Point* start;
    Point* end;
    int order;  //排序值

    Line() {
        start = NULL;
        end = NULL;
        order = -1;

    }
    ~Line() {}

    bool isParallel(Line* line) {
        int deltaX1 = end->x - start->x;
        int deltaY1 = end->y - start->y;

        int deltaX2 = line->end->x - line->start->x;
        int deltaY2 = line->end->y - line->start->y;

        if (deltaX1 == 0 || deltaX2 == 0) {
            if (deltaX1 == deltaX2) {
                return true;
            }
            else {
                return false;
            }
        }
        else {
            if (1.0 * deltaY1 / deltaX1 == 1.0* deltaY2 / deltaX1) {
                return true;
            }
            else {
                return false;
            }
        }
    }

    bool isVertical(Line* line) {
        int deltaX1 = end->x - start->x;
        int deltaY1 = end->y - start->y;

        int deltaX2 = line->end->x - line->start->x;
        int deltaY2 = line->end->y - line->start->y;

        if ((deltaX1 == 0 && deltaY2 == 0) || (deltaX2 == 0 && deltaY1 == 0)) {
            //cout << "分母是0" << endl;
            return true;
        }

        double result = 1.0 * deltaY1 / deltaX1 * deltaY2 / deltaX2;
        //cout << "result:" <equals(*end)) {
            return true;
        }
        else {
            return false;
        }
    }

};

class Rectangle {
public:
    Line* lineSet = NULL;

    Rectangle(){
        lineSet = new Line[4];
    }

    ~Rectangle(){
        //delete lineSet;
    }

    void addLine(int index, Line line) {
        if (lineSet == NULL) {
            lineSet = new Line[4];
        }
        lineSet[index] = line;
    }

    bool isRectangle() {

        //先判断是否首尾相连
        Line firstLine = lineSet[0];
        int currentOrder = lineSet[0].order = 1;

        Point lastPoint = *firstLine.start;
        Point firstPoint = *firstLine.end;

        for (int time = 1; time <= 3; time++) { //需要判断三次吧

            bool isFound = false;

            for (int i = 0; i < 4 && !isFound; i++) {   //从第一条开始

                if (lineSet[i].order == -1) {   //未排序的才可以进行判断
                    if (lineSet[i].start->equals(lastPoint)) {
                        lineSet[i].order = ++currentOrder;  //前自增,先自增再赋值
                        //cout << "order:" << currentOrder << endl;
                        lastPoint = *lineSet[i].end;
                        isFound = true;
                    }
                    else if (lineSet[i].end->equals(lastPoint)) {
                        lineSet[i].order = ++currentOrder;
                        //cout << "order:" << currentOrder << endl;
                        lastPoint = *lineSet[i].start;
                        isFound = true;
                    }

                    if (i == 3 && isFound == false) {
                        return false;
                    }
                }

                /*
                Line b1 = lineSet[0];
                Line b2 = lineSet[1];
                Line b3 = lineSet[2];
                Line b4 = lineSet[3];
                */
            }
        }

        if (!lastPoint.equals(firstPoint)) {
            return false;
        }

        //首尾相连通过
        /*
        Line a1 = lineSet[0];
        Line a2 = lineSet[1];
        Line a3 = lineSet[2];
        Line a4 = lineSet[3];


        Line* l1 = getLineByOrder(1);
        Line* l2 = getLineByOrder(2);
        Line* l3 = getLineByOrder(3);
        Line* l4 = getLineByOrder(4);
        */

        //第二步,判断是否平行
        if (!getLineByOrder(1)->isParallel(getLineByOrder(3)) || !getLineByOrder(2)->isParallel(getLineByOrder(4))) {
            //cout << "不平行" << endl;
            return false;
        }

        //第三步,判断一个垂直即可
        bool hasVertical = false;
        for (int i = 0; i < 4 && !hasVertical; i++) {
            if (getLineByOrder((i + 1) % 4)->isVertical(getLineByOrder((i + 2) % 4))) {
                hasVertical = true;
            }

            if (i = 3 && !hasVertical) {
                //cout << "不垂直" << endl;
                return false;
            }
        }

        //第四步,判断有没有某条线是0长度
        for (int i = 0; i < 4; i++) {
            if (lineSet[i].isZeroLenght()) {
                //cout << "0长度" << endl;
                return false;
            }
        }

        return true;
    }

    Line* getLineByOrder(int order) {
        for (int i = 0; i < 4; i++) {
            if (lineSet[i].order == order) {
                return &lineSet[i];
            }
        }
        return NULL;
    }

};

class RectangleSet {
public:

    Rectangle* rectangleSet = NULL;

    RectangleSet(){}
    RectangleSet(int count) {
        rectangleSet = new Rectangle[count];
    }
    ~RectangleSet(){}

};
void run1040() {

    int m = 0;
    cin >> m;

    int x1, x2, y1, y2 = -1;

    RectangleSet* set = new RectangleSet(m);

    for (int i = 0; i < m; i++) {

        Rectangle* rec = new Rectangle();

        for (int j = 1; j <= 4; j++) {  //一轮输入中需要输4次

            Point* p1 = new Point();
            Point* p2 = new Point();
            Line* line = new Line();

            //cout << "请输入四个整型"<> x1 >> y1 >> x2 >> y2;

            /*
            cout << x1 << endl;
            cout << x2 << endl;
            cout << y1 << endl;
            cout << y2 << endl;
            */

            p1->x = x1;
            p1->y = y1;

            p2->x = x2;
            p2->y = y2;

            line->start = p1;
            line->end = p2;

            rec->addLine(j - 1, *line);

        }
        set->rectangleSet[i] = *rec;
    }

    for (int i = 0; i < m; i++) {
        Rectangle rec = set->rectangleSet[i];
        if (rec.isRectangle()) {
            cout << "YES" << endl;
        }
        else {
            cout << "NO" << endl;
        }

    }
}

心得体会:感觉C++真的需要不断的练习才能熟练,这是我写的第二个比较复杂的C++程序了……这个解题的程序在hiro上并没有跑成功,它说我答案不对,题目给的三个测试用例,我都通过了,但又不知道如果搞到更多的测试用例……

你可能感兴趣的:(图形,C++,算法)