C#处理FEN字符串:多分支if语句的优化方案问询
解决FEN字符串解析中大量if-else的简洁方案
解决这种重复分支判断的问题,以下几个方案可以彻底简化你的代码:
方案1:字典映射(最直接高效)
用Dictionary<char, GameObject>建立FEN字符与棋子预制体的直接映射,遍历字符串时直接查表,完全替代if-else分支。
// 在Inspector面板或初始化方法中绑定各棋子预制体 public Dictionary<char, GameObject> piecePrefabs; void SpawnBoardFromFEN(string fen) { int x = 0; int y = 7; // FEN格式从棋盘第8行开始(对应y轴坐标7) foreach (char c in fen) { if (c == '/') { // 换行处理:重置x坐标,y坐标减1 x = 0; y--; continue; } if (char.IsDigit(c)) { // 空位数:直接跳过对应数量的格子 x += int.Parse(c.ToString()); continue; } // 查表获取预制体并实例化 if (piecePrefabs.TryGetValue(c, out GameObject prefab)) { Vector3 spawnPos = new Vector3(x, 0, y); // 根据你的棋盘坐标系调整 Instantiate(prefab, spawnPos, Quaternion.identity); } x++; } }
优势:配置灵活,新增或修改棋子只需在字典中添加/修改键值对,无需改动核心逻辑代码。
方案2:枚举+自定义属性(类型安全的规范方案)
如果需要对棋子类型做严格约束,可定义枚举配合自定义属性存储FEN字符与预制体的关联,适合需要扩展棋子属性(如颜色、移动规则)的复杂项目。
// 自定义属性:存储FEN字符和对应预制体 [AttributeUsage(AttributeTargets.Field)] public class FenPieceAttribute : Attribute { public char FenChar { get; } public GameObject Prefab { get; set; } public FenPieceAttribute(char fenChar) { FenChar = fenChar; } } // 棋子类型枚举 public enum ChessPiece { [FenPiece('r')] BlackRook, [FenPiece('n')] BlackKnight, [FenPiece('b')] BlackBishop, [FenPiece('q')] BlackQueen, [FenPiece('k')] BlackKing, [FenPiece('p')] BlackPawn, [FenPiece('R')] WhiteRook, [FenPiece('N')] WhiteKnight, [FenPiece('B')] WhiteBishop, [FenPiece('Q')] WhiteQueen, [FenPiece('K')] WhiteKing, [FenPiece('P')] WhitePawn } // 初始化映射表(建议在Awake中执行) private Dictionary<char, GameObject> _fenToPrefabMap; void Awake() { _fenToPrefabMap = new Dictionary<char, GameObject>(); foreach (ChessPiece piece in Enum.GetValues(typeof(ChessPiece))) { var attr = (FenPieceAttribute)Attribute.GetCustomAttribute( typeof(ChessPiece).GetField(piece.ToString()), typeof(FenPieceAttribute)); if (attr != null && attr.Prefab != null) { _fenToPrefabMap.Add(attr.FenChar, attr.Prefab); } } } // 棋盘生成逻辑与方案1一致,直接使用_fenToPrefabMap查表即可
优势:类型安全,棋子与FEN字符的关联固化在枚举中,便于统一管理和扩展。
方案3:工厂类(解耦实例化逻辑)
如果棋子实例化还需要额外处理(如设置颜色、绑定逻辑脚本),可以把这部分封装到工厂类中,让棋盘生成代码只专注于FEN解析和位置计算。
public class ChessPieceFactory { private Dictionary<char, GameObject> _prefabMap; public ChessPieceFactory(Dictionary<char, GameObject> prefabMap) { _prefabMap = prefabMap; } public GameObject SpawnPiece(char fenChar, Vector3 spawnPos) { if (!_prefabMap.TryGetValue(fenChar, out GameObject prefab)) return null; GameObject piece = Instantiate(prefab, spawnPos, Quaternion.identity); // 统一处理棋子初始化逻辑,比如设置颜色标记 ChessPieceComponent pieceComp = piece.GetComponent<ChessPieceComponent>(); if (pieceComp != null) { pieceComp.IsWhite = char.IsUpper(fenChar); } return piece; } } // 在棋盘生成脚本中使用工厂类 public ChessPieceFactory pieceFactory; void SpawnBoardFromFEN(string fen) { int x = 0; int y = 7; foreach (char c in fen) { if (c == '/') { x=0; y--; continue; } if (char.IsDigit(c)) { x += int.Parse(c.ToString()); continue; } Vector3 pos = new Vector3(x, 0, y); pieceFactory.SpawnPiece(c, pos); x++; } }
优势:职责单一,实例化细节完全封装在工厂类中,代码解耦更彻底。
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

