群主发红包带你深入了解继承和super、this关键字

举报
共饮一杯无 发表于 2022/10/20 09:33:51 2022/10/20
【摘要】 需求群主发随机红包或者普通红包。某群有多名成员,群主给成员发普通红包。随机红包规则:群主的一笔金额,从群主余额中扣除,随机分成n等份,让成员领取。成员领取红包后,保存到成员余额中。普通红包的规则:群主的一笔金额,从群主余额中扣除,平均分成n等份,让成员领取。成员领取红包后,保存到成员余额中。 案例分析案例分析,可以得出如下继承关系: 案例代码实现 定义用户类/** * 用户类 * @aut...

需求

群主发随机红包或者普通红包。某群有多名成员,群主给成员发普通红包。
随机红包规则:

  1. 群主的一笔金额,从群主余额中扣除,随机分成n等份,让成员领取。
  2. 成员领取红包后,保存到成员余额中。

普通红包的规则:

  1. 群主的一笔金额,从群主余额中扣除,平均分成n等份,让成员领取。
  2. 成员领取红包后,保存到成员余额中。

案例分析

案例分析,可以得出如下继承关系:
image.png

案例代码实现

定义用户类

/**
 * 用户类
 * @author zjq
 */
public class User {
    /**
     * 姓名
     */
    private String name;
    /**
     * 余额,也就是当前用户拥有的钱数
     */
    private Integer money; 

    public User() {
    }

    public User(String name, Integer money) {
        this.name = name;
        this.money = money;
    }

    // 展示一下当前用户有多少钱
    public void show() {
        System.out.println("我是" + name + ",我有多少钱:" + this.fenToYuan(String.valueOf(money))+"元");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getMoney() {
        return money;
    }

    public void setMoney(Integer money) {
        this.money = money;
    }

    /**
     * 分转元
     * @param amount
     * @return
     */
    public   String fenToYuan(String amount){
        NumberFormat format = NumberFormat.getInstance();
        try{
            Number number = format.parse(amount);
            double temp = number.doubleValue() / 100.0;
            format.setGroupingUsed(false);
            format.setMaximumFractionDigits(2);
            amount = format.format(temp);
        } catch (ParseException e){
            e.printStackTrace();
        }
        return amount;
    }

}

定义群主类

package com.zjq.javabase.base09.demo14;

import org.apache.commons.lang3.RandomUtils;
import java.util.ArrayList;

/**
 * 群主的类
 * @author zjq
 */
public class Manager extends User {

    /**
     * 收到单个红包最大值
     */
    private static final int MAX_AMOUNT = 20000;

    public Manager() {
    }

    public Manager(String name, int money) {
        // 通过super 调用父类构造方法
        super(name, money);
    }


    /**
     * 发红包
     * @param totalMoney 红包总金额(单位分)
     * @param count 发包个数
     * @param type 发包类型(0、随机红包,1、定额红包)
     * @return 红包集合
     * @throws Exception
     */
    public ArrayList<Integer> send(Integer totalMoney, int count,int type) throws Exception {
        // 首先需要一个集合,用来存储若干个红包的金额
        ArrayList<Integer> redList = new ArrayList<>(count);

        // 首先看一下群主自己有多少钱
        Integer leftMoney = super.getMoney(); // 群主当前余额
        if (totalMoney > leftMoney) {
            System.out.println("余额不足");
            return redList; // 返回空集合
        }

        // 扣钱,其实就是重新设置余额
        super.setMoney(leftMoney - totalMoney);


        if (count == 1) {
            redList.add(totalMoney);
            return redList;
        }

        switch (type) {
            case 0:
                // 默认分配1分至每一位
                for (int i = 0; i < count; i++) {
                    redList.add(1);
                }
                int surplus_currency = totalMoney - redList.size(),// 剩余金额数
                        surplus_number = redList.size();// 剩余需追加的数量

                for (int i = 0; i < redList.size(); i++) {

                    // 没值可以追加了
                    if (new Integer(0).equals(surplus_currency)) {
                        break;
                    }

                    // (总数-(总包-i)*最小值) / (总包 - i) 随机安全值算法
                    int safe_total = (int)Math.floor((totalMoney - (count - i)) / (count - i));
                    if (new Integer(0).equals(safe_total)) {// 随机值不能为0
                        safe_total = 1;
                    }
                    // 该次随机值
                    int randomint = surplus_currency >= safe_total - 1 ? safe_total : surplus_currency + 1;
                    // 下次可能最大能剩余值
                    int nextMax_currency = (MAX_AMOUNT - 1) * (surplus_number - 1);
                    // 最小的随机数     剩余金额-剩余最大随机的总数(不含这一次)
                    int minRandom = surplus_currency -  nextMax_currency;
                    if (minRandom < 0) {
                        minRandom = 0;
                    }

                    // 规避一些特殊情况,每个接近2000或1时会发生
                    boolean must = (surplus_currency - count * MAX_AMOUNT <= 2 && surplus_currency - count * MAX_AMOUNT >= 0)
                            /*|| surplus_currency < packet_number * 2*/;
                    // 控制安全随机值           随机安全值不能大于最大限制,并且不能小于最小限 制
                    if (safe_total < minRandom || safe_total > MAX_AMOUNT || must) {
                        safe_total = MAX_AMOUNT;
                        // 该次随机值
                        randomint = surplus_currency >= safe_total - 1 ? safe_total : surplus_currency + 1;
                        // 下次可能最大能剩余值
                        nextMax_currency = (randomint - 1) * (surplus_number - 1);
                        // 最小的随机数     剩余金额-剩余最大随机的总数(不含这一次)
                        minRandom = surplus_currency -  nextMax_currency;
                        if (minRandom < 0) {
                            minRandom = 0;
                        }
                    }

                    // 下一次最大的随机值
                    int nextMaxRandomInt = nextMax_currency - (surplus_currency - (randomint - 1));
                    Integer maxRandom = nextMaxRandomInt <= 0 ? nextMaxRandomInt + randomint: null;
                    // 能随机          剩余的金额  - 最大随机数 >  最大随机数  * 剩余数量
                    boolean canRandom = surplus_currency - (randomint - 1) > nextMax_currency ||
                            nextMaxRandomInt > (randomint - 1)
                            || !new Integer(0).equals(minRandom);

                    int addNumber; // 追加的金额
                    if (canRandom && !new Integer(randomint).equals(minRandom+1) && !(new Integer(randomint).equals(minRandom) && new Integer(safe_total).equals(minRandom)) ) {
                        addNumber = myRandom(minRandom, maxRandom == null ? randomint : maxRandom- 1);
                    }else {
                        addNumber = randomint - 1;
                    }
                    redList.set(i,redList.get(i) + addNumber);
                    surplus_currency -= addNumber;
                    surplus_number--;
                }
                break;
            case 1:
                // 定额红包校验
                redList = new ArrayList<>(count);
                for (int i = 0; i <count; i++) {
                    //定额红包要是不能整除会有问题,正常实现应该是输入单个红包金额和总数直接就能计算
                    redList.add(totalMoney/count);
                }
                break;
            default:
                throw new Exception("类型错误!");
        }

        System.out.println("我是" + this.getName() + "我发了"+fenToYuan(String.valueOf(totalMoney))+"元红包"+",我现在有多少钱:" + fenToYuan(String.valueOf(this.getMoney()))+"元");
        return redList;
    }

