3×3 Bingo游戏CheckForLine函数优化:移除三层嵌套循环(禁用LINQ)
3×3 Bingo游戏代码优化需求
项目说明
- 已实现3×3 Bingo游戏逻辑:读取用户输入的3×3 Bingo卡片和15个抽取数字,判断输出
line、bingo或nothing - 判断规则:
- 当卡片所有数字都在抽取数字中,输出
bingo - 当存在整行数字都在抽取数字中但未全卡片命中,输出
line - 以上条件都不满足时输出
nothing
- 当卡片所有数字都在抽取数字中,输出
- 当前问题:
CheckForLine()使用了三层嵌套循环,希望优化该实现,但受Sonar分析器限制无法使用LINQ
原始代码
using System; class Program { static void Main() { const int numberOfRows = 3; const int numberOfColumns = 3; const int numbersExtracted = 15; int[,] bingoCard = ReadBingoCard(numberOfRows, numberOfColumns); int[] numbers = ReadNumbersExtracted(numbersExtracted); PrintResult(bingoCard, numbers); } static int[,] ReadBingoCard(int rowsNumber, int columnNumber) { int[,] card = new int[rowsNumber, columnNumber]; for (int i = 0; i < rowsNumber; i++) { string[] array = Console.ReadLine().Split(' '); for (int j = 0; j < columnNumber; j++) { card[i, j] = Convert.ToInt32(array[j]); } } return card; } static int[] ReadNumbersExtracted(int numbersExtracted) { int[] numbers = new int[numbersExtracted]; for (int i = 0; i < numbersExtracted; i++) { numbers[i] = Convert.ToInt32(Console.ReadLine()); } return numbers; } static bool CheckForBingo(int[,] bingoCard, int[] numbers) { int numMatchesFound = 0; foreach (var number in bingoCard) { for (int numIndex = 0; numIndex < numbers.Length; numIndex++) { if (number == numbers[numIndex]) { numMatchesFound++; break; } } } return numMatchesFound == bingoCard.Length; } static bool CheckForLine(int[,] bingoCard, int[] numbers) { for (int row = 0; row < bingoCard.GetLength(0); row++) { int colMatchesInRow = 0; for (int col = 0; col < bingoCard.GetLength(1); col++) { for (int numIndex = 0; numIndex < numbers.Length; numIndex++) { if (bingoCard[row, col] != numbers[numIndex]) { continue; } colMatchesInRow++; break; } } if (colMatchesInRow == bingoCard.GetLength(1)) { return true; } } return false; } static void PrintResult(int[,] bingoCard, int[] numbersExtracted) { if (CheckForBingo(bingoCard, numbersExtracted)) { Console.WriteLine("bingo"); } else if (CheckForLine(bingoCard, numbersExtracted)) { Console.WriteLine("line"); } else { Console.WriteLine("nothing"); } } }
优化方案
核心思路是用HashSet<int>存储抽取数字,将数字存在性检查从O(n)降为O(1),从而消除三层嵌套循环:
优化后的关键方法
// 先将抽取数字转换为HashSet,避免重复查找 private static HashSet<int> CreateNumberSet(int[] numbers) { HashSet<int> numberSet = new HashSet<int>(); foreach (int num in numbers) { numberSet.Add(num); } return numberSet; } static bool CheckForBingo(int[,] bingoCard, HashSet<int> numberSet) { foreach (var number in bingoCard) { if (!numberSet.Contains(number)) { return false; } } return true; } static bool CheckForLine(int[,] bingoCard, HashSet<int> numberSet) { int rowCount = bingoCard.GetLength(0); int colCount = bingoCard.GetLength(1); // 检查行 for (int row = 0; row < rowCount; row++) { bool rowComplete = true; for (int col = 0; col < colCount; col++) { if (!numberSet.Contains(bingoCard[row, col])) { rowComplete = false; break; } } if (rowComplete) { return true; } } return false; }
调整Main及相关方法
在Main中先创建HashSet,再传入检查方法:
static void Main() { const int numberOfRows = 3; const int numberOfColumns = 3; const int numbersExtracted = 15; int[,] bingoCard = ReadBingoCard(numberOfRows, numberOfColumns); int[] numbers = ReadNumbersExtracted(numbersExtracted); HashSet<int> numberSet = CreateNumberSet(numbers); PrintResult(bingoCard, numberSet); } // 同步调整PrintResult参数 static void PrintResult(int[,] bingoCard, HashSet<int> numberSet) { if (CheckForBingo(bingoCard, numberSet)) { Console.WriteLine("bingo"); } else if (CheckForLine(bingoCard, numberSet)) { Console.WriteLine("line"); } else { Console.WriteLine("nothing"); } }
优化后,CheckForLine()从三层循环变为两层,同时整体代码的时间复杂度从O(m*n)(m为卡片数字数,n为抽取数字数)降为O(m + n),效率更高且代码更简洁。
内容的提问来源于stack exchange,提问作者Dragos Bogdan
相关产品推荐
相关产品推荐

