您的位置:首页 > 编程语言 > C语言/C++

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

2015-06-11 20:25 399 查看
今天又做了一个题目,这个感觉比昨天的复杂一些,代码量都多了一些。

题目是这样的,要求输入一系列点坐标,一共输入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<iostream>
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:" <<result<< endl;
if (result == 1 || result == -1) {
return true;
}
else {
return false;
}
}

bool isZeroLenght() {
if (start->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 << "请输入四个整型"<<endl;
cin >> 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++