許久沒有寫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<Double> send(double money, int count) {
// 獲取羣主餘額
double leftMoney = getLeftMoney();
// 如果發出去的紅包大於羣主剩餘錢,則發送失敗
if(money > leftMoney) {
System.out.println("發送失敗!");
return null;
}
// 修改羣主餘額的
super.setLeftMoney(leftMoney ‐ money);
// 創建一個集合,保存等份金額
ArrayList<Double> 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<Double> 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<Double> 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.發紅包不僅有普通紅包,還有手氣紅包,那麼可以用到隨機數的知識來解決,博主將在後期慢更之,歡迎各位大犇給出自己的解法。
感謝您的閱讀,不足之處歡迎指正!