nchu-software-oop-2022-4_lastercn的博客-爱代码爱编程
nchu-software-oop-2022-4
前言
为了练习自己,我在类中增加了异常抛出和捕获的操作,可能会导致代码看起来很怪( ,但相应地,尽量把7-2的思路写全了很多。希望是解题思路对你有帮助 😃
输入输出样例就省略吧
7-1 sdut-String-2 识蛟龙号载人深潜,立科技报国志(II)(正则表达式)
“蛟龙号”载人深潜器是我国首台自主设计、自主集成研制的作业型深海载人潜水器,设计最大下潜深度为7000米级,也是目前世界上下潜能力最强的作业型载人潜水器。“蛟龙号”可在占世界海洋面积99.8%的广阔海域中使用,对于我国开发利用深海的资源有着重要的意义。
中国是继美、法、俄、日之后世界上第五个掌握大深度载人深潜技术的国家。在全球载人潜水器中,“蛟龙号”属于第一梯队。目前全世界投入使用的各类载人潜水器约90艘,其中下潜深度超过1000米的仅有12艘,更深的潜水器数量更少,目前拥有6000米以上深度载人潜水器的国家包括中国、美国、日本、法国和俄罗斯。除中国外,其他4国的作业型载人潜水器最大工作深度为日本深潜器的6527米,因此“蛟龙号”载人潜水器在西太平洋的马里亚纳海沟海试成功到达7020米海底,创造了作业类载人潜水器新的世界纪录。
从2009年至2012年,蛟龙号接连取得1000米级、3000米级、5000米级和7000米级海试成功。下潜至7000米,说明蛟龙号载人潜水器集成技术的成熟,标志着我国深海潜水器成为海洋科学考察的前沿与制高点之一。
2012年6月27日11时47分,中国“蛟龙”再次刷新“中国深度”——下潜7062米。6月3日,“蛟龙”出征以来,已经连续书写了5个“中国深度”新纪录:6月15日,6671米;6月19日,6965米;6月22日,6963米;6月24日,7020米;6月27日,7062米。下潜至7000米,标志着我国具备了载人到达全球99%以上海洋深处进行作业的能力,标志着“蛟龙”载人潜水器集成技术的成熟,标志着我国深海潜水器成为海洋科学考察的前沿与制高点之一,标志着中国海底载人科学研究和资源勘探能力达到国际领先水平。
‘蛟龙’号是我国载人深潜发展历程中的一个重要里程碑。它不只是一个深海装备,更代表了一种精神,一种不畏艰险、赶超世界的精神,它是中华民族进军深海的号角。
了解蛟龙号”载人深潜器“的骄人业绩,为我国海底载人科学研究和资源勘探能力达到国际领先水平而自豪,小伙伴们与祖国同呼吸、共命运,一定要学好科学文化知识、提高个人能力,增强创新意识,做事精益求精,立科技报国之志!
请编写程序,实现如下功能:读入关于蛟龙号载人潜水器探测数据的多行字符串,从给定的信息找出数字字符,输出每行的数字之和。
提示 若输入为“2012年2月”,则该行的输出为:2014。若干个连续的数字字符作为一个整体,以十进制形式相加。
输入格式:
读入关于蛟龙号载人潜水器探测数据的多行字符串,每行字符不超过80个字符。
以"end"结束。
输出格式:
与输入行相对应的各个整数之和。
思路:
- 以一列为整体,通过正则表达提取出其中的数字,转化为一个只存在数字的字符串数组。
- 遍历该数组,求和
实现:
package nchu_software_oop_2022_4;
import java.util.*;
import java.util.regex.Pattern;
public class p_1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
while(!str.equals("end")){
String[] tmp = change(str);
int num = 0;
for (String s : tmp) {
if(!s.equals(""))
num += (int)Double.parseDouble(s);
}
System.out.println(num);
str = sc.nextLine();
}
}
public static String[] change(String content){
String regEx="[^0-9]+";
Pattern pattern = Pattern.compile(regEx);
return pattern.split(content);
}
}
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()方法。
输入格式:
输入开户需要的姓名、密码
输入正确密码、存款金额
输入错误密码、取款金额
输入正确密码、大于余额的取款金额
输入正确密码、小于余额的取款金额
输出格式:
中国银行(银行名称)欢迎您的到来!
您的余额有多少元。
您的密码错误!
您的余额不足!
请取走钞票,您的余额还有多少元。
请收好您的证件和物品,欢迎您下次光临!
没啥说的,你就算吧样例输出复制下来交上去都能过(假的
实现
package nchu_software_oop_2022_4;
import java.util.*;
import java.util.Arrays;
public class p_3 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String name,pswd,str;
double bal;
str = sc.nextLine();
String[] tmp_str = str.split(" ");
name = tmp_str[0];
pswd = tmp_str[1];
Bank b = new Bank(name,pswd);
str = sc.nextLine();
tmp_str = str.split(" ");
pswd = tmp_str[0];
bal = Double.parseDouble(tmp_str[1]);
b.deposit(pswd,bal);
for(int i=0;i<3;i++){
str = sc.nextLine();
tmp_str = str.split(" ");
pswd = tmp_str[0];
bal = Double.parseDouble(tmp_str[1]);
b.withdraw(pswd,bal);
}
Bank.welcomeNext();
}
}
class Bank {
public static String bank_name = "中国银行";
private String name,pswd;
double balance;
Bank(String name,String pswd){
this.name = name;
this.pswd = pswd;
this.balance = 0;
welcome();
}
public static void welcome(){
System.out.printf("%s欢迎您的到来!\n",Bank.bank_name);
}
public static void welcomeNext(){
System.out.println("请收好您的证件和物品,欢迎您的下次光临");
}
public void deposit(String pswd,double bal){
if (!this.pswd.equals(pswd)){
System.out.println("您的密码错误");
return;
}
this.balance += bal;
System.out.printf("您的余额有%.1f元。\n",this.balance);
}
public void withdraw(String pswd,double bal){
if (!this.pswd.equals(pswd)){
System.out.println("您的密码错误");
return;
}
if(this.balance - bal < 0){
System.out.println("您的余额不足!");
return;
}
this.balance -= bal;
System.out.printf("请取走钞票,您的余额还有%.1f元.\n",this.balance);
}
}
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坐标之间以英文”,"分隔,点与点之间以一个英文空格分隔。
以"end"结束。
输出格式:
基本输出格式见每种选项的描述。
异常情况输出:
如果不符合基本格式,输出"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"。
思路:
先放三张图,方便描述
图一:异常四边形
图二:凹四边形
图三:凸四边形
- cmd==1: 无法构成四边形的情况有三种:
- 四个点有重合点 (无法构成边)
- 有超过三点共线 (可能构成三角形,反正不会是四边形)
- 如图一异常四边形 (任一对边 [线段] 有交点则异常)
- cmd==2:
- 菱形:四边形四条边长度相等
- 矩形:对角线长度相等
- 正方形:菱形 + 矩形
- cmd==3:
-
判断四边形是凸还是凹可根据四边形不同对角线分割出来的两三角形面积和是否相等判断,例如:
在图二凹四边形中:△(ABC)+△(ADC) != △(ABD)+△(ACD);
在图三凸三角形中:△(ABC)+△(ADC) == △(ABD)+△(ACD); -
周长:求和即可
-
面积:自然会想到用对角线分割四边形为两个三角形再求和得到。但是!这样的方法只针对于凸四边形,看看上面1中的式子,凹四边形不同的对角线分割出来的两三角形面积和是不一样的,而四边形面积只和其中的较小者相同,对此用两条对角线分割求两次,取较小者即可。
-
- cmd==4:
-
后者构成了四边形:
和构成三角形求法几乎一模一样,只不过多了交点在两对角,交点在两对边的情况
例如:
直线交于图三中的AC两点;
直线交于图三中的AB,CD两边
直线交于图三中的BC,DA两边 -
后者构成了三角形:
直接copy上一次练习的代码就行 (练习3那么问题来了,怎么判断后四个点构成的是四边形,还是(合法)三角形呢?
-
!!! 以下解释不对!!!,md我真的服了,就按照他说的合法输入暴力枚举吧,艹
先判断四点是否构成四边形(见cmd==1)。
若是无法构成四边形,再判断是否构成三角形,以下通过图示说明:**(其实在图一这个异常四边形也说明了一些,就是输入的点是有顺序的)**
合法三角形:
![合法三角形](https://img-blog.csdnimg.cn/706228bb9ded46009a073322d752993d.png)
非法三角形:
![非法三角形](https://img-blog.csdnimg.cn/d3670d846985491bafc466a76b4ffb85.png)
**总之就是:按照ABCD这样的连接顺序,最终是否能连接为一个三角形**
我判断是否是三角形纯枚举每一个可能的情况 , (太笨想不到法子
- cmd==5:
-
图形是三角形还是四边形。见(cmd==4)
-
判断点P是否在图形之内,用面积法判断,(图形的任意相邻两点和P构成的三角形面积和是否等于图形面积)
例如在图三中有一个点P判断 △(ABP) + △(BCP) + △(CDP) + △(DAP) 和 □(ABCD) 的面积是否相等。
相等则在三角形内部,不相等则在外部。
在内部也可能在边之上,特判即可。
-
注意:
- 在第二个选项中,无论是点重合还是无法构成四边形,最终的输出都是:“not a quadrilateral or triangle” 属于题目的描述错误 (天知道这套题流传了多久还没改
实现:
package nchu_software_oop_2022_4;
import java.util.*;
import Points.*;
public class p_2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
//判断输入格式是否正确
if(!str.matches("^[1-5][:](([+-]?(0|(0\\.\\d+)|[1-9][0-9]*(\\.\\d+)?))[,]([+-]?(0|(0\\.\\d+)|[1-9][0-9]*(\\.\\d+)?))\\s?)+$")){
System.out.println("Wrong Format");
System.exit(0);
}
//取出cmd,将串转化为浮点型
int cmd = str.charAt(0)-'0';
str = str.substring(2).trim();
String[] tmpstr = str.split(" |,");
double[] num = new double[30];
int cnt = 0;
for(String s:tmpstr){
if(!check(s)){
System.out.println("Wrong Format");
System.exit(0);
}
num[cnt++] = Double.parseDouble(s);
}
//将浮点型转化为坐标点型
Point[] p = new Point[10];
for(int i=0;i<cnt;i+=2){
p[i/2] = new Point(num[i],num[i+1]);
}
//点数不合法
if(cmd==1 || cmd==2 || cmd==3){
if(cnt != 8){
System.out.println("wrong number of points");
return;
}
}
if(cmd==4){
if(cnt != 12){
System.out.println("wrong number of points");
return;
}
}
if(cmd == 5){
if(cnt != 10){
System.out.println("wrong number of points");
return;
}
}
if(cmd == 1){
try{
Quadrilateral q = new Quadrilateral(p[0],p[1],p[2],p[3]);
System.out.printf("true %s\n",q.isParallelQuadrilateral());
}catch (Exception e){
if(e.getMessage().equals("not a quadrilateral"))
System.out.println("false false");
else System.out.println(e.getMessage());
}
}
if(cmd == 2){ //题目描述出问题!!
try{
Quadrilateral q = new Quadrilateral(p[0],p[1],p[2],p[3]);
System.out.printf("%s %s %s\n",q.isDiamond(),q.isRectangle(),q.isSquare());
}catch (Exception e){
System.out.println("not a quadrilateral");
}
}
if(cmd == 3){
try{
Quadrilateral q = new Quadrilateral(p[0],p[1],p[2],p[3]);
System.out.printf("%s %s %s\n",q.isConvexQuadrilateral(),change(q.sideLength()), change(q.area()) );
}catch (Exception e){
System.out.println(e.getMessage());
}
}
if(cmd == 4){
Line l = null;
Quadrilateral q = null;
try{
l = new Line(p[0],p[1]);
}catch (Exception e){ //不构成直线
System.out.println(e.getMessage());
System.exit(0);
}
try{ //构成四边形(执行有关四边形的计算)
q = new Quadrilateral(p[2],p[3],p[4],p[5]);
solve(l,q);
return;
}catch (Exception e){ //可能构成三角形
try{ //保证以下代码正确,捕获异常并吞并
//以5号点作为s顶点
if(!p[2].isSameTo(p[4])){ //2,4点不重合
Line ll = new Line(p[2],p[4]);
//3在ll之上,5在ll之外
if(p[3].inLineSegment_close(ll) && !p[5].inLineSegment_close(ll)){
Triangle t = new Triangle(p[2],p[4],p[5]);
solve(l,t);
return;
}
}
else{ //2,4点重合
if(!p[2].isSameTo(p[3])){ //但是2,3点不重合
Line ll = new Line(p[2],p[3]);
if(!p[5].inLineSegment_close(ll)){ //5点在ll线之外
Triangle t = new Triangle(p[2],p[3],p[5]);
solve(l,t);
return;
}
}
}
//以2号点作为顶点
if(!p[3].isSameTo(p[5])){
Line ll = new Line(p[3],p[5]);
if(p[4].inLineSegment_close(ll) && !p[2].inLine(ll)){
Triangle t = new Triangle(p[2],p[3],p[5]);
solve(l,t);
return;
}
}
else{
if(!p[3].isSameTo(p[4])){
Line ll = new Line(p[3],p[4]);
if(!p[2].inLineSegment_close(ll)){
Triangle t = new Triangle(p[2],p[3],p[4]);
solve(l,t);
return;
}
}
}
//以4号点作为顶点
if(!p[3].isSameTo(p[5])){
Line ll = new Line(p[3],p[5]);
if(p[2].inLineSegment_close(ll) && !p[4].inLine(ll)){
Triangle t = new Triangle(p[3],p[4],p[5]);
solve(l,t);
return;
}
}
//以3号点作为顶点
if(!p[2].isSameTo(p[4])){
Line ll = new Line(p[2],p[4]);
if(p[5].inLineSegment_close(ll) && !p[3].inLine(ll)){
Triangle t = new Triangle(p[2],p[3],p[4]);
solve(l,t);
return;
}
}
//不构成三角形
System.out.println("not a quadrilateral or triangle");
}catch(Exception ee){}
}
}
if(cmd == 5){
try{ //四点构成四边形
Quadrilateral q = new Quadrilateral(p[1],p[2],p[3],p[4]);
int op = q.isContainPoint(p[0]);
if(op == 0) System.out.println("in the quadrilateral");
else if(op == 1) System.out.println("on the quadrilateral");
else System.out.println("outof the quadrilateral");
}catch(Exception e){ //不构成四边形,待确定是否构成三角形
try{ //保证以下代码正确,捕获异常并吞并
//以4号点作为s顶点
if(!p[1].isSameTo(p[3])){ //1,3点不重合
Line ll = new Line(p[1],p[3]);
//2在ll之上,4在ll之外
if(p[2].inLineSegment_close(ll) && !p[4].inLineSegment_close(ll)){
Triangle t = new Triangle(p[1],p[3],p[4]);
inTriangle(p[0],t);
return;
}
}
else{ //1,3点重合
if(!p[1].isSameTo(p[2])){ //但是2,3点不重合
Line ll = new Line(p[1],p[2]);
if(!p[4].inLineSegment_close(ll)){ //5点在ll线之外
Triangle t = new Triangle(p[1],p[2],p[4]);
inTriangle(p[0],t);
return;
}
}
}
//以1号点作为顶点
if(!p[2].isSameTo(p[4])){
Line ll = new Line(p[2],p[4]);
if(p[3].inLineSegment_close(ll) && !p[1].inLine(ll)){
Triangle t = new Triangle(p[1],p[2],p[4]);
inTriangle(p[0],t);
return;
}
}
else{
if(!p[2].isSameTo(p[3])){
Line ll = new Line(p[2],p[3]);
if(!p[1].inLineSegment_close(ll)){
Triangle t = new Triangle(p[1],p[2],p[3]);
inTriangle(p[0],t);
return;
}
}
}
//以3号点作为顶点
if(!p[2].isSameTo(p[4])){
Line ll = new Line(p[2],p[4]);
if(p[1].inLineSegment_close(ll) && !p[3].inLine(ll)){
Triangle t = new Triangle(p[2],p[3],p[4]);
inTriangle(p[0],t);
return;
}
}
//以2号点作为顶点
if(!p[1].isSameTo(p[3])){
Line ll = new Line(p[1],p[3]);
if(p[4].inLineSegment_close(ll) && !p[2].inLine(ll)){
Triangle t = new Triangle(p[1],p[2],p[3]);
inTriangle(p[0],t);
return;
}
}
//不构成三角形
System.out.println("not a quadrilateral or triangle");
}catch(Exception ee){}
}
}
}
public static boolean check(String str){
return str.matches("^[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)$");
}
public static void pr_ans(Triangle t, Point a,Point b,Point c){
double[] ans = new double[2];
ans[0] = Triangle.area(a,b,c);
ans[1] = t.area() - ans[0];
Arrays.sort(ans);
System.out.printf("2 %s %s\n",change(ans[0]),change(ans[1]));
}
public static void pr_ans(Quadrilateral q,Point a,Point b,Point c){
double[] ans = new double[2];
ans[0] = Triangle.area(a,b,c);
ans[1] = q.area() - ans[0];
Arrays.sort(ans);
System.out.printf("2 %s %s\n",change(ans[0]),change(ans[1]));
}
public static String change(double a){
String res = String.format("%.3f",a);
res = res.replaceAll("0+?$", "");
if(res.charAt(res.length()-1) == '.') res+='0';
return res;
}
//三角形交点情况,上次练习题copy
public static void solve(Line l,Triangle t){
//与任意一条边重合
if(l.isSameTo(t.ab) || l.isSameTo(t.ac) || l.isSameTo(t.bc)){
System.out.println("The line is coincide with one of the lines");
return;
}
//与三条边的交点(值可能为null,即平行)
Point p_ab = l.getIntersection(t.ab);
Point p_ac = l.getIntersection(t.ac);
Point p_bc = l.getIntersection(t.bc);
//三交点是否位于边之内
boolean p_ab_in=false, p_ac_in =false, p_bc_in=false;
if(p_ab != null) p_ab_in = p_ab.inLineSegment(t.ab);
if(p_ac != null) p_ac_in = p_ac.inLineSegment(t.ac);
if(p_bc != null) p_bc_in = p_bc.inLineSegment(t.bc);
//任一角在直线之上(特判三角形的角)
if(t.a.inLine(l)){
//与另一条边无交点或者交点在边之外
if(p_bc == null || !p_bc.inLineSegment_close(t.bc)){
System.out.println("1");
}
else pr_ans(t,t.a,t.b,p_bc);
return;
}
if(t.b.inLine(l)){
if(p_ac == null || !p_ac.inLineSegment_close(t.ac)){
System.out.println("1");
}
else pr_ans(t,t.a,t.b,p_ac);
return;
}
if(t.c.inLine(l)){
if(p_ab == null || !p_ab.inLineSegment_close(t.ab)){
System.out.println("1");
}
else pr_ans(t,t.a,t.c,p_ab);
return;
}
//两个交点
if(p_ab_in && p_bc_in){ pr_ans(t,t.b,p_ab,p_bc);return;}
if(p_ab_in && p_ac_in){ pr_ans(t,t.a,p_ab,p_ac);return;}
if(p_bc_in && p_ac_in){ pr_ans(t,t.c,p_bc,p_ac);return;}
//无交点
System.out.println("0");
}
//四边形交点情况
public static void solve(Line l,Quadrilateral q){
//与任意一条边重合
for(Line ll: q.lines){
if(l.isSameTo(ll)){
System.out.println("The line is coincide with one of the lines");
return;
}
}
//与四条边的交点,可能为null;
Point p0 = l.getIntersection(q.lines[0]);
Point p1 = l.getIntersection(q.lines[1]);
Point p2 = l.getIntersection(q.lines[2]);
Point p3 = l.getIntersection(q.lines[3]);
//判断交点是否在边之上
boolean p0_in = false,p1_in = false,p2_in = false,p3_in = false;
if(p0 != null) p0_in = p0.inLineSegment(q.lines[0]);
if(p1 != null) p1_in = p1.inLineSegment(q.lines[1]);
if(p2 != null) p2_in = p2.inLineSegment(q.lines[2]);
if(p3 != null) p3_in = p3.inLineSegment(q.lines[3]);
//任一角在直线l之上
if(q.points[0].inLine(l)){
//它的对角也在边之上
if(q.points[2].inLine(l)){
pr_ans(q,q.points[0],q.points[1],q.points[2]);
}
//对角的邻边任一与直线有交点
else if (p2_in){ //邻边之一
pr_ans(q,q.points[0],p2,q.points[3]);
}
else if (p1_in){ //邻边之二
pr_ans(q,q.points[0],p1,q.points[1]);
}
else{
System.out.println("1");
}
return;
}
else if(q.points[1].inLine(l)){
//它的对角也在边之上
if(q.points[3].inLine(l)){
pr_ans(q,q.points[1],q.points[2],q.points[3]);
}
//对角的邻边任一与直线有交点
else if (p2_in){ //邻边之一
pr_ans(q,q.points[1],p2,q.points[2]);
}
else if (p3_in){ //邻边之二
pr_ans(q,q.points[1],p3,q.points[0]);
}
else{
System.out.println("1");
}
return;
}
else if (q.points[2].inLine(l)) {
//它的对角也在边之上
if(q.points[0].inLine(l)){
pr_ans(q,q.points[2],q.points[3],q.points[0]);
}
//对角的邻边任一与直线有交点
else if (p3_in){ //邻边之一
pr_ans(q,q.points[2],p3,q.points[3]);
}
else if (p0_in){ //邻边之二
pr_ans(q,q.points[2],p0,q.points[1]);
}
else{
System.out.println("1");
}
return;
}
else if (q.points[3].inLine(l)) {
//它的对角也在边之上
if(q.points[1].inLine(l)){
pr_ans(q,q.points[3],q.points[0],q.points[1]);
}
//对角的邻边任一与直线有交点
else if (p0_in){ //邻边之一
pr_ans(q,q.points[3],p0,q.points[0]);
}
else if (p1_in){ //邻边之二
pr_ans(q,q.points[3],p1,q.points[2]);
}
else{
System.out.println("1");
}
return;
}
//两个交点(邻边)
if(p0_in && p1_in){pr_ans(q,p0,p1,q.points[1]);return;}
if(p1_in && p2_in){pr_ans(q,p1,p2,q.points[2]);return;}
if(p2_in && p3_in){pr_ans(q,p2,p3,q.points[3]);return;}
if(p3_in && p0_in){pr_ans(q,p3,p0,q.points[0]);return;}
//对边
if(p0_in && p2_in){
double[] ans = new double[2];
ans[0] = Triangle.area(q.points[0],p0,p2) + Triangle.area(p0,p2,q.points[3]);
ans[1] = Triangle.area(q.points[1],p0,p2) + Triangle.area(p0,p2,q.points[2]);
Arrays.sort(ans);
System.out.printf("2 %s %s\n",change(ans[0]),change(ans[1]));
return;
}
if(p1_in && p3_in){
double[] ans = new double[2];
ans[0] = Triangle.area(q.points[1],p1,p3) + Triangle.area(p1,p3,q.points[0]);
ans[1] = Triangle.area(q.points[2],p1,p3) + Triangle.area(p1,p3,q.points[3]);
Arrays.sort(ans);
System.out.printf("2 %s %s\n",change(ans[0]),change(ans[1]));
return;
}
//0交点
System.out.println("0");
}
//判断点在三角形哪里
public static void inTriangle(Point p,Triangle t){
int op = t.isContainPoint(p);
if(op == 0) System.out.println("in the triangle");
else if (op == 1) System.out.println("on the triangle");
else System.out.println("outof the triangle");
}
}
附录(自定义类说明)
重新封装了之前的三个类,并加上一个Quadrilateral类:
Point
- inLine方法修改传入的参数为Line,(原为:Point , Point)
- 点到点的距离方法重命名为:disToPoint
- 点到直线的距离方法重命名为:disToLine
- 增加了方法:boolean inLineSegment(Line l)(判断是否在线段之内)
- 增加了方法:boolean inLineSegment_close(Line l)(同上,但是包括了端点)
- 删除了方法:double Slope(Point another)(求两点之间斜率)
package Points;
public class Point{
public double x, y;
public Point(){
this.x = 0;
this.y = 0;
}
public Point(double a,double b){
this.x = a;
this.y = b;
}
public void print(){
System.out.printf("(%f,%f)\n",this.x,this.y);
}
//两点坐标相同
public boolean isSameTo(Point a){
return (this.x == a.x)&&(this.y == a.y);
}
//两点距离
public double disToPoint(Point another){
return Math.sqrt(Math.pow(this.x-another.x,2) + Math.pow(this.y-another.y,2));
}
//点到直线的垂直距离
public double disToLine(Line l){
return Math.abs(l.a*this.x+l.b*this.y+l.c) / Math.sqrt(Math.pow(l.a,2)+Math.pow(l.b,2));
}
//判断是否在直线之上
public boolean inLine(Line l){
return Math.abs(l.a*this.x + l.b*this.y + l.c) < 0.000001;
}
//判断是否在线段之内(包括端点)
public boolean inLineSegment_close(Line l){
if(!this.inLine(l)) return false;
double res = this.disToPoint(l.sta) + this.disToPoint(l.ed) - l.length();
return Math.abs(res) < 0.000001;
}
//判断是否在线段之内(不包括端点)
public boolean inLineSegment(Line l){
return this.inLineSegment_close(l) &&
(!this.isSameTo(l.sta)) &&
(!this.isSameTo(l.ed));
}
}
Line
- 重写了构造函数,当两点不能构成直线时,抛出"points coincide"异常
- 判断平行的方法重命名为:isParallelTo
- 增加了方法:double slope()(求直线斜率)
- 增加了方法:boolean isVerticalTo(Line another)(判断与另一条直线是否垂直)
- 删除了方法:boolean inLine(Point p)(判断点是否在直线上)
- 删除了方法:boolean inLineSegment(Point p) (判断点是否在线段上)
- 删除了方法:boolean inLineSegment_close(Point p)(同上,但是包括端点)
package Points;
public class Line extends Point {
public Point sta, ed;
public double a,b,c;
public Line(Point a,Point b)throws Exception{
if(a.isSameTo(b)){
throw new Exception("points coincide");
}
this.sta = a;
this.ed = b;
this.a = (-(a.y-b.y));
this.b = (a.x-b.x);
this.c = (-this.a*this.sta.x-this.b*this.sta.y);
}
public void print(){
System.out.printf("%fX + %fY + %f = 0\n",this.a,this.b,this.c);
}
//求线段长度
public double length(){
return this.sta.disToPoint(this.ed);
}
//求线段斜率
public double slope(){
if(this.b == 0){
return 2^48;
}
return -this.a / this.b;
}
//判断是否平行
public boolean isParallelTo(Line another){
if(this.b==0 || another.b==0){
return (this.b == 0 && another.b == 0);
}
return ((this.a / this.b) == (another.a / another.b));
}
//判断是否重合
public boolean isSameTo(Line another){
return this.isParallelTo(another) && (this.c==another.c);
}
//判断是否垂直
public boolean isVerticalTo(Line another){
return this.a * another.a + this.b * another.b == 0;
}
//求两条直线交点
public Point getIntersection(Line another){
if(this.isParallelTo(another)) return null;
Point res = new Point();
res.y = (another.a*this.c-this.a*another.c) / (this.a*another.b-another.a*this.b);
res.x = (this.b*another.c-another.b*this.c) / (this.a*another.b-another.a*this.b);
return res;
}
}
Triangle
- 重写了构造函数,当三点不能构成三角形是抛出"not a triangle"异常
- 增加静态方法:double area(Point a, Point b, Point c)(求三点构成的图形面积)
package Points;
import java.util.Arrays;
public class Triangle extends Point {
public Point a,b,c;
public Line ab,ac,bc;
public Triangle(Point a, Point b, Point c)throws Exception{
try{
this.a = a;
this.b = b;
this.c = c;
this.ab = new Line(a,b);
this.ac = new Line(a,c);
this.bc = new Line(b,c);
if(this.ab.isParallelTo(this.bc)){
throw new Exception("not a triangle");
}
}catch(Exception e){
throw e;
}
}
public void print(){
System.out.println("三个点坐标为:");
this.a.print();this.b.print();this.c.print();
System.out.println("三条线一般式为:");
this.ab.print();this.ac.print();this.bc.print();
}
//判断是否为等腰三角形
public boolean isIsoscelesTriangle(){
return this.ab.length() == this.ac.length() ||
this.ab.length() == this.bc.length() ||
this.ac.length() == this.bc.length();
}
//判断是否为等边三角形
public boolean isEquilateralTriangle(){
return this.ab.length() == this.ac.length() &&
this.ac.length() == this.bc.length();
}
//求三角形的边长
public double sideLength(){
return this.ab.length() + this.ac.length() + this.bc.length();
}
//求三角形面积
public double area(){
double p = this.sideLength() / 2;
return Math.sqrt(p*(p-this.ab.length())*(p-this.ac.length())*(p-this.bc.length()));
}
//求三个点围成的图形面积(三点可能共线,面积为0)
public static double area(Point a,Point b,Point c){
double len1 = a.disToPoint(b);
double len2 = b.disToPoint(c);
double len3 = c.disToPoint(a);
double p = (len1+len2+len3) / 2;
return Math.sqrt(p*(p-len1)*(p-len2)*(p-len3));
}
//求三角形的重心
public Point focusPoint(){
Point res = new Point();
res.x = (this.a.x + this.b.x + this.c.x) / 3;
res.y = (this.a.y + this.b.y + this.c.y) / 3;
return res;
}
//求三角形类型,(锐角0,直角1,钝角2)
public int type(){
double[] num = new double[3];
num[0] = this.ab.length();num[1] = this.ac.length();num[2] = this.bc.length();
Arrays.sort(num);
double tmp = Math.pow(num[0],2) + Math.pow(num[1],2) - Math.pow(num[2],2);
if(Math.abs(tmp) < 0.0000001) return 1;
if(tmp < 0) return 2;
return 0;
}
// 判断某点是否在三角形之内,(0内,1边,2外);
//面积法
public int isContainPoint(Point p){
//特判在边上的情况
if(p.inLineSegment_close(this.ab) || p.inLineSegment_close(this.bc)
|| p.inLineSegment_close(this.ac)){
return 1;
}
double s1 = Triangle.area(p,this.a,this.b);
double s2 = Triangle.area(p,this.b,this.c);
double s3 = Triangle.area(p,this.c,this.a);
double res = s1+s2+s3 - this.area();
if(Math.abs(res) < 0.000001) return 0;
return 2;
}
}
Quadrilateral
- Quadrilateral(Point a,Point b,Point c,Point d) (构造函数,不能构成四边形时抛出"not a quadrilateral"异常)
- void print() (打印四边形一些信息)咕咕咕~
- boolean isParallelQuadrilateral() (判断是否为平行四边形)
- boolean isDiamond() (判断是否为菱形)
- boolean isRectangle() (判断是否为矩形)
- boolean isSquare() (判断是否为正方形)
- boolean isConvexQuadrilateral() (判断是否为凸四边形)
- int isContainPoint(Point p) (判断一个点是否落在(凸)四边形内部(0内,1边,2外) )
- double sideLength() (四边形周长)
- double area() (四边形面积(切分为两个三角形))
package Points;
public class Quadrilateral{
public Point[] points;
public Line[] lines;
public Quadrilateral(Point a,Point b,Point c,Point d)throws Exception{
try{
this.points = new Point[4];
this.lines = new Line[4];
this.points[0] = a; this.points[1] = b;
this.points[2] = c; this.points[3] = d;
this.lines[0] = new Line(this.points[0], this.points[1]);
this.lines[1] = new Line(this.points[1], this.points[2]);
this.lines[2] = new Line(this.points[2], this.points[3]);
this.lines[3] = new Line(this.points[3], this.points[0]);
//虽然没使用,但删了就报错doge
Line diagonal1 = new Line(points[0],points[2]);
Line diagonal2 = new Line(points[1],points[3]);
if(lines[0].isParallelTo(lines[1]) || lines[0].isParallelTo(lines[3])){
throw new Exception("not a quadrilateral");
}
if(lines[2].isParallelTo(lines[1]) || lines[2].isParallelTo(lines[3])){
throw new Exception("not a quadrilateral");
}
Point p1 = lines[0].getIntersection(lines[2]);
Point p2 = lines[1].getIntersection(lines[3]);
if(p1 != null && p1.inLineSegment_close(lines[0]) && p1.inLineSegment_close(lines[2])) throw new Exception("not a quadrilateral");
if(p2 != null && p2.inLineSegment_close(lines[1]) && p2.inLineSegment_close(lines[3])) throw new Exception("not a quadrilateral");
}catch (Exception e){
throw e;
}
}
public void print(){
}
//判断是否为平行四边形(对边分别平行)
public boolean isParallelQuadrilateral(){
return this.lines[0].isParallelTo(this.lines[2]) &&
this.lines[1].isParallelTo(this.lines[3]);
}
//判断是否为菱形(平行四边形 + 四边长度相等)
public boolean isDiamond(){
boolean v = this.lines[0].length() == this.lines[1].length() &&
this.lines[1].length() == this.lines[2].length() &&
this.lines[2].length() == this.lines[3].length();
return this.isParallelQuadrilateral() && v;
}
//判断是否为矩形(对角线相等)
public boolean isRectangle(){
return this.points[0].disToPoint(this.points[2]) == this.points[1].disToPoint(this.points[3]);
}
//判断是否为正方形(菱形 + 矩形)
public boolean isSquare(){
return this.isDiamond() && this.isRectangle();
}
//判断是否为凸四边形(面积公式)
public boolean isConvexQuadrilateral(){
double s1 = Triangle.area(points[0],points[1],points[2]);
double s2 = Triangle.area(points[2],points[3],points[0]);
double s3 = Triangle.area(points[1],points[2],points[3]);
double s4 = Triangle.area(points[3],points[0],points[1]);
double res = s1 + s2 - s3 - s4;
return Math.abs(res) < 0.000001;
}
//判断一个点是否落在(凸)四边形内部(0内,1边,2外)
//和Triangle类似,用面积法;
public int isContainPoint(Point p){
if(p.inLineSegment_close(this.lines[0]) || p.inLineSegment_close(this.lines[1])
|| p.inLineSegment_close(this.lines[2]) || p.inLineSegment_close(this.lines[3])){
return 1;
}
double s1 = Triangle.area(p,this.points[0],this.points[1]);
double s2 = Triangle.area(p,this.points[1],this.points[2]);
double s3 = Triangle.area(p,this.points[2],this.points[3]);
double s4 = Triangle.area(p,this.points[3],this.points[0]);
double res = s1+s2+s3+s4 - this.area();
if(Math.abs(res) < 0.000001) return 0;
return 2;
}
//四边形周长
public double sideLength(){
return this.lines[0].length() + this.lines[1].length() +this.lines[2].length() +this.lines[3].length();
}
//四边形面积(切分为两个三角形)
public double area(){
double s1 = Triangle.area(this.points[0], this.points[1], this.points[2]);
double s2 = Triangle.area(this.points[0], this.points[3], this.points[2]);
double s3 = Triangle.area(this.points[1], this.points[0], this.points[3]);
double s4 = Triangle.area(this.points[1], this.points[2], this.points[3]);
return Math.min(s1+s2, s3+s4);
}
}
感谢看到最后 😃