You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何重构D&D角色生成器中的重复Python代码?

D&D角色生成器代码重构:消除重复逻辑

问题核心

你当前的character()函数里,每个种族分支都重复执行设置变量+调用race()的操作,冗余代码太多。核心解决思路是用数据驱动替代硬编码的条件判断,把种族属性统一存储,通过用户输入的编号直接匹配对应数据。

重构方案

  1. 用字典存储所有种族数据:把每个种族的名称、体型、身高范围等属性整理成字典的键值对,一次性定义,避免重复写相同逻辑。
  2. 简化种族选择逻辑:用户输入编号后,直接从字典中取出对应种族的完整数据,无需一堆if-elif判断。
  3. 优化函数参数传递:让race()函数接收种族数据字典,减少零散参数的传递,代码更整洁。
  4. 修复文件对象作用域问题:原代码中函数直接依赖全局的txt对象,改为显式传递文件对象,避免作用域混乱。
  5. 简化属性掷骰逻辑:用列表推导式简化stat_roll()的代码,保持功能不变的同时更简洁。

完整重构代码

import random

# 定义所有种族的属性数据,数据驱动替代硬编码判断
RACES = {
    "1": {"name": "Dwarf", "size": "medium", "size_range": "4-5", "age_max": "350", "age_range": "50-300", "speed": "25"},
    "2": {"name": "Elf", "size": "medium", "size_range": "5-6", "age_max": "750", "age_range": "100-750", "speed": "30"},
    "3": {"name": "Halfling", "size": "small", "size_range": "2-4", "age_max": "250", "age_range": "20-250", "speed": "25"},
    "4": {"name": "Human", "size": "medium", "size_range": "5-6", "age_max": "100", "age_range": "15-100", "speed": "30"},
    "5": {"name": "Dragonborn", "size": "medium", "size_range": "6-8", "age_max": "80", "age_range": "10-80", "speed": "30"},
    "6": {"name": "Gnome", "size": "small", "size_range": "3-4", "age_max": "500", "age_range": "40-500", "speed": "25"},
    "7": {"name": "Half-Elf", "size": "medium", "size_range": "5-6", "age_max": "180", "age_range": "20-180", "speed": "30"},
    "8": {"name": "Half-Orc", "size": "medium", "size_range": "5-6", "age_max": "75", "age_range": "10-75", "speed": "30"},
    "9": {"name": "Tiefling", "size": "medium", "size_range": "5-6", "age_max": "100", "age_range": "15-100", "speed": "30"}
}

def character(txt):
    player_name = input("enter your first name! ")
    character_name = input("enter your characters name! ")
    
    # 打印种族选项,直接从RACES字典生成,后续加种族只需改字典
    print("what race do you want your character to be?")
    for num, race_data in RACES.items():
        print(f"{num}. {race_data['name']}")
    
    character_race_num = input("use the corresponding number to pick: ")
    # 取对应种族数据,默认用Tiefling(原else分支)
    race_data = RACES.get(character_race_num, RACES["9"])
    
    # 调用race函数,传递文件对象和种族数据
    race(txt, player_name, character_name, race_data)

def race(txt, player_name, character_name, race_data):
    race_name = race_data["name"]
    print(f"{race_name} live around {race_data['age_max']} years. so i would suggest anywhere between {race_data['age_range']}")
    player_age = input("input character age: ")
    print(f"{race_name} sizes are: {race_data['size_range']} feet tall, {race_data['size']}")
    player_height = input("input character height: ")
    player_weight = input("input character weight: ")

    txt.write(f"player name: {player_name}\ncharacter name: {character_name}\nrace: {race_name}\nage: {player_age}\nheight: {player_height}\nweight: {player_weight}\nspeed: {race_data['speed']} feet\n")
    txt.write("consult the book for items, subraces and stuff. i am tired and dont know how to make this better, will make it better later.\n")

def stat_roll(txt):
    '''this will make a list of stats for the 4d6 rolls, then remove the lowest number, then add them up.'''
    # 用列表推导式简化掷骰逻辑
    stat_list = [random.randint(1,6) for _ in range(4)]
    stat_list.remove(min(stat_list))
    stat_sum = sum(stat_list)
    txt.write(f"{str(stat_sum)}\n")

# 主程序流程
with open("dnd_character.txt", "w") as txt:
    character(txt)
    txt.write("these are the stats of your character!\n")
    for _ in range(6):
        stat_roll(txt)

重构亮点

  • 后续新增种族只需在RACES字典里加一行数据,无需修改任何函数逻辑,扩展性极强。
  • 消除了几十行重复的if-elif代码,可读性和维护性大幅提升。
  • 函数依赖更清晰,通过参数传递文件对象,避免全局变量带来的潜在问题。
  • 掷骰逻辑用列表推导式简化,代码更紧凑但功能不变。

内容的提问来源于stack exchange,提问作者WeaselBug01

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 02:02:04