《面向对象编程学习的BLOG2》
《面向对象编程的BLOG2》
21201705-单梓洋
前言:
本Blog基于南昌航空大学软件工程专业“面向对象程序设计”笔者的收获所写,内容大体关于配套的PTA题集,收获以及笔记等,辛苦批改的同学可以直接翻到下划线后面的正文部分.

<笔记整理>




三个星期的学习中接触了很多新兴的事务,从idea里多出的许许多多的软件包就可以看出,set,map,stream到DoubleLinkedList,lambda表达式,正则表达式等等等等一系列之前接触少而精密的知识,再到银行类设计,再到农夫过河的实验和期中考试(考察继承与多态还有容器类的使用)加以复习之前的技能.
在这几个礼拜的学习中贯穿大段落的词是迭代以及自学,前者体现在每一次的PTA实验的题目当中,比如从点线的设计开始,一路迭代到三角形,然后凹四边形,亦或者是农夫过河中从一开始农夫狼羊菜保证存活,到后面慢慢增加船类,分类,兔子类萝卜类等等,还有后面即将分析的期中考试,这种迭代的方式可以让我们将类设计的思想充分利用,通过一步步的优化,也认识到之前某种设计的不足之处在哪里,比如在后文将分析的农夫过河实验中,船类修复了一开始逻辑上的bug,父类优化了算法的结构,但是几个星期的迭代通过细细的思考的话这样的设计也带来了一部分的问题,粗暴的设计可能会导致很多重复以及在编码的过程中可能导致的一些搞笑的事情,比如羊吃狼,所有的类继承了一个father类,我认为是不如细分类的,这就好比一个富商见到一个需要帮助的人就给钱,这诚然是一种有效的方法,但是如果数量增大,就会造成浪费。这是我们不想见到的,所以食谱的建立以及肉食动物和植物的分开就很有必要,在下一次的实验中也验证了我这个小小的猜想,这些都是迭代思想所带来的,自学则体现在我们每一次的上课中不用太细致的观察,就足以发现这几个礼拜上课的课时逐渐变得少,很多时候都是第1节课讲课,第2节课则是自己开始操练方法 从Set,map,stream这些数据结构类,到lambda,正则表达式,javaFX这些优化代码的方法等等 ,上一次的实验报告中更加偏向一个思考的过程,踩坑思考比较少,得到一些同学的反馈后修改一下模式,由于PTA中凹四边形这种题目代码太长而且我有测试点未通过,故不贴出,结束前言,开始对于这三个礼拜所学所见的正式分析.
-----------------------------------------------------------------------------------------
<题目总结>
期中考试的第1题要求设计类表示平面直角坐标系上的点Point及表示平面直角坐标系上的线Line,没有什么算法难度,考察基础的语法,但是类和类之间的设计要符合题目的要求,输出的时候保证结果是两位小数,可以用题目的String.format("%.2f", data),另外相关的属性要用private,除了行为之外不用public以保证代码的耦合度也要尽可能低

