欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java面向对象解决实际问题【母牛生产问题】

程序员文章站 2022-07-12 17:07:54
...

问题: 已知一只母牛4岁开始生产(人工受孕),12岁停止生产,产下的母牛概率为50%,每只母牛每年只生一只牛, 生下来的牛视为0岁。15岁送入屠宰场,现有一只母牛(0岁),请问25年后有多少只牛?

  1. 使用程序进行模拟此场景,计算25年后牛数量的期望值(平均值)
  2. 使用面向对象的思想去处理问题,会变得更加清晰明了
  3. 问题分析:
  • 核心对象: 牛
  • 核心属性: 性别(影响是否可生育),年龄(影响是否可生育,是否能继续存活)
  • 核心行为: 成长(随时间流逝牛会长大,影响其年龄),生育(产出新牛)
  1. 根据上述分析编写牛类
public class Niu {
    /**
     * 性别 1==>母牛  0==>公牛
     */
    private int sex;
    /**
     * 年龄 生下来0岁,4岁开始生牛,12岁停止生产,15岁送屠宰场
     */
    private int age;

    Niu(int sex) {
        this.sex = sex;
        // 一只新生牛的初始化岁数
        this.age = 0;
    }

    public void grow() {
        this.age = this.age + 1;
    }

    public void produce(List<Niu> list) {
        if (sex != 1 || age < 4 || age > 11) {
            // 公牛不会生产 年龄限制不能生产
            return;
        }
        // 母牛开始生产了 生产的性别随机使用ThreadLocalRandom随机生成 0公牛  1母牛
        Niu newNiu = new Niu(ThreadLocalRandom.current().nextInt(2));
        // 将牛放入家
        list.add(newNiu);
    }
    // 省略getter方法
}
  1. 程序模拟分析
  • 开始时牛场只有一只母牛
  • 时间经过一年,所有的牛都会成长1岁
  • 部分满足条件的牛会被屠宰,部分满足条件的牛会进行生育
  • 25年后,模拟结束
  1. 根据上述分析,编写模拟程序
public class MuNiuProblem {

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        MuNiuProblem problem = new MuNiuProblem();
        // 展示每次模拟的详情记录
        boolean logEnable = false;
        // 模拟次数
        int simulate = 1000000;
        int max = -1;
        int min = -1;
        int sum = 0;
        // 开始模拟
        for (int i = 0; i < simulate; i++) {
            // 执行一次模拟,获取25年后牛的数量
            int temp = problem.answer(logEnable);
            // 累加到sum总
            sum += temp;
            // 初始化max min
            if (i == 0) {
                max = min = temp;
                continue;
            } else if ((i + 1) % 100000 == 0) {
                System.out.println("模拟进行中,已模拟" + (i + 1) + "次");
            }
            // 更新 max min
            max = max < temp ? temp : max;
            min = min > temp ? temp : min;
        }
        // 输出模拟结果
        long end = System.currentTimeMillis();
        System.out.printf("%d次模拟用时%d s\r\n", simulate, (end - start) / 1000);
        System.out.println(simulate + "次模拟最大值" + max);
        System.out.println(simulate + "次模拟最小值" + min);
        System.out.println(simulate + "次模拟平均值" + sum*1.0 / simulate);
    }

    private int answer(boolean logEnable) {
        // 初始化牛场
        List<Niu> list = new ArrayList<>();
        // 初始化母牛
        Niu firstNiu = new Niu(1);
        list.add(firstNiu);
        // 25年光阴 每次循环过去了一年
        for (int i = 0; i < 25; i++) {
            // 所有的牛都增长了1岁,然后过滤年满15岁的牛  已送入屠宰场
            list.forEach(Niu::grow);
            list.removeIf(n -> n.getAge() > 14);
            // 新生牛的家
            ArrayList<Niu> home = new ArrayList<>();
            for (Niu niu : list) {
                niu.produce(home);
            }
            list.addAll(home);
            if (logEnable) {
                showState(list, i + 1);
            }
        }
        return list.size();
    }

    /**
     * 输出详情记录
     */
    private static void showState(List<Niu> list, int year) {
        int count1 = 0;
        int count2 = 0;
        for (Niu niu : list) {
            if (niu.getSex() == 0) {
                count1++;
            } else {
                count2++;
            }
        }
        System.out.printf("%d年后一共有牛%d只,其中母牛%d只,公牛%d只\r\n", year, list.size(), count2, count1);
    }

}
  1. 通过程序模拟得出结果,25年后剩下牛数量的期望约为230只