许久没有写blog
手有点生,但是准备开启常更模式了!
最近重拾Java知识,挑一些有趣的案例分享给大家。(拼手气红包案例)
分析:
首先,群主和成员都是微信、QQ等应用程序的用户,他们都可以归为用户类,那么由此我们可以很快地想到Java中一个很重要的特性:继承性。
一张图很直观地表达其关系:
其次,分析本程序的一些逻辑:
假设群主和成员本来都有一些钱(可以为0)
群主发的一笔金额(红包),从群主余额中扣除,平均分成n等份,让成员领取;成员领取红包后,保存到成员各自的余额中。
实现:
首先,定义用户类User:
public class User {
// 成员变量
private String username; // 用户名
private double leftMoney; // 余额,有角和分
// 构造方法
public User() {
}
public User(String username, double leftMoney) {
this.username = username;
this.leftMoney = leftMoney;
}
// get/set方法
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public double getLeftMoney() {
return leftMoney;
}
public void setLeftMoney(double leftMoney) {
this.leftMoney = leftMoney;
}
// 展示信息的方法
public void show() {
System.out.println("用户名:"+ username +" , 余额为:" + leftMoney + "元");
}
}
(小技巧)快速创建Getter/Setter方法:
Alt + Insert
选择:
Getter and Setter
同理,user无参数方法和有参数方法快速创建可以选择:
Constructor
Select All和Select None即可实现全选和全不选。
其次,可以定义群主类Manager:
public class Manager extends User {
// 添加构造方法
public Manager() {
}
public Manager(String username, double leftMoney) {
// 通过super 调用父类构造方法
super(username, leftMoney);
}
public ArrayList send(double money, int count) {
// 获取群主余额
double leftMoney = getLeftMoney();
// 如果发出去的红包大于群主剩余钱,则发送失败
if(money > leftMoney) {
System.out.println("发送失败!");
return null;
}
// 修改群主余额的
super.setLeftMoney(leftMoney ‐ money);
// 创建一个集合,保存等份金额
ArrayList list = new ArrayList<>();
// 扩大100倍,相当于折算成'分'为单位,避免小数运算损失精度的问题
money *= 100;
money = (int)money;
// 每份的金额
int avg = (int)(money / count);
// 不能整除的余数
int mod = (int)(money % count);
// 无论是否整除,n‐1份,都是每份的等额金额
for (int i = 0; i < count ‐ 1; i++) {
// 缩小100倍,折算成 '元'
list.add(avg / 100.0);
}
// 将最后一份不能整除的金额放到list的最后
double last = (avg + mod)/100.0;
list.add(last);
// 返回集合
return list;
}
}
其中,要考虑到群主发的红包可能不是整数,且红包数为整数,那么有可能不能平均分配,所以我先平均分配,将多余的不能平均分配的金额放到最后一个红包内。
然后,我们定义成员类Member:
public class Member extends User {
public Member() {
}
public Member(String username, double leftMoney) {
super(username, leftMoney);
}
// 打开红包,就是从集合中,随机取出一份,保存到自己的余额中
public void receive(ArrayList list) {
// 创建一个Random对象,随机生成一个红包编号
int index = new Random().nextInt(list.size());
// 从集合中移去相应编号,得到该编号的金额的红包
double delta = list.remove(index);
// 当前成员本来有多少钱
double money = super.getLeftMoney();
// 直接调用父类方法,设置到余额
super.setLeftMoney( money + delta );
}
}
最后,写执行程序,main函数执行:
public class mainRedPacket {
public static void main(String[] args) {
// 创建一个群主对象,三个成员
Manager manager = new manager("群主" , 188.88);
Member one = new Member("成员A",5.23);
Member two = new Member("成员B",0);
Member three = new Member("成员C",16.89);
// 显示原始成员的余额
manager.show();
one.show();
two.show();
three.show();
System.out.println("=================");
// 创建一个键盘录入
Scanner sc = new Scanner(System.in);
System.out.println("请输入发送红包的金额:");
double money = sc.nextDouble();
// 发送红包
ArrayList list = manager.send(money,3);
// 打开红包
one.receive(list);
two.receive(list);
three.receive(list);
// 显示余额信息
manager.show();
one.show();
two.show();
three.show();
}
}
结果展示:
分别进行三次红包发送:
第一次:群主余额188.88元,发送200元红包,发送失败,余额不足!
第二次:群主发送18元红包,三个人正好平分,每人6元。
第三次:群主发送0.31元红包,三人不能平分,所以其中一人多0.01元。
三次结果均正确!
思考:
1.对于double类型的精度并没有控制,很又可能出现浮点数相加减或相乘除精度不正确的情况,读者可以自行思考,或者百度解决。
2.发红包不仅有普通红包,还有手气红包,那么可以用到随机数的知识来解决,博主将在后期慢更之,欢迎各位大犇给出自己的解法。
感谢您的阅读,不足之处欢迎指正!