ts小练习(池塘问题)

326 阅读6分钟

问题

  • 一个池塘很多种类鱼,鱼吃东西,养大之后卖,卖了可以再买鱼
  • 购买逻辑貌似有点问题。没有考虑最优金额之类的。java和ts语法使用的也磕磕碰碰

Java版本

思路

  1. 鱼的价格根据种类固定,鱼的卖出年龄根据种类固定(或者根据重量决定?)
  2. 创建一个池塘类finish来初始化池塘;创建一个抽象类absFinish来规范所有种类鱼的属性和行为
  3. 池塘里面的鱼统一放入一个数组中存储,每年遍历年龄是否达到,达到则卖出。不达到则年龄增加

感想

  1. 对Java太久没用了。语法不熟悉,特别是使用数组的时候发现好多数组类型,List,ArrayList,Object[]都试过。
  2. 本来选定了数组,但是后来发现删除数组在List之类的类型中好像不能删除最后一个(其他的使用arr[i]=arr[i+1]这种方式伪删除),最后选了ArrayList
    package test;
    import java.util.ArrayList;
    import java.util.List;
    public class finish {
     protected static Integer sum=0; // 口袋里面的钱
     public static Integer finishNum=0; // 池塘的鱼数
     protected static ArrayList<Object> arr;
        public static void main(String []args) {
            // 鱼的种类,年龄,单价,数量,最大年龄
            crucianCarp a=new crucianCarp("鲫鱼",1,null,10,4);
            grassCarp b=new grassCarp("草鱼",3,null,3,4); // ""指的是String,''指的是char类型
            bighead c=new bighead("鳙鱼",4,null,4,5);  // 共17条
            arr=new ArrayList<>();
            arr.add(a);
            arr.add(b);
            arr.add(c);
            
            buy(4); // 预测n年后的收益
          System.out.print("钱包余额:");
          System.out.println(sum);
          System.out.print("还剩下的鱼的数量:");
          System.out.print(finishNum); 
        }
        // 卖鱼,买鱼,设置期限(假设买到的鱼都是0年的)
        public static void buy(Integer n) {
         while(n-- > 0) {
          // 卖出
          for(int i=0;i<arr.size();i++) {
           absFinish obj=((absFinish) arr.get(i));
           if(obj.getMaxAge()<=obj.getAge()) {
            sum+=(obj.getPrice()*obj.getNum());
         arr.remove(i);
         i--;
         finishNum-=obj.getNum();// 减少鱼数
           }else {
            obj.SetAge();//年龄增加
           }
          }
          System.out.println("本轮余额:");
          System.out.println(sum);
          // 购买(购买策略。。先买池塘里面还有的鱼,假设市场里面的鱼是无限量的)
          Integer len=arr.size();
          for(int j=0;j<len;j++) {
           Integer buyNum = 0;
        switch (j%3) {
        case 0:
         crucianCarp caseA=new crucianCarp(null,0,null,0,null);
            // 本轮购买数量
         buyNum=(int) Math.floor(sum/caseA.getPrice());
            if(buyNum>0) {
             caseA.setNum(buyNum);
             // 减少余额
             sum-=caseA.getPrice()*buyNum;
          arr.add(caseA);
            }
         break;
        case 1:
         grassCarp caseB=new grassCarp(null,0,null,0,null);
            // 本轮购买数量
         buyNum=(int) Math.floor(sum/caseB.getPrice());
         if(buyNum>0) {
             caseB.setNum(buyNum);
             // 减少余额
             sum-=caseB.getPrice()*buyNum;
          arr.add(caseB);
         }
         break;
        case 2:
         bighead caseC=new bighead(null,0,null,0,null);
            // 本轮购买数量
         buyNum=(int) Math.floor(sum/caseC.getPrice());
         if(buyNum>0) {
             caseC.setNum(buyNum);
             // 减少余额
             sum-=caseC.getPrice()*buyNum;
          arr.add(caseC);
         }
         break;
        default:
         break;
        }
           finishNum+=buyNum;
          }
         }
        }
    }
    
    // 抽象类
    abstract class absFinish extends finish{
     private String name;
     private Integer price;
     private Integer age;
     private Integer num; // 鱼的数量
     private Integer maxAge;
     // 构造器,如js的construtor
     public absFinish(String name,Integer age,Integer price,Integer num,Integer maxAge) {
      this.name=name;
      this.age=age;
      this.price=price;
      this.num=num;
      this.maxAge=maxAge;
     }
     // 获取鱼的年龄
     public final Integer getAge() {
      return age;
     }
     // 获取鱼的成熟年龄
     public final Integer getMaxAge() {
      return maxAge;
     }
     // 获取鱼的数量
     public final Integer getNum() {
      return num;
     }
     // 设置鱼的数量
     public final void setNum(Integer num) {
      this.num=num;
     }
     // 过了一个月,年龄增加
     public final void SetAge() {
      age++;
     }
     // 获取鱼的价格
     public final Integer getPrice() {
      return price;
     }
     // 获取鱼的名称
     public final String getName() {
      return name;
     }
    }
    // 鲫鱼
    class crucianCarp extends absFinish{
     public crucianCarp(String name,Integer age,Integer price,Integer num,Integer maxAge) {
      super(name="鲫鱼",age,price=20,num,maxAge=4);
      // 增加鱼的总数
      finishNum+=num;
     }
    }
    //草鱼
    class grassCarp extends absFinish{
     public grassCarp(String name,Integer age,Integer price,Integer num,Integer maxAge) {
      super(name="草鱼",age,price=10,num,maxAge=4);
      finishNum+=num;
     }
    }
    //鳙鱼
    class bighead extends absFinish{
     public bighead(String name,Integer age,Integer price,Integer num,Integer maxAge) {
      super(name="鳙鱼",age,price=35,num,maxAge=5);
      finishNum+=num;
     }
    }
    
    

    ts版本

    思路

    1. 创建一个池塘类finish来初始化池塘;创建一个抽象类absFinish来规范所有种类鱼的属性和行为
    2. 导出池塘类finish,在index.js中通过require导入该模块
    3. tsc finish.ts编译ts文件,使用node index.js来启动js文件,初始化池塘。

    缺点

    1. switch中根据n%3来决定创建的鱼的实例,但是如果有十几种鱼就要写十几个case?但是直接把字符串放入数组又不行,又不能使用eval("new bighead('苹果')")这种形式。
    2. sum和finishNum由于会在absFinish中用到,所以我放到finish类的外部。但是创建多个鱼塘的时候,就会导致使用的是同一个变量。。
      // index.js
      var {finish,crucianCarp,grassCarp,bighead}=require('./test')
      // 创建一个池塘
      var fi=new finish(6)
      let a=new crucianCarp(undefined,1,undefined,10,undefined)
      let b=new grassCarp(undefined,3,undefined,3,undefined)
      let c=new bighead(undefined,4,undefined,4,undefined)
      fi.arr.push(a,b,c)
      fi.init()
      // 此时是共有变量,不是预期效果
      var qq=new finish(2)
      let d=new crucianCarp(undefined,1,undefined,10,undefined)
      qq.arr.push(d)
      qq.init()
    
    • 下面是ts文件
      // finish.ts
    let finishNum:number = 0; // 鱼的数量
    let sum:number = 0; // 钱包余额
    /* 
     缺点很明显,但是我自己现在想不到需要怎么优化
     */
    class finish{
     arr:Array<absFinish> = []; // 目前的鱼
      year:number=0;
     constructor(year:number){
          this.year=year;
      }
     init(){
      console.log("以前:","余额:",sum," 鱼的数量:",finishNum)
      this.buy(this.year) //6: 余额5,数量24
      console.log("之后:","余额:",sum," 鱼的数量:",finishNum)
     }
     // 开始买卖
     buy(y:number):void{
      while(y-->0){
       // 卖出鱼
       for(var i=0;i<this.arr.length;i++){
        if(this.arr[i].getAge()>=this.arr[i].getMaxAge()){
         let num:number=this.arr[i].getNum();
         sum+=num*(this.arr[i].getPrice() as number);
         finishNum-=num;
         console.log(this.arr[i],sum)
         this.arr.splice(i,1)
         i--;
        }else{
         this.arr[i].setAge();// 年龄增加
        }
       }
       // 买鱼 (购买策略是 y%3,3指的是鱼的种类)
       let len=this.arr.length
       for(var j=0;j<len;j++) {
        let buyNum:number = 0;
        switch (y%3) {
         // 在case中使用let会报错,因为eslint规则
        case 0:
         var caseA:crucianCarp=new crucianCarp(undefined,0,undefined,0,undefined);
         // 本轮购买数量
         buyNum=Math.floor(sum/(caseA.getPrice() as number));
         if(buyNum>0) {
          caseA.setNum(buyNum);
          // 减少余额
          sum-=(caseA.getPrice() as number)*buyNum;
          this.arr.push(caseA);
         }
         break;
        case 1:
         var caseB:grassCarp=new grassCarp(undefined,0,undefined,0,undefined);
         // 本轮购买数量
         buyNum=Math.floor(sum/(caseB.getPrice() as number));
         if(buyNum>0) {
          caseB.setNum(buyNum);
          // 减少余额
          sum-=(caseB.getPrice() as number)*buyNum;
          this.arr.push(caseB);
         }
         break;
        case 2:
         var caseC:bighead=new bighead(undefined,0,undefined,0,undefined);
         // 本轮购买数量
         buyNum=Math.floor(sum/(caseC.getPrice() as number));
         if(buyNum>0) {
          caseC.setNum(buyNum);
          // 减少余额
          sum-=(caseC.getPrice() as number)*buyNum;
          this.arr.push(caseC);
         }
         break;
        default:
         break;
        }
        finishNum+=buyNum;
       }
      }
     }
    }
    
    // 抽象类
    abstract class absFinish{
     private  name:string;
     private  price?:number; // 不一定需要该属性,那么在return应该是联合类型
     private  age:number;  
     private  num:number; // 鱼的数量
     private  maxAge:number;
     // 构造器
     constructor(name:string,age:number,price:number,num:number,maxAge:number) {
      this.name=name;
      this.age=age;
      this.price=price;
      this.num=num;
      this.maxAge=maxAge;
      // 增加鱼的总数
      finishNum+=num;
     }
     // 获取鱼的年龄
     getAge():number {
      return this.age;
     }
     // 获取鱼的成熟年龄
     getMaxAge():number {
      return this.maxAge;
     }
     // 获取鱼的数量
     getNum():number {
      return this.num;
     }
     // 设置鱼的数量
     setNum(num:number):void {
      this.num=num;
     }
     // 过了一个月,年龄增加
     setAge():void {
      this.age++;
     }
     // 获取鱼的价格
     getPrice():number|undefined {
      return this.price;
     }
     // 获取鱼的名称
     getName():string {
      return this.name;
     }
    }
    // crucianCarp
    class crucianCarp extends absFinish{
     constructor(name:string='鲫鱼',age:number=0,price:number=20,num:number,maxAge:number=4){
      super(name,age,price,num,maxAge)
     }
    }
    // grassCarp
    class grassCarp extends absFinish{
     constructor(name:string="草鱼",age:number=0,price:number=10,num:number,maxAge:number=4){
      super(name,age,price,num,maxAge)
     }
    }
    // bighead
    class bighead extends absFinish{
     constructor(name:string="鳙鱼",age:number=0,price:number=35,num:number,maxAge:number=5){
      super(name,age,price,num,maxAge)
     }
    }
    export {finish,bighead,grassCarp,crucianCarp}
    

    java和javascript的区别与相同点

    1. java中使用null作为无效的参数默认值,而javascript中使用undefined(不能使用null),java中没有undefined这个类型
    2. Java对于类型的检查貌似更加严格?使用System.out.println()不能把两种类型的变量凑在一起。而ts使用console.log()打印两种类型明显可以。
    3. 都使用super()来调用父类的构造函数。ts可以通过super.xx()来调用父类的方法。但是不可以通过super.xx来获取父类的属性,解决方法是把属性挂载到父类的原型链上,子类就可以通过this来调用变量

本文使用 mdnice 排版