package element import ( "fmt" "testing" ) // 元素类型枚举(对应Python的IntEnum) type ElementType int const ( ElementTypeFire ElementType = 2 // 火系 ElementTypeGrass ElementType = 4 // 草系 ElementTypeWater ElementType = 5 // 水系 ElementTypeIce ElementType = 6 // 冰系 ElementTypeFighting ElementType = 7 // 战斗系 ElementTypePsychic ElementType = 11 // 超能系 ) // 为ElementType实现String方法,方便打印 func (e ElementType) String() string { switch e { case ElementTypeFire: return "FIRE" case ElementTypeGrass: return "GRASS" case ElementTypeWater: return "WATER" case ElementTypeIce: return "ICE" case ElementTypeFighting: return "FIGHTING" case ElementTypePsychic: return "PSYCHIC" default: return "UNKNOWN" } } // 元素组合结构体(对应Python的@dataclass) type ElementCombination struct { primary ElementType secondary *ElementType // 指针类型表示可选(nil为单属性) } // 创建元素组合实例(构造函数,处理属性排序和重复检查) func NewElementCombination(primary ElementType, secondary *ElementType) (*ElementCombination, error) { // 检查双属性是否重复 if secondary != nil && primary == *secondary { return nil, fmt.Errorf("双属性不能重复") } // 确保primary <= secondary(排序) if secondary != nil && primary > *secondary { primary, *secondary = *secondary, primary } return &ElementCombination{ primary: primary, secondary: secondary, }, nil } // 判断是否为双属性 func (ec *ElementCombination) IsDual() bool { return ec.secondary != nil } // 获取所有属性(返回切片) func (ec *ElementCombination) Elements() []ElementType { if ec.IsDual() { return []ElementType{ec.primary, *ec.secondary} } return []ElementType{ec.primary} } // 为ElementCombination实现String方法,方便打印 func (ec *ElementCombination) String() string { if ec.IsDual() { return fmt.Sprintf("(%s, %s)", ec.primary, *ec.secondary) } return fmt.Sprintf("(%s)", ec.primary) } // 元素克制计算器 type ElementCalculator struct { singleMatrix map[ElementType]map[ElementType]float64 // 单属性克制矩阵 } // 创建计算器实例(初始化克制矩阵) func NewElementCalculator() *ElementCalculator { // 初始化单属性克制关系(对应Python的SINGLE_MATRIX) singleMatrix := map[ElementType]map[ElementType]float64{ ElementTypeFire: { ElementTypePsychic: 0.5, ElementTypeIce: 2.0, }, ElementTypeGrass: { ElementTypeIce: 1.0, ElementTypePsychic: 1.0, ElementTypeGrass: 0.5, ElementTypeWater: 2.0, }, ElementTypeFighting: { ElementTypeIce: 2.0, ElementTypePsychic: 0.5, ElementTypeFighting: 0.5, }, ElementTypeWater: { ElementTypeIce: 2.0, ElementTypePsychic: 0.5, ElementTypeFighting: 0.5, }, } return &ElementCalculator{singleMatrix: singleMatrix} } // 获取单属性攻击单属性的克制倍数 func (c *ElementCalculator) getSingleEffectiveness(attacker, defender ElementType) float64 { // 从矩阵中查找,未定义则默认1.0 if attackerMap, ok := c.singleMatrix[attacker]; ok { if val, ok := attackerMap[defender]; ok { return val } } return 1.0 } // 处理单属性攻击者的计算 func (c *ElementCalculator) handleSingleAttacker(attacker ElementType, defender *ElementCombination) float64 { if !defender.IsDual() { // 攻击单属性防御者 return c.getSingleEffectiveness(attacker, defender.primary) } // 攻击双属性防御者:取两个属性的平均值 m1 := c.getSingleEffectiveness(attacker, defender.primary) m2 := c.getSingleEffectiveness(attacker, *defender.secondary) return (m1 + m2) / 2.0 } // 处理双属性攻击者的计算 func (c *ElementCalculator) handleDualAttacker(attacker, defender *ElementCombination) float64 { a1, a2 := attacker.primary, *attacker.secondary if !defender.IsDual() { // 攻击单属性防御者:取两个攻击属性的平均值 m1 := c.getSingleEffectiveness(a1, defender.primary) m2 := c.getSingleEffectiveness(a2, defender.primary) return (m1 + m2) / 2.0 } // 攻击双属性防御者:取四个组合的平均值 d1, d2 := defender.primary, *defender.secondary m11 := c.getSingleEffectiveness(a1, d1) m12 := c.getSingleEffectiveness(a1, d2) m21 := c.getSingleEffectiveness(a2, d1) m22 := c.getSingleEffectiveness(a2, d2) return (m11 + m12 + m21 + m22) / 4.0 } // 计算最终克制倍数 func (c *ElementCalculator) CalculateEffectiveness(attacker, defender *ElementCombination) float64 { if !attacker.IsDual() { return c.handleSingleAttacker(attacker.primary, defender) } return c.handleDualAttacker(attacker, defender) } // 测试用例 func Test_CalculateEffectiveness(t *testing.T) { calculator := NewElementCalculator() // 测试1:战斗->冰 attacker1, _ := NewElementCombination(ElementTypeFighting, nil) defender1, _ := NewElementCombination(ElementTypeIce, nil) result1 := calculator.CalculateEffectiveness(attacker1, defender1) fmt.Printf("战斗->冰:%v → %v → 倍数:%.2f\n", attacker1, defender1, result1) // 测试2:草战斗->战斗 secondaryFighting := ElementTypeFighting attacker2, _ := NewElementCombination(ElementTypeGrass, &secondaryFighting) defender2, _ := NewElementCombination(ElementTypeFighting, nil) result2 := calculator.CalculateEffectiveness(attacker2, defender2) fmt.Printf("草战斗->战斗:%v → %v → 倍数:%.4f\n", attacker2, defender2, result2) // 测试3:草战斗->草战斗 defender3, _ := NewElementCombination(ElementTypeGrass, &secondaryFighting) result3 := calculator.CalculateEffectiveness(attacker2, defender3) fmt.Printf("草战斗->草战斗:%v → %v → 倍数:%.4f\n", attacker2, defender3, result3) // 测试4:草->草战斗 attacker4, _ := NewElementCombination(ElementTypeGrass, nil) defender4, _ := NewElementCombination(ElementTypeGrass, &secondaryFighting) result4 := calculator.CalculateEffectiveness(attacker4, defender4) fmt.Printf("草->草战斗:%v → %v → 倍数:%.4f\n", attacker4, defender4, result4) // 测试5:草战斗->水战斗 defender5, _ := NewElementCombination(ElementTypeWater, &secondaryFighting) result5 := calculator.CalculateEffectiveness(attacker2, defender5) fmt.Printf("草战斗->水战斗:%v → %v → 倍数:%.4f\n", attacker2, defender5, result5) }