模拟微信群红包
这是一个小小的模拟微信群红包实现的过程,由于能力有限,才学习java一个月,还有很多需要改进的地方,还望大家多多指出
写作背景: 通过老师布置的一个普通红包作业产生灵感,想要试试拼手气红包的实现,经历了数百次测试后,2.0版本终于写好了
其中1.0版本只是作为测试,功能不完善,我就不发出来了,现在来一起看看代码的实现
1.User类
```go
package cn.com.wechat_red_packet;
public class User {
private String name;
private double balance;
public User() {
super();
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public User(String name, double balance) {
super();
this.name = name;
this.balance = balance;
}
public void show() {
System.out.println("姓名:" + getName() + "余额:" + getBalance());
}
}
2.Manager类
package cn.com.wechat_red_packet;
public class Manager extends User {
public Manager() {
super();
// TODO Auto-generated constructor stub
}
public Manager(String name, double balance) {
super(name, balance);
// TODO Auto-generated constructor stub
}
public void send(double totalMoney) {
setBalance(getBalance() - totalMoney);
}
public double send(double totalMoney, int count) {
setBalance(getBalance() - totalMoney);
return totalMoney/count;
}
}
3.Member类
package cn.com.wechat_red_packet;
public class Member extends User {
public static int count;
public Member() {
super();
count++;
// TODO Auto-generated constructor stub
}
public Member(String name, double balance) {
super(name, balance);
count++;
// TODO Auto-generated constructor stub
}
public void income(double money) {
setBalance(getBalance() + money);
}
}
4.RedPacket类: 里面有一个打印红包图案的方法和一个随机群员下标的方法
package cn.com.wechat_red_packet;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
public class RedPacket {
protected static Scanner s = new Scanner(System.in);
protected static Random rd = new Random();
// 红包图案
public static void redDesign() {
System.out.println(" _________");
System.out.println("|\\ /|");
System.out.println("| \\ / |");
System.out.println("| \\ / |");
System.out.println("| ($) |");
System.out.println("| |");
System.out.println("| |");
System.out.println("|_________|");
}
// 根据条件随机选出若干群员下标存入数组 thisCount是红包个数 length是群成员总数
public static int[] ifRepeat(int thisCount, int length) {
// 红包的有效个数
int realCount;
if (thisCount < length)
realCount = thisCount;
else
realCount = length;
// 定义一个int数组用来存储随机生成的用户下标
int[] intRandom = new int[realCount];
// 生成数据集,用来保存不重复的随机生成数
List<Integer> mylist = new ArrayList<Integer>();
Random rd = new Random();
// 调用size方法,用来控制随机数不重复
while (mylist.size() < intRandom.length) {
int num = rd.nextInt(length);
// 如果集合类没有num,则将它存入
if (!mylist.contains(num)) {
mylist.add(num); // 往集合里面添加数据。
}
}
// 将Integer转换成int
for (int i = 0; i < mylist.size(); i++) {
intRandom[i] = (Integer) (mylist.get(i));
}
return intRandom;
}
}
5.AskDesign类 -->这个是键盘输入红包金额和红包个数的
package cn.com.wechat_red_packet;
import java.util.Scanner;
//提示用户键盘输入
final class AskDesign{
public static double totalMoney;
public static int thisCount;
public static boolean menu(Manager ma,Member []m) {
Scanner s = new Scanner(System.in);
boolean bn;
char c,ch;
do {
bn = false;
System.out.println("亲爱的群主大大,请输入你要发送的红包金额^-^");
totalMoney = s.nextDouble();
System.out.print("个数:");
thisCount = s.nextInt();
System.out.println();
if (totalMoney > ma.getBalance()) {
System.out.println("余额不足!");
System.out.println("查询余额-y 不玩了-n");
c = s.next().charAt(0);
if (c == 'y' || c == 'Y') {
System.out.println("您当前账户余额为:" + ma.getBalance() + "元");
System.out.println("是否继续(继续-y 不玩了-n)");
ch = s.next().charAt(0);
s.close();
if (ch == 'y' || ch == 'Y')
bn = true;
else
return false;
} else
return false;
}
} while (bn);
return true;
}
}
6.CommonRedPacket类 -->这是实现普通红包的类 普通红包就是拆分的红包金额是相等的
package cn.com.wechat_red_packet;
import java.math.BigDecimal;
//普通红包
public final class CommonRedPacket extends RedPacket {
public static boolean send(Manager ma, Member[] m) {
boolean bn = AskDesign.menu(ma,m);
if(bn == false) return false;
// (拆分)红包个数
int thisCount = AskDesign.thisCount;
// (剩余)红包个数
int leftCount = thisCount;
// 发送的红包金额
double totalMoney = AskDesign.totalMoney;
int length = m.length;
//每个人分得的红包金额
double bodyMoney = ma.send(totalMoney,thisCount);
// 打印红包图案
redDesign();
// 随机出thisCount个用户下标存储index数组
int[] index = ifRepeat(thisCount, length);
for(int i = 0;i < index.length;i++) {
m[index[i]].income(bodyMoney);
System.out.println(m[index[i]].getName() + "领取了红包");
leftCount--;
}
//精确到小数点后两位
double allRedMoney = bodyMoney*(index.length); //已领取的红包金额
BigDecimal b1 = new BigDecimal(allRedMoney);
allRedMoney = b1.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
double sendBack = totalMoney - allRedMoney; //未领取的红包金额
BigDecimal b2 = new BigDecimal(sendBack);
sendBack = b2.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
BigDecimal b3 = new BigDecimal(ma.getBalance()); //发红包者的余额
double maBalance = b3.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
//未领取的红包退回给发送者
if (thisCount > 10) {
System.out.println("余额:" + maBalance + "元");
// 把红包内剩下的钱退回给发送者
System.out.println("已领取" + allRedMoney + "元,有" + (leftCount) + "个红包没人领,退回" + sendBack + "元");
} else
System.out.println("余额:" + maBalance + "元");
ma.setBalance(ma.getBalance() + sendBack);
System.out.println("是否继续(继续-y,不玩了-n)");
char c = s.next().charAt(0);
if (c == 'y' || c == 'Y')
return true;
else
return false;
}
}
下面这里就是让我非常头疼的类了,也就是所谓的拼手气红包,我在那个随机公式那里耗了差不多两天 QAQ
7.LuckyRedPacket -->拼手气红包
package cn.com.wechat_red_packet;
import java.math.BigDecimal;
//拼手气红包
public final class LuckyRedPacket extends RedPacket {
public static boolean send(Manager ma, Member[] m) {
boolean bn = AskDesign.menu(ma,m);
if(bn == false) return false;
// (剩余)红包个数
int thisCount = AskDesign.thisCount;
int leftCount = thisCount;
// 发送的红包金额
double totalMoney = AskDesign.totalMoney;
int length = m.length;
// 打印红包图案
redDesign();
// 随机出thisCount个用户下标存储index数组
int[] index = ifRepeat(thisCount, length);
ma.send(totalMoney);
// 单个红包的最大金额上限
double maxMoney;
// 运气王的红包金额
double maxRedBag = 0.01;
// 单个红包的金额
double redMoney = 0.01;
// 运气王的下标
int theKingOfLuck = index[0];
// 真正能抢到红包的用户总数
int realUser = index.length;
// 已领取的红包总金额
double allRedMoney = 0;
// 给随机选出来的有效用户各发一个红包
for (int i = 0; i < realUser; i++) {
// 单个红包最大金额的计算公式 : 2*红包金额/剩余红包个数
maxMoney = totalMoney / leftCount * 2;
// 单个红包的计算公式: 0-1之间随机取一个小数乘以红包最大上限
redMoney = rd.nextDouble() * maxMoney;
BigDecimal b = new BigDecimal(redMoney);
// 精确到小数点后两位
redMoney = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
redMoney = redMoney < 0.01?redMoney = 0.01:redMoney;
//如果是最后一个抢到红包的玩家,则判断拆分的红包个数是否大于群员总数
if(i == realUser - 1) {
// 如果拆分的红包个数大于群员总数 ,则将这个随机红包分给该用户并存入钱包
if (thisCount > m.length) {
m[index[realUser - 1]].income(redMoney);
totalMoney -= redMoney;
allRedMoney += redMoney;
System.out.println(m[index[realUser - 1]].getName() + "抢到了" + redMoney + "元");
// 如果拆分的红包个数小于群员总数,则直接将红包里剩余的钱存入该用户钱包
} else {
m[index[realUser - 1]].income(totalMoney);
BigDecimal bd = new BigDecimal(totalMoney);
totalMoney = bd.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
System.out.println(m[index[realUser - 1]].getName() + "抢到了" + totalMoney + "元");
}
leftCount--;
// 比较最后一名群员和前面抢到红包的群员所拆红包的金额,得出运气王
if (maxRedBag < redMoney) {
maxRedBag = redMoney;
theKingOfLuck = index[i];
}
//如果不是最后一个群员,则直接将这个红包存入该群员的钱包
}else {
m[index[i]].income(redMoney);
totalMoney -= redMoney;
allRedMoney += redMoney;
leftCount--; // 每抢一个红包,leftCount-- 得出剩余的红包个数
System.out.println(m[index[i]].getName() + "抢到了" + redMoney + "元");
// 比较拆得红包的金额大小
if (maxRedBag < redMoney) {
maxRedBag = redMoney;
theKingOfLuck = index[i];
}
// System.out.println("余额:" + df.format(m[index[i]].getBalance()) + "元");
}
}
double sendBack = 0;
BigDecimal b = new BigDecimal(ma.getBalance());
double maBalance = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
if (thisCount > 10) {
System.out.println("余额:" + maBalance + "元");
BigDecimal bd = new BigDecimal(totalMoney);
sendBack = bd.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
BigDecimal bi = new BigDecimal(allRedMoney);
allRedMoney = bi.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
// 把红包内剩下的钱退回给发送者
ma.setBalance(ma.getBalance() + sendBack);
System.out.println("已领取" + allRedMoney + "元,有" + (leftCount) + "个红包没人领,退回" + sendBack + "元");
} else
System.out.println("余额:" + maBalance + "元");
System.out.println(m[theKingOfLuck].getName() + "是运气王!");
System.out.println("是否继续(继续-y,不玩了-n)");
char c = s.next().charAt(0);
if (c == 'y' || c == 'Y')
return true;
else
return false;
}
}
好了,实现类都写好了,现在让我们来写个测试类测试一下
package cn.com.wechat_red_packet;
import java.util.*;
public class WechatRedPacket2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner s = new Scanner(System.in);
Manager ma = new Manager("朱兴旺", 1000);
Member[] m = { new Member("阴子航", 66.6), new Member("娄文卫", 87.2), new Member("赵旭", 78.3),
new Member("赵志强", 88.8), new Member("刘昌鑫", 79.2), new Member("高自豪", 68.5), new Member("侯森", 72.3),
new Member("杨立业", 55.9), new Member("丁海涛", 68.4), new Member("陈世启", 74.3) };
boolean bn;
do {
System.out.println("请选择你要发送的红包类型");
System.out.println("1-普通红包 2-拼手气红包");
int a = s.nextInt();
if(a == 1)
bn = CommonRedPacket.send(ma, m);
else if(a == 2)
bn = LuckyRedPacket.send(ma,m);
else {
System.out.println("输入有误!请输入正确指令!");
bn = true;
}
} while (bn);
s.close();
}
}
实现效果
总结: 在这一个月的学习里,有过曾因为一个项目或者一个题写了好几个通宵的体验,过程虽然很不容易(主要是心疼我的头发),但是既然选择了java这门语言 那就必须坚持下来 总有那么一个节点,你会得到你想要的
借用爱5里的一句台词 ,人生就是一个起起落落落落落落落落落落然后又起的过程