如何重构包含重复代码的UpFirst()与RightFirst()函数?
重构方案:消除UpFirst和RightFirst的重复代码
核心思路
通过提取公共逻辑和参数化差异部分,将两个高度重复的函数拆分为通用框架+专用逻辑,大幅提升代码可读性和可维护性。
步骤1:定义方向枚举(区分上下/左右检查)
创建枚举标记检查方向,让通用方法能区分不同处理逻辑:
private enum CheckDirection { Up, Right }
步骤2:提取公共匹配组处理逻辑
将两个函数中if(isAllMatch)块内的重复代码抽离为独立方法,同时优化匹配类型的判断顺序(减少嵌套):
private void ProcessMatchGroup(int x, int y, List<Tiles> sameBlocks) { sameBlocks.Add(_tiles[x, y]); var newBlocks = FloodFill(x, y); // 合并新找到的块 foreach (var block in newBlocks.Where(block => !sameBlocks.Contains(block))) { sameBlocks.Add(block); } // 确定匹配组类型(从严格到宽松判断,避免嵌套) var matchType = TileGroupType.Default; if (sameBlocks.Count > _ConditionCCount) { matchType = TileGroupType.C; } else if (sameBlocks.Count > _ConditionBCount) { matchType = TileGroupType.B; } else if (sameBlocks.Count > _ConditionACount) { matchType = TileGroupType.A; } // 设置所有匹配块的类型 foreach (var block in sameBlocks) { block.SetMatchGroupType(matchType); } }
步骤3:提取连续匹配判断逻辑
将检查连续同色块的逻辑抽离,通过方向参数适配上下/左右的检查方式:
private bool HasConsecutiveMatches(int x, int y, CheckDirection direction) { var currentBlock = _tiles[x, y]; for (var i = 1; i < _MinNumberToBlast; i++) { Tiles blockToCheck; switch (direction) { case CheckDirection.Up: blockToCheck = _tiles[x, y + i]; break; case CheckDirection.Right: blockToCheck = _tiles[x + i, y]; break; default: throw new ArgumentOutOfRangeException(nameof(direction)); } // 只要有一个块不匹配,直接终止检查 if (currentBlock.Color != blockToCheck.Color) { return false; } } return true; }
步骤4:创建通用检查方法
将循环框架、跳过条件、方向相关的差异逻辑整合到通用方法中:
private bool CheckMatches(CheckDirection direction) { var sameBlocks = new List<Tiles>(); var isAnyMatch = false; switch (direction) { case CheckDirection.Up: for (var x = 0; x < _RowCount; x++) { for (var y = 0; y < _ColumnCount; y++) { // 跳过无法形成最小匹配的位置 if (y > _ColumnCount - _MinNumberToBlast) continue; if (HasConsecutiveMatches(x, y, direction)) { isAnyMatch = true; ProcessMatchGroup(x, y, sameBlocks); } sameBlocks.Clear(); } } break; case CheckDirection.Right: for (var y = 0; y < _ColumnCount; y++) { for (var x = 0; x < _RowCount; x++) { // 跳过无法形成最小匹配的位置 if (x > _RowCount - _MinNumberToBlast) continue; // RightFirst独有的初始化操作 var currentBlock = _tiles[x, y]; currentBlock.SetMatchGroupType(TileGroupType.Default); if (HasConsecutiveMatches(x, y, direction)) { isAnyMatch = true; ProcessMatchGroup(x, y, sameBlocks); } sameBlocks.Clear(); } } break; default: throw new ArgumentOutOfRangeException(nameof(direction)); } return isAnyMatch; }
步骤5:简化原方法
原有两个函数只需调用通用方法即可,代码简洁明了:
private bool UpFirst() { return CheckMatches(CheckDirection.Up); } private bool RightFirst() { return CheckMatches(CheckDirection.Right); }
额外优化点(可选)
- 原代码中
sameBlocks.Contains(block)的时间复杂度是O(n),如果FloodFill返回的集合较大,建议用HashSet<Tiles>代替List<Tiles>来提升性能。 - 可以将
ProcessMatchGroup中的sameBlocks改为方法内创建,避免外部传入带来的状态管理问题。
内容的提问来源于stack exchange,提问作者Ecem Belgin
相关产品推荐
相关产品推荐