    /**
     * 生成随机金额
     * @param min
     * @param randomint
     * @return
     */
    public static int myRandom(int min,int randomint) {
        if (min == 0) {
            return  RandomUtils.nextInt(0,randomint);
        }else {
            int nextInt = RandomUtils.nextInt(min,randomint - min);
            return nextInt + min;
        }
    }
}

定义成员类

/**
 * 普通成员
 * @author zjq
 */
public class Member extends User {

    public Member() {
    }

    public Member(String name, Integer money) {
        super(name, money);
    }

    public void receive(ArrayList<Integer> list) {
        // 从多个红包当中随便抽取一个,给我自己。
        // 随机获取一个集合当中的索引编号
        int index = new Random().nextInt(list.size());
        // 根据索引,从集合当中删除,并且得到被删除的红包,给我自己
        Integer delta = list.remove(index);
        // 当前成员自己本来有多少钱:
        Integer money = super.getMoney();
        // 加法,并且重新设置回去
        super.setMoney(money + delta);
        System.out.println("我是" + this.getName() + ",我抢到了"+fenToYuan(String.valueOf(delta))+"元红包"+",我现在有多少钱:" + fenToYuan(String.valueOf(this.getMoney()))+"元");
    }
}

定义测试类

public class MainRedPacket {

    public static void main(String[] args) throws Exception {
        Manager manager = new Manager("群主", 10000);
        Member member1 = new Member("张三", 1000);
        Member member2 = new Member("李四", 1000);
        Member member3 = new Member("王五", 1000);
        Member member4 = new Member("赵六", 1000);
        Member member5 = new Member("孙七", 1000);
        Member member6 = new Member("小詹", 1000);
        Member member7 = new Member("小明", 1000);
        Member member8 = new Member("小红", 1000);

        manager.show(); // 100
        member1.show(); // 10
        member2.show(); // 10
        member3.show(); // 10
        member4.show(); // 10
        member5.show(); // 10
        member6.show(); // 10
        member7.show(); // 10
        member8.show(); // 10
        System.out.println("============================");

        // 群主总共发20块钱,分成8个红包
        ArrayList<Integer> redList = manager.send(2000, 8,0);
        // 八个普通成员收红包
        member1.receive(redList);
        member2.receive(redList);
        member3.receive(redList);
        member4.receive(redList);
        member5.receive(redList);
        member6.receive(redList);
        member7.receive(redList);
        member8.receive(redList);
    }

}

结果输出如下:
image.png

本文内容到此结束了,
如有收获欢迎点赞👍收藏💖关注✔️,您的鼓励是我最大的动力。
如有错误❌疑问💬欢迎各位指出。

保持热爱,奔赴下一场山海。🏃🏃🏃

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。