diff --git a/common/data/Element/main.go b/common/data/Element/main.go deleted file mode 100644 index 40f9429d..00000000 --- a/common/data/Element/main.go +++ /dev/null @@ -1,163 +0,0 @@ -package main - -import ( - "fmt" -) - -// 定义属性枚举 -type ElementType int - -const ( - FIRE ElementType = iota + 1 // 火系 - GRASS // 草系 - WATER // 水系 - ICE // 冰系 - FIGHTING // 战斗系 - PSYCHIC // 超能系 -) - -// 定义属性组合 -type ElementCombination struct { - primary ElementType - secondary *ElementType -} - -// 创建新的属性组合 -func NewElementCombination(primary ElementType, secondary *ElementType) (ElementCombination, error) { - if secondary != nil { - if primary > *secondary { - primary, *secondary = *secondary, primary - } - if primary == *secondary { - return ElementCombination{}, fmt.Errorf("双属性不能重复") - } - } - 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} -} - -// 属性计算器 -type ElementCalculator struct{} - -// 单属性克制关系矩阵 -var singleMatrix = map[ElementType]map[ElementType]float64{ - FIRE: { - PSYCHIC: 0.5, - ICE: 2.0, - }, - GRASS: { - ICE: 1.0, - PSYCHIC: 1.0, - GRASS: 0.5, - WATER: 2.0, - }, - FIGHTING: { - ICE: 2.0, - PSYCHIC: 0.5, - FIGHTING: 0.5, - }, - WATER: { - ICE: 2.0, - PSYCHIC: 0.5, - FIGHTING: 0.5, - }, -} - -// 获取单属性克制系数 -func (ec ElementCalculator) getSingleEffectiveness(attacker ElementType, defender ElementType) float64 { - if attackerMatrix, exists := singleMatrix[attacker]; exists { - if value, ok := attackerMatrix[defender]; ok { - return value - } - } - return 1.0 -} - -// 计算克制系数 -func (ec ElementCalculator) CalculateEffectiveness(attacker, defender ElementCombination) float64 { - if !attacker.IsDual() { - return ec.handleSingleAttacker(attacker.primary, defender) - } - return ec.handleDualAttacker(attacker, defender) -} - -// 处理单属性攻击 -func (ec ElementCalculator) handleSingleAttacker(attacker ElementType, defender ElementCombination) float64 { - if !defender.IsDual() { - return ec.getSingleEffectiveness(attacker, defender.primary) - } - m1 := ec.getSingleEffectiveness(attacker, defender.primary) - m2 := ec.getSingleEffectiveness(attacker, *defender.secondary) - return (m1 + m2) / 2.0 -} - -// 处理双属性攻击 -func (ec ElementCalculator) handleDualAttacker(attacker, defender ElementCombination) float64 { - aElements := attacker.Elements() - a1, a2 := aElements[0], aElements[1] - - if !defender.IsDual() { - m1 := ec.getSingleEffectiveness(a1, defender.primary) - m2 := ec.getSingleEffectiveness(a2, defender.primary) - return (m1 + m2) / 2.0 - } - - dElements := defender.Elements() - d1, d2 := dElements[0], dElements[1] - - m11 := ec.getSingleEffectiveness(a1, d1) - m12 := ec.getSingleEffectiveness(a1, d2) - m21 := ec.getSingleEffectiveness(a2, d1) - m22 := ec.getSingleEffectiveness(a2, d2) - - return (m11 + m12 + m21 + m22) / 4.0 -} - -func main() { - calculator := ElementCalculator{} - - // 测试用例1 - attacker1, _ := NewElementCombination(FIGHTING, nil) - defender1, _ := NewElementCombination(ICE, nil) - result1 := calculator.CalculateEffectiveness(attacker1, defender1) - fmt.Printf("战斗->冰:%v → %v → 倍数:%.1f\n", attacker1, defender1, result1) - - // 测试用例2 - attacker2, _ := NewElementCombination(GRASS, &FIGHTING) - defender2, _ := NewElementCombination(FIGHTING, nil) - result2 := calculator.CalculateEffectiveness(attacker2, defender2) - fmt.Printf("草战斗->战斗:%v → %v → 倍数:%.1f\n", attacker2, defender2, result2) - - // 测试用例3 - attacker3, _ := NewElementCombination(GRASS, &FIGHTING) - defender3, _ := NewElementCombination(GRASS, &FIGHTING) - result3 := calculator.CalculateEffectiveness(attacker3, defender3) - fmt.Printf("草战斗->草战斗:%v → %v → 倍数:%.1f\n", attacker3, defender3, result3) - - // 测试用例4 - attacker4, _ := NewElementCombination(GRASS, nil) - defender4, _ := NewElementCombination(GRASS, &FIGHTING) - result4 := calculator.CalculateEffectiveness(attacker4, defender4) - fmt.Printf("草->草战斗:%v → %v → 倍数:%.1f\n", attacker4, defender4, result4) - - // 测试用例5 - attacker5, _ := NewElementCombination(GRASS, &FIGHTING) - defender5, _ := NewElementCombination(WATER, &FIGHTING) - result5 := calculator.CalculateEffectiveness(attacker5, defender5) - fmt.Printf("草战斗->水战斗:%v → %v → 倍数:%.1f\n", attacker5, defender5, result5) -} diff --git a/common/data/Element/main_test.go b/common/data/Element/main_test.go new file mode 100644 index 00000000..85df3dce --- /dev/null +++ b/common/data/Element/main_test.go @@ -0,0 +1,201 @@ +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) +}