如何重构CheckForBingo函数解决Sonar S134控制流嵌套过深问题
拆分C#宾果游戏CheckForBingo函数以消除Sonar S134错误
问题根源
Sonar S134触发的原因是控制流嵌套层数超过阈值(通常为3层),你的原函数大概率在检查行、列、对角线时存在多层循环+条件判断的嵌套。通过将单一职责的逻辑拆分为独立辅助函数,可彻底扁平化控制流,解决该问题。
拆分方案
1. 定义结果枚举与辅助函数
先提取重复逻辑(如判断数字是否被抽取)和单一职责逻辑(检查行、列、对角线、统计匹配数)为独立函数:
public enum BingoResult { NoMatch, Line, FullHouse } private bool IsNumberDrawn(int number, HashSet<int> drawnNumbers) { return drawnNumbers.Contains(number); } private bool HasCompleteRow(int[,] card, HashSet<int> drawnNumbers) { for (int row = 0; row < 3; row++) { if (IsNumberDrawn(card[row, 0], drawnNumbers) && IsNumberDrawn(card[row, 1], drawnNumbers) && IsNumberDrawn(card[row, 2], drawnNumbers)) { return true; } } return false; } private bool HasCompleteColumn(int[,] card, HashSet<int> drawnNumbers) { for (int col = 0; col < 3; col++) { if (IsNumberDrawn(card[0, col], drawnNumbers) && IsNumberDrawn(card[1, col], drawnNumbers) && IsNumberDrawn(card[2, col], drawnNumbers)) { return true; } } return false; } private bool HasCompleteDiagonal(int[,] card, HashSet<int> drawnNumbers) { bool mainDiagonal = IsNumberDrawn(card[0, 0], drawnNumbers) && IsNumberDrawn(card[1, 1], drawnNumbers) && IsNumberDrawn(card[2, 2], drawnNumbers); bool antiDiagonal = IsNumberDrawn(card[0, 2], drawnNumbers) && IsNumberDrawn(card[1, 1], drawnNumbers) && IsNumberDrawn(card[2, 0], drawnNumbers); return mainDiagonal || antiDiagonal; } private int CountTotalMatches(int[,] card, HashSet<int> drawnNumbers) { int matchCount = 0; for (int row = 0; row < 3; row++) { for (int col = 0; col < 3; col++) { if (IsNumberDrawn(card[row, col], drawnNumbers)) { matchCount++; } } } return matchCount; }
2. 重构主CheckForBingo函数
主函数仅负责调用辅助函数,控制流完全扁平化,无嵌套问题:
public BingoResult CheckForBingo(int[,] card, List<int> drawnNumbers) { // 转换为HashSet提升查询效率(O(1) vs List的O(n)) var drawnNumberSet = new HashSet<int>(drawnNumbers); // 优先检查连线(行/列/对角线) if (HasCompleteRow(card, drawnNumberSet) || HasCompleteColumn(card, drawnNumberSet) || HasCompleteDiagonal(card, drawnNumberSet)) { return BingoResult.Line; } // 检查全中 if (CountTotalMatches(card, drawnNumberSet) == 9) { return BingoResult.FullHouse; } return BingoResult.NoMatch; }
方案优势
- 消除嵌套问题:所有辅助函数的控制流嵌套最多2层(统计匹配数的双层循环为必要逻辑,Sonar不会触发S134),主函数无嵌套。
- 单一职责:每个辅助函数仅处理一件事,代码可读性、可维护性大幅提升,后续修改逻辑只需对应调整单个函数。
- 性能优化:将
List<int>转为HashSet<int>,数字查询效率从线性时间优化为常数时间,适合15个抽取数字的场景。
内容的提问来源于stack exchange,提问作者Bogdan Dragoş
相关产品推荐
相关产品推荐

