Java 第二阶段总结
前言
这里只对四边形、五边形、以及期中考试第三题做分析。因为另外的题目挺简单的(十几行能解决的那都不是事www)。主要考察对类的设计,正则的使用,以及图形的各种性质等等。用一些ArrayList等库类可以更方便地解决问题。难度的话,我感觉还是五边形的下半部分更难一些()。如果加些时间应该可以多拿几分吧QAQ.
设计分析
类代码
这里先放四边形和五边形大作业的类代码块,代码都有注释,有需要的可以看看。下面单独的分析就不放代码了,只做分析。(类包括四边形、五边形、多边形以及点线的类代码。)
1)点类:
也没啥方法。我就后面加了个处理点集的方法:用来去除重复点和三点共线的中间点
点击查看代码
import java.util.ArrayList;
/**
* 点类
*/
public class Point {
//x、y 坐标
private double x;
private double y;
public Point() {
}
public Point(double x, double y) {
this.x = x;
this.y = y;
}
// get 、set 方法
public void setX(double x) {
this.x = x;
}
public void setY(double y) {
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
/**
* 计算两点之间的距离
*
* @param p 计算距离的点
* @return 返回距离值double
*/
public double getDistanceTo(Point p) {
return Math.sqrt(Math.pow(p.getX() - this.x, 2) + Math.pow(p.getY() - this.y, 2));
}
/**
* 比较两点是否相等
*
* @param p 比较的点
* @return 返回是否相等的 bool 值
*/
public boolean equals(Point p) {
if (p.getX() == x && p.getY() == y) {
return true;
}
return false;
}
@Override
public String toString() {
return "Point [x=" + x + ", y=" + y + "]";
}
/**
* 处理传入的点集 除去重合的点,以及 除去三点共线的中间点
* 还有bug 不能通过所有测试点
*/
public static Point[] disposePointSet(Point[] vertexes) {
int[] flag = new int[vertexes.length]; // 标记
for (int i = 0; i < flag.length; i++)
flag[i] = 0;
int num =vertexes.length;
// 检查每一个点是否重合 选择是否进行判断
for (int i = 0; i < vertexes.length; ++i) {
for (int j = i + 1; j < vertexes.length; ++j) {
if (vertexes[i].equals(vertexes[j])) {
flag[j] = 1;
num--;
}
}
}
// 任意三点共线 则去掉一个中间点 需要在去除重复点的基础上
for (int i = 0; i < vertexes.length; ++i) {
if (Line.isThreePointsCollinear(vertexes[(i-1+vertexes.length)%vertexes.length],vertexes[i],vertexes[(i+1+vertexes.length)%vertexes.length])) {
flag[i] = 1;
num--;
}
}
//处理
Point[] p = new Point[num];
for (int i = 0,j = 0; j < flag.length;j++)
if (flag[j] != 1) {
p[i++] = new Point(vertexes[j].getX(),vertexes[j].getY());
}
// for(int i=0;i< p.length;i++) {
// System.out.println(p[i].toString());
// }
return p;
}
}
2)线类:
线类用的是直线的一般式 ,用y=kx+b会不会更好一点。这个类都是前面写的了 懒得改了
我的建议是 可以用向量积(叉乘点乘)去判断和计算位置关系或者距离等值 会更方便些
点击查看代码
//直线 Ax + By + C = 0
public class Line {
// 构成直线的两个点
private Point p1;
private Point p2;
// 直线的三个参数
private double A;
private double B;
private double C;
public Line() {
}
public Line(Point s1, Point s2) {
this.A = s2.getY() - s1.getY();
this.B = s1.getX() - s2.getX();
this.C = s1.getY() * s2.getX() - s1.getX() * s2.getY();
this.p1 = s1;
this.p2 = s2;
}
// get、set 方法
public Point getP1() {
return p1;
}
public void setP1(Point x) {
this.p1 = x;
}
public Point getP2() {
return p2;
}
public void setP2(Point y) {
this.p2 = y;
}
public double getA() {
return A;
}
public void setA(double a) {
A = a;
}
public double getB() {
return B;
}
public void setB(double b) {
B = b;
}
public double getC() {
return C;
}
public void setC(double c) {
C = c;
}
/**
* 判断两点是否能构成一条直线,即两点不能重合
*
* @return 返回能否构成直线的bool值
*/
public boolean isLegal() {
if (p1.getX() == p2.getX() && p1.getY() == p2.getY()) {
return true;
}
return false;
}
/**
* 判断 该直线是否有斜率
*
* @return 返回直线是否有斜率的bool值
*/
public boolean haveSlope() {
if (p1.getX() != p2.getX())
return true;
else
return false;
}
/**
* 计算直线的斜率 (y1-y2)/(x1-x2)
*
* @return 返回直线的斜率
*/
public double getSlope() {
return (p2.getY() - p1.getY()) / (p2.getX() - p1.getX());
}
/**
* 计算点到直线的距离
*
* @param p 传入该点
* @return 返回点到直线的距离
*/
public double getDistanceToLine(Point p) {
double ji = Math.sqrt(A * A + B * B);
return Math.abs(A * p.getX() + B * p.getY() + C) / ji;
}
/**
* 判断点是否在线上
*
* @param p 需要判断的点
* @return 返回点是否在直线上的bool值
*/
public boolean isPointOnLine(Point p) {
if (((p1.getX() - p.getX()) * (p2.getY() - p.getY()) - (p1.getY() - p.getY()) * (p2.getX() - p.getX())) == 0) {
return true;
}
return false;
}
/**
* 判断 两线是否为同一条线 y = kx + b 判断k和y是否相等
*
* @param l 需要判断的线
* @return 返回两条线是否为同一条线的bool值
*/
public boolean isSameLine(Line l) {
if (this.getSlope() == l.getSlope() && this.isPointOnLine(l.getP1()) && this.isPointOnLine(l.getP2())) {
return true;
}
return false;
}
/**
* 判断两直线是否平行
*
* @param l 需要判断的直线
* @return 返回两直线是否平行的bool值
*/
public boolean isParallelWithLine(Line l) {
if (l.getSlope() == getSlope())
return true;
else
return false;
}
/**
* 计算两直线的交点
*
* @param l 需要判断的直线
* @return 返回交点的坐标
*/
public Point getIntersectPoint(Line l) {
double d = l.getA() * this.getB() - l.getB() * this.getA();
return new Point((l.getB() * this.getC() - l.getC() * this.getB()) / d,
(l.getC() * this.getA() - l.getA() * this.getC()) / d);
}
/**
* 判断两直线是否垂直
*
* @param l 需要判断的线
* @return 返回直线是否垂直的bool值
*/
public boolean isVerticalLine(Line l) {
if (p1.getDistanceTo(l.p1) == l.getDistanceToLine(this.p1)) {
return true;
}
return false;
}
/**
* 判断点是否在线的左侧
*
* @param l 传入线
* @param p 需要判断位置的点
* @return 返回点是否在线的左侧的bool值
*/
public boolean isPointOnLineLeft(Point p) {
if (((p1.getX() - p.getX()) * (p2.getY() - p.getY()) - (p1.getY() - p.getY()) * (p2.getX() - p.getX())) > 0) {
return true;
}
return false;
}
/**
* 判断点是否在线的右侧
*
* @param l 传入线
* @param p 需要判断的点
* @return 返回点是否在线的右侧的bool值
*/
public boolean isPointOnLineRight(Point p) {
if ((p1.getX() - p.getX()) * (p2.getY() - p.getY()) - (p1.getY() - p.getY()) * (p2.getX() - p.getX()) < 0) {
return true;
}
return false;
}
/**
* 判断点是否在构成线的两点之间 不包括点重合
*
* @param p 需要判断的点
* @return 返回点是否在线段两点之间的bool值
*/
public boolean isBetweenLineOfPoint(Point p) {
if ((p.getDistanceTo(p1) + p.getDistanceTo(p2)) == p1.getDistanceTo(p2) && !p.equals(p1) && !p.equals(p2))
return true;
else
return false;
}
/**
* 三点共线 且任意两点不重合
* @param 传入三个点
* @return 返回三点是否共线的Boolean 值
*/
public static boolean isThreePointsCollinear(Point p,Point p1,Point p2) {
if(!p.equals(p1)&&!p.equals(p2)&&!p2.equals(p1)&&((p1.getX() - p.getX()) * (p2.getY() - p.getY()) - (p1.getY() - p.getY()) * (p2.getX() - p.getX())) == 0) {
return true;
}
return false;
}
}
3)多边形类:
多边形类只写了一些基本的判断方法,如下
点击查看代码
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;
public class Polygon {
protected Line[] sides;
protected Point[] vertexes;
/**
* 多边形构造方法 这里默认为 p.length = size 即有相同多的点去构成对应的多边形 默认按点顺序连接
*
* @param p 构成多边形的点集Point[]
* @param size 需要构成多边形的边数int
*/
public Polygon(Point[] p, int size) {
//
if (p.length != size)
throw new RuntimeException("polygon constructor error");
// 检查每一个点是否重合 选择是否进行判断
for (int i = 0; i < p.length; ++i) {
for (int j = i + 1; j < p.length; ++j) {
if (p[i].equals(p[j])) {
}
}
}
vertexes = p;
sides = new Line[size];
// 构造边
for (int i = 0; i < p.length; ++i) {
sides[i] = new Line(vertexes[i], vertexes[(i + 1) % p.length]);
}
}
/**
* 判断点集是否能构成对应的n边形
*
* @param size 对应构成多边形的边数
* @return 返回是否能构成对应的多边形
*/
public boolean isThePolygon(int size) {
int num = vertexes.length;
// 检查每一个点是否重合 选择是否进行判断
for (int i = 0; i < vertexes.length; ++i) {
for (int j = i + 1; j < vertexes.length; ++j) {
if (vertexes[i].equals(vertexes[j])) {
num--;
}
}
}
// 任意三点共线 则去掉一个中间点
for (int i = 0; i < sides.length; ++i) {
if (sides[i].isPointOnLine(vertexes[(i + 2) % vertexes.length])) {
num--;
}
}
// 非相邻边无交点判断 即按顺序相连接
for (int i = 0; i < sides.length; i++) {
for (int j = i + 2; j < i + 2 + sides.length - 3; j++) {
// 不平行且交点未在边上
if (!sides[i].isParallelWithLine(sides[j % sides.length])
&& sides[i].isBetweenLineOfPoint(sides[i].getIntersectPoint(sides[j % sides.length]))) {
return false;
}
}
}
if (num == size)
return true;
else
return false;
}
/**
* 暴力计算分割的面积
*/
public void splitPolygon() {
}
/**
* 判断多边形的凹凸 需判断sides.length>3 即四边及以上才具有凹凸性 利用向量的叉乘 若两边叉乘值小于0 则夹角大于180
*
* @return 凸返回true 凹返回false
*/
public boolean isConcaveOrConvex() {
double multip = 0;
double a, b, c, d;
for (int i = 0; i < vertexes.length; i++) {
// 向量1
a = vertexes[i].getX() - vertexes[(i + vertexes.length - 1) % vertexes.length].getX();
b = vertexes[i].getY() - vertexes[(i + vertexes.length - 1) % vertexes.length].getY();
// 向量2
c = vertexes[(i + 1) % vertexes.length].getX() - vertexes[i].getX();
d = vertexes[(i + 1) % vertexes.length].getY() - vertexes[i].getY();
// 叉乘 交叉相乘
multip = (a * d) - (c * b);
if (multip < 0)
return false;
}
return true;
}
/**
* 计算对应多边形的周长 循环计算每边长度相加
*
* @return 返回该多边形的周长
*/
public double getPerimeter() {
double sum = 0;
for (int i = 0; i < vertexes.length; i++) {
sum += vertexes[i].getDistanceTo(vertexes[(i + 1) % vertexes.length]);
}
return sum;
}
/**
* 计算对应多边形的面积 利用叉乘的定义
*
* @return 返回该多边形的面积
*/
public double getArea() {
double area = 0;
double a, b, c, d;
// 从第二点开始遍历节点
for (int i = 1; i < vertexes.length - 1; i++) {
// 向量a
a = vertexes[i].getX() - vertexes[0].getX();
b = vertexes[i].getY() - vertexes[0].getY();
// 向量b
c = vertexes[i + 1].getX() - vertexes[0].getX();
d = vertexes[i + 1].getY() - vertexes[0].getY();
// 叉乘
area += a * d - b * c;
}
return area / 2;
}
// public int getIntersectionNumPolygon(Line l) {
//
// }
/**
* 判断点是否与多边形的顶点重合
*
* @param p 需要判断的点
* @return 返回该点是否与多边形顶点重合的bool值
*/
public boolean isPolygonVertex(Point p) {
for (Point vertex : vertexes) {
if (p.equals(vertex))
return true;
}
return false;
}
/**
* 判断点是否在多边形的边上 包括顶点重合的情况
*
* @param p 需要判断的点
* @return 返回该点是否在边上的bool值
*/
public boolean isPointOnPolygonSide(Point p) {
// 分别与每边比较
for (int i = 0; i < sides.length; ++i) {
if ((p.getDistanceTo(vertexes[i]) + p.getDistanceTo(vertexes[(i + 1) % vertexes.length])) == sides[i].getP1()
.getDistanceTo(sides[i].getP2()))
return true;
}
return false;
}
/**
* 判断点是否在多边形上 分别判断顶点和边的情况
*
* @param p 需要判断的点
* @return 返回是否在多边形边上的bool值
*/
public boolean isPointOnPolygon(Point p) {
if (isPolygonVertex(p) || isPointOnPolygonSide(p)) {
return true;
} else
return false;
}
/**
* 判断线是否是多边形的边 即与边重合
*
* @param l
* @return
*/
public boolean haveCoincideLine(Line l) {
for (Line line : sides) {
if (l.isSameLine(line)) {
return true;
}
}
return false;
}
/**
* 判断 点是否在多边形里 射线法判断 以传入点 p(x0,y0)、p1(x0 + 1, y0) 构造一线 l 计算 l 与多边形各边交点,
* 并统计交点 x坐标大于 x0 的数量 c 若c为奇数则点一定在多边形内 c为偶数则在多边形外
*
* @param p 需要判断的点
* @return 是否在多边形里的bool值
*/
public boolean isPointInPolygon(Point p) {
Traingle tra[] =new Traingle[vertexes.length];
double sum=0;
for(int i=0;i<vertexes.length;i++) {
tra[i] = new Traingle(new Point[] {p,vertexes[i],vertexes[(i+1+vertexes.length)%vertexes.length]});
}
for(int i=0;i<tra.length;i++)
sum += tra[i].getArea();
return sum == this.getArea();
// int cnt = 0;
// Point p1 = new Point(p.getX() + 1, p.getY());
// Line l = new Line(p1, p);
// for (Line line : sides) {
// Point cross = line.getIntersectPoint(l);
// if (line.isBetweenLineOfPoint(cross))
// if (cross.getX() > p.getX()) {
// ++cnt;
// }
// }
// return cnt % 2 != 0;
}
}
4)四边形类:
点击查看代码
public class Quadrangle extends Polygon {
// 构造函数
public Quadrangle(Point[] p) {
super(p, 4);
}
// 平行四边形
public boolean isParallelQuard() {
if (this.vertexes[0].getDistanceTo(vertexes[1]) == this.vertexes[2].getDistanceTo(vertexes[3])
&& this.vertexes[1].getDistanceTo(vertexes[2]) == this.vertexes[3].getDistanceTo(vertexes[0])) {
return true;
} else
return false;
}
// 矩形
public boolean isRectangle() {
if (this.isParallelQuard()) {
if (this.sides[0].isVerticalLine(this.sides[1])) {
return true;
}
}
return false;
}
// 菱形
public boolean isRhombus() {
if (this.isParallelQuard()) {
if (this.vertexes[0].getDistanceTo(vertexes[1]) == this.vertexes[2].getDistanceTo(vertexes[1])) {
return true;
}
}
return false;
}
// 正方形
public boolean isSquare() {
if (this.isRectangle()) {
if (this.vertexes[0].getDistanceTo(vertexes[1]) == this.vertexes[1].getDistanceTo(vertexes[2])) {
return true;
}
}
return false;
}
// 返回四边形交点数量
public int getIntersectionNum(Line l) {
int num = 0, leftn = 0, rightn = 0;
for (int i = 0; i < this.vertexes.length; i++) {
if (l.isPointOnLineLeft(vertexes[i])) {
leftn++;
}
if (l.isPointOnLineRight(vertexes[i])) {
rightn++;
}
}
// 四边形判断 凹凸
if (this.isConcaveOrConvex()) {
if (leftn == 0 || leftn == 4)
num = 0;
else if ((leftn == 3 && rightn == 0) || (leftn == 0 && rightn == 3))
num = 1;
else
num = 2;
} else {
if (leftn == 0 || leftn == 4)
num = 0;
else if ((leftn == 3 && rightn == 0) || (leftn == 0 && rightn == 3))
num = 1;
else if ((leftn == 1 && rightn == 2) || (leftn == 2 && rightn == 1))
num = 3;
else if (leftn == 2 && rightn == 2)
num = 4;
else
num = 2;
}
return num;
}
// 分割面积 四边形分割
public Polygon splitQuadrangle(Line l) {
Polygon polygon = new Polygon();
Point[] p = new Point[2];
// 分割成两个四边形
for (int i = 0; i < 2; i++) {
if (this.isPointOnPolygon(l.getIntersectPoint(sides[i]))
&& this.isPointOnPolygon(l.getIntersectPoint(sides[i + 2]))) {
p[0] = new Point(l.getIntersectPoint(sides[i]).getX(), l.getIntersectPoint(sides[i]).getY());
p[1] = new Point(l.getIntersectPoint(sides[i + 2]).getX(), l.getIntersectPoint(sides[i + 2]).getY());
polygon = new Quadrangle(new Point[] { p[0], vertexes[i + 1], vertexes[i + 2], p[1] });
}
}
// 分割成一个三角和一个四边形
for (int i = 0; i < sides.length; i++) {
if (this.isPointOnPolygon(l.getIntersectPoint(sides[i]))
&& this.isPointOnPolygon(l.getIntersectPoint(sides[(i + 1) % 4]))) {
p[0] = new Point(l.getIntersectPoint(sides[i]).getX(), l.getIntersectPoint(sides[i]).getY());
p[1] = new Point(l.getIntersectPoint(sides[(i + 1) % 4]).getX(),
l.getIntersectPoint(sides[(i + 1) % 4]).getY());
polygon = new Traingle(new Point[] {p[0], p[1], vertexes[(i + 1) % 4]});
break;
}
}
return polygon;
}
}
5)五边形类:
点击查看代码
import java.util.ArrayList;
public class Pentagon extends Polygon {
public Pentagon(Point[] p) {
super(p, 5);
}
/**
* 求直线与五边形的交点数量
*
* @param l 需要判断的直线
* @return 返回五边形交点数量
*/
public int getIntersectionNum(Line l) {
int num = 0,left = 0,right=0;
for (int i = 0; i < vertexes.length; i++) {
if (l.isPointOnLineLeft(vertexes[i])) {
left++;
}if(l.isPointOnLineRight(vertexes[i])) {
right++;
}
}
if(left==5||left==0)
num=0;
else if((left==4 &&right==0)||(left==0 &&right==4))
num=1;
else num=2;
return num;
}
/**
* 求线切割后的面积
* @param l 传入线
*/
public void splitByLine(Line l) {
int place[] =new int[2],j = 0;//存 交点在线上的位置 包括交点与顶点重合
int flag = 0; //动态确定加入点的位置
ArrayList<Point> points = new ArrayList<Point>();
for(int i=0;i<vertexes.length;i++)
points.add(vertexes[i]);
//对交点操作
for(int i=0;i<vertexes.length&&j<2;i++) {
if (vertexes[i].equals(sides[i].getIntersectPoint(l))) {
place[j++] = i;
}
else if(sides[i].isBetweenLineOfPoint(sides[i].getIntersectPoint(l))) {
points.add(i+1+flag, sides[i].getIntersectPoint(l));
flag++;
place[j++] = i + flag;
}
}
//计算面积
Point p[] = new Point[place[1]-place[0]+1];
for(int i=0;i<p.length;i++) {
p[i] = new Point(points.get(i).getX(),points.get(i).getY());
}
Polygon po =new Polygon(p,p.length);
String temp = String.format("%.3f",po.getArea());
double area1 = Double.parseDouble(temp);
temp = String.format("%.3f",this.getArea() - po.getArea());
double area2 = Double.parseDouble(temp);
System.out.print(" " + Math.min(area1,area2) + " "
+ Math.max(area1,area2));
}
}
6)输入处理类:
对字符串进行处理,先格式匹配判断合法,再分离出对应的点集
点击查看代码
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Inputer {
private String str;
public Inputer(String string) {
str = string;
}
/**
* 对传入的字符串进行匹配 判断输入是否符合要求
*
* @return 返回是否匹配成功的bool值
*/
public boolean matchString() {
String regEx = "^[1-6]:([+-]?\\d+(\\.\\d+)?,[+-]?\\d+(\\.\\d+)?\\s?)+$";
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(str);
if (!m.matches()) {
System.out.print("Wrong Format");
return false;
}
//特判 0x 的情况
String po = str.substring(2, str.length());
String[] x = po.split("[, ]");
for (String i : x) {
String[] j = i.split("\\.");
if (!j[0].matches("[+-]?(0|[1-9][0-9]*)")) {
System.out.print("Wrong Format");
return false;
}
}
return true;
}
// 返回 选项
public String selectNum() {
return str.substring(0, 1);
}
/**
* 对字符串进行处理 分离点集
*
* @return 返回输入的点集
*/
public Point[] disposeString() {
String[] num = str.split("[:, ]"), a = str.split(" ");
Point[] p = new Point[a.length];
for (int i = 1, j = 0; i < num.length && j < a.length; i += 2, j++) {
p[j] = new Point();
p[j].setX(Double.parseDouble(num[i]));
p[j].setY(Double.parseDouble(num[i + 1]));
}
return p;
}
}
7-2 点线形系列4-凸四边形的计算
当时做这题的时候还没有写多边形类,就是把每种情况都列出来(反正也就两三种情况 ovo),就感觉还在写c,对类没有清楚的认识。
题目要求如下
用户输入一组选项和数据,进行与四边形有关的计算。
以下四边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
1:输入四个点坐标,判断是否是四边形、平行四边形,判断结果输出true/false,结果之间以一个英文空格符分隔。
2:输入四个点坐标,判断是否是菱形、矩形、正方形,判断结果输出true/false,结果之间以一个英文空格符分隔。 若四个点坐标无法构成四边形,输出"not a quadrilateral"
3:输入四个点坐标,判断是凹四边形(false)还是凸四边形(true),输出四边形周长、面积,结果之间以一个英文空格符分隔。 若四个点坐标无法构成四边形,输出"not a quadrilateral"
4:输入六个点坐标,前两个点构成一条直线,后四个点构成一个四边形或三角形,输出直线与四边形(也可能是三角形)相交的交点数量。如果交点有两个,再按面积从小到大输出四边形(或三角形)被直线分割成两部分的面积(不换行)。若直线与四边形或三角形的一条边线重合,输出"The line is coincide with one of the lines"。若后四个点不符合四边形或三角形的输入,输出"not a quadrilateral or triangle"。
后四个点构成三角形的情况:假设三角形一条边上两个端点分别是x、y,边线中间有一点z,另一顶点s:
1)符合要求的输入:顶点重复或者z与xy都相邻,如x x y s、x z y s、x y x s、s x y y。此时去除冗余点,保留一个x、一个y。
2) 不符合要求的输入:z 不与xy都相邻,如z x y s、x z s y、x s z y
5:输入五个点坐标,输出第一个是否在后四个点所构成的四边形(限定为凸四边形,不考虑凹四边形)或三角形(判定方法见选项4)的内部(若是四边形输出in the quadrilateral/outof the quadrilateral,若是三角形输出in the triangle/outof the triangle)。如果点在多边形的某条边上,输出"on the triangle或者on the quadrilateral"。若后四个点不符合四边形或三角形,输出"not a quadrilateral or triangle"。
输入格式:
基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。点的x、y坐标之间以英文","分隔,点与点之间以一个英文空格分隔。
输出格式:
基本输出格式见每种选项的描述。
异常情况输出:
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
注意:输出的数据若小数点后超过3位,只保留小数点后3位,多余部分采用四舍五入规则进到最低位。小数点后若不足3位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333,1.0按格式输出为1.0
选项1、2、3中,若四边形四个点中有重合点,输出"points coincide"。
选项4中,若前两个输入线的点重合,输出"points coincide"。
这题写到面一直有两个点过不去,de了半天才发现1,3 位置点重复也行,就加了一个判断。另一个测试点是逻辑判断问题,就是四边形,三角形要先判断是否能构成,再判断线与边重合的情况(好像是这样,时间久有点忘了QAQ)
类图以及报表:


点线形系列5-凸五边形的计算
做这题之前把类重构好,直接用多边形类真的很方便,可以少写很多东西。当时写的时候时间有点紧,第二部分就没写多少。凑合看QAQ。
题目要求如下
用户输入一组选项和数据,进行与五边形有关的计算。
以下五边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的
顶点相邻。
选项包括:
1:输入五个点坐标,判断是否是五边形,判断结果输出 true/false。
2:输入五个点坐标,判断是凹五边形(false)还是凸五边形(true),如果是凸五边形,则再输出五边形周
长、面积,结果之间以一个英文空格符分隔。 若五个点坐标无法构成五边形,输出"not a pentagon"
3:输入七个点坐标,前两个点构成一条直线,后五个点构成一个五边形、四边形或三角形,输出直线与五
边形、四边形或三角形相交的交点数量。如果交点有两个,再按面积从小到大输出被直线分割成两部分的
面积(不换行)。若直线与多边形形的一条边线重合,输出"The line is coincide with one of the lines"。若
后五个点不符合五边形输入,若前两点重合,输出"points coincide"。
4:输入十个点坐标,前、后五个点分别构成一个凸多边形(三角形、四边形、五边形),判断它们两个之
间是否存在包含关系(一个多边形有一条或多条边与另一个多边形重合,其他部分都包含在另一个多边形
内部,也算包含)。
两者存在六种关系:1、分离(完全无重合点) 2、连接(只有一个点或一条边重合) 3、完全重合 4、
被包含(前一个多边形在后一个多边形的内部)5、交错 6、包含(后一个多边形在前一个多边形的内部)。
各种关系的输出格式如下:
1、no overlapping area between the previous triangle/quadrilateral/ pentagon and the
following triangle/quadrilateral/ pentagon
2、the previous triangle/quadrilateral/ pentagon is connected to the following
triangle/quadrilateral/ pentagon
3 、 the previous triangle/quadrilateral/ pentagon coincides with the following
triangle/quadrilateral/ pentagon
4 、 the previous triangle/quadrilateral/ pentagon is inside the following
triangle/quadrilateral/ pentagon
5、the previous triangle/quadrilateral/ pentagon is interlaced with the following
triangle/quadrilateral/ pentagon
6 、 the previous triangle/quadrilateral/ pentagon contains the following
triangle/quadrilateral/ pentagon
5:输入十个点坐标,前、后五个点分别构成一个凸多边形(三角形、四边形、五边形),输出两个多边形
公共区域的面积。注:只考虑每个多边形被另一个多边形分割成最多两个部分的情况,不考虑一个多边形
将另一个分割成超过两个区域的情况。
6:输入六个点坐标,输出第一个是否在后五个点所构成的多边形(限定为凸多边形,不考虑凹多边形),
的内部(若是五边形输出 in the pentagon/outof the pentagon,若是四边形输出 in the quadrilateral/outof
the quadrilateral,若是三角形输出 in the triangle/outof the triangle)。输入入错存在冗余点要排除,冗余
点的判定方法见选项 5。如果点在多边形的某条边上,输出"on the triangle/on the quadrilateral/on the
pentagon"。
以上 3、4、5、6 选项中,若输入的点无法构成多边形,则输出"not a polygon"。输入的五个点坐标可
能存在冗余,假设多边形一条边上两个端点分别是 x、y,边线中间有一点 z,另一顶点 s:
1)符合要求的输入:顶点重复或者 z 与 xy 都相邻,如:x x y s、x z y s、x y x s、s x y y。此时去除冗余点,
保留一个 x、一个 y。
2) 不符合要求的输入:z 不与 xy 都相邻,如:z x y s、x z s y、x s z y
输入格式:
基本格式:选项+":"+坐标 x+","+坐标 y+" "+坐标 x+","+坐标 y。点的 x、y 坐标之间以英文","
分隔,点与点之间以一个英文空格分隔。
输出格式:
基本输出格式见每种选项的描述。
异常情况输出:
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
注意:输出的数据若小数点后超过 3 位,只保留小数点后 3 位,多余部分采用四舍五入规则
进到最低位。小数点后若不足 3 位,按原始位数显示,不必补齐。例如:1/3 的结果按格式
输出为 0.333,1.0 按格式输出为 1.0
类图以及报表:


期中考试-7-3 点线面问题再重构
期中考试的内容真的很简单啊,这里就只看第三题,前面两题直接把以前写的点线类拿过来用即可,没什么好讲的。
在“点与线(继承与多态)”题目基础上,对题目的类设计进行重构,增加容器类保存点、线、面对象,并对该容器进行相应增、删、遍历操作。
在原有类设计的基础上,增加一个GeometryObject容器类,其属性为ArrayList
增加该类的add()方法及remove(int index)方法,其功能分别为向容器中增加对象及删除第index - 1(ArrayList中index>=0)个对象
在主方法中,用户循环输入要进行的操作(choice∈[0,4]),其含义如下:
1:向容器中增加Point对象
2:向容器中增加Line对象
3:向容器中增加Plane对象
4:删除容器中第index - 1个数据,若index数据非法,则无视此操作
0:输入结束
示例代码如下:
choice = input.nextInt(); while(choice != 0) { switch(choice) { case 1://insert Point object into list ... break; case 2://insert Line object into list ... break; case 3://insert Plane object into list ... break; case 4://delete index - 1 object from list int index = input.nextInt(); ... } choice = input.nextInt(); }
输入结束后,按容器中的对象顺序分别调用每个对象的display()方法进行输出。
以下情况为无效作业
- 无法运行
- 设计不符合所给类图要求
- 未通过任何测试点测试
- 判定为抄袭
输入格式:
switch(choice) { case 1://insert Point object into list 输入“点”对象的x,y值 break; case 2://insert Line object into list 输入“线”对象两个端点的x,y值 break; case 3://insert Plane object into list 输入“面”对象的颜色值 break; case 4://delete index - 1 object from list 输入要删除的对象位置(从1开始) ... }
输出格式:
- Point、Line、Plane的输出参考题目2
- 删除对象时,若输入的index超出合法范围,程序自动忽略该操作
代码如下:
点击查看代码
import java.util.ArrayList;
import java.util.Scanner;
public class Mid_Text {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
GeometryObject g = new GeometryObject();
int choice = in.nextInt();
double x,y;
String color;
while(choice != 0) {
switch(choice) {
case 1://insert Point object into list
x = in.nextDouble();
y = in.nextDouble();
if(x <=0 || x>200 || y <=0 || y>200) {
System.out.print("Wrong Format");
break;
}
Point p = new Point(x,y);
g.add(p);
break;
case 2://insert Line object into list
x = in.nextDouble();
y = in.nextDouble();
if(x <=0 || x>200 || y <=0 || y>200) {
System.out.print("Wrong Format");
break;
}
Point p1 = new Point(x,y);
x = in.nextDouble();
y = in.nextDouble();
if(x <=0 || x>200 || y <=0 || y>200) {
System.out.print("Wrong Format");
break;
}
Point p2 = new Point(x,y);
color = in.next();
Line l = new Line(p1,p2,color);
g.add(l);
break;
case 3://insert Plane object into list
Plane plane = new Plane();
color = in.next();
plane.setColor(color);
g.add(plane);
break;
case 4://delete index - 1 object from list
int index = in.nextInt();
if(g.getList().size() < index)
break;
else
g.remove(index);
}
choice = in.nextInt();
}
for(int i=0;i<g.getList().size();i++) {
g.getList().get(i).display();
}
}
}
abstract class Element{
public abstract void display();
}
class Point extends Element{
private double x;
private double y;
public Point() {
}
public Point(double x, double y) {
this.x = x;
this.y = y;
}
// get 、set 方法
public void setX(double x) {
this.x = x;
}
public void setY(double y) {
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
@Override
public void display() {
System.out.printf("(%.2f,%.2f)\n", x,y);
}
/**
* 计算两点之间的距离
*
* @param p 计算距离的点
* @return 返回距离值double
*/
public double getDistanceTo(Point p) {
return Math.sqrt(Math.pow(p.getX() - this.x, 2) + Math.pow(p.getY() - this.y, 2));
}
}
class Line extends Element{
// 构成线段的两个点
private Point point1;
private Point point2;
private String color;
public Line() {
}
public Line(Point p1, Point p2,String color) {
this.point1 = p1;
this.point2 = p2;
this.color = color;
}
public Point getPoint1() {
return point1;
}
public void setPoint1(Point point1) {
this.point1 = point1;
}
public Point getPoint2() {
return point2;
}
public void setPoint2(Point point2) {
this.point2 = point2;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
//求线段的距离
public double getDistance() {
return Math.sqrt(Math.pow(point1.getX() - point2.getX(), 2) + Math.pow(point1.getY() - point2.getY(), 2));
}
@Override
public void display() {
System.out.println("The line's color is:"+this.color);
System.out.println("The line's begin point's Coordinate is:");
point1.display();
System.out.println("The line's end point's Coordinate is:");
point2.display();
System.out.print("The line's length is:");
System.out.printf("%.2f\n", this.getDistance());
}
}
class Plane extends Element{
String color;
public Plane(){
}
public Plane(String color){
this.color = color;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public void display() {
System.out.println("The Plane's color is:" + this.color);
}
}
class GeometryObject{
private ArrayList<Element> list = new ArrayList<Element>();
public GeometryObject() {
}
public void remove(int index) {
list.remove(index - 1);
}
public void add(Element element) {
list.add(element);
}
public ArrayList<Element> getList() {
return list;
}
}
类图以及报表:


踩坑心得
发现自己debug的能力真的不行,有时候会因为一个测试点de半天都发现不了。有时候bug de出来了,但又会出现新的bug。属于是正常操作了QAQ
需要对输出的数格式化处理时,String.format()与System.out.printf() 都能用,只不过得看情况选择。
改进建议
- 写代码时,应该先弄清楚类与类之间的关系,设计好类的结构,画好类图,这样思路才能更清晰。
- 可以多用用Java库中写好的类方法,以及像ArrayList、StringBuffer等可变容量的结构,这样会使程序更加灵活,不用每次都去更改数组的大小。
- 可以在类中改写toString方法,可以更方便的进行调试分析。需不要每次都加一个System.out.print去输出信息。、
- 每个类方法以及属性,包括方法中的每个步骤都尽量在旁边写注释,这样才不至于在写完后就忘了怎么来的。
- 每个类应该遵循单一职责的原则,即属于该类的职责就放到该类下,反之则不放入。(在五边形的分割面积时就偷懒直接在类方法下直接输出了T_T ,其实可以直接写一个output方法,对输出的内容单独进行处理,这样条理就十分清晰了)
总结
总的来说,经过这几次大作业的学习,收获还是非常多的。学习到了很多关于java的知识点,比如说Obeject类等。

浙公网安备 33010602011771号