题目集4、5以及期中考试的总结性Blog
前言:这两次的pta题目也是多边形系列的,题目要求复杂,测试点多,难度高,虽然题目数量少了,但所需时间更多。知识点涉及的其实主要还是类的运用,只是为实现功能所需的各种算法难度较大,需要借鉴网上的方法。由于之前就没能跟上,这两次作业很完成度都低。相比之下期中考试就简单很多了,主要考察的是基础知识,题目不仅给出了类图,还有部分所需代码可以使用。
7-1 sdut-String-2 识蛟龙号载人深潜,立科技报国志(II)(正则表达式)
输入格式:
读入关于蛟龙号载人潜水器探测数据的多行字符串,每行字符不超过80个字符。
以"end"结束。
输出格式:
与输入行相对应的各个整数之和。
代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args){
boolean flag = true;
Scanner input = new Scanner(System.in);
while (flag){
int sum = 0; //用于计算总和
int num = 0; //用于依次存放数字
String str = input.nextLine();
String[] s = str.split("\\D+");
// \D+表示一个或多个非数字字符
//利用正则表达式将数字存放在数组s[]中
if (str.equals("end"))
break; //跳出循环
for (int i = 0;i < s.length;i++){
if (!s[i].equals("")){
num = Integer.parseInt(s[i]); //类型转换
sum += num;
}
}
System.out.println(sum);
}
}
}
这题还是很简单的,就是熟悉一下正则表达式的用法。还有就是while(flag)实现循坏输入。
采坑心得:String需要进行类型强制转换用来计算。
改进建议:暂无
7-3 设计一个银行业务类
编写一个银行业务类BankBusiness,具有以下属性和方法:
(1)公有、静态的属性:银行名称bankName,初始值为“中国银行”。
(2)私有属性:账户名name、密码password、账户余额balance。
(3)银行对用户到来的欢迎(welcome)动作(静态、公有方法),显示“中国银行欢迎您的到来!”,其中“中国银行”自动使用bankName的值。
(4)银行对用户离开的提醒(welcomeNext)动作(静态、公有方法),显示“请收好您的证件和物品,欢迎您下次光临!”
(5)带参数的构造方法,完成开户操作。需要账户名name、密码password信息,同时让账户余额为0。
(6)用户的存款(deposit)操作(公有方法,需要密码和交易额信息),密码不对时无法存款且提示“您的密码错误!”;密码正确、完成用户存款操作后,要提示用户的账户余额,例如“您的余额有1000.0元。”。
(7)用户的取款(withdraw)操作(公有方法,需要密码和交易额信息)。密码不对时无法取款且提示“您的密码错误!”;密码正确但余额不足时提示“您的余额不足!”;密码正确且余额充足时扣除交易额并提示用户的账户余额,例如“请取走钞票,您的余额还有500.0元。”。
编写一个测试类Main,在main方法中,先后执行以下操作:
(1)调用BankBusiness类的welcome()方法。
(2)接收键盘输入的用户名、密码信息作为参数,调用BankBusiness类带参数的构造方法,从而创建一个BankBusiness类的对象account。
(3)调用account的存款方法,输入正确的密码,存入若干元。密码及存款金额从键盘输入。
(4)调用account的取款方法,输入错误的密码,试图取款若干元。密码及取款金额从键盘输入。
(5)调用account的取款方法,输入正确的密码,试图取款若干元(取款金额大于余额)。密码及取款金额从键盘输入。
(6)调用account的取款方法,输入正确的密码,试图取款若干元(取款金额小于余额)。密码及取款金额从键盘输入。
(7)调用BankBusiness类的welcomeNext()方法。
部分代码:
//银行类
class BankBussiness {
public static String bankName = "中国银行";
private String name,password;
private double balance; //声明账号密码余额
public static void welcome() {
System.out.println(bankName+"欢迎您的到来!");
}
public static void welcomeNext() {
System.out.println("请收好您的证件和物品,欢迎您下次光临!");
}
public void openAccount(String name,String password) {
//初始化
this.name = name;
this.password = password;
balance = 0;
}
public void deposit(String password,double numIn) {
if(this.password.equals(password)) { //判断密码是否正确
balance += numIn;
System.out.println("您的余额有"+balance+"元。");
}
else
System.out.println("您的密码错误!");
}
public void withdraw(String password,double numOut) {
if(this.password.equals(password)) {
if(balance>=numOut) {
balance -= numOut;
System.out.println("请取走钞票,您的余额还有"+balance+"元。");
}
else
System.out.println("您的余额不足!");
}
else
System.out.println("您的密码错误!");
}
}
这题考察的是类与方法的运用,将所需要完成的功能放在银行类里封装成方法,再用主函数调用,实现问题的要求。
采坑心得:不熟悉this的含义,理解错误导致部分使用的地方出错
改进建议:暂无
7-2 点线形系列4-凸四边形的计算
用户输入一组选项和数据,进行与四边形有关的计算。
以下四边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
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"。
设计与分析:用变量存点坐标,创建线类和四边形类,由于对类的操作不熟悉,将各种功能实现放在四边形类的方法中。

