如何从CardValue枚举创建Dictionary<CardValue, int>统计牌值出现次数
扑克游戏中高效统计CardValue出现次数的实现方案
问题背景
我正在开发一个扑克游戏,拥有一个Card数组,每张牌都具备CardValue枚举类型的属性,需要创建Dictionary<CardValue, int>来统计数组中各CardValue的出现次数。
枚举定义如下:
public enum CardValue { Ace = 1, Two = 2, Three = 3, Four = 4, Five = 5, Six = 6, Seven = 7, Eight = 8, Nine = 9, Ten = 10, Jack = 11, Queen = 12, King = 13 }
目前已手动创建字典,但如果枚举规模扩大,希望找到更高效的自动创建方式,同时必须保留枚举作为字典键以保证可读性(例如用CardValueCount[CardValue.Queen]而非数字索引查询)。当前手动实现代码如下:
public Card[] Cards {get; set;} private Dictionary <CardValue, int> CardValueCount { get { var cardValueCount = new Dictionary<CardValue, int>() { { CardValue.Ace, 0}, { CardValue.Two, 0}, { CardValue.Three, 0}, { CardValue.Four, 0}, { CardValue.Five, 0}, { CardValue.Six, 0}, { CardValue.Seven, 0}, { CardValue.Eight, 0}, { CardValue.Nine, 0}, { CardValue.Ten, 0}, { CardValue.Jack, 0}, { CardValue.Queen, 0}, { CardValue.King, 0} }; if (Cards.Length < 1 || Cards == null) { return cardValueCount; } else { foreach (Card card in Cards) { cardValueCount[card.Value]++; } return cardValueCount; } } }
解决方案
方法一:自动初始化全枚举字典
通过Enum.GetValues<CardValue>()获取所有枚举值,自动生成初始计数为0的字典,无需手动编写每个键值对:
public Card[] Cards { get; set; } private Dictionary<CardValue, int> CardValueCount { get { // 自动生成所有CardValue对应的初始计数0 var countDict = Enum.GetValues<CardValue>() .ToDictionary(value => value, _ => 0); if (Cards == null) return countDict; foreach (var card in Cards) { countDict[card.Value]++; } return countDict; } }
注意:原代码先判断Cards.Length <1会触发空引用异常,需优先判断Cards == null。
方法二:LINQ GroupBy直接生成统计字典
如果允许未出现的枚举值不显示在字典中,可直接用GroupBy一步完成统计:
private Dictionary<CardValue, int> CardValueCount { get { if (Cards == null || Cards.Length == 0) { // 若需要空数组时返回全0字典,复用方法一的初始化逻辑 return Enum.GetValues<CardValue>().ToDictionary(v => v, _ => 0); } return Cards.GroupBy(card => card.Value) .ToDictionary(group => group.Key, group => group.Count()); } }
如果要求未出现的枚举值也保留键并设为0,可将GroupBy结果与全枚举字典合并:
private Dictionary<CardValue, int> CardValueCount { get { var baseDict = Enum.GetValues<CardValue>().ToDictionary(v => v, _ => 0); if (Cards == null || Cards.Length == 0) return baseDict; var grouped = Cards.GroupBy(c => c.Value) .ToDictionary(g => g.Key, g => g.Count()); foreach (var kvp in grouped) { baseDict[kvp.Key] = kvp.Value; } return baseDict; } }
关键优化点
- 修复原代码的空引用风险:必须先判断
Cards == null,再访问Length属性 - 自动生成字典的方式可避免枚举扩展时手动修改初始化代码,提升可维护性
内容的提问来源于stack exchange,提问作者Adam Cook
相关产品推荐
相关产品推荐

