問題代碼核心
htCards.Remove(index); // 移除已發牌的鍵
while (!htCards.Contains(index) || randomList.Contains(index)) {
index = r.Next(1, 54);
}
randomList.Add(index);
// 後續 hxCards[index] 取值時,index 已不在 htCards 中,返回 null
錯誤分析
- Remove 後鍵不存在:
htCards.Remove(index) 刪除了該鍵,後續 hxCards[index] 自然為 null。
- 隨機邏輯缺陷:
r.Next(1,54) 最大返回 53,無法取到 54;且移除鍵後總數變少,導致死循環風險。
- 數據結構選型不當:發牌屬於洗牌抽樣,應使用
List<int> 洗牌後切片,而非 Hashtable 刪除鍵。
正確實現:Fisher-Yates 洗牌
public List DealCards(int count = 13) {
var deck = Enumerable.Range(1, 54).ToList(); // 1-54
var rnd = new Random();
// 洗牌
for (int i = deck.Count - 1; i > 0; i--) {
int j = rnd.Next(i + 1);
var tmp = deck[i]; deck[i] = deck[j]; deck[j] = tmp;
}
return deck.Take(count).ToList(); // 取前 13 張
}
顯示邏輯
var cards = DealCards();
foreach (var idx in cards) {
Console.Write(cardDict[idx] + "\t"); // cardDict 為 Dictionary
}
代碼簡化建議
- 用
Dictionary 替代 Hashtable,類型安全且性能更好。
- 花色/點數生成邏輯可用數組/枚舉表驅動,消除冗長
switch。
- 利用 LINQ
OrderBy(_ => Guid.NewGuid()) 快速洗牌(小數據量可接受)。