import java.text.DecimalFormat;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Scanner in = new Scanner(System.in);
String str;
str = in.nextLine();
int i = (int)str.charAt(0)-48;
str=str.substring(2);
if((!str.matches("((-|[+])?((([1-9]\\d*)|[0])(\\.\\d+)?),(-|[+])?((([1-9]\\d*)|[0])(\\.\\d+)?))((\\s)(-|[+])?((([1-9]\\d*)|[0])(\\.\\d+)?),(-|[+])?((([1-9]\\d*)|[0])(\\.\\d+)?))*\\s?"))) {
System.out.println("Wrong Format");
System.exit(0);
}
switch(i) {
case 1:{
if(str.matches("((-|[+])?(([1-9]\\d*|[0])(\\.\\d+)?),(-|[+])?(([1-9]\\d*|[0])(\\.\\d+)?))((\\s)(-|[+])?(([1-9]\\d*|[0])(.\\d+)?),(-|[+])?(([1-9]\\d*|[0])(.\\d+)?)){3}")) {
String[] a = str.split(",|\\s");
Quadrilateral q = new Quadrilateral(Float.parseFloat(a[0]),Float.parseFloat(a[1]),Float.parseFloat(a[2]),Float.parseFloat(a[3]),Float.parseFloat(a[4]),Float.parseFloat(a[5]),Float.parseFloat(a[6]),Float.parseFloat(a[7]));
if(q.isCoincide()) {
System.out.println("points coincide");
System.exit(0);
}
else System.out.println(q.isQuadrilateral()+" "+q.isParallelogram());
}
break;
}
case 2:{
if(str.matches("((-|[+])?(([1-9]\\d*|[0])(.\\d+)?),(-|[+])?(([1-9]\\d*|[0])(.\\d+)?))((\\s)(-|[+])?(([1-9]\\d*|[0])(.\\d+)?),(-|[+])?(([1-9]\\d*|[0])(.\\d+)?)){3}")) {
String[] a = str.split(",|\\s");
Quadrilateral q = new Quadrilateral(Float.parseFloat(a[0]),Float.parseFloat(a[1]),Float.parseFloat(a[2]),Float.parseFloat(a[3]),Float.parseFloat(a[4]),Float.parseFloat(a[5]),Float.parseFloat(a[6]),Float.parseFloat(a[7]));
if(q.isCoincide()) System.out.println("points coincide");
else if(!q.isQuadrilateral()) System.out.println("not a quadrilateral");
else System.out.println(q.isDiamond()+" "+q.isRectangle()+" "+q.isSquare());
}
break;
}
case 3:{
if(str.matches("((-|[+])?(([1-9]\\d*|[0])(.\\d+)?),(-|[+])?(([1-9]\\d*|[0])(.\\d+)?))((\\s)(-|[+])?(([1-9]\\d*|[0])(.\\d+)?),(-|[+])?(([1-9]\\d*|[0])(.\\d+)?)){3}")) {
String[] a = str.split(",|\\s");
Quadrilateral q = new Quadrilateral(Float.parseFloat(a[0]),Float.parseFloat(a[1]),Float.parseFloat(a[2]),Float.parseFloat(a[3]),Float.parseFloat(a[4]),Float.parseFloat(a[5]),Float.parseFloat(a[6]),Float.parseFloat(a[7]));
if(q.isCoincide()) {
System.out.println("points coincide");
System.exit(0);
}else if(!q.isQuadrilateral()) System.out.println("not a quadrilateral");
else {
if(q.isBump()) System.out.println(q.isBump()+" "+q.format(q.circumference())+" "+q.format(q.Area1()));
else System.out.println(q.isBump()+" "+q.format(q.circumference())+" "+q.format(q.Area2()));
}
}
break;
}
}
}
}
//四边形判断类
class Quadrilateral{
private float x1,y1,x2,y2,x3,y3,x4,y4; //点坐标
public Quadrilateral() {
super();
// TODO 自动生成的构造函数存根
}
public Quadrilateral(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) {
super();
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.x3 = x3;
this.y3 = y3;
this.x4 = x4;
this.y4 = y4;
}
public boolean isCoincide(){//是否重合
if((x1==x2&&y1==y2)||(x2==x3&&y2==y3)||(x3==x4&&y3==y4)||(x4==x1&&y4==y1))
return true;
return false;
}
public boolean isQuadrilateral() {//是否是四边形
Line a1 = new Line(x2,y2,x3,y3,x1,y1,x4,y4);
Line a2 = new Line(x4,y4,x3,y3,x1,y1,x2,y2);
if((x1==x3&&y1==y3)||(x2==x4&&y2==y4)||(x1==x2&&y1==y2)||(x4==x3&&y4==y3)||a1.isDot3()||a2.isDot3()) return false;
else if((x1==x2&&x1==x3)||(x1==x2&&x1==x4)||(x1==x3&&x1==x4)||(x3==x2&&x3==x4)) return false;
else if(Math.abs((y1-y2)/(x1-x2)-(y1-y3)/(x1-x3))<0.01||Math.abs((y1-y2)/(x1-x2)-(y1-y4)/(x1-x4))<0.01||Math.abs((y1-y4)/(x1-x4)-(y1-y3)/(x1-x3))<0.01||Math.abs((y3-y2)/(x3-x2)-(y2-y4)/(x2-x4))<0.01) return false;
else return true;
}
public boolean isParallelogram() {//是否是平行四边形
if(isQuadrilateral()) {
if((x1==x2&&x3==x4||(y1-y2)/(x1-x2)==(y4-y3)/(x4-x3))&&(x3==x2&&x1==x4||(y3-y2)/(x3-x2)==(y4-y1)/(x4-x1)))
return true;
else return false;
}
else return false;
}
public boolean isDiamond() {//是否是菱形
if(isParallelogram()) {
if(((y1==y3&&x2==x4)||(y2==y4&&x1==x3))||(((y1-y3)/(x1-x3))*((y4-y2)/(x4-x2))==-1)) return true;
else return false;
}
else return false;
}
public boolean isRectangle() {//是否是矩形
if(isParallelogram()) {
if((x1==x2&&y2==y3)||(y1==y2&&x2==x3)||((y1-y2)/(x1-x2))*((y3-y2)/(x3-x2))==-1) return true;
else return false;
}
else return false;
}
public boolean isSquare() {//是否是正方形
if(isRectangle()&&isDiamond()) return true;
else return false;
}
public boolean isBump() {//凹为false 凸为true
double x = -((x2-x4)*(x3*y1-x1*y3)-(x1-x3)*(x4*y2-x2*y4))/((y2-y4)*(x1-x3)-(y1-y3)*(x2-x4));
double y = -((y2-y4)*(y3*x1-y1*x3)-(y1-y3)*(y4*x2-y2*x4))/((x2-x4)*(y1-y3)-(x1-x3)*(y2-y4));
if ((((x>=x3&&x<=x1)||(x<=x3&&x>=x1))&&((y>=y3&&y<=y1)||(y<=y3&&y>=y1)))&&(((x>=x2&&x<=x4)||(x<=x2&&x>=x4))&&((y>=y2&&y<=y4)||(y<=y2&&y>=y4)))) return true;
else return false;
}
public boolean isComposition() {//是否为三角形和四边形
if(isQuadrilateral()) return true;
if((x1==x2&&y1==y2&&x3==x2&&y3==y2)||(x1==x2&&y1==y2&&x4==x2&&y4==y2)||(x1==x4&&y1==y4&&x3==x4&&y3==y4)||(x4==x2&&y4==y2&&x3==x4&&y3==y4))
return false;
if((x1==x2&&x2==x3&&x3==x4)||(y1-y3)/(x1-x3)==(y2-y4)/(x2-x4)) return false;
if((x1==x2&&y1==y2)||(x4==x2&&y4==y2)||(x3==x4&&y3==y4)||(x4==x1&&y4==y1)) return true;
if((x1==x2&&x2==x3||Math.abs((y1-y2)/(x1-x2)-(y2-y3)/(x2-x3))<0.01)&&((x1>=x2&&x2>=x3)||x3>=x2&&x2>=x1)&&((y1>=y2&&y2>=y3)||y3>=y2&&y2>=y1)) return true;
if((x1==x2&&x2==x4||Math.abs((y1-y2)/(x1-x2)-(y2-y4)/(x2-x4))<0.01)&&((x4>=x1&&x1>=x2)||x1>=x2&&x2>=x4)&&((y4>=y1&&y1>=y2)||y2>=y1&&y1>=y4)) return true;
if((x4==x2&&x2==x3||Math.abs((y4-y2)/(x4-x2)-(y2-y3)/(x2-x3))<0.01)&&((x4>=x3&&x3>=x2)||x2>=x3&&x3>=x4)&&((y4>=y3&&y3>=y2)||y2>=y3&&y3>=y4)) return true;
if((x1==x4&&x4==x3||Math.abs((y1-y4)/(x1-x4)-(y4-y3)/(x4-x3))<0.01)&&((x1>=x4&&x4>=x3)||x3>=x4&&x4>=x1)&&((y1>=y4&&y4>=y3)||y3>=y4&&y4>=y1)) return true;
return false;
}
public boolean isDCoincide(float x5,float y5) {//是否三点共线
if((x1==x2&&x5==x1&&((x5>=x1&&x5<=x2)||(x5<=x1&&x5>=x2))&&((y5>=y1&&y5<=y2)||(y5<=y1&&y5>=y2)))||(x3==x2&&x5==x2&&((x5>=x3&&x5<=x2)||(x5<=x3&&x5>=x2))&&((y5>=y3&&y5<=y2)||(y5<=y3&&y5>=y2)))||(x3==x4&&x5==x3&&((x5>=x3&&x5<=x4)||(x5<=x3&&x5>=x4))&&((y5>=y3&&y5<=y4)||(y5<=y3&&y5>=y4)))||(x1==x4&&x5==x4&&((x5>=x1&&x5<=x4)||(x5<=x1&&x5>=x4))&&((y5>=y1&&y5<=y4)||(y5<=y1&&y5>=y4))))
return true;
if((x1!=x2&&y1!=y2&&(y1-y2)/(x1-x2)==(y5-y1)/(x5-x1)&&((x5>=x1&&x5<=x2)||(x5<=x1&&x5>=x2))&&((y5>=y1&&y5<=y2)||(y5<=y1&&y5>=y2)))||(x3!=x2&&y3!=y2&&(y3-y2)/(x3-x2)==(y5-y2)/(x5-x2)&&((x5>=x3&&x5<=x2)||(x5<=x3&&x5>=x2))&&((y5>=y3&&y5<=y2)||(y5<=y3&&y5>=y2)))||(x3!=x4&&y3!=y4&&(y3-y4)/(x3-x4)==(y5-y3)/(x5-x3)&&((x5>=x3&&x5<=x4)||(x5<=x3&&x5>=x4))&&((y5>=y3&&y5<=y4)||(y5<=y3&&y5>=y4)))||(x1!=x4&&y1!=y4&&(y1-y4)/(x1-x4)==(y5-y4)/(x5-x4)&&((x5>=x1&&x5<=x4)||(x5<=x1&&x5>=x4))&&((y5>=y1&&y5<=y4)||(y5<=y1&&y5>=y4))))
return true;
return false;
}
public String format(double a) {//格式化
return new DecimalFormat("0.0##").format(a);
}
public double Area(float x1, float y1, float x2, float y2, float x3, float y3) {//三角形面积
return 0.5 * Math.abs(x1 * y3 + x2 * y1 + x3 * y2 - x1 * y2 - x2 * y3 -x3 * y1);
}
public double Area1() {//凸形面积
return 0.5*Math.abs((x3-x1)*(y4-y2)-(y3-y1)*(x4-x2));
}
public double Area2() {//凹形面积
return 0.5*Math.abs((x3-x1)*(y4-y2)-(y3-y1)*(x4-x2));
}
public boolean Area3(float x5,float y5) {//面积是否相等 面积法
double a = 0.5 * Math.abs(x1 * y3 + x2 * y1 + x3 * y2 - x1 * y2 - x2 * y3 -x3 * y1) + 0.5 * Math.abs(x1 * y3 + x4 * y1 + x3 * y4 - x1 * y4 - x4 * y3 -x3 * y1);
double b = 0.5 * Math.abs(x1 * y5 + x2 * y1 + x5 * y2 - x1 * y2 - x2 * y5 -x5 * y1) + 0.5 * Math.abs(x2 * y3 + x5 * y2 + x3 * y5 - x2 * y5 - x5 * y3 -x3 * y2) + 0.5 * Math.abs(x4 * y3 + x5 * y4 + x3 * y5 - x4 * y5 - x5 * y3 -x3 * y4) + 0.5 * Math.abs(x1 * y4 + x5 * y1 + x4 * y5 - x1 * y5 - x5 * y4 -x4 * y1);
if(Math.abs(a-b)<0.01) return true;
return false;
}
public double circumference() {//四边形周长
return Math.pow((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2),0.5) + Math.pow((x3-x2)*(x3-x2)+(y3-y2)*(y3-y2),0.5) + Math.pow((x3-x4)*(x3-x4)+(y3-y4)*(y3-y4),0.5) +Math.pow((x1-x4)*(x1-x4)+(y1-y4)*(y1-y4),0.5);
}
}
//线类
class Line{
private float x1,x2,x3,x4,y1,y2,y3,y4;
public Line(float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4) {
super();
this.x1 = x1;
this.x2 = x2;
this.x3 = x3;
this.x4 = x4;
this.y1 = y1;
this.y2 = y2;
this.y3 = y3;
this.y4 = y4;
}
public Line() {
super();
// TODO 自动生成的构造函数存根
}
boolean isDot() {
double x = -((x3-x4)*(x2*y1-x1*y2)-(x1-x2)*(x4*y3-x3*y4))/((y3-y4)*(x1-x2)-(y1-y2)*(x3-x4));
double y = -((y3-y4)*(y2*x1-y1*x2)-(y1-y2)*(y4*x3-y3*x4))/((x3-x4)*(y1-y2)-(x1-x2)*(y3-y4));
if(Math.abs((y1-y2)/(x1-x2)-(y3-y4)/(x3-x4))<0.01) return false;
else if (((x>=x3&&x<=x4)||(x<=x3&&x>=x4))&&((y>=y3&&y<=y4)||(y<=y3&&y>=y4))) return true;
else return false;
}
boolean isDot3() {
double x = -((x3-x4)*(x2*y1-x1*y2)-(x1-x2)*(x4*y3-x3*y4))/((y3-y4)*(x1-x2)-(y1-y2)*(x3-x4));
double y = -((y3-y4)*(y2*x1-y1*x2)-(y1-y2)*(y4*x3-y3*x4))/((x3-x4)*(y1-y2)-(x1-x2)*(y3-y4));
if(Math.abs((y1-y2)/(x1-x2)-(y3-y4)/(x3-x4))<0.01) return false;
else if (((x>=x3&&x<=x4)||(x<=x3&&x>=x4))&&((y>=y3&&y<=y4)||(y<=y3&&y>=y4))&&((x>=x1&&x<=x2)||(x<=x1&&x>=x2))&&((y>=y1&&y<=y2)||(y<=y1&&y>=y2))) return true;
else return false;
}
boolean isCoincide(){
if(Math.abs((y4-y3)*x1+(x3-x4)*y1+x4*y3-y4*x3)/Math.sqrt((y4-y3)*(y4-y3)+(x4-x3)*(x4-x3))<0.01&&(Math.abs((y1-y2)/(x1-x2)-(y3-y4)/(x3-x4))<0.01||((x1==x2)&&(x3==x4))))
return true;
else return false;
}
float getxValue(){
return -((x3-x4)*(x2*y1-x1*y2)-(x1-x2)*(x4*y3-x3*y4))/((y3-y4)*(x1-x2)-(y1-y2)*(x3-x4));
}
float getyValue(){
return -((y3-y4)*(y2*x1-y1*x2)-(y1-y2)*(y4*x3-y3*x4))/((x3-x4)*(y1-y2)-(x1-x2)*(y3-y4));
}
}
改进建议:功能四和五没能实现,后续需要补完。可以构造更多的类,将部分的方法放在类中,减少单个类的复杂度。
7-1 点线形系列5-凸五边形的计算-1
用户输入一组选项和数据,进行与五边形有关的计算。
以下五边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
1:输入五个点坐标,判断是否是五边形,判断结果输出true/false。
2:输入五个点坐标,判断是凹五边形(false)还是凸五边形(true),如果是凸五边形,则再输出五边形周长、面积,结果之间以一个英文空格符分隔。 若五个点坐标无法构成五边形,输出"not a pentagon"
3:输入七个点坐标,前两个点构成一条直线,后五个点构成一个凸五边形、凸四边形或凸三角形,输出直线与五边形、四边形或三角形相交的交点数量。如果交点有两个,再按面积从小到大输出被直线分割成两部分的面积(不换行)。若直线与多边形形的一条边线重合,输出"The line is coincide with one of the lines"。若后五个点不符合五边形输入,若前两点重合,输出"points coincide"。
以上3选项中,若输入的点无法构成多边形,则输出"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
输入样例1:
选项1,点重合。例如:
1:-1,-1 1,2 -1,1 1,0
输出样例:
在这里给出相应的输出。例如:
wrong number of points
设计与分析:构造点线类,主要判断直接放在主函数中,调用类方法实现功能。
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
String s =in.nextLine();
if(s.charAt(0)=='1') {
String regrex1 = "[1-5]{1}\\:(([+-]?(0|[1-9](\\d+)?)(\\.\\d+)?,[+-]?(0|[1-9](\\d+)?)(\\.\\d+)?[\\s])*)[+-]?(0|[1-9](\\d+)?)(\\.\\d+)?,[+-]?(0|[1-9](\\d+)?)(\\.\\d+)?";
boolean flag = s.matches(regrex1);
if(flag){
int o = 2;
int m = 0;
for(o=2;o<s.length();o++){
if(s.charAt(o)==','){
m++;
}
}
if(m==5){
Matcher matcher = Pattern.compile("(-?\\d*)\\.?\\d+").matcher(s);
double[] num = new double[20];
int n=0;
while(matcher.find()){
num[n] = Double.valueOf(matcher.group().toString());
n++;
}
Point p1 = new Point();
Point p2 = new Point();
Point p3 = new Point();
Point p4 = new Point();
Point p5 = new Point();
p1.setX(num[1]);
p1.setY(num[2]);
p2.setX(num[3]);
p2.setY(num[4]);
p3.setX(num[5]);
p3.setY(num[6]);
p4.setX(num[7]);
p4.setY(num[8]);
p5.setX(num[9]);
p5.setY(num[10]);
Line l1 = new Line(p1,p2);
Line l2 = new Line(p2,p3);
Line l3 = new Line(p3,p4);
Line l4 = new Line(p4,p5);
Line l5 = new Line(p5,p1);
if(l1.isParallel(l2)||l2.isParallel(l3)||l3.isParallel(l4)||l4.isParallel(l5)||l5.isParallel(l1)){
System.out.println("false");
}
else{
if(java.awt.geom.Line2D.linesIntersect(p1.getX(), p1.getY(),p2.getX(), p2.getY(),p3.getX(), p3.getY(),p4.getX(), p4.getY())||java.awt.geom.Line2D.linesIntersect(p1.getX(), p1.getY(),p2.getX(), p2.getY(),p4.getX(), p4.getY(),p5.getX(), p5.getY())||java.awt.geom.Line2D.linesIntersect(p2.getX(), p2.getY(),p3.getX(), p3.getY(),p4.getX(), p4.getY(),p5.getX(), p5.getY())||java.awt.geom.Line2D.linesIntersect(p2.getX(), p2.getY(),p3.getX(), p3.getY(),p5.getX(), p5.getY(),p1.getX(), p1.getY()) ||java.awt.geom.Line2D.linesIntersect(p3.getX(), p3.getY(),p4.getX(), p4.getY(),p5.getX(), p5.getY(),p1.getX(), p1.getY())){
System.out.println("false");
}
else{
System.out.println("true");
}
}
}
else{
System.out.println("wrong number of points");
}
}
else{
System.out.println("Wrong Format");
}}
if(s.charAt(0)=='2') {
String regrex2 = "[1-5]{1}\\:(([+-]?(0|[1-9](\\d+)?)(\\.\\d+)?,[+-]?(0|[1-9](\\d+)?)(\\.\\d+)?[\\s])*)[+-]?(0|[1-9](\\d+)?)(\\.\\d+)?,[+-]?(0|[1-9](\\d+)?)(\\.\\d+)?";
boolean flag = s.matches(regrex2);
if(flag){
int o = 2;
int m = 0;
for(o=2;o<s.length();o++){
if(s.charAt(o)==','){
m++;
}
}
if(m==5)
{
Matcher matcher = Pattern.compile("(-?\\d*)\\.?\\d+").matcher(s);
double[] num = new double[20];
int n=0;
while(matcher.find()){
num[n] = Double.valueOf(matcher.group().toString());
n++;
}
Point p1 = new Point();
Point p2 = new Point();
Point p3 = new Point();
Point p4 = new Point();
Point p5 = new Point();
p1.setX(num[1]);
p1.setY(num[2]);
p2.setX(num[3]);
p2.setY(num[4]);
p3.setX(num[5]);
p3.setY(num[6]);
p4.setX(num[7]);
p4.setY(num[8]);
p5.setX(num[9]);
p5.setY(num[10]);
Line l1 = new Line(p1,p2);
Line l2 = new Line(p2,p3);
Line l3 = new Line(p3,p4);
Line l4 = new Line(p4,p5);
Line l5 = new Line(p5,p1);
int t = -1;
if(l1.isParallel(l2)||l2.isParallel(l3)||l3.isParallel(l4)||l4.isParallel(l5)||l5.isParallel(l1))
{
t =0;
}
else
{
if(java.awt.geom.Line2D.linesIntersect(p1.getX(), p1.getY(),p2.getX(), p2.getY(),p3.getX(), p3.getY(),p4.getX(), p4.getY())||java.awt.geom.Line2D.linesIntersect(p1.getX(), p1.getY(),p2.getX(), p2.getY(),p4.getX(), p4.getY(),p5.getX(), p5.getY())||java.awt.geom.Line2D.linesIntersect(p2.getX(), p2.getY(),p3.getX(), p3.getY(),p4.getX(), p4.getY(),p5.getX(), p5.getY())||java.awt.geom.Line2D.linesIntersect(p2.getX(), p2.getY(),p3.getX(), p3.getY(),p5.getX(), p5.getY(),p1.getX(), p1.getY()) ||java.awt.geom.Line2D.linesIntersect(p3.getX(), p3.getY(),p4.getX(), p4.getY(),p5.getX(), p5.getY(),p1.getX(), p1.getY()))
{
t=0;
}
else
{
t = 1;
}
}
if(t == 0)
{
System.out.println("not a pentagon");
}
if(t == 1)
{
System.out.println("false");
}
}
else
{
System.out.println("wrong number of points");
}
}
else
{
System.out.println("Wrong Format");
}
}
}
}
class Point {
public double x;
public double y;
public Point() {
}
public Point(double x,double y) {
this.x=x;
this.y=y;
}
/* 设置坐标x,将输入参数赋值给属性x */
public void setX(double x) {
this.x = x;
}
/* 设置坐标y,将输入参数赋值给属性y */
public void setY(double y) {
this.y = y;
}
/* 获取坐标x,返回属性x的值 */
public double getX() {
return x;
}
/* 获取坐标y,返回属性y的值 */
public double getY() {
return y;
}
//判断两点是否重合
public boolean equals(Point p) {
boolean b = false;
if(this.x==p.getX()&&this.y==p.getY()) {
b=true;
}
return b;
}
/* 计算当前点和输入点p之间的距离 */
public double getDistance(Point p) {
return 0;
}
}
class Line {
private Point p1;//线上的第一个点
private Point p2;//线上的第二个点
public Line(double x1, double y1, double x2, double y2) {
Point p1 = new Point(x1, y1);
Point p2 = new Point(x2, y2);
LineInputError.pointsCoincideError(p1, p2);//两点是否重合,重合则报错并退出
this.p1 = p1;
this.p2 = p2;
}
public Line(Point p1, Point p2) {
LineInputError.pointsCoincideError(p1, p2);//两点是否重合,重合则报错并退出
this.p1 = p1;
this.p2 = p2;
}
/* 获取线条的斜率 */
public Double getSlope() {
// (x1-x2=0)注意考虑斜率不存在即返回double类型无穷大"Infinite"
return (p2.getY() - p1.getY()) / (p2.getX() - p1.getX());
}
/* 判断x是否在线上 */
public boolean isOnline(Point x) {
//System.out.println("isOnline");
//System.out.println(p1.x + " " + p1.y + " " + p2.x + " " + p2.y + " " + x.x + " " + x.y + " ");
// 点重合
if ((x.getX() == p1.getX() && x.getY() == p1.getY()) || (x.getX() == p2.getX() && x.getY() == p2.getY())) {
return true;
}
Line l = new Line(p1, x);
if (l.getSlope().isInfinite() && this.getSlope().isInfinite()) {
return true;
}
// 此点与线上任意一点构成的线的斜率相等则此点在线上
double b1 = l.getSlope(), b2 = this.getSlope();
//System.out.println(b1 + " " + b2 + " " + (b1- b2) + " " + (Math.abs(b1 - b2) < 0.00000000001));
return Math.abs(b1 - b2) < 0.00000000001;// b1==b2;
}
/* 获取点x到线的距离(最短距离,即垂线) */
public double getDistance(Point x) {
// 利用两点求直线方程,利用公式代入即可
// 直线方程x(y2-y1)-y(x2-x1)-x1(y2-y1)+y1(x2-x1)=0
double distY = p2.getY() - p1.getY();
double distX = p2.getX() - p1.getX();
return Math.abs(x.getX() * distY - x.getY() * distX - p1.getX() * distY + p1.getY() * distX)
/ p1.getDistance(p2);
}
/* 判断x是否在线上且在两点之间 */
public boolean isBetween(Point x) {
//System.out.println("isBetween" + " " + this.p1.x + " " + p1.y + " " + p2.x + " " + p2.y + " " + x.x + " " + x.y);
if (!this.isOnline(x)) {
return false;
}
// 与端点重合,认为不在在两点之间,
if (x.equals(p1) || x.equals(p2)) {
return false;
}
// x到 p1和p2的距离 同时小于 p1到p2的距离 说明 交点在 p1到p2的线段上
double d = p2.getDistance(p1);
boolean b = x.getDistance(p2) < d && x.getDistance(p1) < d;
//System.out.println("isBetween" + b);
return b;
}
/* 判断p1、p2是否在x的同一侧 */
public boolean isSameSide(Point x) {
// 点在线上且不在点之间
return isOnline(x) && !isBetween(x);
}
/* 获取p1、p2之间的中点 */
public Point getMiddlePoint() {
Point p = new Point();
p.setX((p1.getX() + p2.getX()) / 2);
p.setY((p1.getY() + p2.getY()) / 2);
return p;
}
/* 获取线段的第一个坐标点 */
public Point getPointA() {
return p1;
}
/* 获取线段的第二个坐标点 */
public Point getPointB() {
return p2;
}
/* 获取与线条l之间的夹角,若两条线段交叉(交叉点位于其中一条线的两点之间),取较小的夹角 */
public double getAngle(Line l) {
// 利用公式θ=arctan∣(k2- k1)/(1+ k1k2)∣,此时求较小的夹角
double k2 = getSlope();
double k1 = l.getSlope();
return (double) (Math.atan(Math.abs((k2 - k1) / (1 + k1 * k2))) * 180.0 / Math.PI);// 返回值为角度
}
// 是否平行,平行返回true,否则false。
public boolean isParallel(Line l) {
Double b1 = this.getSlope();
Double b2 = l.getSlope();
if ((b1.isInfinite()) && (b2.isInfinite())) {
return true;
} else {
return (this.getSlope().doubleValue() == l.getSlope().doubleValue());
}
}
// 两条线是否重合,重合返回true,否则false。
public boolean isCoincide(Line l) {
if (!this.isParallel(l)) {
return false;
}
if (this.isOnline(l.p1)) {
return true;
}
return false;
}
// 获取交叉点,若两条线平行,返回null。
public Point getIntersection(Line l) {
if (this.isParallel(l)) {
return null;
}
if (p1.equals(l.p1) || p1.equals(l.p2)) {
return p1;
}
if (p2.equals(l.p1) || p2.equals(l.p2)) {
return p2;
}
Point p3 = l.p1, p4 = l.p2;
double x_member, x_denominator, y_member, y_denominator;
Point cross_point = new Point();
x_denominator = p4.x * p2.y - p4.x * p1.y - p3.x * p2.y + p3.x * p1.y - p2.x * p4.y + p2.x * p3.y + p1.x * p4.y
- p1.x * p3.y;
x_member = p3.y * p4.x * p2.x - p4.y * p3.x * p2.x - p3.y * p4.x * p1.x + p4.y * p3.x * p1.x
- p1.y * p2.x * p4.x + p2.y * p1.x * p4.x + p1.y * p2.x * p3.x - p2.y * p1.x * p3.x;
if (x_denominator == 0)
cross_point.x = 0;
else
cross_point.x = x_member / x_denominator;
y_denominator = p4.y * p2.x - p4.y * p1.x - p3.y * p2.x + p1.x * p3.y - p2.y * p4.x + p2.y * p3.x + p1.y * p4.x
- p1.y * p3.x;
y_member = -p3.y * p4.x * p2.y + p4.y * p3.x * p2.y + p3.y * p4.x * p1.y - p4.y * p3.x * p1.y
+ p1.y * p2.x * p4.y - p1.y * p2.x * p3.y - p2.y * p1.x * p4.y + p2.y * p1.x * p3.y;
if (y_denominator == 0)
cross_point.y = 0;
else
cross_point.y = y_member / y_denominator;
return cross_point; // 平行返回(0,0)
}
}
//处理异常提示。
class LineInputError {
public static void pointsCoincideError(Point p1, Point p2) {
if ((p1.getX() == p2.getX()) && p1.getY() == p2.getY()) {
System.out.println("points coincide");
System.exit(0);
}
}
}
采坑心得:功能判断的算法太难了想不出来,只好借鉴网上代码了。
改进建议:功能未实现完,后续需要补足。还是添加更多的类,减少单个类的复杂度,后续水平增强后优化代码
7-2 点线形系列5-凸五边形的计算-2
用户输入一组选项和数据,进行与五边形有关的计算。
以下五边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
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"。
以上4、5、6选项输入的五个点坐标可能存在冗余,假设多边形一条边上两个端点分别是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
设计与分析:这题难度太大,时间不够,没能完成,后续有时间再写吧。
期中考试
7-1 点与线(类设计)
-
设计一个类表示平面直角坐标系上的点Point,私有属性分别为横坐标x与纵坐标y,数据类型均为实型数,除构造方法以及属性的getter与setter方法外,定义一个用于显示信息的方法display(),用来输出该坐标点的坐标信息,格式如下:
(x,y),数值保留两位小数。为简化题目,其中,坐标点的取值范围设定为(0,200]。若输入有误,系统则直接输出Wrong Format -
设计一个类表示平面直角坐标系上的线Line,私有属性除了标识线段两端的点point1、point2外,还有一个字符串类型的color,用于表示该线段的颜色,同样,除构造方法以及属性的getter与setter方法外,定义一个用于计算该线段长度的方法getDistance(),还有一个用于显示信息的方法display(),用来输出线段的相关信息,输出格式如下:
``` The line's color is:颜色值 The line's begin point's Coordinate is: (x1,y1) The line's end point's Coordinate is: (x2,y2) The line's length is:长度值 ```其中,所有数值均保留两位小数,建议可用
String.format("%.2f", data)方法。设计类图如下图所示。
设计与分析:

