基于随机生成权重的元组分组排序——TRPG先攻值生成器开发需求
TRPG先攻值生成器:同先攻值分组+随机排序解决方案
嘿,这个TRPG先攻值的需求太贴合实际场景了!我来帮你完善这个逻辑,解决分组后随机排序的问题,让你的先攻生成器完全符合规则。
首先,你的分组逻辑已经能正常工作,但可以更简洁;另外还需要补上同先攻值组内随机roll点排序的核心步骤,最后把所有组按先攻值从高到低、组内按随机数排序合并成最终列表。
完整实现代码
from itertools import groupby from random import randint # 初始先攻列表(可以是未排序的,代码里会先处理排序) iniList = [('Enemy 3', 15), ('Aldare', 14), ('Enemy 2', 14), ('Enemy 5', 14), ('Enemy 1', 13), ('Enemy 4', 13)] # 第一步:按先攻值从高到低排序(确保大的先攻值组排在前面) sorted_ini = sorted(iniList, key=lambda x: x[1], reverse=True) # 第二步:按先攻值分组(用itertools.groupby更简洁,前提是列表已排序) ini_groups = [] for initiative, group in groupby(sorted_ini, key=lambda x: x[1]): ini_groups.append(list(group)) # 第三步:每组内生成1-6随机数模拟骰子,按随机数降序排序后合并到最终列表 final_ini_list = [] for group in ini_groups: # 给每个角色添加随机骰子值 roll_results = [(randint(1, 6), char_name, ini_value) for char_name, ini_value in group] # 按骰子结果从大到小排序(骰子大的先行动) roll_results_sorted = sorted(roll_results, key=lambda x: x[0], reverse=True) # 去掉骰子值,保留角色和先攻值,加入最终列表 final_ini_list.extend( (name, val) for _, name, val in roll_results_sorted ) # 输出最终先攻顺序 print("=== 最终先攻顺序 ===") for pos, (char, ini) in enumerate(final_ini_list, 1): # 匹配当前角色的骰子值用于输出 roll_val = next(r for r,n,v in roll_results if n == char) print(f"{pos}. {char} | 先攻值:{ini} (骰子roll点:{roll_val})")
代码解释
- 排序处理:先对初始列表按先攻值降序排序,确保高先攻值的组排在最前面,这是
groupby能正确分组的前提(groupby只会把连续相同的元素分组)。 - 分组优化:用
itertools.groupby替代手动循环分组,代码更简洁易读,同时也能保证分组的准确性。 - 随机roll点排序:
- 给组内每个角色生成1-6的随机数,模拟TRPG里的骰子roll点;
- 按随机数降序排序,模拟“骰子大的角色先行动”的规则;
- 去掉临时的骰子值,把角色信息合并到最终列表。
如果你不想用itertools.groupby(纯手动分组)
如果想保留手动分组的逻辑,我优化了你的原代码,解决了原代码中可能的边界问题:
from random import randint iniList = [('Enemy 3', 15), ('Aldare', 14), ('Enemy 2', 14), ('Enemy 5', 14), ('Enemy 1', 13), ('Enemy 4', 13)] sorted_ini = sorted(iniList, key=lambda x: x[1], reverse=True) ini_groups = [] if sorted_ini: current_ini = sorted_ini[0][1] current_group = [sorted_ini[0]] # 从第二个元素开始遍历 for item in sorted_ini[1:]: if item[1] == current_ini: current_group.append(item) else: ini_groups.append(current_group) current_ini = item[1] current_group = [item] # 最后别忘了把最后一组加入 ini_groups.append(current_group) # 后续随机排序和合并逻辑和上面一致 final_ini_list = [] for group in ini_groups: roll_results = [(randint(1,6), *item) for item in group] roll_results_sorted = sorted(roll_results, key=lambda x: x[0], reverse=True) final_ini_list.extend(item[1:] for item in roll_results_sorted) print("=== 最终先攻顺序 ===") for pos, char in enumerate(final_ini_list, 1): print(f"{pos}. {char[0]} (先攻值:{char[1]})")
这样处理后,你的先攻生成器就完全符合TRPG规则:高先攻值的组优先,同先攻值的角色通过随机roll点决定行动顺序,所有同先攻值的角色是“同时”参与roll点排序,而不是逐个对比。
内容的提问来源于stack exchange,提问作者PandSkin




