崩壞3精準補給池抽卡模擬,求數學期望及一些相關概率

簡單的模擬,記錄一下結果。

沒有編寫10連保底的機制。因爲官方公示的概率已經把保底的機制算上了,所以不寫也完全不影響求期望。不過這會使很歐和很非的人的比例同時增大,不過差的不大(大概)。 或者說,同概率下,十連保底機制對歐洲人不友好,對亞洲非洲人稍友好。

1.不考慮使用許願池的情況

	static boolean checkFlags(boolean[] flags) {
		for (int i = 0; i < flags.length; i++)
			if (flags[i] == false)
				return false;
		return true;
	}

	public static void main(String[] args) {
		double average = 0;
		long countOfLottery = 0;
		int numberOfTestPeople = 100000;
		int[] boundOfLottery = new int[] { 10, 40, 93, // 648*4
				130, 150, 185 // 648*8
		};
		int[] numberOfLessThanBound = new int[boundOfLottery.length];
		int minCount = 30000;
		int maxCount = -1;
		double rate = 0.015;
		double[] rates = { 2.479, 1.24, 1.24, 1.24 };// 百分比
		double[] rates2 = new double[rates.length + 1];
		boolean[] flags = new boolean[rates.length];

		double sum = 0;
		for (int i = 0; i < rates.length; i++) {
			rates2[i] = sum;
			sum += rates[i];
		}
		rates2[rates2.length - 1] = sum;

		for (int i = 0; i < numberOfTestPeople; i++) {
			int count2 = 0;
			for (int j = 0; j < rates.length; j++) {
				flags[j] = false;
			}
			do {
				countOfLottery++;
				count2++;
				double temp = Math.random() * 100;
				for (int j = 0; j < rates.length; j++) {
					if (rates2[j] <= temp & temp < rates2[j + 1])
						flags[j] = true;
				}
			} while (!checkFlags(flags));
			if (maxCount < count2)
				maxCount = count2;
			if (minCount > count2)
				minCount = count2;
			for (int j = 0; j < boundOfLottery.length; j++)
				if (count2 <= boundOfLottery[j])
					numberOfLessThanBound[j]++;
		}
		average = (double) countOfLottery / (double) numberOfTestPeople;
		System.out.println("模擬十萬人抽卡");
		System.out.println("每個人當其抽齊up的武器以及一套聖痕時就停止抽卡");
		System.out.println("平均抽卡次數: " + String.format("%8.2f", average));
		System.out.println("最大抽卡次數: " + String.format("%8d", maxCount));
		System.out.println("最小抽卡次數: " + String.format("%8d", minCount));
		for (int i = 0; i < boundOfLottery.length; i++)
			System.out.println("抽卡次數<=" + String.format("%3d", boundOfLottery[i]) + " 的概率:"
					+ String.format("%8.2f",
							(double) numberOfLessThanBound[i] * 100 / (double) numberOfTestPeople)
					+ "%");
	}

執行結果:

模擬十萬人抽卡
每個人當其抽齊up的武器以及一套聖痕時就停止抽卡
平均抽卡次數:   151.89
最大抽卡次數:     1019
最小抽卡次數:        6
抽卡次數<= 10 的概率:    0.02%
抽卡次數<= 40 的概率:    3.60%
抽卡次數<= 93 的概率:   28.90%
抽卡次數<=130 的概率:   49.43%
抽卡次數<=150 的概率:   58.91%
抽卡次數<=185 的概率:   72.23%

2.考慮使用許願池的情況

	static boolean QiYuan(int b, int c, int d) {
		if (d > 0)
			return false;
		if (b > 0 && c > 0)
			if (b + c >= 4)
				return true;
		return false;
	}

	public static void main(String[] args) {
		double average = 0;
		long countOfLottery = 0;
		int numberOfTestPeople = 100000;
		int[] boundOfLottery = new int[] { 10, 40, 93, // 648*4
				130, 150, 185 // 648*8
		};
		int[] numberOfLessThanBound = new int[boundOfLottery.length];
		int minCount = 30000;
		int maxCount = -1;
		double rate = 0.015;
		double rate1 = 2.479, rate2 = 1.24, rate3 = 1.24, rate4 = 1.24;
		for (int i = 0; i < numberOfTestPeople; i++) {
			int count2 = 0;
			int a = 0, b = 0, c = 0, d = 0;
			do {
				countOfLottery++;
				count2++;
				double temp = Math.random() * 100;
				if (temp < rate1 & 0 <= temp)
					a++;
				else if (temp < rate1 + rate2 & rate1 <= temp)
					b++;
				else if (temp < rate1 + 2 * rate2 & rate1 + rate2 <= temp)
					c++;
				else if (temp < rate1 + 3 * rate2 & rate1 + 2 * rate2 <= temp)
					d++;
				if (QiYuan(b, c, d) || QiYuan(b, d, c) || QiYuan(c, d, b))
					break;

			} while (a == 0 || b == 0 || c == 0 || d == 0);
			if (maxCount < count2)
				maxCount = count2;
			if (minCount > count2)
				minCount = count2;
			for (int j = 0; j < boundOfLottery.length; j++)
				if (count2 <= boundOfLottery[j])
					numberOfLessThanBound[j]++;
		}
		average = (double) countOfLottery / (double) numberOfTestPeople;
		System.out.println("模擬十萬人抽卡");
		System.out.println("每個人當其抽齊up的武器以及一套聖痕時就停止抽卡");
		System.out.println("平均抽卡次數: " + String.format("%8.2f", average));
		System.out.println("最大抽卡次數: " + String.format("%8d", maxCount));
		System.out.println("最小抽卡次數: " + String.format("%8d", minCount));
		for (int i = 0; i < boundOfLottery.length; i++)
			System.out.println("抽卡次數<=" + String.format("%3d", boundOfLottery[i]) + " 的概率:"
					+ String.format("%8.2f",
							(double) numberOfLessThanBound[i] * 100 / (double) numberOfTestPeople)
					+ "%");
	}

執行結果:

模擬十萬人抽卡
每個人當其抽齊up的武器以及一套聖痕時就停止抽卡
平均抽卡次數:   106.05
最大抽卡次數:      596
最小抽卡次數:        5
抽卡次數<= 10 的概率:    0.04%
抽卡次數<= 40 的概率:    6.56%
抽卡次數<= 93 的概率:   47.11%
抽卡次數<=130 的概率:   72.75%
抽卡次數<=150 的概率:   81.96%
抽卡次數<=185 的概率:   91.81%

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章