根据题目中已给出类图,根据类图设计类、变量和方法即可。重点在于用getDistance()的算法计算长度和display()方法的构造和使用。
部分代码(点类和线类):
//点类
class Point{
private double x,y;
public Point(double x,double y){
this.x = x;
this.y = y;
}
public double getX(){
return x;
}
public double getY(){
return y;
}
public void setX(double x){
this.x = x;
}
public void setY(double y){
this.y = y;
}
public void display(){
System.out.println("("+String.format("%.2f", x)+","+String.format("%.2f",y)+")");
}
}
//线类
class Line{
Point point1;
Point point2;
String color;
public Line(Point point1,Point point2,String color){
this.point1 = point1;
this.point2 = point2;
this.color = color;
}
public void setPoint1(Point point1){
this.point1 = point1;
}
public void setPoint2(Point point2){
this.point2 = point2;
}
public void setColor(String color){
this.color = color;
}
public Point getPoint1(){
return point1;
}
public Point getPoint2(){
return point2;
}
public String getColor(){
return color;
}
public double getDistance(){
double distance=Math.sqrt((point1.getX()-point2.getX())*(point1.getX()-point2.getX())+(point1.getY()-point2.getY())*(point1.getY()-point2.getY()));
return distance;
}
public void display(){
System.out.println("The line's color is:"+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.println("The line's length is:"+String.format("%.2f",getDistance()));
}
}
采坑心得:仔细审题,注意输入范围的判断(其实是别人踩的坑,借用一下)
改进建议:暂无
7-2 点线面问题重构(继承与多态)
在“点与线(类设计)”题目基础上,对题目的类设计进行重构,以实现继承与多态的技术性需求。
在“点与线(类设计)”题目基础上,对题目的类设计进行重构,以实现继承与多态的技术性需求。
- 对题目中的点Point类和线Line类进行进一步抽象,定义一个两个类的共同父类Element(抽象类),将display()方法在该方法中进行声明(抽象方法),将Point类和Line类作为该类的子类。
- 再定义一个Element类的子类面Plane,该类只有一个私有属性颜色color,除了构造方法和属性的getter、setter方法外,display()方法用于输出面的颜色,输出格式如下:
The Plane's color is:颜色
在主方法内,定义两个Point(线段的起点和终点)对象、一个Line对象和一个Plane对象,依次从键盘输入两个Point对象的起点、终点坐标和颜色值(Line对象和Plane对象颜色相同),然后定义一个Element类的引用,分别使用该引用调用以上四个对象的display()方法,从而实现多态特性。示例代码如下:
element = p1;//起点Point
element.display();
element = p2;//终点Point
element.display();
element = line;//线段
element.display();
element = plane;//面
element.display();
设计与分析:

这题就是在第一题基础上加上继承,所需的类方法也都已给出,主类中所需修改的代码题目也已经给出,按类图修改就行啦。
部分代码(主类和新建的两个类)
import java.util.*;
//主类
public class Main {
public static void main(String args[]){
Scanner input = new Scanner(System.in);
double x1=input.nextDouble();
double y1=input.nextDouble();
double x2=input.nextDouble();
double y2=input.nextDouble();
String color=input.next();
if(x1>0&&x1<=200&&x2>0&&x2<=200&&y1>0&&y1<=200&&y2>0&&y2<=200){ //设定范围
Point p1=new Point(x1,y1);
Point p2=new Point(x2,y2);
Line line=new Line(p1,p2,color);
Element element = new Element();
Plane plane = new Plane(color);
element = p1;//起点Point
element.display();
element = p2;//终点Point
element.display();
element = line;//线段
element.display();
element = plane;//面
element.display();
}
else
System.out.print("Wrong Format");
}
}
//共同父类
class Element{
public void display(){
}
}
//颜色类
class Plane extends Element{
String color;
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:"+color);
}
}
采坑心得:用题目给的代码注意变量名统一
改进建议:暂无
7-3 点线面问题再重构(容器类)
在“点与线(继承与多态)”题目基础上,对题目的类设计进行重构,增加容器类保存点、线、面对象,并对该容器进行相应增、删、遍历操作。
- 在原有类设计的基础上,增加一个GeometryObject容器类,其属性为
ArrayList<Element>类型的对象(若不了解泛型,可以不使用<Element>) - 增加该类的
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(); }
由于在补前面的知识,容器没有学好,这题也没拿什么分。
总结:这几周的学习状态一直都不好,再加之要补前面落下的知识,作业的完成情况不太好。类和方法的知识有了一定的进步,但仍需写一些练习题完善。继承只后的知识还没怎么学,需要加快进度了。在算法方面遇到了很多困难,要多加练习,多学习网上的算法来提高自己。正则表达式也是用的网上的,需要更深入的学习才能自己写出需要的正则表达式解决问题。不会就多问,多看网课多练习,上课不能再划水摸鱼了,努力追上进度。
浙公网安备 33010602011771号