对对碰游戏概率计算

  • 2025-09-23 03:24:36

经常在直播中刷到对对碰游戏,好奇概率是怎么分布的,故用python做了个模拟实验。

实验假设:有一大箱含有type_num种颜色的球,现在要随机拿出initial_draws个,每当拿出的球中出现1对相同颜色的2个球就把这2个球放到一边并重新从箱子里拿出1个球(如果出现2对相同颜色的2个球则放一边并重新拿2个球,以此类推),若出现3个一样颜色的球则随机放2个球到一边并重新拿1个球,与此同时可以指定lucky_color_num个幸运颜色,当拿出指定的幸运颜色时,可以再拿1个球,最后所有拿出的球中没有重复的球时过程结束,进行100000次实验模拟最后总共拿出球的可能个数及其对应概率。

以下为实现代码:

可自行设定type_num、initial_draws、lucky_color_num参数得到拿球平均数、众数、中位数及可视化分布图;也可设定ball_cost、transport_cost、other_cost参数计算最终成本。

#!/usr/bin/env python

# -*- coding: UTF-8 -*-

"""

@File : ball_experiment.py

@Author : ggb

@Date : 2024/9/26 14:08

@Desc : 拿球模拟实验

"""

import random

from collections import Counter

import tqdm

import matplotlib.pyplot as plt

def calculate_median(data):

""" 计算中位数 """

data_sorted = sorted(data) # 将数据按大小顺序排列

n = len(data)

if n % 2 == 1: # 如果数据个数为奇数

median = data_sorted[n // 2]

else: # 如果数据个数为偶数

median = (data_sorted[n // 2 - 1] + data_sorted[n // 2]) / 2

return median

def plot_results(result_dict, simulation_trials):

""" 画出柱状图 """

# 设置中文字

plt.rcParams['font.sans-serif'] = ['SimHei'] # SimHei是黑体

plt.rcParams['axes.unicode_minus'] = False # 解决负号'-'显示为方块的问题

labels, counts = zip(*result_dict.items())

plt.figure(figsize=(10, 6))

plt.bar(labels, counts, width=0.8, color='skyblue')

plt.xlabel('拿球次数')

plt.ylabel('频率')

plt.title('次数分布')

plt.xticks(range(min(labels), max(labels) + 1, max(len(labels) // 10, 1))) # 设置横坐标的显示间隔

plt.show()

def with_lucky_color(type_num, initial_draws, simulation_trials, lucky_color_num):

""" 有幸运颜色 """

def process_balls(current_balls, colors):

""" 碰球 """

counts = Counter(current_balls)

new_balls = []

total_draws = 0

for color, count in counts.items():

if count == 1: # 将不重复的球加入新球列表

new_balls.append(color)

elif count >= 2: # 每找出一对相同颜色的球,加入一次新球

pairs = count // 2

new_balls.extend([color] * (count % 2)) # 保留多余的一个球,也可以用new_balls.append(color)

total_draws += pairs

for _ in range(pairs): # 对于每对相同颜色的球,加入新的球

new_balls.append(random.choice(colors))

return new_balls, total_draws

def simulate_draws_with_lucky(colors, initial_draws, lucky_colors):

total_draws = 0

current_balls = random.choices(colors, k=initial_draws)

total_draws += len(current_balls)

# 继续直到所有球颜色不重复

while len(set(current_balls)) != len(current_balls):

lucky_count = sum(color in lucky_colors for color in current_balls) # 检查当前球中有多少个幸运色

if lucky_count > 0:

for _ in range(lucky_count): # 根据幸运色数量增加相应数量的新球

new_ball = random.choice(colors)

current_balls.append(new_ball)

total_draws += 1

# 处理碰球逻辑

current_balls, new_draws = process_balls(current_balls, colors)

total_draws += new_draws

return total_draws

colors = list(f'col{i + 1}' for i in range(type_num))

lucky_colors = random.sample(colors, lucky_color_num) # 随机选择幸运颜色

results = []

for _ in tqdm.tqdm(range(simulation_trials)):

results.append(simulate_draws_with_lucky(colors, initial_draws, lucky_colors))

average_draws = sum(results) / simulation_trials

print(f"幸运颜色: {lucky_colors}")

print(f"平均拿球数量: {average_draws}")

result_dict = Counter(results)

for key in result_dict: # 替换次数为比例

result_dict[key] = round((result_dict[key] / simulation_trials) * 100, 2)

print(f'拿球情况:{result_dict}')

# 找出最大、最小拿球数

max_key = max(result_dict.keys())

min_key = min(result_dict.keys())

max_value = result_dict[max_key]

min_value = result_dict[min_key]

print(f"最大拿球数是: {max_key}, 占比是: {max_value}")

print(f"最小拿球数是: {min_key}, 占比是: {min_value}")

# 计算众数和中位数

mode = [k for k, v in result_dict.items() if v == max(result_dict.values())]

median = calculate_median(results)

print(f'众数: {mode}')

print(f'中位数: {median}')

# 画图

# plot_results(result_dict, simulation_trials)

return average_draws

if __name__ == "__main__":

simulation_trials = 100000 # 模拟实验次数

type_num = 8 # 颜色种类数

initial_draws = 8 # 拿出数量

lucky_color_num = 2 # 幸运色数量

ball_cost = 3 # 每件成本

transport_cost = 4 # 运输成本

other_cost = 2 # 其他成本

average_draws = with_lucky_color(type_num, initial_draws, simulation_trials, lucky_color_num) # 有幸运色

total_cost = average_draws * ball_cost + transport_cost + other_cost # 全部成本

print(f'全部成本为:{total_cost}')

友情链接
Copyright © 2022 墨西哥世界杯|瑞奇马丁世界杯主题曲|河东家电世界杯智能观赛馆|hedongjdj.com All Rights Reserved.