【编程练习】明日非舟抽卡模拟器(1)按照概率抽取干员星级

好友封掣写了一个明日方舟模拟寻访,于是也想做一个来作为 java 的练手,这学期写课设的时候就体现出我平时写代码写太少了。

当然,经过这学期末的编码轰炸,我现在可不敢像以前一样没有计划地直接开始,先想好它的架构,随后再开始编写,并留下系列博文记录,供以后参考。

本项目连载 github 库地址

目前已经构思的架构

  • 主包
    • 视图包 view
    • 模型包 model
      • 简历类 Resume:用于存储干员的信息,比如名字,星级,立绘路径等
      • 人事资源类 HumanResourse:用于存储合成玉以及其他抽卡资源数目
        • 属性
          • 合成玉数目
          • 卡池
        • 方法
          • 单抽
          • 十连
      • 卡池类 Pool
        • 属性
          • 星级出率:一维数组,下标对应星级,值为对应出率
          • 简历池:二维数组,一维下标对应星级,二维下标动态,值为干员引用
        • 方法
          • 载入简历 loadResume(String fileName)
            从文件中读取出简历,并加入简历池
          • 抽出下一份简历 recruit()
            先抽取星级,再从对应的星级池中抽取简历
          • 抽取星级 randomStar()
            生成 1~100 的随机整数,根据星级出率确定每个星级的区间,判断随机数落在哪个区间,从而确定星级
          • 抽取对应星级的简历 randomResume(int star)
            从简历池中随机抽取下标,并返回下标对应的干员引用

算法

根据卡池的出率抽取星级。

干员的星级分为一星到六星,每个星级的概率不一定相同。

这个目标的要点在于,如何给予六个星级不同的抽取概率。


方法一是创建一个 100 个元素的数组,根据不同星级各自的概率分配不同的元素数量。比如,三星有 45%概率被抽出,那么就将 45 个元素赋值为“3”,六星有 2%的概率,那么就将 2 个元素赋值为“6”。最后抽取下标来获取星级。

不过我没有采取这种方式,这种方式有点暴力。这个例子里面还好,是 100 个整数,假如是 100 个开销比较大的对象,或者概率精确到了很多位小数,那么就不太合适了。


方法二是对每个星级划分一个区间,概率决定了区间的长度,在总区间内随机一个数,然后判断落在哪个星级区间。我用的是这个方法。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/**
* 卡池类
* 负责存储卡池概率信息
*/

package africanights.model;
import java.util.Random;

public class Pool {

protected double[] m_starProbability = new double[] {
0.00,0.00,0.00,//1,2星
0.40,0.50,//3,4星
0.08,0.02//5,6星
};//星级出率,下标1~6对应星级,0暂时闲置

/**
* 根据星级概率抽取出一个星级,取值为1~6
* @return 干员星级
*/
public int randomStar() {
Random random = new Random();
int star = 0;//返回值

int randomInt = random.nextInt(100) + 1;//产生[1,100]之间的随机数
//判断星级区间
/**
* 每一个星级根据概率大小占据[1,100]区间不同长度的区间,
* 判断随机数落在哪个区间,就是抽取到了哪个星级
*
*/
int lowerInt=1;//边界整数,用于给星级区域定界
int upperInt=1;
for(int i=1;i<m_starProbability.length;i++) {
lowerInt = upperInt;//上一个星级的上界变为这个星级的下界
int areaLength = (int)Math.round(m_starProbability[i] * 100);
upperInt += areaLength;
if(lowerInt <= randomInt && randomInt < upperInt) {
//如果随机数落在[lowerInt,upperInt)区间
star = i;
break;
}
}

//单独处理抽到100的情况
//抽到100则为最高星级
if(randomInt == 100) return m_starProbability.length-1;
return star;
}




public static void main(String[] args) {
//测试randomStar()
Pool pool = new Pool();
int[] counter=new int[7];
for(int i=0;i<100;i++) {
int star = pool.randomStar();//测试randomStar()
System.out.format("%d\n",star);
counter[star]++;
}
for(int i=0;i<7;i++) {
System.out.format("抽到%d星%d个\n",i,counter[i]);
}
//测试randomStar()*/

}

}

【编程练习】明日非舟抽卡模拟器(1)按照概率抽取干员星级

https://yxchangingself.xyz/posts/Africanights_simu_hr_1/

作者

憧憬少

发布于

2020-01-27

更新于

2020-01-27

许可协议