You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 23:31:06