标签:
/**
*10、 一位老农带着猫、狗、鱼过河,河边有一条船,每次老农只能带一只动物过河。
*当老农不和猫狗鱼在一起时,狗会咬猫,猫会吃鱼,当老农和猫狗鱼在一起时,则不会发生这种问题。
*编程解决猫狗鱼过河问题。
*
*分析:
* 问题中的对象:猫、狗、鱼、老农、岸1(这岸)、岸2(对岸)
*
*
* 限制条件是:老农每次只能带一只动物过河
* 老农不在时,狗咬猫
* 老农不在时,猫吃鱼
* 目标是:将猫、狗、鱼从这岸运到对岸。
* 当农夫到达一个岸后,即为一个中间状态,则这个中间状态需要满足,岸1,岸2都是安全的
*
* 初始输入:是岸1中有3个对象,老农处在岸1
*
* 结果输出:将岸1中的对象移动到岸2中的具体步骤
*
* 岸1、岸2:可以添加不同类的对象,所以内部是一个集合,同时岸上是否有冲突,岸清楚,所以岸中有检测方法。
* 他们属于同一个类。对于具体要运送哪个对象才是合适的(即运送后岸是安全的),岸最清楚,所以要有
* 运送方法。
*
* 猫、狗、鱼:虽然是不同类,但是有共性,那就是他们可能有自己的天敌(也有可能没有),所以要有获取天敌的方法。
* 还有就是他们是否是安全的,所以有两个方法。
* 他们属于不同类,而检测是否安全的方法代码完全相同,所以定义一个抽象类来被他们继承。
*
* 老农:有两个方法,一个是自己过河,一个是运送动物过河。如何运送一个具体动物过河,以及运送该动物成功与否,
* 老农自己最清楚,老农是一个单独的类
*
* 审题结果:这个问题重在练习面向对象的思想和对象的设计,以及问题的分析能力,这个问题并不具备太强的
* 可扩展性,如果扩展大了,那么问题就改变了,不再是同类型的问题了。这是个A->B->C,有向图,且要首先
* 带走度为2的节点B,如果出现两个以上的度为2的节点,这个问题就无解了,如果出现一个度为3或者3以上的节点
* ,也是无解的。
*
*思路:
*
*1,定义 岸、猫、狗、鱼、老农 5个类
*2,老农运送 岸1中的一只动物到岸2,如果岸1处于和谐状态,则运送这只动物,否则换另一只动物。
*3,老农到达岸2后,检查岸2是否和谐,和谐,则自己离开,到2,否则运送一只动物离开,使其和谐,再到2
*4,全部运送完后,岸1空结束。
*
*(为使得代码尽量简洁,就不自定义hashCode,equals方法,程序中没有用到,但如果实际项目的话,需要进行
*覆盖。)
*/
package com.itheima; import java.util.HashMap; import java.util.Map; import java.util.Set; //定义一个抽象类Animal,表示动物必须实现的方法,以及必须具备的功能 abstract class Animal { //每个动物都必须具备这项功能,即判断自己在给定的Bank下是否是安全的 public boolean isSafe(Bank bank) { // TODO Auto-generated method stub return !(bank.containsClass(naturalEnemy())); //如果给定bank中天敌存在,则不安全,否则安全 } //让子类去实现的方法,每个子类都要定义自己的天敌,并通过该方法返回 public abstract String naturalEnemy(); } //定义Bank类,表示“岸”这类事物 class Bank { //定义Bank的名字,方便打印输出 private String name = null; //定义容器,用来存储将要加进来的动物对象 private Map<String, Object> map = new HashMap<String,Object>(); //定义当前出现安全问题的动物 private Animal currentProblem = null; //创建对象的时候,就指定岸对象的名字 Bank(String name) { this.name = name; } @Override//覆盖toString方法 public String toString() { return name; } //定义岸的添加动物对象的方法 void add(Object obj) { map.put(obj.getClass().getName(), obj); //调用容器的相应添加方法 } //定义岸的删除对象的方法,并返回删除的对象 Object delete(Object obj) { return map.remove(obj.getClass().getName()); //调用容器的相应删除方法 } //定义方法用来判断一种动物在该岸中是否存在 boolean containsClass(String className) { return map.containsKey(className); } //打印Bank中的动物对象 void printBank() { System.out.print(this+" : "); Set<Map.Entry<String,Object>> entrys = map.entrySet();//获取Map集合中的所有条目的Set集合 //打印Bank中封装map容器中的内容, for(Map.Entry<String, Object> entry : entrys) { Animal obj = (Animal)entry.getValue(); System.out.print(obj+" "); //用空格分隔每个动物对象 } System.out.println(); } //判断岸的当前状态是否是安全的,即动物们是否是和谐相处的 boolean isSafe() { boolean flag = true; Set<Map.Entry<String,Object>> entrys = map.entrySet();//获取Map集合中的所有条目的Set集合 //循环判断每个动物是否是安全,如果每个动物都是安全的,那么岸就是安全的,否则岸就是不安全的 for(Map.Entry<String, Object> entry : entrys) { String className = entry.getKey(); Animal obj = (Animal)entry.getValue(); if(!obj.isSafe(this)){ //判断动物在当前岸的状态下是否是安全的 flag = false; currentProblem = obj; //如果不安全,则记录当前处于不安全状态的那个对象 break; } } return flag; //返回结果 } //定义方法供当前岸对象,指挥farmer,将自己的一个对象运送到对岸,也即bank boolean transport(Farmer farmer,Bank bank) { boolean flag = false;//初始设置为运送失败 Map<String, Object> mapTemp = new HashMap<String,Object>(map);//拷贝副本,用来遍历 //获取当前bank中目前有的对象 Set<Map.Entry<String,Object>> entrys = mapTemp.entrySet(); for(Map.Entry<String, Object> entry : entrys) //运送一个对象到bank,直到成功为止 { Animal obj = (Animal)entry.getValue();//取得一个具体的对象 //指挥farmer将obj从当前岸(this)运送到彼岸(bank) if(farmer.transport(obj,this,bank)) { flag = true; System.out.println("将 \""+obj+"\" 从 "+this+" 运送到 "+bank); //如果运送成功,则打印 break; } } return flag; } //定义方法,用来判断当前岸是否是空的状态,即当前岸中一个动物也没有 boolean isEmpty() { return (map.size() == 0); } } //定义猫子类,继承父类Animal class Cat extends Animal { //实现抽象方法,定义自己的天敌 public String naturalEnemy() { // TODO Auto-generated method stub return "com.itheima.Dog"; //将天敌的类型返回 } @Override //覆盖toString方法,方便打印 public String toString() { return "猫"; } } //定义狗子类,继承父类Animal class Dog extends Animal { //实现抽象方法,定义自己的天敌 public String naturalEnemy() { // TODO Auto-generated method stub return "null"; //将天敌的类型返回,狗没有天敌,用"null"字符串表示没有天敌 } @Override //覆盖toString方法,方便打印 public String toString() { return "狗"; } } //定义狗子类,继承父类Animal class Fish extends Animal { //实现抽象方法,定义自己的天敌 public String naturalEnemy() { // TODO Auto-generated method stub return "com.itheima.Cat"; //将天敌的类型返回 } @Override //覆盖toString方法,方便打印 public String toString() { return "鱼"; } } //定义农夫类 class Farmer { //定义属性animal,用来记录上一次运送的对象,防止死循环 private Animal animal = null; //定义属性bank,用来表示农夫现在所处的位置是哪个岸 private Bank bank = null; //初始化时,指定farmer位于那个岸,即哪个bank Farmer(Bank bank) { this.bank = bank; } //农夫只将自己运送到指定的岸bank boolean transport(Bank bank) { this.bank = bank; return true; } //farmer将指定对象obj,从bank1运送到bank2 boolean transport(Object obj,Bank bank1,Bank bank2) { this.bank = bank2; //farmer即将划船到bank2 //obj刚刚才运过,刚从bank2运送到bank1,所以不能再从bank1运送到bank2了 if(animal == obj) return false; //直接返回运送失败 //开始运送obj,现将其从bank1中删除 animal = (Animal)bank1.delete(obj); //看看bank1是否是安全的 if(bank1.isSafe()) { bank2.add(obj); //bank1安全,将obj运送到bank2,即添加进bank2 return true; } else //bank1不是安全的,运送失败 { bank1.add(obj); //运送失败,将obj添加回bank1 return false; //返回运送失败 } } @Override //覆盖toString方法,方便打印 public String toString() { return "农夫"; } //打印农夫现在位于哪个岸 void printBank() { System.out.println(this+" 位于 "+bank); } } //测试类 public class Test10 { //用于打印问题的初始情况 public static void initSituation(Farmer farmer ,Bank bank1,Bank bank2) { System.out.println("初始情况:"); bank1.printBank(); bank2.printBank(); farmer.printBank(); System.out.println("-------------------------------------"); } //用于打印问题的最终情况 public static void endSituation(Farmer farmer ,Bank bank1,Bank bank2) { System.out.println("-------------------------------------"); System.out.println("最终情况:"); bank1.printBank(); bank2.printBank(); farmer.printBank(); } //main函数 public static void main(String[] args) { //创建bank1,bank2 Bank bank1 = new Bank("岸A"); Bank bank2 = new Bank("岸B"); //将猫、狗、鱼添加到bank1中 bank1.add(new Dog()); bank1.add(new Cat()); bank1.add(new Fish()); //创建农夫对象farmer Farmer farmer = new Farmer(bank1); //打印问题的初始情况 initSituation(farmer, bank1, bank2); //一直运送直到bank1岸为空 while(!bank1.isEmpty()) { //bank1不为空,则从bank1运送一个对象到bank2 if(bank1.transport(farmer, bank2)) { //运送完一次,立即判断bank1是否为空,如果为空,则完成目标,跳出循环,结束 if(bank1.isEmpty()) break; //如果bank1运送成功,则农夫从bank2返回到bank1,并检查bank2当前是否安全,由此决定以何种 //方式返回到bank1,是只运送自己,还是再从bank2中带走一个对象到bank1 if(bank2.isSafe()) { System.out.println("\""+farmer+"\""+" 自己一个人从 "+bank2+" 划船到 "+bank1); //如果运送成功,则打印 farmer.transport(bank1);//bank2安全,只运送自己到bank1 } else { bank2.transport(farmer,bank1);//bank2不安全,需要带走bank2中的一个对象到bank1 } } else { System.out.println("对于这个问题,暂时无解");//针对于这个具体的问题,出现这种情况意味着无解 } } //打印问题的最终情况 endSituation(farmer, bank1, bank2); } }
标签:
原文地址:http://www.cnblogs.com/wllbelief-win/p/4437885.html