最近入坑了dnf手游,染上了合天空,大黑蛋子一个,突发奇想,模拟下合天空概率,看看是否真的有20%。
梳理代码逻辑如下:
不考虑礼包和其他东西
条件:
- 合成概率20%,每次需要2个装扮和一个合成器
- 每次失败一件装扮和合成器会消耗
逻辑
1. 按每次都需要一件装扮和一个合成器(目前v区,价格是2.2w)
2. 先模拟一个勇士合成,循环800次取平均值
代码如下:
use rand::Rng;
use std::time::Instant;
const NUM_PLAYERS: usize = 8_000;
const SUCCESS_PROBABILITY: f64 = 0.20;
// 固定花费
const BASE_COST: f32 = 12.0;
// 每次合成的花费
const COST_PER_TRIAL: f32 = 2.2;
fn simulate_player(rng: &mut impl Rng) -> u32 {
let mut total_amount = 0;
let mut sub_equipments = 8;
let mut count = 0;
while sub_equipments > 0 {
if rng.gen_bool(SUCCESS_PROBABILITY) {
sub_equipments -= 1;
}
count += 1;
}
total_amount += count;
total_amount
}
fn main() {
let start = Instant::now();
let mut rng = rand::thread_rng();
let mut total_success = 0;
let mut total_cost: f32 = 0.0;
for _ in 0..NUM_PLAYERS {
let temp_count = simulate_player(&mut rng);
total_cost += temp_count as f32 * COST_PER_TRIAL;
total_success += temp_count;
}
let average_cost = total_cost / NUM_PLAYERS as f32;
let success_time = total_success as f64 / NUM_PLAYERS as f64;
println!(
"Average synthesis times: {:.2}",
success_time
);
println!(
"Average Cost: {:.2}w, If you have a set of fashion, then all you need is {:.2}w",
average_cost + BASE_COST, average_cost
);
println!("Elapsed Time: {:.2}", start.elapsed().as_secs_f32());
}
这里运行太慢了,暂时改成8000人结果
我花了130w,这差这么多,继续加大数据,因为执行时间长,又改了下
use rand::Rng;
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Instant;
const NUM_PLAYERS: usize = 8_000_000;
const SUCCESS_PROBABILITY: f64 = 0.20;
// 固定花费
const BASE_COST: f32 = 12.0;
// 每次合成的花费
const COST_PER_TRIAL: f32 = 2.2;
// 线程数,可以根据你的 CPU 核心数进行调整
const NUM_THREADS: usize = 10;
fn simulate_player(rng: &mut impl Rng) -> u32 {
let mut total_amount = 0;
let mut sub_equipments = 8;
let mut count = 0;
while sub_equipments > 0 {
if rng.gen_bool(SUCCESS_PROBABILITY) {
sub_equipments -= 1;
}
count += 1;
}
total_amount += count;
total_amount
}
fn main() {
let start = Instant::now();
let players_per_thread = NUM_PLAYERS / NUM_THREADS;
let mut handles = vec![];
let total_success = Arc::new(Mutex::new(0u32));
let total_cost = Arc::new(Mutex::new(0.0f32));
for _ in 0..NUM_THREADS {
let total_success = Arc::clone(&total_success);
let total_cost = Arc::clone(&total_cost);
handles.push(thread::spawn(move || {
let mut rng = rand::thread_rng();
let mut thread_success = 0;
let mut thread_cost = 0.0;
for _ in 0..players_per_thread {
let temp_count = simulate_player(&mut rng);
thread_cost += temp_count as f32 * COST_PER_TRIAL;
thread_success += temp_count;
}
let mut total_success = total_success.lock().unwrap();
*total_success += thread_success;
let mut total_cost = total_cost.lock().unwrap();
*total_cost += thread_cost;
}));
}
for handle in handles {
handle.join().unwrap();
}
let total_success = Arc::try_unwrap(total_success).unwrap().into_inner().unwrap();
let total_cost = Arc::try_unwrap(total_cost).unwrap().into_inner().unwrap();
let average_cost = total_cost / NUM_PLAYERS as f32;
let success_time = total_success as f64 / NUM_PLAYERS as f64;
println!(
"Average combine time: {:.2}",
success_time
);
println!(
"Average Cost: {:.2}w, If you have a set of fashion, then all you need is {:.2}w",
average_cost + BASE_COST, average_cost
);
println!("Elapsed Time: {:.2}s", start.elapsed().as_secs_f32());
}
800w勇士模拟结果:
虽说不知道官方的概率算法是什么,但是应该差别很大,
恩,就这样算法问题,我不是非酋!