import java.util.Scanner; public class Main { public static boolean inputright(double x ,double y) { return (x>0&&x<=200&&y>0&&y<=200); } public static void main(String[] args) { Scanner in = new Scanner(System.in); // String arr = in.nextLine(); // String[] x = arr.split(" ");//去除空格符 double x1, x2, y1, y2; x1 = Double.parseDouble(in.next()); y1 = Double.parseDouble(in.next()); x2 = Double.parseDouble(in.next()); y2 = Double.parseDouble(in.next()); String color=in.next(); if(inputright(x1, y1)&&inputright(x2, y2)){ Point P1 =new Point(x1,y1); Point P2 =new Point(x2,y2); Line l=new Line(P1,P2,color); l.display();} else System.out.print("Wrong Format\n"); } } class Point { private double x=0; private double y=0; public Point() { } public Point(double x ,double y) { this.x=x; this.y=y; } 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; } public void display() { String s = String.format("(%.2f,%.2f)", x, y); System.out.println(s); } } class Line { Point Point1; Point Point2; private String color="Red" ; public Line() { } public Line(Point p1 ,Point p2,String colorin) { Point1=p1; Point2=p2; this.color=colorin; } 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 Point getPoint1(){ return Point1; } public Point getPoint2() { return Point2; } public String getColor() { return color; } public void setPoint1(Point p1 ){ Point1=p1; } public void setPoint2(Point p2 ){ Point2=p2; } public void setColor(String color) { this.color=color; } public void display() { System.out.println("The line's color is:"+color); String s = String.format("(%.2f,%.2f)", Point1.getX(), Point1.getY()); String x = String.format("(%.2f,%.2f)", Point2.getX(), Point2.getY()); System.out.println("The line's begin point's Coordinate is:"); System.out.println(s); System.out.println("The line's end point's Coordinate is:"); System.out.println(x); System.out.println("The line's length is:"+String.format("%.2f", getDistance())); } }
回到前文所说的迭代,期中考试第2题是对第1题的迭代,要求增加一个类Plane,另外定义一个共同父类Element(抽象类),将display()方法在该方法中进行声明(抽象方法),这个共同父类中其实是没东西的,只有一个display的方法继承给下面三个类,子类在根据需求完善这个继承来的方法,最后答案通过Main里面定义子类对象赋值给父类对象然后由父类进行调用向下。这样说可能会比较抽象,说简单一点点。这道题目就是一个子类完善方法,然后把子类赋值给父类父类进行展示。也就是一个element来display然后你把子类方法写好以后接受子类对象给父类就可以了。

import java.util.Scanner; public class Main { public static boolean inputright(double x ,double y) { return (x>0&&x<=200&&y>0&&y<=200); } public static void main(String[] args) { Scanner in = new Scanner(System.in); double x1, x2, y1, y2; x1 = Double.parseDouble(in.next()); y1 = Double.parseDouble(in.next()); x2 = Double.parseDouble(in.next()); y2 = Double.parseDouble(in.next()); String color=in.next(); if(inputright(x1, y1)&&inputright(x2, y2)){ Point P1 =new Point(x1,y1); Point P2 =new Point(x2,y2); Line line=new Line(P1,P2,color); Plane plane=new Plane(color); Element element; element = P1;//起点Point element.display(); element = P2;//终点Point element.display(); element = line;//线段 element.display(); element = plane;//面 element.display(); } else { System.out.print("Wrong Format\n"); } } } abstract class Element { public void display() { } } class Line extends Element { Point Point1; Point Point2; private String color ; public Line() { } public Line(Point p1 ,Point p2,String colorin) { Point1=p1; Point2=p2; this.color=colorin; } 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 Point getPoint1(){ return Point1; } public Point getPoint2() { return Point2; } public String getColor() { return color; } public void setPoint1(Point p1 ){ Point1=p1; } public void setPoint2(Point p2 ){ Point2=p2; } public void setColor(String color) { this.color=color; } @Override public void display() { System.out.println("The line's color is:"+color); String s = String.format("(%.2f,%.2f)", Point1.getX(), Point1.getY()); String x = String.format("(%.2f,%.2f)", Point2.getX(), Point2.getY()); System.out.println("The line's begin point's Coordinate is:"); System.out.println(s); System.out.println("The line's end point's Coordinate is:"); System.out.println(x); System.out.println("The line's length is:"+String.format("%.2f", getDistance())); } } class Plane extends Element{ private 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:"+color); } } class Point extends Element{ private double x=0; private double y=0; public Point() { } public Point(double x ,double y) { this.x=x; this.y=y; } 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() { String s = String.format("(%.2f,%.2f)", x, y); System.out.println(s); } }

期中考试第3题在第2题的基础上面继续的迭代,要求在原有类设计的基础上,增加一个GeometryObject容器类,其属性为ArrayList类型的对象(若不了解泛型,可以不使用),增加该类的add()方法及remove(int index)方法,其功能分别为向容器中增加对象及删除第index - 1(ArrayList中index>=0)个对象,这里使用了Java自带的Arrylist,要求添加的类型element,element和第二题一样都是其他类的父类,对于point,line,plane没有变化依然和第二题一样,除此之外对于main进行了一定的改良,要求我们要按照要求判定是添加删除还是退出,这个地方一开始没有看到题目写好的switch浪费了一点时间提醒我们要更好的审题GeometryObject这个容器内用到了一点点泛型的内容,但是实际上来说,他其实是没有怎么用的,使用arraylist把子类添加到list里面,或者从list里面删除,输出的时候其实没有那么复杂,用foreach直接遍历arraylist其实就可以,考试的时候忘了可以这样操作,所以在容器里面加一个方法返回容器里的值,然后在main里面直接
for(int i=0;i<list.size();i++) {
Element element=list.get(i);
element.display();
}
此外的话在删除的时候有说删除对象时,若输入的index超出合法范围,程序自动忽略该操作,要求我们自己去判定index的范围,有点类似于银行类和链表的结合体,主要要求根据题目给的类图合理的设计,代码贴到下面:
import java.util.Scanner; import java.util.ArrayList; public class Main { public static boolean inputright(double x ,double y) { return (x>0&&x<=200&&y>0&&y<=200); } public static void main(String[] args) { Scanner in = new Scanner(System.in); int choice = in.nextInt(); GeometryObject list=new GeometryObject(); while(choice != 0) { double x1, x2, y1, y2; switch(choice) { case 1: x1 = Double.parseDouble(in.next()); y1 = Double.parseDouble(in.next()); Point P1 =new Point(x1,y1); list.add( P1 ); break; case 2: x1 = Double.parseDouble(in.next()); y1 = Double.parseDouble(in.next()); x2 = Double.parseDouble(in.next()); y2 = Double.parseDouble(in.next()); String color=in.next(); Point P3 =new Point(x1,y1); Point P2 =new Point(x2,y2); Line line=new Line(P3,P2,color); list.add( line ); break; case 3: String colorx=in.next(); Plane plane=new Plane(colorx); list.add( plane ); break; case 4: int index = in.nextInt(); if(index>list.size()||index<0) break; else list.remove(index - 1); } choice = in.nextInt(); } for(int i=0;i<list.size();i++) { Element element=list.get(i); element.display(); } } } abstract class Element { public void display() { } } class GeometryObject { ArrayList<Element>list=new ArrayList<>(); public void add(Element element){ list.add(element); } public void remove(int index){ list.remove(index); } public ArrayList<Element> getList(){ return list; } public int size() { return list.size(); } public Element get(int index) { return list.get(index); } } class Line extends Element { Point Point1; Point Point2; private String color ; public Line() { } public Line(Point p1 ,Point p2,String colorin) { Point1=p1; Point2=p2; this.color=colorin; } 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 Point getPoint1(){ return Point1; } public Point getPoint2() { return Point2; } public String getColor() { return color; } public void setPoint1(Point p1 ){ Point1=p1; } public void setPoint2(Point p2 ){ Point2=p2; } public void setColor(String color) { this.color=color; } @Override public void display() { System.out.println("The line's color is:"+color); String s = String.format("(%.2f,%.2f)", Point1.getX(), Point1.getY()); String x = String.format("(%.2f,%.2f)", Point2.getX(), Point2.getY()); System.out.println("The line's begin point's Coordinate is:"); System.out.println(s); System.out.println("The line's end point's Coordinate is:"); System.out.println(x); System.out.println("The line's length is:"+String.format("%.2f", getDistance())); } } class Plane extends Element{ private 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:"+color); } } class Point extends Element{ private double x=0; private double y=0; public Point() { } public Point(double x ,double y) { this.x=x; this.y=y; } 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() { String s = String.format("(%.2f,%.2f)", x, y); System.out.println(s); } }
<链表>
有关链表的设计单项链表中,其实跟C语言差不多我的功能存在一定的障碍,主要问题集中在删除,源码就不贴了,这次的设计通过了接口和泛型来实现,主要的思想其实也是通过Java类存储数据来模拟结构体,其实仍然是地址输出完之后到下一个地方,双向链表的功能与单向链表差不多都是用来进行对链表中的数据进行增加删除查询修改等,但是在实现的过程中有些许的差异,以删除为例,单向链表的删除要将指针指到被删除节点的前一个节点,而双向的列表可以直接删除等等
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); DoubleLinkedList<Integer> szy = new DoubleLinkedList<>() ; int flag=0; while(true) { System.out.println("*********************************************************"); System.out.println("start"); System.out.println("input your numbers"); System.out.println("1.delete a kot");// System.out.println("2.Increment at specified position (enter subscript and number to increment)"); System.out.println("3.Tail increment (directly enter the number to be added)"); System.out.println("4.Prints the number in the linked list"); System.out.println("5.Get the number of nodes"); System.out.println("6.Gets the number of specified nodes"); System.out.println("7.Exiting the System"); int choice = input.nextInt(); switch (choice) { case 1: System.out.println("Input adding value"); int index = input.nextInt(); if (szy.getData(index) == null) System.out.println("Find null!"); else { szy.remove(index); System.out.println("OK"); } break; case 2: System.out.println("Input location and value"); int indexa = input.nextInt(); int value = input.nextInt(); if (szy.getData(indexa) == null) System.out.println("no!"); else { szy.add(indexa, value); System.out.println("finished"); } break; case 3: System.out.println("Input adding value:"); int valuea = input.nextInt(); szy.add(valuea); System.out.println("OK"); break; case 4: szy.printList(); break; case 5: System.out.println("Numbers" + szy.getSize()); break; case 6: System.out.println(szy.getSize()); break; case 7: flag++; default: System.out.println("exit"); break; } if(flag!=0) { break; } } } } public class Node<E> { private E data;//数据域,类型为泛型E protected Node<E> next;//后继引用(指针) protected Node<E> previous;//前驱引用(指针) Node(E data, Node<E> next,Node<E> prenext){ this.data = data; this.next =next; this.previous = previous; } Node(E data){ this.data=data; this.next=null; } Node(Node<E> next){ this.next = next; } public E getData(){ return data; } public void setData(E data){ this.data=data; } public Node<E> getNext(){ return next; } public void setNext(Node<E> next){ this.next =next; } public Node<E> getPreNext(){ return previous; } public void setPreNext(Node<E> next){ this.previous =next; } } public interface DoubleLinkedListImpl<E> { /** * 判断链表是否为空 * @return */ public boolean isEmpty(); /** * 获取当前链表节点数量 * @return 节点数 */ public int getSize(); /** * 获取链表中第index个位置的节点的data值 * @param index:节点在链表中的位置 * @return:返回该节点的data值 */ public E getData(int index); /** * 删除链表最后一个节点 */ public void remove(); /** *删除链表中第index位置的节点 * @param index:节点在链表中的位置 */ public void remove(int index); /** * 在链表的第index个位置之前插入一个节点,值为theElement,index∈[1,size] * @param index:插入节点在链表中的位置 * @param theElement:新插入节点的data值 */ public void add(int index, E theElement); /** * 在链表尾插入节点,插入节点data值为element * @param element */ public void add(E element); /** * 输出链表 */ public void printList(); /** * 获取第一个节点的data值 * @return */ public E getFirst(); /** * 获取链表最后一个节点的data值 * @return */ public E getLast(); } public class DoubleLinkedList<E> implements DoubleLinkedListImpl<E> { private Node<E> head;//头结点,非第一个节点 private Node<E> curr;//当前节点 private Node<E> tail;//最后一个节点 private int size;//当前链表节点数 @Override public boolean isEmpty() { // TODO 自动生成的方法存根 return size==0; } @Override public int getSize() { // TODO 自动生成的方法存根 return size; } @Override public E getData(int index) { // TODO 自动生成的方法存根 int size = 0; Node<E> temp = head; while(temp!=null) { size++; if (size == index) return temp.getData(); } return null; } @Override public void remove() { // TODO 自动生成的方法存根 tail=tail.previous; tail.next=null; } @Override public void remove(int index) { // TODO 自动生成的方法存根 Node<E> temp = head; Node<E> curl = null; int size = 0; while(temp!=null){ size++; temp=temp.next; if(size==index&&temp.getNext()!=null) { curl.setNext(temp); temp.getNext().setPreNext(curl); return; } if(size==index&&temp.getNext()==null){ curl.setNext(null); return; } curl=temp; } System.out.println("dont exist"); } @Override public void add(int index, E theElement) { // TODO 自动生成的方法存根 Node<E> temp = head; Node<E> curl = null; int size = 0; while(temp!=null){ size++; curl=temp; temp=temp.next; if(size==index) { Node<E> k = new Node<>(theElement); curl.setNext(k); k.setNext(temp); return; } } if(size==index-1) { Node<E> n = new Node<>(theElement); tail.setNext(n); return; } else System.out.println("该位置不存在"); } @Override public void add(E element) { // TODO 自动生成的方法存根 if(head==null) { head = new Node<E>(element); return; } if(tail==null) { tail = new Node<E>(element); head.setNext(tail); tail.setPreNext(head); return; } Node<E> temp = new Node<>(element,null,tail); tail.setNext(temp); tail = temp; } @Override public void printList() { // TODO 自动生成的方法存根 Node<E> temp = head; while(temp!=null){ System.out.println(temp.getData()); temp = temp.next;} return; } @Override public E getFirst() { // TODO 自动生成的方法存根 return head.getData(); } @Override public E getLast() { // TODO 自动生成的方法存根 return tail.getData(); } }
<图形类设计>
设计中所用正则表达式如下
String the = "[12345]\\:[\\+|-]?([0]|([1-9]((\\d)?)+))(\\.\\d+)?\\,([+\\-]?([0]|([1-9]((\\d)?)+)))(\\.\\d+)?(\\s([+\\-" + "]?([0]|([1-9]((\\d)?)+)))(\\.\\d+)?\\,([+\\-]?([0]|([1-9]((\\d)?)+)))(\\.\\d+)?)+";
7-2 点线形系列4-凸四边形的计算
要求用户输入一组选项和数据,进行与四边形有关的计算。判断是否是四边形、平行四边形,判断是否是菱形、矩形、正方形,判断是凹四边形(false)还是凸四边形(true),前两个点构成一条直线,后四个点构成一个四边形或三角形,输出直线与四边形(也可能是三角形)相交的交点数量,以及五个点坐标,输出第一个是否在后四个点所构成的四边形(限定为凸四边形,不考虑凹四边形)或三角形(判定方法见选项4)的内部.
<实验>

农夫过河的大实验。主要的思路已经在前言处有过一定的讲解,我这里不多赘叙,主要讲一下不足和待优化的点,要分析这些,我们首先要对整个实验中用到的方法进行一个总结,整个实验中总共有三个大块,一个是每一个对象都有的过河以及死亡这些共同的方法,然后是部分对象有的吃,以及农夫位置所带来的保护机制,目前是一个大的夫类,下面很多子类,我也没有建立食谱,直接在主方法下面硬性判断,毫无疑问这是不科学的,弊端就不讲了,优化的思路想到了多继承,区别于Python和C++支持多继承,java可能需要多个接口或者内部类,仔细思考后将这个问题分成了两块,以狼为例,狼的父类从father变成肉食类,肉食类中需要的是一些死亡过河以及吃,以菜为例他则只需要死亡和过河,把对象分为肉食类和菜食类两大父类下面的子类,然后再加一个父类加死亡以及过河的方法还有属性则可有效解决,考虑到我们现在写的代码没有用接口,这也比用接口更方便修改。
public class Wolf extends Father{ private String name="unokown"; // private boolean crossRiver=false; public Wolf(String name) { this.name=name; // System.out.println(" 啊呜~~~我"+this.name+"狼又回来了"); System.out.println(" awwww~~~ "+this.name+" wolf is back"); // System.out.println(this.name); } public Wolf() { } public String GetName() { return name; } // public void setCrossRiver(boolean crossRiver) { // this.crossRiver=crossRiver; // } // public boolean hasCross() { // return crossRiver; // } // public void eatSheep(Sheep sheep) { // if(sheep.GetisAlive()) // { // if(sheep.hasCross()==crossRiver) // sheep.SetisAlive(false); // } // } @Override public void showStatus() { System.out.print("Wolf "+ name+ " is alive :true "); if (super.hasCross()) { System.out.println("Wolf "+ name+ " has Cross :true "); } else System.out.println("Wolf "+ name+ " has Cross :false "); } } public class Sheep extends Father{ private String name="unokown"; // private boolean isAlive=true; // private boolean crossRiver = false; public Sheep(String name) { this.name=name; System.out.println(" miemie.I am a cute sheep named"+this.name); // System.out.println(this.name); } public Sheep() { } // public boolean GetisAlive() // { // return isAlive; // } // public void SetisAlive(boolean isAlive) // { // this.isAlive=isAlive; // } // public boolean hasCross() // { // return crossRiver; // } // public void setCrossRiver(boolean crossRiver) { // this.crossRiver=crossRiver; // } // public void eatCabbage (Cabbage cabbage){ // if (cabbage.GetisAlive() && isAlive) { // if (cabbage.hasCross() == crossRiver) // cabbage.SetisAlive(false) ; // } // } @Override public void showStatus () { if (super.GetisAlive()) System.out.print("Sheep "+ name+ "is alive:true "); else System.out.print("Sheep "+ name+ " is alive:false "); if (super.hasCross()) { System.out.println("Sheep "+ name+ " has Cross :true "); } else System.out.println("Sheep "+ name+ " has Cross :false "); } } public class Rabbit extends Father{ private String name="unokown"; public Rabbit(String name) { this.name=name; System.out.println(" 咩咩,我是可爱的小羊"+this.name); // System.out.println(this.name); } public Rabbit() { } @Override public void showStatus () { if (super.GetisAlive()) System.out.print("Rabbit "+ name+ "is alive:true "); else System.out.print("Rabbit "+ name+ " is alive:false "); if (super.hasCross()) { System.out.println("Rabbit "+ name+ " has Cross :true "); } else System.out.println("Rabbit "+ name+ " has Cross :false "); } } import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in= new Scanner(System.in); System.out.println(" Choice game pattern: 1. three goods pattren 2. five goods pattren"); int choice=in.nextInt(); // TODO Auto-generated method stub switch (choice) { case 1: Game game = new Game(); game.play(); break; case 2: Game newgame = new Game(); newgame.newplay(); break; } } } public class GameGui { public static void menu() { /* 显示菜单 */ System.out.println("==================Please choose operation============"); System.out.println("\t==========1:Cross the river alone==========="); System.out.println("\t==========2:Cross the river with wolf========="); System.out.println("\t==========3:Cross the river with sheep============"); System.out.println("\t==========4:Cross the river with cabbage=========="); System.out.println("\t==========0:Quit==============="); System.out.println("==================================================="); System.out.println("Input the number(0~4):"); } public static void newmenu() { /* 显示菜单 */ System.out.println("==================Please choose operation============"); System.out.println("\t==========1:Cross the river alone==========="); System.out.println("\t==========2:Cross the river with wolf and sheep========"); System.out.println("\t==========3:Cross the river with wolf and cabbage========"); System.out.println("\t==========4:Cross the river with wolf and rabbit========"); System.out.println("\t==========5:Cross the river with wolf and carrot========"); System.out.println("\t==========6:Cross the river with sheep and cabbage============"); System.out.println("\t==========7:Cross the river with sheep and rabbit============"); System.out.println("\t==========8:Cross the river with sheep and carrot============"); System.out.println("\t==========9:Cross the river with cabbage and rabbit=========="); System.out.println("\t==========10:Cross the river with cabbage and carrot=========="); System.out.println("\t==========11:Cross the river with rabbit and carrot=========="); System.out.println("\t==========12:Cross the river with wolf========="); System.out.println("\t==========13:Cross the river with sheep============"); System.out.println("\t==========14:Cross the river with cabbage=========="); System.out.println("\t==========15:Cross the river with rabbit============"); System.out.println("\t==========16:Cross the river with carrot=========="); System.out.println("\t==========0:Quit==============="); System.out.println("==================================================="); System.out.println("Input the number(0~16):"); } public static void showStatus(Farmer farmer, Wolf wolf, Sheep sheep, Cabbage cabbage) { /* 输出农夫、各种动物、物品的状态(生存、位置) */ farmer.showStatus(); wolf.showStatus(); sheep.showStatus(); cabbage.showStatus(); } public static void newshowStatus(Farmer farmer, Wolf wolf, Sheep sheep, Cabbage cabbage,Rabbit rabbit,Carrot carrot) { /* 输出农夫、各种动物、物品的状态(生存、位置) */ farmer.showStatus(); wolf.showStatus(); sheep.showStatus(); cabbage.showStatus(); rabbit.showStatus(); carrot.showStatus(); } } import java.util.Scanner; public class Game { Wolf wolf; Sheep sheep; Cabbage cabbage; Farmer farmer; Boat boat; Carrot carrot; Rabbit rabbit; //GameGui gui; Game() { wolf = new Wolf("mad"); sheep = new Sheep("lazy "); cabbage = new Cabbage(); farmer = new Farmer(); boat=new Boat(); carrot=new Carrot(); rabbit=new Rabbit(); } protected void play() { Scanner input = new Scanner(System.in); int choice ; //用户输入选择 boolean gameOver=false,//游戏结束标志,默认为false,代表游戏进行中,未结束 win; //游戏输赢标志,默认为false,代表未赢得游戏。 while(!gameOver) { int flag=0; GameGui.menu(); choice = input.nextInt(); switch(choice) { case 0: gameOver=true; break; case 1:/* 农夫独自过河的处理 */ farmer.setCrossRiver(!( farmer.hasCross())); boat.setCrossRiver(farmer.hasCross()); break; case 2:/* 农夫带狼的处理 */ if(boat.insameway(wolf.hasCross())) { farmer.setCrossRiver(!( farmer.hasCross())); boat.setCrossRiver(farmer.hasCross()); wolf.setCrossRiver(!( wolf.hasCross())); } else { flag++; } break; case 3:/* 农夫带羊的处理 */ if(boat.insameway(sheep.hasCross())) { farmer.setCrossRiver(!(farmer.hasCross())); boat.setCrossRiver(farmer.hasCross()); sheep.setCrossRiver(!(sheep.hasCross())); } else { flag++; } break; case 4:/* 农夫带白菜的处理 */ if(boat.insameway(cabbage.hasCross())) { farmer.setCrossRiver(!(farmer.hasCross())); boat.setCrossRiver(farmer.hasCross()); cabbage.setCrossRiver(!(cabbage.hasCross())); } else { flag++; } break; } if(farmer.hasCross()!=sheep.hasCross()) { wolf.eat(sheep);//狼吃羊,如果羊不在同一边,则吃不到,如果在同一边,羊被吃 sheep.eat(cabbage);//同上 } if(flag!=0) { continue; } GameGui.showStatus(farmer,wolf,sheep,cabbage); gameOver = isGameOver(); } win=this.hasWin(); if(win) { System.out.println("game over: you win !"); }else { System.out.println("game over: you lose !"); } input.close(); } /* * 判断游戏是否结束 * 输入:无 * 运算:羊、白菜任一实体被吃,游戏结束,或者狼、羊、白菜均未被吃且全部渡过河,游戏结束 * 输出:游戏结束--返回true ,未结束--返回false */ public boolean isGameOver() { if(!sheep.GetisAlive() || !cabbage.GetisAlive()) { return true; } return wolf.hasCross() && sheep.hasCross() && cabbage.hasCross(); } public boolean isGameOver2() { if(!sheep.GetisAlive() || !cabbage.GetisAlive() || !rabbit.GetisAlive() ||!carrot.GetisAlive()) { return true; } return wolf.hasCross() && sheep.hasCross() && cabbage.hasCross()&&carrot.hasCross()&&rabbit.hasCross(); } /* * 判断游戏是否胜利 * 前置条件:游戏结束 * 输入:无 * 运算:狼、羊、白菜均未被吃且全部渡过河,游戏胜利,否则失败 * 输出:游戏胜利--返回true ,失败--返回false */ public boolean hasWin() { if(!sheep.GetisAlive() || !cabbage.GetisAlive()) { return false; } return wolf.hasCross() && sheep.hasCross() && cabbage.hasCross(); } public boolean hasWin2() { if(!sheep.GetisAlive() || !cabbage.GetisAlive() || !rabbit.GetisAlive() ||!carrot.GetisAlive()) { return false; } return wolf.hasCross() && sheep.hasCross() && cabbage.hasCross()&&carrot.hasCross()&&rabbit.hasCross(); } public void newplay() { Scanner input = new Scanner(System.in); int choice ; //用户输入选择 boolean gameOver=false,//游戏结束标志,默认为false,代表游戏进行中,未结束 win; //游戏输赢标志,默认为false,代表未赢得游戏。 while(!gameOver) { int flag=0; GameGui.newmenu(); choice = input.nextInt(); switch(choice) { case 0: gameOver=true; break; case 1:/* 农夫独自过河的处理 */ farmer.setCrossRiver(!( farmer.hasCross())); boat.setCrossRiver(farmer.hasCross()); break; case 2:/* 农夫带狼羊的处理 */ if(boat.insameway(wolf.hasCross())) { farmer.setCrossRiver(!( farmer.hasCross())); boat.setCrossRiver(farmer.hasCross()); wolf.setCrossRiver(!( wolf.hasCross())); sheep.setCrossRiver(!( sheep.hasCross())); } else { flag++; } break; case 3:/* 农夫带狼菜的处理 */ if(boat.insameway(wolf.hasCross())) { farmer.setCrossRiver(!( farmer.hasCross())); boat.setCrossRiver(farmer.hasCross()); wolf.setCrossRiver(!( wolf.hasCross())); cabbage.setCrossRiver(!( cabbage.hasCross())); } else { flag++; } break; case 4:/* 农夫带狼羊的处理 */ if(boat.insameway(wolf.hasCross())) { farmer.setCrossRiver(!( farmer.hasCross())); boat.setCrossRiver(farmer.hasCross()); wolf.setCrossRiver(!( wolf.hasCross())); rabbit.setCrossRiver(!( rabbit.hasCross())); } else { flag++; } break; case 5:/* 农夫带狼胡萝卜的处理 */ if(boat.insameway(wolf.hasCross())) { farmer.setCrossRiver(!( farmer.hasCross())); boat.setCrossRiver(farmer.hasCross()); wolf.setCrossRiver(!( wolf.hasCross())); carrot.setCrossRiver(!( carrot.hasCross())); } else { flag++; } break; case 6:/* 农夫带羊菜的处理 */ if(boat.insameway(sheep.hasCross())) { farmer.setCrossRiver(!(farmer.hasCross())); boat.setCrossRiver(farmer.hasCross()); sheep.setCrossRiver(!(sheep.hasCross())); cabbage.setCrossRiver(!(cabbage.hasCross())); } else { flag++; } break; case 7:/* 农夫带羊兔的处理 */ if(boat.insameway(sheep.hasCross())) { farmer.setCrossRiver(!(farmer.hasCross())); boat.setCrossRiver(farmer.hasCross()); sheep.setCrossRiver(!(sheep.hasCross())); rabbit.setCrossRiver(!(rabbit.hasCross())); } else { flag++; } break; case 8:/* 农夫带羊菜的处理 */ if(boat.insameway(sheep.hasCross())) { farmer.setCrossRiver(!(farmer.hasCross())); boat.setCrossRiver(farmer.hasCross()); sheep.setCrossRiver(!(sheep.hasCross())); carrot.setCrossRiver(!(carrot.hasCross())); } else { flag++; } break; case 9:/* 农夫带菜兔的处理 */ if(boat.insameway(cabbage.hasCross())) { farmer.setCrossRiver(!(farmer.hasCross())); boat.setCrossRiver(farmer.hasCross()); cabbage.setCrossRiver(!(cabbage.hasCross())); rabbit.setCrossRiver(!(rabbit.hasCross())); } else { flag++; } break; case 10:/* 农夫带菜胡萝卜的处理 */ if(boat.insameway(cabbage.hasCross())) { farmer.setCrossRiver(!(farmer.hasCross())); boat.setCrossRiver(farmer.hasCross()); cabbage.setCrossRiver(!(cabbage.hasCross())); carrot.setCrossRiver(!(carrot.hasCross())); } else { flag++; } break; case 11:/* 农夫带兔胡萝卜的处理 */ if(boat.insameway(cabbage.hasCross())) { farmer.setCrossRiver(!(farmer.hasCross())); boat.setCrossRiver(farmer.hasCross()); rabbit.setCrossRiver(!(rabbit.hasCross())); carrot.setCrossRiver(!(carrot.hasCross())); } case 12:/* 农夫带狼的处理 */ if(boat.insameway(wolf.hasCross())) { farmer.setCrossRiver(!( farmer.hasCross())); boat.setCrossRiver(farmer.hasCross()); wolf.setCrossRiver(!( wolf.hasCross())); } else { flag++; } break; case 13:/* 农夫带羊的处理 */ if(boat.insameway(sheep.hasCross())) { farmer.setCrossRiver(!(farmer.hasCross())); boat.setCrossRiver(farmer.hasCross()); sheep.setCrossRiver(!(sheep.hasCross())); } else { flag++; } break; case 14:/* 农夫带白菜的处理 */ if(boat.insameway(cabbage.hasCross())) { farmer.setCrossRiver(!(farmer.hasCross())); boat.setCrossRiver(farmer.hasCross()); cabbage.setCrossRiver(!(cabbage.hasCross())); } else { flag++; } break; case 15:/* 农夫带兔子的处理 */ if(boat.insameway(cabbage.hasCross())) { farmer.setCrossRiver(!(farmer.hasCross())); boat.setCrossRiver(farmer.hasCross()); rabbit.setCrossRiver(!(rabbit.hasCross())); } else { flag++; } break; case 16:/* 农夫带胡萝卜的处理 */ if(boat.insameway(cabbage.hasCross())) { farmer.setCrossRiver(!(farmer.hasCross())); boat.setCrossRiver(farmer.hasCross()); carrot.setCrossRiver(!(carrot.hasCross())); } else { flag++; } break; } if(farmer.hasCross()!=wolf.hasCross()) { wolf.eat(sheep);//狼吃羊,如果羊不在同一边,则吃不到,如果在同一边,羊被吃 wolf.eat(rabbit);//同上 } if(farmer.hasCross()!=sheep.hasCross()) { sheep.eat(cabbage); sheep.eat(carrot); } if(farmer.hasCross()!=rabbit.hasCross()) { rabbit.eat(carrot); rabbit.eat(cabbage); } if(flag!=0) { continue; } GameGui.newshowStatus(farmer,wolf,sheep,cabbage,rabbit,carrot); gameOver = isGameOver2(); } win=this.hasWin2(); if(win) { System.out.println("game over: you win !"); }else { System.out.println("game over: you lose !"); } input.close(); } } public abstract class Father { private boolean isAlive=true; private boolean crossRiver = false; public void SetisAlive(boolean isAlive) { this.isAlive=isAlive; } public boolean GetisAlive() { return isAlive; } public boolean hasCross() { return crossRiver; } public void setCrossRiver(boolean crossRiver) { this.crossRiver=crossRiver; } public void eat (Father animal){ if (animal.GetisAlive() && isAlive) { if (animal.hasCross() == crossRiver) animal.SetisAlive(false) ; } } public void showStatus () { } } public class Farmer extends Father{ // public void setCrossRiver(boolean crossRiver) { // this.crossRiver=crossRiver; // } // public boolean hasCross() { // return crossRiver; // } @Override public void showStatus() { if (hasCross()) { System.out.println("Farmer has Cross :true"); } else { System.out.println("Farmer has Cross :false"); } } } public class Carrot extends Father{ @Override public void showStatus() { if(super.GetisAlive()) System.out.print("Carrot is alive:true "); else System.out.print("Carrot is alive:false "); if (super.hasCross()) { System.out.println("Carrot has Cross :true "); } else System.out.println("Carrot has Cross :false "); } } public class Cabbage extends Father{ // private boolean isAlive=true; // private boolean crossRiver=false; // public boolean hasCross() // { // return crossRiver; // } // public void setCrossRiver(boolean crossRiver) { // this.crossRiver=crossRiver; // } // public void SetisAlive(boolean isAlive) { // this.isAlive = isAlive; // } // public boolean GetisAlive() // { // return isAlive; // } @Override public void showStatus() { if(super.GetisAlive()) System.out.print("Cabbage is alive:true "); else System.out.print("Cabbage is alive:false "); if (super.hasCross()) { System.out.println("Cabbage has Cross :true "); } else System.out.println("Cabbage has Cross :false "); } } public class Boat extends Father{ // public void setCrossRiver( boolean crossRiver) { // this.crossRiver=crossRiver; // } public boolean insameway( boolean crossRiver) { if(this.hasCross()==crossRiver) return true; else System.out.println("Boat cannot get there."); return false; } }
<ATM机类设计>
输入要求每一行输入一次业务操作,可以输入多行,最终以字符#终止。实现代码如下:
while (!s.equals("#")) {
String[] information = s.split("\\s+");
// if(s.length()!=1){
Information.Wrongformat(information);
// }
s=in.nextLine();
题目要求如下
https://images.ptausercontent.com/93fc7ad6-5e85-445a-a759-5790d0baab28.pdf
这道atm设计题目的难度较大,要求对于每个类有清晰明确的认知,在耦合度尽可能低的情况下对功能做出区分,通过切分对数据进行判定,对应题目,主要难点在于对check,如何对输入的帐户进行匹配,匹配对应的用户名和帐户名,要求我们在写代码的时候必须要对整个代码有整体概念,明白整个题目是由哪些点哪些类所构成,梳理好每个类的所拥有的属性,明白每个属性存在的意义说是什么,有什么作用,那些功能由哪些类来实现,这样的时候一个类图能解决很多问题,怎样能够合理调用这些类,并且减小类之间的耦合性,在对我们所得到的结果进行输出时,我们应该要进行分开,这道题目的输入有两种情况,应该分开讨论,account类在设计时应该要注意类与bank的关系做到合理调用,并且对于类也要区分它们的功能,判断它们是用来做什么的,如changemoney和present是功能类,考虑清楚一对多和多对一的关系,在输入保存数据是清晰分配存储,然后在对应的存储位置进行搜索需要的结果,做到层层调用,层层检查,遇到不符合题目要求的数据,就可以输出对应的错误,然后就结束程序,进行下一次的输入,并且在对帐户的余额进行修改时也应该有一个独立的类来实现该功能.
-----------------------------------------------------------------------------------------
<改进建议>
在设计的时候不要过于盲目,有的时候要先考虑清楚什么样的算法适合什么样的题目,对于一些复杂的题目如果可以要先画一个类图,比如说对于ATM机类设计这样的大题目,掌握类中发放的作用比如:changemoney和present功能类,此外还有农夫过河的实验提醒了对于继承与组合的区别和程序设计中代码复用的重要性,合理的继承复用对于代码的优化作用,另外对于Java语言中多态的基本概念及使用方法,上转型和下转型,以及set,map,stream到DoubleLinkedList,lambda表达式,正则表达式等刚接触的知识要加以巩固.
-----------------------------------------------------------------------------------------
浙公网安备 33010602011771号